14#ifndef SK_GPU_TOOLS_VK_LIBRARY_NAME
16 #define SK_GPU_TOOLS_VK_LIBRARY_NAME vulkan-1.dll
17 #elif defined SK_BUILD_FOR_MAC
18 #define SK_GPU_TOOLS_VK_LIBRARY_NAME libvk_swiftshader.dylib
20 #define SK_GPU_TOOLS_VK_LIBRARY_NAME libvulkan.so
21 #define SK_GPU_TOOLS_VK_LIBRARY_NAME_BACKUP libvulkan.so.1
25#define STRINGIFY2(S) #S
26#define STRINGIFY(S) STRINGIFY2(S)
39#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
40#include <sanitizer/lsan_interface.h>
48 static void* vkLib =
nullptr;
55#ifdef SK_GPU_TOOLS_VK_LIBRARY_NAME_BACKUP
65 "vkGetInstanceProcAddr");
70 *instProc = localInstProc;
77#ifdef SK_ENABLE_VK_LAYERS
78const char* kDebugLayerNames[] = {
80 "VK_LAYER_KHRONOS_validation",
87static uint32_t remove_patch_version(uint32_t specVersion) {
88 return (specVersion >> 12) << 12;
92static int should_include_debug_layer(
const char* layerName,
95 for (uint32_t i = 0; i < layerCount; ++i) {
96 if (!strcmp(layerName, layers[i].layerName)) {
100 if (version <= remove_patch_version(layers[i].specVersion)) {
110static void print_backtrace() {
111#if defined(__GLIBC__)
113 int count = backtrace(stack, std::size(stack));
114 backtrace_symbols_fd(stack,
count, 2);
126 const char* pLayerPrefix,
127 const char* pMessage,
131 if (strstr(pMessage,
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01521") ||
132 strstr(pMessage,
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-01522")) {
136 if (strstr(pMessage,
"VUID-vkCmdDraw-None-02686") ||
137 strstr(pMessage,
"VUID-vkCmdDrawIndexed-None-02686")) {
140 SkDebugf(
"Vulkan error [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
145 SkDebugf(
"Vulkan warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
148 SkDebugf(
"Vulkan perf warning [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
151 SkDebugf(
"Vulkan info/debug [%s]: code: %d: %s\n", pLayerPrefix, messageCode, pMessage);
157#define ACQUIRE_VK_INST_PROC_LOCAL(name, instance) \
158 PFN_vk##name grVk##name = \
159 reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name)); \
161 if (grVk##name == nullptr) { \
162 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
168 uint32_t specVersion,
171 if (getInstProc ==
nullptr) {
175 ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceExtensionProperties,
VK_NULL_HANDLE);
176 ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceLayerProperties,
VK_NULL_HANDLE);
179 uint32_t layerCount = 0;
180#ifdef SK_ENABLE_VK_LAYERS
182 res = grVkEnumerateInstanceLayerProperties(&layerCount,
nullptr);
187 res = grVkEnumerateInstanceLayerProperties(&layerCount, layers);
193 uint32_t nonPatchVersion = remove_patch_version(specVersion);
194 for (
size_t i = 0; i < std::size(kDebugLayerNames); ++i) {
195 int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
198 instanceLayers->
push_back() = layers[idx];
207 uint32_t extensionCount = 0;
208 res = grVkEnumerateInstanceExtensionProperties(
nullptr, &extensionCount,
nullptr);
213 res = grVkEnumerateInstanceExtensionProperties(
nullptr, &extensionCount, extensions);
218 for (uint32_t i = 0; i < extensionCount; ++i) {
225 layerCount = instanceLayers->
size();
226 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
227 uint32_t extensionCount = 0;
228 res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
229 &extensionCount,
nullptr);
234 res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
235 &extensionCount, extensions);
240 for (uint32_t i = 0; i < extensionCount; ++i) {
249#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
252 uint32_t specVersion, VkInstance inst,
253 VkPhysicalDevice physDev,
256 if (getProc ==
nullptr) {
263 if (!EnumerateDeviceExtensionProperties ||
264 !EnumerateDeviceLayerProperties) {
270 uint32_t layerCount = 0;
271#ifdef SK_ENABLE_VK_LAYERS
272 res = EnumerateDeviceLayerProperties(physDev, &layerCount,
nullptr);
277 res = EnumerateDeviceLayerProperties(physDev, &layerCount, layers);
283 uint32_t nonPatchVersion = remove_patch_version(specVersion);
284 for (
size_t i = 0; i < std::size(kDebugLayerNames); ++i) {
285 int idx = should_include_debug_layer(kDebugLayerNames[i], layerCount, layers,
297 uint32_t extensionCount = 0;
298 res = EnumerateDeviceExtensionProperties(physDev,
nullptr, &extensionCount,
nullptr);
303 res = EnumerateDeviceExtensionProperties(physDev,
nullptr, &extensionCount, extensions);
308 for (uint32_t i = 0; i < extensionCount; ++i) {
315 layerCount = deviceLayers->
size();
316 for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
317 uint32_t extensionCount = 0;
318 res = EnumerateDeviceExtensionProperties(physDev,
319 (*deviceLayers)[layerIndex].layerName,
320 &extensionCount,
nullptr);
325 res = EnumerateDeviceExtensionProperties(physDev,
326 (*deviceLayers)[layerIndex].layerName,
327 &extensionCount, extensions);
332 for (uint32_t i = 0; i < extensionCount; ++i) {
341#define ACQUIRE_VK_INST_PROC_NOCHECK(name, instance) \
342 PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name))
344#define ACQUIRE_VK_INST_PROC(name, instance) \
345 PFN_vk##name grVk##name = \
346 reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name)); \
348 if (grVk##name == nullptr) { \
349 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
350 if (inst != VK_NULL_HANDLE) { \
351 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
357#define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
358 PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device))
360#define ACQUIRE_VK_PROC(name, instance, device) \
361 PFN_vk##name grVk##name = \
362 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
364 if (grVk##name == nullptr) { \
365 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
366 if (inst != VK_NULL_HANDLE) { \
367 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
373#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \
374 PFN_vk##name grVk##name = \
375 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
377 if (grVk##name == nullptr) { \
378 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
384 VkDebugReportCallbackEXT* debugCallback,
385 bool hasDebugExtension) {
387 ACQUIRE_VK_INST_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst);
388 grVkDestroyDebugReportCallbackEXT(inst, *debugCallback,
nullptr);
391 ACQUIRE_VK_INST_PROC_LOCAL(DestroyInstance, inst);
392 grVkDestroyInstance(inst,
nullptr);
397 VkPhysicalDevice physDev, uint32_t physDeviceVersion,
404 void** tailPNext = &features->
pNext;
410 protectedMemoryFeatures =
413 protectedMemoryFeatures->
sType =
415 protectedMemoryFeatures->
pNext =
nullptr;
416 *tailPNext = protectedMemoryFeatures;
417 tailPNext = &protectedMemoryFeatures->
pNext;
425 blend->pNext =
nullptr;
427 tailPNext = &
blend->pNext;
436 ycbcrFeature->
pNext =
nullptr;
438 *tailPNext = ycbcrFeature;
439 tailPNext = &ycbcrFeature->
pNext;
444 grVkGetPhysicalDeviceFeatures2(physDev, features);
449 grVkGetPhysicalDeviceFeatures2KHR(physDev, features);
483 VkDebugReportCallbackEXT* debugCallback,
484 uint32_t* presentQueueIndexPtr,
485 const CanPresentFn& canPresent,
488 if (!CreateVkBackendContext(getInstProc,
493 presentQueueIndexPtr,
501 ConvertBackendContext(skgpuCtx, ctx);
509 VkDebugReportCallbackEXT* debugCallback,
510 uint32_t* presentQueueIndexPtr,
511 const CanPresentFn& canPresent,
515 ACQUIRE_VK_INST_PROC_NOCHECK(EnumerateInstanceVersion,
VK_NULL_HANDLE);
516 uint32_t instanceVersion = 0;
517 if (!grVkEnumerateInstanceVersion) {
520 err = grVkEnumerateInstanceVersion(&instanceVersion);
522 SkDebugf(
"failed to enumerate instance version. Err: %d\n", err);
528 SkDebugf(
"protected requires vk instance version 1.1\n");
541 instanceVersion = std::min(instanceVersion, apiVersion);
560 if (!init_instance_extensions_and_layers(getInstProc, instanceVersion,
568 for (
int i = 0; i < instanceLayers.
size(); ++i) {
569 instanceLayerNames.
push_back(instanceLayers[i].layerName);
571 for (
int i = 0; i < instanceExtensions.
size(); ++i) {
572 if (strncmp(instanceExtensions[i].extensionName,
"VK_KHX", 6) != 0) {
573 instanceExtensionNames.
push_back(instanceExtensions[i].extensionName);
582 (uint32_t) instanceLayerNames.
size(),
583 instanceLayerNames.
begin(),
584 (uint32_t) instanceExtensionNames.
size(),
585 instanceExtensionNames.
begin(),
588 bool hasDebugExtension =
false;
591 err = grVkCreateInstance(&instance_create,
nullptr, &inst);
593 SkDebugf(
"vkCreateInstance failed: %d\n", err);
597 ACQUIRE_VK_INST_PROC(GetDeviceProcAddr, inst);
598 auto getProc = [getInstProc, grVkGetDeviceProcAddr](
const char* proc_name,
601 return grVkGetDeviceProcAddr(
device, proc_name);
603 return getInstProc(
instance, proc_name);
606#ifdef SK_ENABLE_VK_LAYERS
608 for (
int i = 0; i < instanceExtensionNames.
size() && !hasDebugExtension; ++i) {
610 hasDebugExtension =
true;
613 if (hasDebugExtension) {
617 callbackCreateInfo.
pNext =
nullptr;
623 callbackCreateInfo.
pfnCallback = &DebugReportCallback;
626 ACQUIRE_VK_PROC(CreateDebugReportCallbackEXT, inst,
VK_NULL_HANDLE);
628 grVkCreateDebugReportCallbackEXT(inst, &callbackCreateInfo,
nullptr, debugCallback);
633 ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst,
VK_NULL_HANDLE);
634 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst,
VK_NULL_HANDLE);
642 err = grVkEnumeratePhysicalDevices(inst, &gpuCount,
nullptr);
644 SkDebugf(
"vkEnumeratePhysicalDevices failed: %d\n", err);
645 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
649 SkDebugf(
"vkEnumeratePhysicalDevices returned no supported devices.\n");
650 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
656 physDevs.
resize(gpuCount);
657 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, physDevs.
data());
659 SkDebugf(
"vkEnumeratePhysicalDevices failed: %d\n", err);
660 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
665 VkPhysicalDevice physDev = physDevs.
front();
668 grVkGetPhysicalDeviceProperties(physDev, &physDeviceProperties);
669 uint32_t physDeviceVersion = std::min(physDeviceProperties.
apiVersion, apiVersion);
672 SkDebugf(
"protected requires vk physical device version 1.1\n");
673 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
679 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount,
nullptr);
681 SkDebugf(
"vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
682 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
690 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
693 uint32_t graphicsQueueIndex = queueCount;
694 for (uint32_t i = 0; i < queueCount; i++) {
696 graphicsQueueIndex = i;
700 if (graphicsQueueIndex == queueCount) {
701 SkDebugf(
"Could not find any supported graphics queues.\n");
702 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
707 uint32_t presentQueueIndex = queueCount;
708 if (presentQueueIndexPtr && canPresent) {
709 for (uint32_t i = 0; i < queueCount; i++) {
710 if (canPresent(inst, physDev, i)) {
711 presentQueueIndex = i;
715 if (presentQueueIndex == queueCount) {
716 SkDebugf(
"Could not find any supported present queues.\n");
717 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
720 *presentQueueIndexPtr = presentQueueIndex;
724 presentQueueIndex = graphicsQueueIndex;
729 if (!init_device_extensions_and_layers(getProc, physDeviceVersion,
733 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
739 for (
int i = 0; i < deviceLayers.
size(); ++i) {
740 deviceLayerNames.
push_back(deviceLayers[i].layerName);
746 bool hasKHRBufferDeviceAddress =
false;
747 for (
int i = 0; i < deviceExtensions.
size(); ++i) {
748 if (!strcmp(deviceExtensions[i].extensionName,
"VK_KHR_buffer_device_address")) {
749 hasKHRBufferDeviceAddress =
true;
754 for (
int i = 0; i < deviceExtensions.
size(); ++i) {
758 if (0 != strncmp(deviceExtensions[i].extensionName,
"VK_KHX", 6) &&
759 0 != strncmp(deviceExtensions[i].extensionName,
"VK_NVX", 6)) {
764 if (0 == strcmp(deviceExtensions[i].extensionName,
"VK_EXT_provoking_vertex") ||
765 0 == strcmp(deviceExtensions[i].extensionName,
"VK_EXT_shader_object") ||
766 0 == strcmp(deviceExtensions[i].extensionName,
"VK_KHR_dynamic_rendering") ||
767 0 == strcmp(deviceExtensions[i].extensionName,
"VK_NV_acquire_winrt_display") ||
768 0 == strcmp(deviceExtensions[i].extensionName,
"VK_NV_cuda_kernel_launch") ||
769 0 == strcmp(deviceExtensions[i].extensionName,
"VK_NV_low_latency") ||
770 0 == strcmp(deviceExtensions[i].extensionName,
"VK_NV_present_barrier")) {
774 if (!hasKHRBufferDeviceAddress ||
775 0 != strcmp(deviceExtensions[i].extensionName,
"VK_EXT_buffer_device_address")) {
776 deviceExtensionNames.
push_back(deviceExtensions[i].extensionName);
782 (uint32_t) instanceExtensionNames.
size(),
783 instanceExtensionNames.
begin(),
784 (uint32_t) deviceExtensionNames.
size(),
785 deviceExtensionNames.
begin());
789 features->
pNext =
nullptr;
792 void* pointerToFeatures =
nullptr;
795 if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features,
797 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
803 pointerToFeatures = features;
805 grVkGetPhysicalDeviceFeatures(physDev, deviceFeatures);
813 float queuePriorities[1] = { 0.0 };
835 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
843 (uint32_t) deviceLayerNames.
size(),
844 deviceLayerNames.
begin(),
845 (uint32_t) deviceExtensionNames.
size(),
846 deviceExtensionNames.
begin(),
847 pointerToFeatures ? nullptr : deviceFeatures
851#if defined(SK_ENABLE_SCOPED_LSAN_SUPPRESSIONS)
853 __lsan::ScopedDisabler lsanDisabler;
855 err = grVkCreateDevice(physDev, &deviceInfo,
nullptr, &
device);
858 SkDebugf(
"CreateDevice failed: %d\n", err);
859 destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
865 ACQUIRE_VK_PROC(GetDeviceQueue2, inst,
device);
866 SkASSERT(grVkGetDeviceQueue2 !=
nullptr);
874 grVkGetDeviceQueue2(
device, &queue_info2, &queue);
876 grVkGetDeviceQueue(
device, graphicsQueueIndex, 0, &queue);
881 SkASSERT(interface.validate(instanceVersion, physDeviceVersion, extensions));
884 inst, physDev,
device, physDeviceVersion, extensions, &interface);
905 struct CommonVulkanHeader {
910 void* pNext = features->
pNext;
912 void* current = pNext;
913 pNext =
static_cast<CommonVulkanHeader*
>(current)->pNext;
#define GET_PROC_LOCAL(F)
#define ACQUIRE_VK_PROC_LOCAL(name, inst)
#define SkDEBUGFAIL(message)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
void * SkGetProcedureAddress(void *library, const char *functionName)
void * SkLoadDynamicLibrary(const char *libraryName)
static sk_sp< VulkanMemoryAllocator > Make(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, uint32_t physicalDeviceVersion, const skgpu::VulkanExtensions *extensions, const skgpu::VulkanInterface *interface)
void resize(size_t count)
FlutterSemanticsFlag flags
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
std::function< PFN_vkVoidFunction(const char *, VkInstance, VkDevice)> VulkanGetProc
const skgpu::VulkanExtensions * fVkExtensions
skgpu::Protected fProtectedContext
const VkPhysicalDeviceFeatures * fDeviceFeatures
VkPhysicalDevice fPhysicalDevice
uint32_t fGraphicsQueueIndex
skgpu::VulkanGetProc fGetProc
const VkPhysicalDeviceFeatures2 * fDeviceFeatures2
sk_sp< skgpu::VulkanMemoryAllocator > fMemoryAllocator
PFN_vkDebugReportCallbackEXT pfnCallback
VkDebugReportFlagsEXT flags
VkPhysicalDeviceFeatures features
VkBool32 robustBufferAccess
VkBool32 samplerYcbcrConversion
const VkPhysicalDeviceFeatures2 * fDeviceFeatures2
Protected fProtectedContext
sk_sp< VulkanMemoryAllocator > fMemoryAllocator
const VkPhysicalDeviceFeatures * fDeviceFeatures
uint32_t fGraphicsQueueIndex
skgpu::VulkanGetProc fGetProc
VkPhysicalDevice fPhysicalDevice
const skgpu::VulkanExtensions * fVkExtensions
@ VK_DEBUG_REPORT_WARNING_BIT_EXT
@ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT
@ VK_DEBUG_REPORT_ERROR_BIT_EXT
#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME
VkFlags VkDeviceQueueCreateFlags
@ VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT
VkDebugReportObjectTypeEXT
#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME
#define VK_MAKE_VERSION(major, minor, patch)
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
#define VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME
VkFlags VkDebugReportFlagsEXT
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
@ VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
@ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES
@ VK_STRUCTURE_TYPE_APPLICATION_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT
@ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
@ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
@ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO