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