• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/gpu/graphite/vk/VulkanSharedContext.h"
9 
10 #include "include/gpu/GpuTypes.h"
11 #include "include/gpu/graphite/ContextOptions.h"
12 #include "include/gpu/vk/VulkanBackendContext.h"
13 #include "include/gpu/vk/VulkanExtensions.h"
14 #include "include/private/base/SkMutex.h"
15 #include "src/gpu/GpuTypesPriv.h"
16 #include "src/gpu/graphite/Log.h"
17 #include "src/gpu/graphite/ResourceTypes.h"
18 #include "src/gpu/graphite/vk/VulkanBuffer.h"
19 #include "src/gpu/graphite/vk/VulkanCaps.h"
20 #include "src/gpu/graphite/vk/VulkanResourceProvider.h"
21 #include "src/gpu/vk/VulkanInterface.h"
22 #include "src/gpu/vk/VulkanUtilsPriv.h"
23 
24 #if defined(SK_USE_VMA)
25 #include "src/gpu/vk/vulkanmemoryallocator/VulkanMemoryAllocatorPriv.h"
26 #endif
27 
28 namespace skgpu::graphite {
29 
Make(const VulkanBackendContext & context,const ContextOptions & options)30 sk_sp<SharedContext> VulkanSharedContext::Make(const VulkanBackendContext& context,
31                                                const ContextOptions& options) {
32     if (context.fInstance == VK_NULL_HANDLE ||
33         context.fPhysicalDevice == VK_NULL_HANDLE ||
34         context.fDevice == VK_NULL_HANDLE ||
35         context.fQueue == VK_NULL_HANDLE) {
36         SKGPU_LOG_E("Failed to create VulkanSharedContext because either fInstance,"
37                     "fPhysicalDevice, fDevice, or fQueue in the VulkanBackendContext is"
38                     "VK_NULL_HANDLE.");
39         return nullptr;
40     }
41     if (!context.fGetProc) {
42         SKGPU_LOG_E("Failed to create VulkanSharedContext because there is no valid VulkanGetProc"
43                     "on the VulkanBackendContext");
44         return nullptr;
45     }
46     // If no extensions are provided, make sure we don't have a null dereference downstream.
47     skgpu::VulkanExtensions noExtensions;
48     const skgpu::VulkanExtensions* extensions = &noExtensions;
49     if (context.fVkExtensions) {
50         extensions = context.fVkExtensions;
51     }
52 
53     uint32_t physDevVersion = 0;
54     sk_sp<const skgpu::VulkanInterface> interface =
55             skgpu::MakeInterface(context, extensions, &physDevVersion, nullptr);
56     if (!interface) {
57         SKGPU_LOG_E("Failed to create VulkanInterface.");
58         return nullptr;
59     }
60 
61     VkPhysicalDeviceFeatures2 features;
62     const VkPhysicalDeviceFeatures2* featuresPtr;
63     // If fDeviceFeatures2 is not null, then we ignore fDeviceFeatures. If both are null, we assume
64     // no features are enabled.
65     if (!context.fDeviceFeatures2 && context.fDeviceFeatures) {
66         features.pNext = nullptr;
67         features.features = *context.fDeviceFeatures;
68         featuresPtr = &features;
69     } else {
70         featuresPtr = context.fDeviceFeatures2;
71     }
72 
73     std::unique_ptr<const VulkanCaps> caps(new VulkanCaps(options,
74                                                           interface.get(),
75                                                           context.fPhysicalDevice,
76                                                           physDevVersion,
77                                                           featuresPtr,
78                                                           extensions,
79                                                           context.fProtectedContext));
80 
81     sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator = context.fMemoryAllocator;
82 #if defined(SK_USE_VMA)
83     if (!memoryAllocator) {
84         // We were not given a memory allocator at creation
85         skgpu::ThreadSafe threadSafe = options.fClientWillExternallySynchronizeAllThreads
86                                                ? skgpu::ThreadSafe::kNo
87                                                : skgpu::ThreadSafe::kYes;
88         memoryAllocator = skgpu::VulkanMemoryAllocators::Make(context,
89                                                               threadSafe,
90                                                               options.fVulkanVMALargeHeapBlockSize);
91     }
92 #endif
93     if (!memoryAllocator) {
94         SKGPU_LOG_E("No supplied vulkan memory allocator and unable to create one internally.");
95         return nullptr;
96     }
97 
98     return sk_sp<SharedContext>(new VulkanSharedContext(context,
99                                                         std::move(interface),
100                                                         std::move(memoryAllocator),
101                                                         std::move(caps),
102                                                         options.fUserDefinedKnownRuntimeEffects));
103 }
104 
VulkanSharedContext(const VulkanBackendContext & backendContext,sk_sp<const skgpu::VulkanInterface> interface,sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator,std::unique_ptr<const VulkanCaps> caps,SkSpan<sk_sp<SkRuntimeEffect>> userDefinedKnownRuntimeEffects)105 VulkanSharedContext::VulkanSharedContext(
106                 const VulkanBackendContext& backendContext,
107                 sk_sp<const skgpu::VulkanInterface> interface,
108                 sk_sp<skgpu::VulkanMemoryAllocator> memoryAllocator,
109                 std::unique_ptr<const VulkanCaps> caps,
110                 SkSpan<sk_sp<SkRuntimeEffect>> userDefinedKnownRuntimeEffects)
111         : SharedContext(std::move(caps), BackendApi::kVulkan, userDefinedKnownRuntimeEffects)
112         , fInterface(std::move(interface))
113         , fMemoryAllocator(std::move(memoryAllocator))
114         , fPhysDevice(backendContext.fPhysicalDevice)
115         , fDevice(backendContext.fDevice)
116         , fQueueIndex(backendContext.fGraphicsQueueIndex)
117         , fDeviceLostContext(backendContext.fDeviceLostContext)
118         , fDeviceLostProc(backendContext.fDeviceLostProc) {}
119 
~VulkanSharedContext()120 VulkanSharedContext::~VulkanSharedContext() {
121     // need to clear out resources before the allocator is removed
122     this->globalCache()->deleteResources();
123 }
124 
makeResourceProvider(SingleOwner * singleOwner,uint32_t recorderID,size_t resourceBudget)125 std::unique_ptr<ResourceProvider> VulkanSharedContext::makeResourceProvider(
126         SingleOwner* singleOwner,
127         uint32_t recorderID,
128         size_t resourceBudget) {
129     return std::unique_ptr<ResourceProvider>(
130             new VulkanResourceProvider(this,
131                                        singleOwner,
132                                        recorderID,
133                                        resourceBudget));
134 }
135 
checkVkResult(VkResult result) const136 bool VulkanSharedContext::checkVkResult(VkResult result) const {
137     switch (result) {
138     case VK_SUCCESS:
139         return true;
140     case VK_ERROR_DEVICE_LOST:
141         {
142             SkAutoMutexExclusive lock(fDeviceIsLostMutex);
143             if (fDeviceIsLost) {
144                 return false;
145             }
146             fDeviceIsLost = true;
147             // Fall through to InvokeDeviceLostCallback (on first VK_ERROR_DEVICE_LOST) only afer
148             // releasing fDeviceIsLostMutex, otherwise clients might cause deadlock by checking
149             // isDeviceLost() from the callback.
150         }
151         skgpu::InvokeDeviceLostCallback(interface(),
152                                         device(),
153                                         fDeviceLostContext,
154                                         fDeviceLostProc,
155                                         vulkanCaps().supportsDeviceFaultInfo());
156         return false;
157     case VK_ERROR_OUT_OF_DEVICE_MEMORY:
158     case VK_ERROR_OUT_OF_HOST_MEMORY:
159         // TODO: determine how we'll track this in a thread-safe manner
160         //this->setOOMed();
161         return false;
162     default:
163         return false;
164     }
165 }
166 } // namespace skgpu::graphite
167