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 #include "VkDevice.hpp"
16
17 #include "VkConfig.hpp"
18 #include "VkDescriptorSetLayout.hpp"
19 #include "VkFence.hpp"
20 #include "VkQueue.hpp"
21 #include "VkSemaphore.hpp"
22 #include "VkTimelineSemaphore.hpp"
23 #include "Debug/Context.hpp"
24 #include "Debug/Server.hpp"
25 #include "Device/Blitter.hpp"
26 #include "System/Debug.hpp"
27
28 #include <chrono>
29 #include <climits>
30 #include <new> // Must #include this to use "placement new"
31
32 namespace {
33
34 using time_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>;
35
now()36 time_point now()
37 {
38 return std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now());
39 }
40
getEndTimePoint(uint64_t timeout,bool & infiniteTimeout)41 const time_point getEndTimePoint(uint64_t timeout, bool &infiniteTimeout)
42 {
43 const time_point start = now();
44 const uint64_t max_timeout = (LLONG_MAX - start.time_since_epoch().count());
45 infiniteTimeout = (timeout > max_timeout);
46 return start + std::chrono::nanoseconds(std::min(max_timeout, timeout));
47 }
48
49 } // anonymous namespace
50
51 namespace vk {
52
updateSnapshot()53 void Device::SamplingRoutineCache::updateSnapshot()
54 {
55 marl::lock lock(mutex);
56
57 if(snapshotNeedsUpdate)
58 {
59 snapshot.clear();
60
61 for(auto it : cache)
62 {
63 snapshot[it.key()] = it.data();
64 }
65
66 snapshotNeedsUpdate = false;
67 }
68 }
69
~SamplerIndexer()70 Device::SamplerIndexer::~SamplerIndexer()
71 {
72 ASSERT(map.empty());
73 }
74
index(const SamplerState & samplerState)75 uint32_t Device::SamplerIndexer::index(const SamplerState &samplerState)
76 {
77 marl::lock lock(mutex);
78
79 auto it = map.find(samplerState);
80
81 if(it != map.end())
82 {
83 it->second.count++;
84 return it->second.id;
85 }
86
87 nextID++;
88
89 map.emplace(samplerState, Identifier{ nextID, 1 });
90
91 return nextID;
92 }
93
remove(const SamplerState & samplerState)94 void Device::SamplerIndexer::remove(const SamplerState &samplerState)
95 {
96 marl::lock lock(mutex);
97
98 auto it = map.find(samplerState);
99 ASSERT(it != map.end());
100
101 auto count = --it->second.count;
102 if(count == 0)
103 {
104 map.erase(it);
105 }
106 }
107
Device(const VkDeviceCreateInfo * pCreateInfo,void * mem,PhysicalDevice * physicalDevice,const VkPhysicalDeviceFeatures * enabledFeatures,const std::shared_ptr<marl::Scheduler> & scheduler)108 Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice *physicalDevice, const VkPhysicalDeviceFeatures *enabledFeatures, const std::shared_ptr<marl::Scheduler> &scheduler)
109 : physicalDevice(physicalDevice)
110 , queues(reinterpret_cast<Queue *>(mem))
111 , enabledExtensionCount(pCreateInfo->enabledExtensionCount)
112 , enabledFeatures(enabledFeatures ? *enabledFeatures : VkPhysicalDeviceFeatures{})
113 , // "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."
114 scheduler(scheduler)
115 {
116 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
117 {
118 const VkDeviceQueueCreateInfo &queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
119 queueCount += queueCreateInfo.queueCount;
120 }
121
122 uint32_t queueID = 0;
123 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
124 {
125 const VkDeviceQueueCreateInfo &queueCreateInfo = pCreateInfo->pQueueCreateInfos[i];
126
127 for(uint32_t j = 0; j < queueCreateInfo.queueCount; j++, queueID++)
128 {
129 new(&queues[queueID]) Queue(this, scheduler.get());
130 }
131 }
132
133 extensions = reinterpret_cast<ExtensionName *>(static_cast<uint8_t *>(mem) + (sizeof(Queue) * queueCount));
134 for(uint32_t i = 0; i < enabledExtensionCount; i++)
135 {
136 strncpy(extensions[i], pCreateInfo->ppEnabledExtensionNames[i], VK_MAX_EXTENSION_NAME_SIZE);
137 }
138
139 if(pCreateInfo->enabledLayerCount)
140 {
141 // "The ppEnabledLayerNames and enabledLayerCount members of VkDeviceCreateInfo are deprecated and their values must be ignored by implementations."
142 UNSUPPORTED("enabledLayerCount");
143 }
144
145 // FIXME (b/119409619): use an allocator here so we can control all memory allocations
146 blitter.reset(new sw::Blitter());
147 samplingRoutineCache.reset(new SamplingRoutineCache());
148 samplerIndexer.reset(new SamplerIndexer());
149
150 #ifdef ENABLE_VK_DEBUGGER
151 static auto port = getenv("VK_DEBUGGER_PORT");
152 if(port)
153 {
154 // Construct the debugger context and server - this may block for a
155 // debugger connection, allowing breakpoints to be set before they're
156 // executed.
157 debugger.context = vk::dbg::Context::create();
158 debugger.server = vk::dbg::Server::create(debugger.context, atoi(port));
159 }
160 #endif // ENABLE_VK_DEBUGGER
161
162 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
163 const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(pCreateInfo->pNext);
164 while(extensionCreateInfo)
165 {
166 if(extensionCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT)
167 {
168 auto deviceMemoryReportCreateInfo = reinterpret_cast<const VkDeviceDeviceMemoryReportCreateInfoEXT *>(pCreateInfo->pNext);
169 if(deviceMemoryReportCreateInfo->pfnUserCallback != nullptr)
170 {
171 deviceMemoryReportCallbacks.emplace_back(deviceMemoryReportCreateInfo->pfnUserCallback, deviceMemoryReportCreateInfo->pUserData);
172 }
173 }
174 extensionCreateInfo = extensionCreateInfo->pNext;
175 }
176 #endif // SWIFTSHADER_DEVICE_MEMORY_REPORT
177 }
178
destroy(const VkAllocationCallbacks * pAllocator)179 void Device::destroy(const VkAllocationCallbacks *pAllocator)
180 {
181 for(uint32_t i = 0; i < queueCount; i++)
182 {
183 queues[i].~Queue();
184 }
185
186 vk::deallocate(queues, pAllocator);
187 }
188
ComputeRequiredAllocationSize(const VkDeviceCreateInfo * pCreateInfo)189 size_t Device::ComputeRequiredAllocationSize(const VkDeviceCreateInfo *pCreateInfo)
190 {
191 uint32_t queueCount = 0;
192 for(uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++)
193 {
194 queueCount += pCreateInfo->pQueueCreateInfos[i].queueCount;
195 }
196
197 return (sizeof(Queue) * queueCount) + (pCreateInfo->enabledExtensionCount * sizeof(ExtensionName));
198 }
199
hasExtension(const char * extensionName) const200 bool Device::hasExtension(const char *extensionName) const
201 {
202 for(uint32_t i = 0; i < enabledExtensionCount; i++)
203 {
204 if(strncmp(extensions[i], extensionName, VK_MAX_EXTENSION_NAME_SIZE) == 0)
205 {
206 return true;
207 }
208 }
209 return false;
210 }
211
getQueue(uint32_t queueFamilyIndex,uint32_t queueIndex) const212 VkQueue Device::getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex) const
213 {
214 ASSERT(queueFamilyIndex == 0);
215
216 return queues[queueIndex];
217 }
218
waitForFences(uint32_t fenceCount,const VkFence * pFences,VkBool32 waitAll,uint64_t timeout)219 VkResult Device::waitForFences(uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout)
220 {
221 bool infiniteTimeout = false;
222 const time_point end_ns = getEndTimePoint(timeout, infiniteTimeout);
223
224 if(waitAll != VK_FALSE) // All fences must be signaled
225 {
226 for(uint32_t i = 0; i < fenceCount; i++)
227 {
228 if(timeout == 0)
229 {
230 if(Cast(pFences[i])->getStatus() != VK_SUCCESS) // At least one fence is not signaled
231 {
232 return VK_TIMEOUT;
233 }
234 }
235 else if(infiniteTimeout)
236 {
237 if(Cast(pFences[i])->wait() != VK_SUCCESS) // At least one fence is not signaled
238 {
239 return VK_TIMEOUT;
240 }
241 }
242 else
243 {
244 if(Cast(pFences[i])->wait(end_ns) != VK_SUCCESS) // At least one fence is not signaled
245 {
246 return VK_TIMEOUT;
247 }
248 }
249 }
250
251 return VK_SUCCESS;
252 }
253 else // At least one fence must be signaled
254 {
255 marl::containers::vector<marl::Event, 8> events;
256 for(uint32_t i = 0; i < fenceCount; i++)
257 {
258 events.push_back(Cast(pFences[i])->getCountedEvent()->event());
259 }
260
261 auto any = marl::Event::any(events.begin(), events.end());
262
263 if(timeout == 0)
264 {
265 return any.isSignalled() ? VK_SUCCESS : VK_TIMEOUT;
266 }
267 else if(infiniteTimeout)
268 {
269 any.wait();
270 return VK_SUCCESS;
271 }
272 else
273 {
274 return any.wait_until(end_ns) ? VK_SUCCESS : VK_TIMEOUT;
275 }
276 }
277 }
278
waitForSemaphores(const VkSemaphoreWaitInfo * pWaitInfo,uint64_t timeout)279 VkResult Device::waitForSemaphores(const VkSemaphoreWaitInfo *pWaitInfo, uint64_t timeout)
280 {
281 bool infiniteTimeout = false;
282 const time_point end_ns = getEndTimePoint(timeout, infiniteTimeout);
283
284 if(pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT)
285 {
286 TimelineSemaphore any = TimelineSemaphore();
287
288 for(uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++)
289 {
290 TimelineSemaphore *semaphore = DynamicCast<TimelineSemaphore>(pWaitInfo->pSemaphores[i]);
291 uint64_t waitValue = pWaitInfo->pValues[i];
292
293 if(semaphore->getCounterValue() == waitValue)
294 {
295 return VK_SUCCESS;
296 }
297
298 semaphore->addDependent(any, waitValue);
299 }
300
301 if(infiniteTimeout)
302 {
303 any.wait(1ull);
304 return VK_SUCCESS;
305 }
306 else
307 {
308 if(any.wait(1, end_ns) == VK_SUCCESS)
309 {
310 return VK_SUCCESS;
311 }
312 }
313
314 return VK_TIMEOUT;
315 }
316 else
317 {
318 ASSERT(pWaitInfo->flags == 0);
319 for(uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++)
320 {
321 TimelineSemaphore *semaphore = DynamicCast<TimelineSemaphore>(pWaitInfo->pSemaphores[i]);
322 uint64_t value = pWaitInfo->pValues[i];
323 if(infiniteTimeout)
324 {
325 semaphore->wait(value);
326 }
327 else if(semaphore->wait(pWaitInfo->pValues[i], end_ns) != VK_SUCCESS)
328 {
329 return VK_TIMEOUT;
330 }
331 }
332 return VK_SUCCESS;
333 }
334 }
335
waitIdle()336 VkResult Device::waitIdle()
337 {
338 for(uint32_t i = 0; i < queueCount; i++)
339 {
340 queues[i].waitIdle();
341 }
342
343 return VK_SUCCESS;
344 }
345
getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport) const346 void Device::getDescriptorSetLayoutSupport(const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
347 VkDescriptorSetLayoutSupport *pSupport) const
348 {
349 // From Vulkan Spec 13.2.1 Descriptor Set Layout, in description of vkGetDescriptorSetLayoutSupport:
350 // "This command does not consider other limits such as maxPerStageDescriptor*, and so a descriptor
351 // set layout that is supported according to this command must still satisfy the pipeline layout limits
352 // such as maxPerStageDescriptor* in order to be used in a pipeline layout."
353
354 // We have no "strange" limitations to enforce beyond the device limits, so we can safely always claim support.
355 pSupport->supported = VK_TRUE;
356 }
357
updateDescriptorSets(uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)358 void Device::updateDescriptorSets(uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
359 uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies)
360 {
361 for(uint32_t i = 0; i < descriptorWriteCount; i++)
362 {
363 DescriptorSetLayout::WriteDescriptorSet(this, pDescriptorWrites[i]);
364 }
365
366 for(uint32_t i = 0; i < descriptorCopyCount; i++)
367 {
368 DescriptorSetLayout::CopyDescriptorSet(pDescriptorCopies[i]);
369 }
370 }
371
getRequirements(VkMemoryDedicatedRequirements * requirements) const372 void Device::getRequirements(VkMemoryDedicatedRequirements *requirements) const
373 {
374 requirements->prefersDedicatedAllocation = VK_FALSE;
375 requirements->requiresDedicatedAllocation = VK_FALSE;
376 }
377
getSamplingRoutineCache() const378 Device::SamplingRoutineCache *Device::getSamplingRoutineCache() const
379 {
380 return samplingRoutineCache.get();
381 }
382
updateSamplingRoutineSnapshotCache()383 void Device::updateSamplingRoutineSnapshotCache()
384 {
385 samplingRoutineCache->updateSnapshot();
386 }
387
indexSampler(const SamplerState & samplerState)388 uint32_t Device::indexSampler(const SamplerState &samplerState)
389 {
390 return samplerIndexer->index(samplerState);
391 }
392
removeSampler(const SamplerState & samplerState)393 void Device::removeSampler(const SamplerState &samplerState)
394 {
395 samplerIndexer->remove(samplerState);
396 }
397
setDebugUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT * pNameInfo)398 VkResult Device::setDebugUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT *pNameInfo)
399 {
400 // Optionally maps user-friendly name to an object
401 return VK_SUCCESS;
402 }
403
setDebugUtilsObjectTag(const VkDebugUtilsObjectTagInfoEXT * pTagInfo)404 VkResult Device::setDebugUtilsObjectTag(const VkDebugUtilsObjectTagInfoEXT *pTagInfo)
405 {
406 // Optionally attach arbitrary data to an object
407 return VK_SUCCESS;
408 }
409
registerImageView(ImageView * imageView)410 void Device::registerImageView(ImageView *imageView)
411 {
412 if(imageView != nullptr)
413 {
414 marl::lock lock(imageViewSetMutex);
415 imageViewSet.insert(imageView);
416 }
417 }
418
unregisterImageView(ImageView * imageView)419 void Device::unregisterImageView(ImageView *imageView)
420 {
421 if(imageView != nullptr)
422 {
423 marl::lock lock(imageViewSetMutex);
424 auto it = imageViewSet.find(imageView);
425 if(it != imageViewSet.end())
426 {
427 imageViewSet.erase(it);
428 }
429 }
430 }
431
prepareForSampling(ImageView * imageView)432 void Device::prepareForSampling(ImageView *imageView)
433 {
434 if(imageView != nullptr)
435 {
436 marl::lock lock(imageViewSetMutex);
437
438 auto it = imageViewSet.find(imageView);
439 if(it != imageViewSet.end())
440 {
441 imageView->prepareForSampling();
442 }
443 }
444 }
445
contentsChanged(ImageView * imageView)446 void Device::contentsChanged(ImageView *imageView)
447 {
448 if(imageView != nullptr)
449 {
450 marl::lock lock(imageViewSetMutex);
451
452 auto it = imageViewSet.find(imageView);
453 if(it != imageViewSet.end())
454 {
455 imageView->contentsChanged();
456 }
457 }
458 }
459
460 #ifdef SWIFTSHADER_DEVICE_MEMORY_REPORT
emitDeviceMemoryReport(VkDeviceMemoryReportEventTypeEXT type,uint64_t memoryObjectId,VkDeviceSize size,VkObjectType objectType,uint64_t objectHandle,uint32_t heapIndex)461 void Device::emitDeviceMemoryReport(VkDeviceMemoryReportEventTypeEXT type, uint64_t memoryObjectId, VkDeviceSize size, VkObjectType objectType, uint64_t objectHandle, uint32_t heapIndex)
462 {
463 if(deviceMemoryReportCallbacks.empty()) return;
464
465 const VkDeviceMemoryReportCallbackDataEXT callbackData = {
466 VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT, // sType
467 nullptr, // pNext
468 0, // flags
469 type, // type
470 memoryObjectId, // memoryObjectId
471 size, // size
472 objectType, // objectType
473 objectHandle, // objectHandle
474 heapIndex, // heapIndex
475 };
476 for(const auto &callback : deviceMemoryReportCallbacks)
477 {
478 callback.first(&callbackData, callback.second);
479 }
480 }
481 #endif // SWIFTSHADER_DEVICE_MEMORY_REPORT
482
483 } // namespace vk
484