xref: /aosp_15_r20/external/skia/src/gpu/vk/VulkanUtilsPriv.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2023 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/vk/VulkanUtilsPriv.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanBackendContext.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanInterface.h"
13*c8dee2aaSAndroid Build Coastguard Worker 
14*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
15*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu {
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker /**
20*c8dee2aaSAndroid Build Coastguard Worker  * Define a macro that both ganesh and graphite can use to make simple calls into Vulkan so we can
21*c8dee2aaSAndroid Build Coastguard Worker  * share more code between them.
22*c8dee2aaSAndroid Build Coastguard Worker */
23*c8dee2aaSAndroid Build Coastguard Worker #define SHARED_GR_VULKAN_CALL(IFACE, X) (IFACE)->fFunctions.f##X
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker /**
26*c8dee2aaSAndroid Build Coastguard Worker  * Returns a populated VkSamplerYcbcrConversionCreateInfo object based on VulkanYcbcrConversionInfo
27*c8dee2aaSAndroid Build Coastguard Worker */
SetupSamplerYcbcrConversionInfo(VkSamplerYcbcrConversionCreateInfo * outInfo,const VulkanYcbcrConversionInfo & conversionInfo)28*c8dee2aaSAndroid Build Coastguard Worker void SetupSamplerYcbcrConversionInfo(VkSamplerYcbcrConversionCreateInfo* outInfo,
29*c8dee2aaSAndroid Build Coastguard Worker                                      const VulkanYcbcrConversionInfo& conversionInfo) {
30*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
31*c8dee2aaSAndroid Build Coastguard Worker     const VkFormatFeatureFlags& featureFlags = conversionInfo.fFormatFeatures;
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker     // Format feature flags are only representative of an external format's capabilities, so skip
34*c8dee2aaSAndroid Build Coastguard Worker     // these checks in the case of using a known format.
35*c8dee2aaSAndroid Build Coastguard Worker     if (conversionInfo.fFormat == VK_FORMAT_UNDEFINED) {
36*c8dee2aaSAndroid Build Coastguard Worker         if (conversionInfo.fXChromaOffset == VK_CHROMA_LOCATION_MIDPOINT ||
37*c8dee2aaSAndroid Build Coastguard Worker             conversionInfo.fYChromaOffset == VK_CHROMA_LOCATION_MIDPOINT) {
38*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(featureFlags & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT);
39*c8dee2aaSAndroid Build Coastguard Worker         }
40*c8dee2aaSAndroid Build Coastguard Worker         if (conversionInfo.fXChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN ||
41*c8dee2aaSAndroid Build Coastguard Worker             conversionInfo.fYChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN) {
42*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(featureFlags & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT);
43*c8dee2aaSAndroid Build Coastguard Worker         }
44*c8dee2aaSAndroid Build Coastguard Worker         if (conversionInfo.fChromaFilter == VK_FILTER_LINEAR) {
45*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT);
46*c8dee2aaSAndroid Build Coastguard Worker         }
47*c8dee2aaSAndroid Build Coastguard Worker         if (conversionInfo.fForceExplicitReconstruction) {
48*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(featureFlags &
49*c8dee2aaSAndroid Build Coastguard Worker                     VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT);
50*c8dee2aaSAndroid Build Coastguard Worker         }
51*c8dee2aaSAndroid Build Coastguard Worker     }
52*c8dee2aaSAndroid Build Coastguard Worker #endif
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker     VkFilter chromaFilter = conversionInfo.fChromaFilter;
55*c8dee2aaSAndroid Build Coastguard Worker     if (!(conversionInfo.fFormatFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
56*c8dee2aaSAndroid Build Coastguard Worker         if (!(conversionInfo.fFormatFeatures &
57*c8dee2aaSAndroid Build Coastguard Worker               VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT)) {
58*c8dee2aaSAndroid Build Coastguard Worker             // Because we don't have have separate reconstruction filter, the min, mag and
59*c8dee2aaSAndroid Build Coastguard Worker             // chroma filter must all match. However, we also don't support linear sampling so
60*c8dee2aaSAndroid Build Coastguard Worker             // the min/mag filter have to be nearest. Therefore, we force the chrome filter to
61*c8dee2aaSAndroid Build Coastguard Worker             // be nearest regardless of support for the feature
62*c8dee2aaSAndroid Build Coastguard Worker             // VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT.
63*c8dee2aaSAndroid Build Coastguard Worker             chromaFilter = VK_FILTER_NEAREST;
64*c8dee2aaSAndroid Build Coastguard Worker         }
65*c8dee2aaSAndroid Build Coastguard Worker     }
66*c8dee2aaSAndroid Build Coastguard Worker 
67*c8dee2aaSAndroid Build Coastguard Worker     outInfo->sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
68*c8dee2aaSAndroid Build Coastguard Worker     outInfo->pNext = nullptr;
69*c8dee2aaSAndroid Build Coastguard Worker     outInfo->format = conversionInfo.fFormat;
70*c8dee2aaSAndroid Build Coastguard Worker     outInfo->ycbcrModel = conversionInfo.fYcbcrModel;
71*c8dee2aaSAndroid Build Coastguard Worker     outInfo->ycbcrRange = conversionInfo.fYcbcrRange;
72*c8dee2aaSAndroid Build Coastguard Worker     outInfo->components = conversionInfo.fComponents;
73*c8dee2aaSAndroid Build Coastguard Worker     outInfo->xChromaOffset = conversionInfo.fXChromaOffset;
74*c8dee2aaSAndroid Build Coastguard Worker     outInfo->yChromaOffset = conversionInfo.fYChromaOffset;
75*c8dee2aaSAndroid Build Coastguard Worker     outInfo->chromaFilter = chromaFilter;
76*c8dee2aaSAndroid Build Coastguard Worker     outInfo->forceExplicitReconstruction = conversionInfo.fForceExplicitReconstruction;
77*c8dee2aaSAndroid Build Coastguard Worker }
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_ANDROID
80*c8dee2aaSAndroid Build Coastguard Worker 
81*c8dee2aaSAndroid Build Coastguard Worker /**
82*c8dee2aaSAndroid Build Coastguard Worker  * Shared Vulkan AHardwareBuffer utility functions between graphite and ganesh
83*c8dee2aaSAndroid Build Coastguard Worker */
GetYcbcrConversionInfoFromFormatProps(VulkanYcbcrConversionInfo * outConversionInfo,const VkAndroidHardwareBufferFormatPropertiesANDROID & formatProps)84*c8dee2aaSAndroid Build Coastguard Worker void GetYcbcrConversionInfoFromFormatProps(
85*c8dee2aaSAndroid Build Coastguard Worker         VulkanYcbcrConversionInfo* outConversionInfo,
86*c8dee2aaSAndroid Build Coastguard Worker         const VkAndroidHardwareBufferFormatPropertiesANDROID& formatProps) {
87*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fYcbcrModel = formatProps.suggestedYcbcrModel;
88*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fYcbcrRange = formatProps.suggestedYcbcrRange;
89*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fComponents = formatProps.samplerYcbcrConversionComponents;
90*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fXChromaOffset = formatProps.suggestedXChromaOffset;
91*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fYChromaOffset = formatProps.suggestedYChromaOffset;
92*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fForceExplicitReconstruction = VK_FALSE;
93*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fExternalFormat = formatProps.externalFormat;
94*c8dee2aaSAndroid Build Coastguard Worker     outConversionInfo->fFormatFeatures = formatProps.formatFeatures;
95*c8dee2aaSAndroid Build Coastguard Worker     if (VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT &
96*c8dee2aaSAndroid Build Coastguard Worker         formatProps.formatFeatures) {
97*c8dee2aaSAndroid Build Coastguard Worker         outConversionInfo->fChromaFilter = VK_FILTER_LINEAR;
98*c8dee2aaSAndroid Build Coastguard Worker     } else {
99*c8dee2aaSAndroid Build Coastguard Worker         outConversionInfo->fChromaFilter = VK_FILTER_NEAREST;
100*c8dee2aaSAndroid Build Coastguard Worker     }
101*c8dee2aaSAndroid Build Coastguard Worker }
102*c8dee2aaSAndroid Build Coastguard Worker 
GetAHardwareBufferProperties(VkAndroidHardwareBufferFormatPropertiesANDROID * outHwbFormatProps,VkAndroidHardwareBufferPropertiesANDROID * outHwbProps,const skgpu::VulkanInterface * interface,const AHardwareBuffer * hwBuffer,VkDevice device)103*c8dee2aaSAndroid Build Coastguard Worker bool GetAHardwareBufferProperties(
104*c8dee2aaSAndroid Build Coastguard Worker         VkAndroidHardwareBufferFormatPropertiesANDROID* outHwbFormatProps,
105*c8dee2aaSAndroid Build Coastguard Worker         VkAndroidHardwareBufferPropertiesANDROID* outHwbProps,
106*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::VulkanInterface* interface,
107*c8dee2aaSAndroid Build Coastguard Worker         const AHardwareBuffer* hwBuffer,
108*c8dee2aaSAndroid Build Coastguard Worker         VkDevice device) {
109*c8dee2aaSAndroid Build Coastguard Worker     outHwbFormatProps->sType =
110*c8dee2aaSAndroid Build Coastguard Worker             VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
111*c8dee2aaSAndroid Build Coastguard Worker     outHwbFormatProps->pNext = nullptr;
112*c8dee2aaSAndroid Build Coastguard Worker 
113*c8dee2aaSAndroid Build Coastguard Worker     outHwbProps->sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
114*c8dee2aaSAndroid Build Coastguard Worker     outHwbProps->pNext = outHwbFormatProps;
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker     VkResult result =
117*c8dee2aaSAndroid Build Coastguard Worker             SHARED_GR_VULKAN_CALL(interface,
118*c8dee2aaSAndroid Build Coastguard Worker                                   GetAndroidHardwareBufferProperties(device,
119*c8dee2aaSAndroid Build Coastguard Worker                                                                      hwBuffer,
120*c8dee2aaSAndroid Build Coastguard Worker                                                                      outHwbProps));
121*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
122*c8dee2aaSAndroid Build Coastguard Worker         // The spec suggests VK_ERROR_OUT_OF_HOST_MEMORY and VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR
123*c8dee2aaSAndroid Build Coastguard Worker         // are the only failure codes, but some platforms may report others, such as
124*c8dee2aaSAndroid Build Coastguard Worker         // VK_ERROR_FORMAT_NOT_SUPPORTED (-11).
125*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Failed to get AndroidHardwareBufferProperties (result:%d)", result);
126*c8dee2aaSAndroid Build Coastguard Worker #if __ANDROID_API__ >= 26
127*c8dee2aaSAndroid Build Coastguard Worker         AHardwareBuffer_Desc hwbDesc;
128*c8dee2aaSAndroid Build Coastguard Worker         AHardwareBuffer_describe(hwBuffer, &hwbDesc);
129*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("^ %" PRIu32 "x%" PRIu32 " AHB -- format:%" PRIu32 ", usage:%" PRIu64
130*c8dee2aaSAndroid Build Coastguard Worker                  ", layers:%" PRIu32,
131*c8dee2aaSAndroid Build Coastguard Worker                  hwbDesc.width,
132*c8dee2aaSAndroid Build Coastguard Worker                  hwbDesc.height,
133*c8dee2aaSAndroid Build Coastguard Worker                  hwbDesc.format,
134*c8dee2aaSAndroid Build Coastguard Worker                  hwbDesc.usage,
135*c8dee2aaSAndroid Build Coastguard Worker                  hwbDesc.layers);
136*c8dee2aaSAndroid Build Coastguard Worker #endif
137*c8dee2aaSAndroid Build Coastguard Worker         return false;
138*c8dee2aaSAndroid Build Coastguard Worker     }
139*c8dee2aaSAndroid Build Coastguard Worker     return true;
140*c8dee2aaSAndroid Build Coastguard Worker }
141*c8dee2aaSAndroid Build Coastguard Worker 
AllocateAndBindImageMemory(skgpu::VulkanAlloc * outVulkanAlloc,VkImage image,const VkPhysicalDeviceMemoryProperties2 & phyDevMemProps,const VkAndroidHardwareBufferPropertiesANDROID & hwbProps,AHardwareBuffer * hardwareBuffer,const skgpu::VulkanInterface * interface,VkDevice device)142*c8dee2aaSAndroid Build Coastguard Worker bool AllocateAndBindImageMemory(skgpu::VulkanAlloc* outVulkanAlloc,
143*c8dee2aaSAndroid Build Coastguard Worker                                 VkImage image,
144*c8dee2aaSAndroid Build Coastguard Worker                                 const VkPhysicalDeviceMemoryProperties2& phyDevMemProps,
145*c8dee2aaSAndroid Build Coastguard Worker                                 const VkAndroidHardwareBufferPropertiesANDROID& hwbProps,
146*c8dee2aaSAndroid Build Coastguard Worker                                 AHardwareBuffer* hardwareBuffer,
147*c8dee2aaSAndroid Build Coastguard Worker                                 const skgpu::VulkanInterface* interface,
148*c8dee2aaSAndroid Build Coastguard Worker                                 VkDevice device) {
149*c8dee2aaSAndroid Build Coastguard Worker     VkResult result;
150*c8dee2aaSAndroid Build Coastguard Worker     uint32_t typeIndex = 0;
151*c8dee2aaSAndroid Build Coastguard Worker     bool foundHeap = false;
152*c8dee2aaSAndroid Build Coastguard Worker     uint32_t memTypeCnt = phyDevMemProps.memoryProperties.memoryTypeCount;
153*c8dee2aaSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < memTypeCnt && !foundHeap; ++i) {
154*c8dee2aaSAndroid Build Coastguard Worker         if (hwbProps.memoryTypeBits & (1 << i)) {
155*c8dee2aaSAndroid Build Coastguard Worker             const VkPhysicalDeviceMemoryProperties& pdmp = phyDevMemProps.memoryProperties;
156*c8dee2aaSAndroid Build Coastguard Worker             uint32_t supportedFlags = pdmp.memoryTypes[i].propertyFlags &
157*c8dee2aaSAndroid Build Coastguard Worker                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
158*c8dee2aaSAndroid Build Coastguard Worker             if (supportedFlags == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
159*c8dee2aaSAndroid Build Coastguard Worker                 typeIndex = i;
160*c8dee2aaSAndroid Build Coastguard Worker                 foundHeap = true;
161*c8dee2aaSAndroid Build Coastguard Worker             }
162*c8dee2aaSAndroid Build Coastguard Worker         }
163*c8dee2aaSAndroid Build Coastguard Worker     }
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     /**
166*c8dee2aaSAndroid Build Coastguard Worker      * Fallback to use any available memory type for AHB.
167*c8dee2aaSAndroid Build Coastguard Worker      *
168*c8dee2aaSAndroid Build Coastguard Worker      * For external memory import, compatible memory types are decided by the Vulkan driver since
169*c8dee2aaSAndroid Build Coastguard Worker      * the memory has been allocated externally. There are usually special requirements against
170*c8dee2aaSAndroid Build Coastguard Worker      * external memory. e.g. AHB allocated with CPU R/W often usage bits is only importable for
171*c8dee2aaSAndroid Build Coastguard Worker      * non-device-local heap on some AMD systems.
172*c8dee2aaSAndroid Build Coastguard Worker     */
173*c8dee2aaSAndroid Build Coastguard Worker     if (!foundHeap && hwbProps.memoryTypeBits) {
174*c8dee2aaSAndroid Build Coastguard Worker         typeIndex = ffs(hwbProps.memoryTypeBits) - 1;
175*c8dee2aaSAndroid Build Coastguard Worker         foundHeap = true;
176*c8dee2aaSAndroid Build Coastguard Worker     }
177*c8dee2aaSAndroid Build Coastguard Worker     if (!foundHeap) {
178*c8dee2aaSAndroid Build Coastguard Worker         return false;
179*c8dee2aaSAndroid Build Coastguard Worker     }
180*c8dee2aaSAndroid Build Coastguard Worker 
181*c8dee2aaSAndroid Build Coastguard Worker     VkImportAndroidHardwareBufferInfoANDROID hwbImportInfo;
182*c8dee2aaSAndroid Build Coastguard Worker     hwbImportInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
183*c8dee2aaSAndroid Build Coastguard Worker     hwbImportInfo.pNext = nullptr;
184*c8dee2aaSAndroid Build Coastguard Worker     hwbImportInfo.buffer = hardwareBuffer;
185*c8dee2aaSAndroid Build Coastguard Worker 
186*c8dee2aaSAndroid Build Coastguard Worker     VkMemoryDedicatedAllocateInfo dedicatedAllocInfo;
187*c8dee2aaSAndroid Build Coastguard Worker     dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
188*c8dee2aaSAndroid Build Coastguard Worker     dedicatedAllocInfo.pNext = &hwbImportInfo;
189*c8dee2aaSAndroid Build Coastguard Worker     dedicatedAllocInfo.image = image;
190*c8dee2aaSAndroid Build Coastguard Worker     dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     VkMemoryAllocateInfo allocInfo = {
193*c8dee2aaSAndroid Build Coastguard Worker         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
194*c8dee2aaSAndroid Build Coastguard Worker         &dedicatedAllocInfo,                         // pNext
195*c8dee2aaSAndroid Build Coastguard Worker         hwbProps.allocationSize,                     // allocationSize
196*c8dee2aaSAndroid Build Coastguard Worker         typeIndex,                                   // memoryTypeIndex
197*c8dee2aaSAndroid Build Coastguard Worker     };
198*c8dee2aaSAndroid Build Coastguard Worker 
199*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceMemory memory;
200*c8dee2aaSAndroid Build Coastguard Worker     result = SHARED_GR_VULKAN_CALL(interface,
201*c8dee2aaSAndroid Build Coastguard Worker                                    AllocateMemory(device, &allocInfo, nullptr, &memory));
202*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
203*c8dee2aaSAndroid Build Coastguard Worker         return false;
204*c8dee2aaSAndroid Build Coastguard Worker     }
205*c8dee2aaSAndroid Build Coastguard Worker 
206*c8dee2aaSAndroid Build Coastguard Worker     VkBindImageMemoryInfo bindImageInfo;
207*c8dee2aaSAndroid Build Coastguard Worker     bindImageInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
208*c8dee2aaSAndroid Build Coastguard Worker     bindImageInfo.pNext = nullptr;
209*c8dee2aaSAndroid Build Coastguard Worker     bindImageInfo.image = image;
210*c8dee2aaSAndroid Build Coastguard Worker     bindImageInfo.memory = memory;
211*c8dee2aaSAndroid Build Coastguard Worker     bindImageInfo.memoryOffset = 0;
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     result = SHARED_GR_VULKAN_CALL(interface, BindImageMemory2(device, 1, &bindImageInfo));
214*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
215*c8dee2aaSAndroid Build Coastguard Worker         SHARED_GR_VULKAN_CALL(interface, FreeMemory(device, memory, nullptr));
216*c8dee2aaSAndroid Build Coastguard Worker         return false;
217*c8dee2aaSAndroid Build Coastguard Worker     }
218*c8dee2aaSAndroid Build Coastguard Worker 
219*c8dee2aaSAndroid Build Coastguard Worker     outVulkanAlloc->fMemory = memory;
220*c8dee2aaSAndroid Build Coastguard Worker     outVulkanAlloc->fOffset = 0;
221*c8dee2aaSAndroid Build Coastguard Worker     outVulkanAlloc->fSize = hwbProps.allocationSize;
222*c8dee2aaSAndroid Build Coastguard Worker     outVulkanAlloc->fFlags = 0;
223*c8dee2aaSAndroid Build Coastguard Worker     outVulkanAlloc->fBackendMemory = 0;
224*c8dee2aaSAndroid Build Coastguard Worker     return true;
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_BUILD_FOR_ANDROID
228*c8dee2aaSAndroid Build Coastguard Worker 
229*c8dee2aaSAndroid Build Coastguard Worker // Note: since this is called from Vulkan result-checking functions, any Vk calls this function
230*c8dee2aaSAndroid Build Coastguard Worker // makes must NOT be checked with those same functions to avoid infinite recursion.
InvokeDeviceLostCallback(const skgpu::VulkanInterface * vulkanInterface,VkDevice vkDevice,skgpu::VulkanDeviceLostContext deviceLostContext,skgpu::VulkanDeviceLostProc deviceLostProc,bool supportsDeviceFaultInfoExtension)231*c8dee2aaSAndroid Build Coastguard Worker void InvokeDeviceLostCallback(const skgpu::VulkanInterface* vulkanInterface,
232*c8dee2aaSAndroid Build Coastguard Worker                               VkDevice vkDevice,
233*c8dee2aaSAndroid Build Coastguard Worker                               skgpu::VulkanDeviceLostContext deviceLostContext,
234*c8dee2aaSAndroid Build Coastguard Worker                               skgpu::VulkanDeviceLostProc deviceLostProc,
235*c8dee2aaSAndroid Build Coastguard Worker                               bool supportsDeviceFaultInfoExtension) {
236*c8dee2aaSAndroid Build Coastguard Worker     if (!deviceLostProc) {
237*c8dee2aaSAndroid Build Coastguard Worker         return;
238*c8dee2aaSAndroid Build Coastguard Worker     }
239*c8dee2aaSAndroid Build Coastguard Worker 
240*c8dee2aaSAndroid Build Coastguard Worker     std::vector<VkDeviceFaultAddressInfoEXT> addressInfos = {};
241*c8dee2aaSAndroid Build Coastguard Worker     std::vector<VkDeviceFaultVendorInfoEXT> vendorInfos = {};
242*c8dee2aaSAndroid Build Coastguard Worker     std::vector<std::byte> vendorBinaryData = {};
243*c8dee2aaSAndroid Build Coastguard Worker 
244*c8dee2aaSAndroid Build Coastguard Worker     if (!supportsDeviceFaultInfoExtension) {
245*c8dee2aaSAndroid Build Coastguard Worker         deviceLostProc(deviceLostContext,
246*c8dee2aaSAndroid Build Coastguard Worker                        "No details: VK_EXT_device_fault not available/enabled.",
247*c8dee2aaSAndroid Build Coastguard Worker                        addressInfos,
248*c8dee2aaSAndroid Build Coastguard Worker                        vendorInfos,
249*c8dee2aaSAndroid Build Coastguard Worker                        vendorBinaryData);
250*c8dee2aaSAndroid Build Coastguard Worker         return;
251*c8dee2aaSAndroid Build Coastguard Worker     }
252*c8dee2aaSAndroid Build Coastguard Worker 
253*c8dee2aaSAndroid Build Coastguard Worker     // Query counts
254*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceFaultCountsEXT faultCounts = {};
255*c8dee2aaSAndroid Build Coastguard Worker     faultCounts.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT;
256*c8dee2aaSAndroid Build Coastguard Worker     VkResult result = SHARED_GR_VULKAN_CALL(vulkanInterface,
257*c8dee2aaSAndroid Build Coastguard Worker                                             GetDeviceFaultInfo(vkDevice, &faultCounts, NULL));
258*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
259*c8dee2aaSAndroid Build Coastguard Worker         deviceLostProc(
260*c8dee2aaSAndroid Build Coastguard Worker                 deviceLostContext,
261*c8dee2aaSAndroid Build Coastguard Worker                 "No details: VK_EXT_device_fault error counting failed: " + std::to_string(result),
262*c8dee2aaSAndroid Build Coastguard Worker                 addressInfos,
263*c8dee2aaSAndroid Build Coastguard Worker                 vendorInfos,
264*c8dee2aaSAndroid Build Coastguard Worker                 vendorBinaryData);
265*c8dee2aaSAndroid Build Coastguard Worker         return;
266*c8dee2aaSAndroid Build Coastguard Worker     }
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker     // Prepare storage
269*c8dee2aaSAndroid Build Coastguard Worker     addressInfos.resize(faultCounts.addressInfoCount);
270*c8dee2aaSAndroid Build Coastguard Worker     vendorInfos.resize(faultCounts.vendorInfoCount);
271*c8dee2aaSAndroid Build Coastguard Worker     vendorBinaryData.resize(faultCounts.vendorBinarySize);
272*c8dee2aaSAndroid Build Coastguard Worker 
273*c8dee2aaSAndroid Build Coastguard Worker     // Query fault info
274*c8dee2aaSAndroid Build Coastguard Worker     VkDeviceFaultInfoEXT faultInfo = {};
275*c8dee2aaSAndroid Build Coastguard Worker     faultInfo.sType             = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT;
276*c8dee2aaSAndroid Build Coastguard Worker     faultInfo.pAddressInfos     = addressInfos.data();
277*c8dee2aaSAndroid Build Coastguard Worker     faultInfo.pVendorInfos      = vendorInfos.data();
278*c8dee2aaSAndroid Build Coastguard Worker     faultInfo.pVendorBinaryData =
279*c8dee2aaSAndroid Build Coastguard Worker             faultCounts.vendorBinarySize > 0 ? vendorBinaryData.data() : nullptr;
280*c8dee2aaSAndroid Build Coastguard Worker     result = SHARED_GR_VULKAN_CALL(vulkanInterface,
281*c8dee2aaSAndroid Build Coastguard Worker                                    GetDeviceFaultInfo(vkDevice, &faultCounts, &faultInfo));
282*c8dee2aaSAndroid Build Coastguard Worker     if (result != VK_SUCCESS) {
283*c8dee2aaSAndroid Build Coastguard Worker         deviceLostProc(
284*c8dee2aaSAndroid Build Coastguard Worker                 deviceLostContext,
285*c8dee2aaSAndroid Build Coastguard Worker                 "No details: VK_EXT_device_fault info dumping failed: " + std::to_string(result),
286*c8dee2aaSAndroid Build Coastguard Worker                 addressInfos,
287*c8dee2aaSAndroid Build Coastguard Worker                 vendorInfos,
288*c8dee2aaSAndroid Build Coastguard Worker                 vendorBinaryData);
289*c8dee2aaSAndroid Build Coastguard Worker         return;
290*c8dee2aaSAndroid Build Coastguard Worker     }
291*c8dee2aaSAndroid Build Coastguard Worker 
292*c8dee2aaSAndroid Build Coastguard Worker     deviceLostProc(deviceLostContext,
293*c8dee2aaSAndroid Build Coastguard Worker                    std::string(faultInfo.description),
294*c8dee2aaSAndroid Build Coastguard Worker                    addressInfos,
295*c8dee2aaSAndroid Build Coastguard Worker                    vendorInfos,
296*c8dee2aaSAndroid Build Coastguard Worker                    vendorBinaryData);
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker 
MakeInterface(const skgpu::VulkanBackendContext & context,const skgpu::VulkanExtensions * extOverride,uint32_t * instanceVersionOut,uint32_t * physDevVersionOut)299*c8dee2aaSAndroid Build Coastguard Worker sk_sp<skgpu::VulkanInterface> MakeInterface(const skgpu::VulkanBackendContext& context,
300*c8dee2aaSAndroid Build Coastguard Worker                                             const skgpu::VulkanExtensions* extOverride,
301*c8dee2aaSAndroid Build Coastguard Worker                                             uint32_t* instanceVersionOut,
302*c8dee2aaSAndroid Build Coastguard Worker                                             uint32_t* physDevVersionOut) {
303*c8dee2aaSAndroid Build Coastguard Worker     if (!extOverride) {
304*c8dee2aaSAndroid Build Coastguard Worker         extOverride = context.fVkExtensions;
305*c8dee2aaSAndroid Build Coastguard Worker     }
306*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(extOverride);
307*c8dee2aaSAndroid Build Coastguard Worker     PFN_vkEnumerateInstanceVersion localEnumerateInstanceVersion =
308*c8dee2aaSAndroid Build Coastguard Worker             reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
309*c8dee2aaSAndroid Build Coastguard Worker                     context.fGetProc("vkEnumerateInstanceVersion", VK_NULL_HANDLE, VK_NULL_HANDLE));
310*c8dee2aaSAndroid Build Coastguard Worker     uint32_t instanceVersion = 0;
311*c8dee2aaSAndroid Build Coastguard Worker     if (!localEnumerateInstanceVersion) {
312*c8dee2aaSAndroid Build Coastguard Worker         instanceVersion = VK_MAKE_VERSION(1, 0, 0);
313*c8dee2aaSAndroid Build Coastguard Worker     } else {
314*c8dee2aaSAndroid Build Coastguard Worker         VkResult err = localEnumerateInstanceVersion(&instanceVersion);
315*c8dee2aaSAndroid Build Coastguard Worker         if (err) {
316*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
317*c8dee2aaSAndroid Build Coastguard Worker         }
318*c8dee2aaSAndroid Build Coastguard Worker     }
319*c8dee2aaSAndroid Build Coastguard Worker 
320*c8dee2aaSAndroid Build Coastguard Worker     PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
321*c8dee2aaSAndroid Build Coastguard Worker             reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(context.fGetProc(
322*c8dee2aaSAndroid Build Coastguard Worker                     "vkGetPhysicalDeviceProperties", context.fInstance, VK_NULL_HANDLE));
323*c8dee2aaSAndroid Build Coastguard Worker 
324*c8dee2aaSAndroid Build Coastguard Worker     if (!localGetPhysicalDeviceProperties) {
325*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
326*c8dee2aaSAndroid Build Coastguard Worker     }
327*c8dee2aaSAndroid Build Coastguard Worker     VkPhysicalDeviceProperties physDeviceProperties;
328*c8dee2aaSAndroid Build Coastguard Worker     localGetPhysicalDeviceProperties(context.fPhysicalDevice, &physDeviceProperties);
329*c8dee2aaSAndroid Build Coastguard Worker     uint32_t physDevVersion = physDeviceProperties.apiVersion;
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker     uint32_t apiVersion = context.fMaxAPIVersion ? context.fMaxAPIVersion : instanceVersion;
332*c8dee2aaSAndroid Build Coastguard Worker 
333*c8dee2aaSAndroid Build Coastguard Worker     instanceVersion = std::min(instanceVersion, apiVersion);
334*c8dee2aaSAndroid Build Coastguard Worker     physDevVersion = std::min(physDevVersion, apiVersion);
335*c8dee2aaSAndroid Build Coastguard Worker 
336*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<skgpu::VulkanInterface> interface(new skgpu::VulkanInterface(context.fGetProc,
337*c8dee2aaSAndroid Build Coastguard Worker                                                                        context.fInstance,
338*c8dee2aaSAndroid Build Coastguard Worker                                                                        context.fDevice,
339*c8dee2aaSAndroid Build Coastguard Worker                                                                        instanceVersion,
340*c8dee2aaSAndroid Build Coastguard Worker                                                                        physDevVersion,
341*c8dee2aaSAndroid Build Coastguard Worker                                                                        extOverride));
342*c8dee2aaSAndroid Build Coastguard Worker     if (!interface->validate(instanceVersion, physDevVersion, extOverride)) {
343*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
344*c8dee2aaSAndroid Build Coastguard Worker     }
345*c8dee2aaSAndroid Build Coastguard Worker     if (physDevVersionOut) {
346*c8dee2aaSAndroid Build Coastguard Worker         *physDevVersionOut = physDevVersion;
347*c8dee2aaSAndroid Build Coastguard Worker     }
348*c8dee2aaSAndroid Build Coastguard Worker     if (instanceVersionOut) {
349*c8dee2aaSAndroid Build Coastguard Worker         *instanceVersionOut = instanceVersion;
350*c8dee2aaSAndroid Build Coastguard Worker     }
351*c8dee2aaSAndroid Build Coastguard Worker     return interface;
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker 
354*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu
355