Flutter Engine
The Flutter Engine
VulkanSharedContext.cpp
Go to the documentation of this file.
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
9
20
21#if defined(SK_USE_VMA)
23#endif
24
25namespace skgpu::graphite {
26
28 const ContextOptions& options) {
29 if (context.fInstance == VK_NULL_HANDLE ||
31 context.fDevice == VK_NULL_HANDLE ||
32 context.fQueue == VK_NULL_HANDLE) {
33 SKGPU_LOG_E("Failed to create VulkanSharedContext because either fInstance,"
34 "fPhysicalDevice, fDevice, or fQueue in the VulkanBackendContext is"
35 "VK_NULL_HANDLE.");
36 return nullptr;
37 }
38 if (!context.fGetProc) {
39 SKGPU_LOG_E("Failed to create VulkanSharedContext because there is no valid VulkanGetProc"
40 "on the VulkanBackendContext");
41 return nullptr;
42 }
43
44 PFN_vkEnumerateInstanceVersion localEnumerateInstanceVersion =
45 reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
46 context.fGetProc("vkEnumerateInstanceVersion", VK_NULL_HANDLE, VK_NULL_HANDLE));
47 uint32_t instanceVersion = 0;
48 if (!localEnumerateInstanceVersion) {
49 instanceVersion = VK_MAKE_VERSION(1, 0, 0);
50 } else {
51 VkResult err = localEnumerateInstanceVersion(&instanceVersion);
52 if (err) {
53 SKGPU_LOG_E("Failed to enumerate instance version. Err: %d\n", err);
54 return nullptr;
55 }
56 }
57
58 PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
59 reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
60 context.fGetProc("vkGetPhysicalDeviceProperties",
61 context.fInstance,
63
64 if (!localGetPhysicalDeviceProperties) {
65 SKGPU_LOG_E("Failed to get function pointer to vkGetPhysicalDeviceProperties.");
66 return nullptr;
67 }
68 VkPhysicalDeviceProperties physDeviceProperties;
69 localGetPhysicalDeviceProperties(context.fPhysicalDevice, &physDeviceProperties);
70 uint32_t physDevVersion = physDeviceProperties.apiVersion;
71
72 uint32_t apiVersion = context.fMaxAPIVersion ? context.fMaxAPIVersion : instanceVersion;
73
74 instanceVersion = std::min(instanceVersion, apiVersion);
75 physDevVersion = std::min(physDevVersion, apiVersion);
76
79 context.fInstance,
80 context.fDevice,
81 instanceVersion,
82 physDevVersion,
83 context.fVkExtensions));
84 if (!interface->validate(instanceVersion, physDevVersion, context.fVkExtensions)) {
85 SKGPU_LOG_E("Failed to validate VulkanInterface.");
86 return nullptr;
87 }
88
90 const VkPhysicalDeviceFeatures2* featuresPtr;
91 // If fDeviceFeatures2 is not null, then we ignore fDeviceFeatures. If both are null, we assume
92 // no features are enabled.
93 if (!context.fDeviceFeatures2 && context.fDeviceFeatures) {
94 features.pNext = nullptr;
95 features.features = *context.fDeviceFeatures;
96 featuresPtr = &features;
97 } else {
98 featuresPtr = context.fDeviceFeatures2;
99 }
100
101 std::unique_ptr<const VulkanCaps> caps(new VulkanCaps(options,
102 interface.get(),
103 context.fPhysicalDevice,
104 physDevVersion,
105 featuresPtr,
106 context.fVkExtensions,
107 context.fProtectedContext));
108
110#if defined(SK_USE_VMA)
111 if (!memoryAllocator) {
112 // We were not given a memory allocator at creation
113 skgpu::ThreadSafe threadSafe = options.fClientWillExternallySynchronizeAllThreads
117 context.fPhysicalDevice,
118 context.fDevice,
119 physDevVersion,
120 context.fVkExtensions,
121 interface.get(),
122 threadSafe);
123 }
124#endif
125 if (!memoryAllocator) {
126 SKGPU_LOG_E("No supplied vulkan memory allocator and unable to create one internally.");
127 return nullptr;
128 }
129
130 return sk_sp<SharedContext>(new VulkanSharedContext(context,
131 std::move(interface),
132 std::move(memoryAllocator),
133 std::move(caps)));
134}
135
136VulkanSharedContext::VulkanSharedContext(const VulkanBackendContext& backendContext,
139 std::unique_ptr<const VulkanCaps> caps)
140 : skgpu::graphite::SharedContext(std::move(caps), BackendApi::kVulkan)
141 , fInterface(std::move(interface))
142 , fMemoryAllocator(std::move(memoryAllocator))
143 , fDevice(std::move(backendContext.fDevice))
144 , fQueueIndex(backendContext.fGraphicsQueueIndex)
145 , fDeviceLostContext(backendContext.fDeviceLostContext)
146 , fDeviceLostProc(backendContext.fDeviceLostProc) {}
147
149 // need to clear out resources before the allocator is removed
150 this->globalCache()->deleteResources();
151}
152
153std::unique_ptr<ResourceProvider> VulkanSharedContext::makeResourceProvider(
154 SingleOwner* singleOwner,
155 uint32_t recorderID,
156 size_t resourceBudget) {
157 // Establish a uniform buffer that can be updated across multiple render passes and cmd buffers
158 size_t alignedIntrinsicConstantSize =
160 this->vulkanCaps().requiredUniformBufferAlignment());
161 sk_sp<Buffer> intrinsicConstantBuffer = VulkanBuffer::Make(
162 this, alignedIntrinsicConstantSize, BufferType::kUniform, AccessPattern::kGpuOnly);
163 if (!intrinsicConstantBuffer) {
164 SKGPU_LOG_E("Failed to create intrinsic constant uniform buffer");
165 return nullptr;
166 }
167 SkASSERT(static_cast<VulkanBuffer*>(intrinsicConstantBuffer.get())->bufferUsageFlags()
169 intrinsicConstantBuffer->setLabel("IntrinsicConstantBuffer");
170
171 // Establish a vertex buffer that can be updated across multiple render passes and cmd buffers
172 // for loading MSAA from resolve
173 sk_sp<Buffer> loadMSAAVertexBuffer =
178 if (!loadMSAAVertexBuffer) {
179 SKGPU_LOG_E("Failed to create vertex buffer for loading MSAA from resolve");
180 return nullptr;
181 }
182 SkASSERT(static_cast<VulkanBuffer*>(loadMSAAVertexBuffer.get())->bufferUsageFlags()
184 loadMSAAVertexBuffer->setLabel("LoadMSAAVertexBuffer");
185
186 return std::unique_ptr<ResourceProvider>(
187 new VulkanResourceProvider(this,
188 singleOwner,
189 recorderID,
190 resourceBudget,
191 std::move(intrinsicConstantBuffer),
192 std::move(loadMSAAVertexBuffer)));
193}
194
196 switch (result) {
197 case VK_SUCCESS:
198 return true;
200 {
201 SkAutoMutexExclusive lock(fDeviceIsLostMutex);
202 if (fDeviceIsLost) {
203 return false;
204 }
205 fDeviceIsLost = true;
206 // Fall through to InvokeDeviceLostCallback (on first VK_ERROR_DEVICE_LOST) only afer
207 // releasing fDeviceIsLostMutex, otherwise clients might cause deadlock by checking
208 // isDeviceLost() from the callback.
209 }
211 device(),
212 fDeviceLostContext,
213 fDeviceLostProc,
214 vulkanCaps().supportsDeviceFaultInfo());
215 return false;
218 // TODO: determine how we'll track this in a thread-safe manner
219 //this->setOOMed();
220 return false;
221 default:
222 return false;
223 }
224}
225} // namespace skgpu::graphite
const char * options
#define SKGPU_LOG_E(fmt,...)
Definition: Log.h:38
#define SkASSERT(cond)
Definition: SkAssert.h:116
T * get() const
Definition: SkRefCnt.h:303
static sk_sp< VulkanMemoryAllocator > Make(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, uint32_t physicalDeviceVersion, const VulkanExtensions *extensions, const VulkanInterface *interface, ThreadSafe)
const Caps * caps() const
Definition: SharedContext.h:39
VkBufferUsageFlags bufferUsageFlags() const
Definition: VulkanBuffer.h:24
static sk_sp< Buffer > Make(const VulkanSharedContext *, size_t, BufferType, AccessPattern)
skgpu::VulkanMemoryAllocator * memoryAllocator() const
bool checkVkResult(VkResult result) const
const skgpu::VulkanInterface * interface() const
const VulkanCaps & vulkanCaps() const
std::unique_ptr< ResourceProvider > makeResourceProvider(SingleOwner *, uint32_t recorderID, size_t resourceBudget) override
static sk_sp< SharedContext > Make(const VulkanBackendContext &, const ContextOptions &)
@ kVulkan
Definition: embedder.h:86
GAsyncResult * result
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
Definition: GpuTools.h:21
BackendApi
Definition: GpuTypes.h:22
void InvokeDeviceLostCallback(const skgpu::VulkanInterface *vulkanInterface, VkDevice vkDevice, skgpu::VulkanDeviceLostContext deviceLostContext, skgpu::VulkanDeviceLostProc deviceLostProc, bool supportsDeviceFaultInfoExtension)
Definition: ref_ptr.h:256
VkPhysicalDeviceFeatures features
Definition: vulkan_core.h:5271
const VkPhysicalDeviceFeatures2 * fDeviceFeatures2
sk_sp< VulkanMemoryAllocator > fMemoryAllocator
const VkPhysicalDeviceFeatures * fDeviceFeatures
const skgpu::VulkanExtensions * fVkExtensions
bool validate(uint32_t instanceVersion, uint32_t physicalDeviceVersion, const VulkanExtensions *) const
void(VKAPI_PTR * PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
Definition: vulkan_core.h:3986
#define VK_MAKE_VERSION(major, minor, patch)
Definition: vulkan_core.h:78
@ VK_BUFFER_USAGE_TRANSFER_DST_BIT
Definition: vulkan_core.h:2546
@ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
Definition: vulkan_core.h:2552
VkResult
Definition: vulkan_core.h:140
@ VK_ERROR_DEVICE_LOST
Definition: vulkan_core.h:150
@ VK_SUCCESS
Definition: vulkan_core.h:141
@ VK_ERROR_OUT_OF_HOST_MEMORY
Definition: vulkan_core.h:147
@ VK_ERROR_OUT_OF_DEVICE_MEMORY
Definition: vulkan_core.h:148
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46
VkResult(VKAPI_PTR * PFN_vkEnumerateInstanceVersion)(uint32_t *pApiVersion)
Definition: vulkan_core.h:5608