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