blob: 879b4e2625789340ce2d6c1fe19edc404cfcca35 [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
Nicolas Capensd689d1c2018-11-19 16:02:36 -050015#include "VkDevice.hpp"
16
Antonio Maiorano42fd1592020-04-27 11:30:40 -040017#include "VkConfig.hpp"
Alexis Hetu048974f2019-02-15 15:28:37 -050018#include "VkDescriptorSetLayout.hpp"
Alexis Hetue1f51b92019-04-23 15:34:34 -040019#include "VkFence.hpp"
Alexis Hetu9e4d0402018-10-16 15:44:12 -040020#include "VkQueue.hpp"
Ben Claytona4e06ca2019-12-03 12:38:14 +000021#include "Debug/Context.hpp"
22#include "Debug/Server.hpp"
Alexis Hetu0da99f52019-02-27 12:54:52 -050023#include "Device/Blitter.hpp"
Ben Clayton25e06e02020-02-07 11:19:08 +000024#include "System/Debug.hpp"
Nicolas Capensd689d1c2018-11-19 16:02:36 -050025
Alexis Hetue1f51b92019-04-23 15:34:34 -040026#include <chrono>
27#include <climits>
Ben Clayton2ed93ab2019-12-17 20:38:03 +000028#include <new> // Must #include this to use "placement new"
Alexis Hetu767b41b2018-09-26 11:25:46 -040029
Nicolas Capens157ba262019-12-10 17:49:14 -050030namespace {
31
32std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> now()
Alexis Hetue1f51b92019-04-23 15:34:34 -040033{
Nicolas Capens157ba262019-12-10 17:49:14 -050034 return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now());
Alexis Hetue1f51b92019-04-23 15:34:34 -040035}
36
Nicolas Capens157ba262019-12-10 17:49:14 -050037} // anonymous namespace
38
39namespace vk {
Alexis Hetu767b41b2018-09-26 11:25:46 -040040
Nicolas Capensd53eeca2020-03-19 13:31:41 -040041void Device::SamplingRoutineCache::updateSnapshot()
Alexis Hetu35755502019-07-22 13:51:49 -040042{
Ben Clayton377573c2020-04-03 20:36:40 +010043 marl::lock lock(mutex);
Nicolas Capens1c294772020-03-28 23:04:55 -040044
Ben Claytonac43aa72020-04-04 00:48:13 +010045 if(snapshotNeedsUpdate)
46 {
47 snapshot.clear();
48
49 for(auto it : cache)
50 {
51 snapshot[it.key()] = it.data();
52 }
53
54 snapshotNeedsUpdate = false;
55 }
Alexis Hetu35755502019-07-22 13:51:49 -040056}
57
Nicolas Capens73c4a0c2020-03-17 17:29:11 -040058Device::SamplerIndexer::~SamplerIndexer()
59{
60 ASSERT(map.empty());
61}
62
63uint32_t Device::SamplerIndexer::index(const SamplerState &samplerState)
64{
Ben Clayton377573c2020-04-03 20:36:40 +010065 marl::lock lock(mutex);
Nicolas Capens73c4a0c2020-03-17 17:29:11 -040066
67 auto it = map.find(samplerState);
68
69 if(it != map.end())
70 {
71 it->second.count++;
72 return it->second.id;
73 }
74
75 nextID++;
76
77 map.emplace(samplerState, Identifier{ nextID, 1 });
78
79 return nextID;
80}
81
82void Device::SamplerIndexer::remove(const SamplerState &samplerState)
83{
Ben Clayton377573c2020-04-03 20:36:40 +010084 marl::lock lock(mutex);
Nicolas Capens73c4a0c2020-03-17 17:29:11 -040085
86 auto it = map.find(samplerState);
87 ASSERT(it != map.end());
88
89 auto count = --it->second.count;
90 if(count == 0)
91 {
92 map.erase(it);
93 }
94}
95
Ben Clayton2ed93ab2019-12-17 20:38:03 +000096Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures, const std::shared_ptr<marl::Scheduler> &scheduler)
97 : physicalDevice(physicalDevice)
98 , queues(reinterpret_cast<Queue *>(mem))
99 , enabledExtensionCount(pCreateInfo->enabledExtensionCount)
100 , enabledFeatures(enabledFeatures ? *enabledFeatures : VkPhysicalDeviceFeatures{})
101 , // "Setting pEnabledFeatures to NULL and not including a VkPhysicalDeviceFeatures2 in the pNext member of VkDeviceCreateInfo is equivalent to setting all members of the structure to VK_FALSE."
102 scheduler(scheduler)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400103{
Alexis Hetu767b41b2018-09-26 11:25:46 -0400104 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
105 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000106 const VkDeviceQueueCreateInfo &queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
Alexis Hetue70c3512018-10-17 13:18:04 -0400107 queueCount += queueCreateInfo.queueCount;
Alexis Hetu767b41b2018-09-26 11:25:46 -0400108 }
109
110 uint32_t queueID = 0;
111 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
112 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000113 const VkDeviceQueueCreateInfo &queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
Alexis Hetu767b41b2018-09-26 11:25:46 -0400114
115 for(uint32_t j = 0; j < queueCreateInfo.queueCount; j++, queueID++)
116 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000117 new(&queues[queueID]) Queue(this, scheduler.get());
Alexis Hetu767b41b2018-09-26 11:25:46 -0400118 }
119 }
Nicolas Capensd689d1c2018-11-19 16:02:36 -0500120
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000121 extensions = reinterpret_cast<ExtensionName *>(static_cast<uint8_t *>(mem) + (sizeof(Queue) * queueCount));
Alexis Hetu352791e2019-05-17 16:42:34 -0400122 for(uint32_t i = 0; i < enabledExtensionCount; i++)
123 {
124 strncpy(extensions[i], pCreateInfo->ppEnabledExtensionNames[i], VK_MAX_EXTENSION_NAME_SIZE);
125 }
126
Nicolas Capensd689d1c2018-11-19 16:02:36 -0500127 if(pCreateInfo->enabledLayerCount)
128 {
129 // "The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations."
Nicolas Capens44bd43a2020-01-22 03:07:14 -0500130 UNSUPPORTED("enabledLayerCount");
Nicolas Capensd689d1c2018-11-19 16:02:36 -0500131 }
Alexis Hetu0da99f52019-02-27 12:54:52 -0500132
Alexis Hetu1a9714a2019-04-12 11:48:12 -0400133 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
Alexis Hetu6448bd62019-06-11 15:58:59 -0400134 blitter.reset(new sw::Blitter());
Alexis Hetu35755502019-07-22 13:51:49 -0400135 samplingRoutineCache.reset(new SamplingRoutineCache());
Nicolas Capens73c4a0c2020-03-17 17:29:11 -0400136 samplerIndexer.reset(new SamplerIndexer());
Ben Claytona4e06ca2019-12-03 12:38:14 +0000137
138#ifdef ENABLE_VK_DEBUGGER
139 static auto port = getenv("VK_DEBUGGER_PORT");
140 if(port)
141 {
142 // Construct the debugger context and server - this may block for a
143 // debugger connection, allowing breakpoints to be set before they're
144 // executed.
145 debugger.context = vk::dbg::Context::create();
146 debugger.server = vk::dbg::Server::create(debugger.context, atoi(port));
147 }
148#endif // ENABLE_VK_DEBUGGER
Alexis Hetu767b41b2018-09-26 11:25:46 -0400149}
150
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000151void Device::destroy(const VkAllocationCallbacks *pAllocator)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400152{
Alexis Hetuaf3c1022018-12-12 13:26:15 -0500153 for(uint32_t i = 0; i < queueCount; i++)
154 {
Ben Clayton7e0a0362019-05-20 11:32:35 +0100155 queues[i].~Queue();
Alexis Hetuaf3c1022018-12-12 13:26:15 -0500156 }
157
Alexis Hetu767b41b2018-09-26 11:25:46 -0400158 vk::deallocate(queues, pAllocator);
159}
160
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000161size_t Device::ComputeRequiredAllocationSize(const VkDeviceCreateInfo *pCreateInfo)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400162{
163 uint32_t queueCount = 0;
Nicolas Capens0c736802019-05-27 12:53:31 -0400164 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
Alexis Hetu767b41b2018-09-26 11:25:46 -0400165 {
Nicolas Capens0c736802019-05-27 12:53:31 -0400166 queueCount += pCreateInfo->pQueueCreateInfos[i].queueCount;
Alexis Hetu767b41b2018-09-26 11:25:46 -0400167 }
168
Nicolas Capens0c736802019-05-27 12:53:31 -0400169 return (sizeof(Queue) * queueCount) + (pCreateInfo->enabledExtensionCount * sizeof(ExtensionName));
Alexis Hetu352791e2019-05-17 16:42:34 -0400170}
171
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000172bool Device::hasExtension(const char *extensionName) const
Alexis Hetu352791e2019-05-17 16:42:34 -0400173{
174 for(uint32_t i = 0; i < enabledExtensionCount; i++)
175 {
176 if(strncmp(extensions[i], extensionName, VK_MAX_EXTENSION_NAME_SIZE) == 0)
177 {
178 return true;
179 }
180 }
181 return false;
Alexis Hetu767b41b2018-09-26 11:25:46 -0400182}
183
184VkQueue Device::getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const
185{
186 ASSERT(queueFamilyIndex == 0);
187
188 return queues[queueIndex];
189}
190
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000191VkResult Device::waitForFences(uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout)
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500192{
Ben Clayton6779e5e2019-05-20 11:07:58 +0100193 using time_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400194 const time_point start = now();
195 const uint64_t max_timeout = (LLONG_MAX - start.time_since_epoch().count());
196 bool infiniteTimeout = (timeout > max_timeout);
197 const time_point end_ns = start + std::chrono::nanoseconds(std::min(max_timeout, timeout));
Nicolas Capens85035be2019-06-05 13:54:18 -0400198
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000199 if(waitAll != VK_FALSE) // All fences must be signaled
Alexis Hetue1f51b92019-04-23 15:34:34 -0400200 {
201 for(uint32_t i = 0; i < fenceCount; i++)
202 {
203 if(timeout == 0)
204 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000205 if(Cast(pFences[i])->getStatus() != VK_SUCCESS) // At least one fence is not signaled
Alexis Hetue1f51b92019-04-23 15:34:34 -0400206 {
207 return VK_TIMEOUT;
208 }
209 }
210 else if(infiniteTimeout)
211 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000212 if(Cast(pFences[i])->wait() != VK_SUCCESS) // At least one fence is not signaled
Alexis Hetue1f51b92019-04-23 15:34:34 -0400213 {
214 return VK_TIMEOUT;
215 }
216 }
217 else
218 {
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000219 if(Cast(pFences[i])->wait(end_ns) != VK_SUCCESS) // At least one fence is not signaled
Alexis Hetue1f51b92019-04-23 15:34:34 -0400220 {
221 return VK_TIMEOUT;
222 }
223 }
224 }
225
226 return VK_SUCCESS;
227 }
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000228 else // At least one fence must be signaled
Alexis Hetue1f51b92019-04-23 15:34:34 -0400229 {
Ben Clayton951d48d2019-11-13 21:46:59 +0000230 marl::containers::vector<marl::Event, 8> events;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400231 for(uint32_t i = 0; i < fenceCount; i++)
232 {
Ben Clayton951d48d2019-11-13 21:46:59 +0000233 events.push_back(Cast(pFences[i])->getEvent());
Alexis Hetue1f51b92019-04-23 15:34:34 -0400234 }
235
Ben Clayton951d48d2019-11-13 21:46:59 +0000236 auto any = marl::Event::any(events.begin(), events.end());
237
238 if(timeout == 0)
Alexis Hetue1f51b92019-04-23 15:34:34 -0400239 {
Ben Clayton951d48d2019-11-13 21:46:59 +0000240 return any.isSignalled() ? VK_SUCCESS : VK_TIMEOUT;
Alexis Hetue1f51b92019-04-23 15:34:34 -0400241 }
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500242 else if(infiniteTimeout)
Ben Clayton951d48d2019-11-13 21:46:59 +0000243 {
244 any.wait();
245 return VK_SUCCESS;
246 }
247 else
248 {
249 return any.wait_until(end_ns) ? VK_SUCCESS : VK_TIMEOUT;
250 }
Alexis Hetue1f51b92019-04-23 15:34:34 -0400251 }
Alexis Hetuc4bd9df2018-12-07 11:28:40 -0500252}
253
Alexis Hetue1f51b92019-04-23 15:34:34 -0400254VkResult Device::waitIdle()
Ben Clayton00424c12019-03-17 17:29:30 +0000255{
256 for(uint32_t i = 0; i < queueCount; i++)
257 {
258 queues[i].waitIdle();
259 }
Alexis Hetue1f51b92019-04-23 15:34:34 -0400260
261 return VK_SUCCESS;
Alexis Hetucda0cf92019-01-24 15:48:55 -0500262}
263
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000264void Device::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
265 VkDescriptorSetLayoutSupport *pSupport) const
Alexis Hetu9e4d0402018-10-16 15:44:12 -0400266{
Chris Forbesaee3c362019-11-22 12:09:45 -0800267 // From Vulkan Spec 13.2.1 Descriptor Set Layout, in description of vkGetDescriptorSetLayoutSupport:
268 // "This command does not consider other limits such as maxPerStageDescriptor*, and so a descriptor
269 // set layout that is supported according to this command must still satisfy the pipeline layout limits
270 // such as maxPerStageDescriptor* in order to be used in a pipeline layout."
271
272 // We have no "strange" limitations to enforce beyond the device limits, so we can safely always claim support.
273 pSupport->supported = VK_TRUE;
Alexis Hetu9e4d0402018-10-16 15:44:12 -0400274}
275
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000276void Device::updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
277 uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies)
Alexis Hetu048974f2019-02-15 15:28:37 -0500278{
279 for(uint32_t i = 0; i < descriptorWriteCount; i++)
280 {
Alexis Hetu6448bd62019-06-11 15:58:59 -0400281 DescriptorSetLayout::WriteDescriptorSet(this, pDescriptorWrites[i]);
Alexis Hetu048974f2019-02-15 15:28:37 -0500282 }
283
284 for(uint32_t i = 0; i < descriptorCopyCount; i++)
285 {
286 DescriptorSetLayout::CopyDescriptorSet(pDescriptorCopies[i]);
287 }
288}
289
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000290void Device::getRequirements(VkMemoryDedicatedRequirements *requirements) const
Alexis Hetu131a1ba2019-11-21 16:39:06 -0500291{
292 requirements->prefersDedicatedAllocation = VK_FALSE;
293 requirements->requiresDedicatedAllocation = VK_FALSE;
294}
295
Ben Clayton2ed93ab2019-12-17 20:38:03 +0000296Device::SamplingRoutineCache *Device::getSamplingRoutineCache() const
Alexis Hetu6448bd62019-06-11 15:58:59 -0400297{
Alexis Hetu6448bd62019-06-11 15:58:59 -0400298 return samplingRoutineCache.get();
299}
300
Nicolas Capensd53eeca2020-03-19 13:31:41 -0400301void Device::updateSamplingRoutineSnapshotCache()
Alexis Hetu35755502019-07-22 13:51:49 -0400302{
Nicolas Capensd53eeca2020-03-19 13:31:41 -0400303 samplingRoutineCache->updateSnapshot();
Alexis Hetu35755502019-07-22 13:51:49 -0400304}
305
Nicolas Capens73c4a0c2020-03-17 17:29:11 -0400306uint32_t Device::indexSampler(const SamplerState &samplerState)
307{
308 return samplerIndexer->index(samplerState);
309}
310
311void Device::removeSampler(const SamplerState &samplerState)
312{
313 samplerIndexer->remove(samplerState);
314}
315
Nicolas Capens157ba262019-12-10 17:49:14 -0500316} // namespace vk