In vulkan tests, use vkGetInstanceProcAddr to get vkGetDeviceProcAddr.

We've run into drivers a few times now that have bugs where they only
expose vkGetInstaneProcAddr and not vkGetDeviceProcAddr. The latest
being swiftshader (which is getting fixed). To avoid this issue in the
future we can just have our tests use vkGetInstanceProcAddr to get
vkGetDeviceProcAddr.

Change-Id: I6d73abde507519c145b873042393f50ce6c4527c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/494822
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2022-01-14 11:30:38 -05:00 committed by SkCQ
parent f260a297c6
commit 6658fd1584
12 changed files with 153 additions and 163 deletions

View File

@ -508,17 +508,9 @@ private:
bool VulkanTestHelper::init(skiatest::Reporter* reporter) { bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return false; return false;
} }
auto getProc = [&instProc, &devProc](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return devProc(device, proc_name);
}
return instProc(instance, proc_name);
};
fExtensions = new GrVkExtensions(); fExtensions = new GrVkExtensions();
fFeatures = new VkPhysicalDeviceFeatures2; fFeatures = new VkPhysicalDeviceFeatures2;
@ -529,11 +521,12 @@ bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
fBackendContext.fInstance = VK_NULL_HANDLE; fBackendContext.fInstance = VK_NULL_HANDLE;
fBackendContext.fDevice = VK_NULL_HANDLE; fBackendContext.fDevice = VK_NULL_HANDLE;
if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, fExtensions, if (!sk_gpu_test::CreateVkBackendContext(instProc, &fBackendContext, fExtensions,
fFeatures, &fDebugCallback)) { fFeatures, &fDebugCallback)) {
return false; return false;
} }
fDevice = fBackendContext.fDevice; fDevice = fBackendContext.fDevice;
auto getProc = fBackendContext.fGetProc;
if (fDebugCallback != VK_NULL_HANDLE) { if (fDebugCallback != VK_NULL_HANDLE) {
fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc( fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(

View File

@ -14,34 +14,35 @@
#include "tests/Test.h" #include "tests/Test.h"
#include "tools/gpu/vk/VkTestUtils.h" #include "tools/gpu/vk/VkTestUtils.h"
#define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \ #define ACQUIRE_VK_PROC_NOCHECK(name, instance) \
PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)) PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE))
#define ACQUIRE_VK_PROC(name, instance, device) \ #define ACQUIRE_VK_PROC(name, instance) \
PFN_vk##name grVk##name = \ PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \ reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE)); \
do { \ do { \
if (grVk##name == nullptr) { \ if (grVk##name == nullptr) { \
if (device != VK_NULL_HANDLE) { \ if (instance != VK_NULL_HANDLE) { \
destroy_instance(getProc, inst); \ destroy_instance(getProc, instance); \
} \ } \
return; \ return; \
} \ } \
} while (0) } while (0)
#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \ #define ACQUIRE_VK_PROC_LOCAL(name, instance) \
PFN_vk##name grVk##name = \ PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \ reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, VK_NULL_HANDLE)); \
do { \ do { \
if (grVk##name == nullptr) { \ if (grVk##name == nullptr) { \
return; \ return; \
} \ } \
} while (0) } while (0)
#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device) #define GET_PROC_LOCAL(F, inst) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, VK_NULL_HANDLE)
static void destroy_instance(GrVkGetProc getProc, VkInstance inst) { static void destroy_instance(GrVkGetProc getProc, VkInstance inst) {
ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst);
grVkDestroyInstance(inst, nullptr); grVkDestroyInstance(inst, nullptr);
} }
@ -50,21 +51,17 @@ static void destroy_instance(GrVkGetProc getProc, VkInstance inst) {
// doesn't crash. // doesn't crash.
DEF_GPUTEST(VulkanPriorityExtension, reporter, options) { DEF_GPUTEST(VulkanPriorityExtension, reporter, options) {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return; return;
} }
auto getProc = [instProc, devProc](const char* proc_name, // This isn't the most effecient but we just use the instProc to get all ptrs.
VkInstance instance, VkDevice device) { auto getProc = [instProc](const char* proc_name, VkInstance instance, VkDevice) {
if (device != VK_NULL_HANDLE) {
return devProc(device, proc_name);
}
return instProc(instance, proc_name); return instProc(instance, proc_name);
}; };
VkResult err; VkResult err;
ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE);
uint32_t instanceVersion = 0; uint32_t instanceVersion = 0;
if (!grVkEnumerateInstanceVersion) { if (!grVkEnumerateInstanceVersion) {
instanceVersion = VK_MAKE_VERSION(1, 0, 0); instanceVersion = VK_MAKE_VERSION(1, 0, 0);
@ -112,21 +109,21 @@ DEF_GPUTEST(VulkanPriorityExtension, reporter, options) {
nullptr, // ppEnabledExtensionNames nullptr, // ppEnabledExtensionNames
}; };
ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE);
err = grVkCreateInstance(&instance_create, nullptr, &inst); err = grVkCreateInstance(&instance_create, nullptr, &inst);
if (err < 0) { if (err < 0) {
ERRORF(reporter, "Failed to create VkInstance"); ERRORF(reporter, "Failed to create VkInstance");
return; return;
} }
ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst);
ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(GetPhysicalDeviceProperties, inst);
ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst);
ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst);
ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(CreateDevice, inst);
ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(GetDeviceQueue, inst);
ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(DeviceWaitIdle, inst);
ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE); ACQUIRE_VK_PROC(DestroyDevice, inst);
uint32_t gpuCount; uint32_t gpuCount;
err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr); err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
@ -180,8 +177,8 @@ DEF_GPUTEST(VulkanPriorityExtension, reporter, options) {
return; return;
} }
GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst, VK_NULL_HANDLE); GET_PROC_LOCAL(EnumerateDeviceExtensionProperties, inst);
GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst, VK_NULL_HANDLE); GET_PROC_LOCAL(EnumerateDeviceLayerProperties, inst);
if (!EnumerateDeviceExtensionProperties || if (!EnumerateDeviceExtensionProperties ||
!EnumerateDeviceLayerProperties) { !EnumerateDeviceLayerProperties) {

View File

@ -37,21 +37,14 @@ public:
ownsContext = false; ownsContext = false;
} else { } else {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return nullptr; return nullptr;
} }
auto getProc = [instProc, devProc](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return devProc(device, proc_name);
}
return instProc(instance, proc_name);
};
extensions = new GrVkExtensions(); extensions = new GrVkExtensions();
features = new VkPhysicalDeviceFeatures2; features = new VkPhysicalDeviceFeatures2;
memset(features, 0, sizeof(VkPhysicalDeviceFeatures2)); memset(features, 0, sizeof(VkPhysicalDeviceFeatures2));
if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, extensions, if (!sk_gpu_test::CreateVkBackendContext(instProc, &backendContext, extensions,
features, &debugCallback)) { features, &debugCallback)) {
sk_gpu_test::FreeVulkanFeaturesStructs(features); sk_gpu_test::FreeVulkanFeaturesStructs(features);
delete features; delete features;

View File

@ -13,16 +13,15 @@
#include "include/gpu/GrDirectContext.h" #include "include/gpu/GrDirectContext.h"
#include "tools/gpu/vk/VkTestUtils.h" #include "tools/gpu/vk/VkTestUtils.h"
#define ACQUIRE_INST_VK_PROC(name) \ #define ACQUIRE_INST_VK_PROC(name) \
fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\ fVk##name = reinterpret_cast<PFN_vk##name>(instProc(fBackendContext.fInstance, "vk" #name)); \
VK_NULL_HANDLE)); \ if (fVk##name == nullptr) { \
if (fVk##name == nullptr) { \ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \ return false; \
return false; \
} }
#define ACQUIRE_DEVICE_VK_PROC(name) \ #define ACQUIRE_DEVICE_VK_PROC(name) \
fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \ fVk##name = reinterpret_cast<PFN_vk##name>(fVkGetDeviceProcAddr(fDevice, "vk" #name)); \
if (fVk##name == nullptr) { \ if (fVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
return false; \ return false; \
@ -30,17 +29,9 @@
bool VkTestHelper::init() { bool VkTestHelper::init() {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return false; return false;
} }
auto getProc = [&instProc, &devProc](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return devProc(device, proc_name);
}
return instProc(instance, proc_name);
};
fFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; fFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
fFeatures.pNext = nullptr; fFeatures.pNext = nullptr;
@ -48,7 +39,7 @@ bool VkTestHelper::init() {
fBackendContext.fInstance = VK_NULL_HANDLE; fBackendContext.fInstance = VK_NULL_HANDLE;
fBackendContext.fDevice = VK_NULL_HANDLE; fBackendContext.fDevice = VK_NULL_HANDLE;
if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, &fExtensions, if (!sk_gpu_test::CreateVkBackendContext(instProc, &fBackendContext, &fExtensions,
&fFeatures, &fDebugCallback, nullptr, &fFeatures, &fDebugCallback, nullptr,
sk_gpu_test::CanPresentFn(), fIsProtected)) { sk_gpu_test::CanPresentFn(), fIsProtected)) {
return false; return false;
@ -66,6 +57,8 @@ bool VkTestHelper::init() {
ACQUIRE_INST_VK_PROC(GetPhysicalDeviceFormatProperties) ACQUIRE_INST_VK_PROC(GetPhysicalDeviceFormatProperties)
ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties) ACQUIRE_INST_VK_PROC(GetPhysicalDeviceMemoryProperties)
ACQUIRE_INST_VK_PROC(GetDeviceProcAddr)
ACQUIRE_DEVICE_VK_PROC(CreateImage) ACQUIRE_DEVICE_VK_PROC(CreateImage)
ACQUIRE_DEVICE_VK_PROC(DestroyImage) ACQUIRE_DEVICE_VK_PROC(DestroyImage)
ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements) ACQUIRE_DEVICE_VK_PROC(GetImageMemoryRequirements)

View File

@ -39,6 +39,7 @@ private:
DECLARE_VK_PROC(DestroyInstance); DECLARE_VK_PROC(DestroyInstance);
DECLARE_VK_PROC(DeviceWaitIdle); DECLARE_VK_PROC(DeviceWaitIdle);
DECLARE_VK_PROC(DestroyDevice); DECLARE_VK_PROC(DestroyDevice);
DECLARE_VK_PROC(GetDeviceProcAddr);
DECLARE_VK_PROC(GetPhysicalDeviceFormatProperties); DECLARE_VK_PROC(GetPhysicalDeviceFormatProperties);
DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties); DECLARE_VK_PROC(GetPhysicalDeviceMemoryProperties);

View File

@ -33,26 +33,21 @@
namespace sk_gpu_test { namespace sk_gpu_test {
bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc, bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr* instProc) {
PFN_vkGetDeviceProcAddr* devProc) {
static void* vkLib = nullptr; static void* vkLib = nullptr;
static PFN_vkGetInstanceProcAddr localInstProc = nullptr; static PFN_vkGetInstanceProcAddr localInstProc = nullptr;
static PFN_vkGetDeviceProcAddr localDevProc = nullptr;
if (!vkLib) { if (!vkLib) {
vkLib = SkLoadDynamicLibrary(SK_GPU_TOOLS_VK_LIBRARY_NAME); vkLib = SkLoadDynamicLibrary(SK_GPU_TOOLS_VK_LIBRARY_NAME);
if (!vkLib) { if (!vkLib) {
return false; return false;
} }
localInstProc = (PFN_vkGetInstanceProcAddr) SkGetProcedureAddress(vkLib, localInstProc = (PFN_vkGetInstanceProcAddr) SkGetProcedureAddress(vkLib,
"vkGetInstanceProcAddr"); "vkGetInstanceProcAddr");
localDevProc = (PFN_vkGetDeviceProcAddr) SkGetProcedureAddress(vkLib,
"vkGetDeviceProcAddr");
} }
if (!localInstProc || !localDevProc) { if (!localInstProc) {
return false; return false;
} }
*instProc = localInstProc; *instProc = localInstProc;
*devProc = localDevProc;
return true; return true;
} }
@ -139,34 +134,37 @@ VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(
} }
#endif #endif
#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device) #define ACQUIRE_VK_INST_PROC_LOCAL(name, instance) \
PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name)); \
do { \
if (grVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
return false; \
} \
} while (0)
static bool init_instance_extensions_and_layers(GrVkGetProc getProc, static bool init_instance_extensions_and_layers(PFN_vkGetInstanceProcAddr getInstProc,
uint32_t specVersion, uint32_t specVersion,
SkTArray<VkExtensionProperties>* instanceExtensions, SkTArray<VkExtensionProperties>* instanceExtensions,
SkTArray<VkLayerProperties>* instanceLayers) { SkTArray<VkLayerProperties>* instanceLayers) {
if (getProc == nullptr) { if (getInstProc == nullptr) {
return false; return false;
} }
GET_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceExtensionProperties, VK_NULL_HANDLE);
GET_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC_LOCAL(EnumerateInstanceLayerProperties, VK_NULL_HANDLE);
if (!EnumerateInstanceExtensionProperties ||
!EnumerateInstanceLayerProperties) {
return false;
}
VkResult res; VkResult res;
uint32_t layerCount = 0; uint32_t layerCount = 0;
#ifdef SK_ENABLE_VK_LAYERS #ifdef SK_ENABLE_VK_LAYERS
// instance layers // instance layers
res = EnumerateInstanceLayerProperties(&layerCount, nullptr); res = grVkEnumerateInstanceLayerProperties(&layerCount, nullptr);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
return false; return false;
} }
VkLayerProperties* layers = new VkLayerProperties[layerCount]; VkLayerProperties* layers = new VkLayerProperties[layerCount];
res = EnumerateInstanceLayerProperties(&layerCount, layers); res = grVkEnumerateInstanceLayerProperties(&layerCount, layers);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
delete[] layers; delete[] layers;
return false; return false;
@ -187,12 +185,12 @@ static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
// via Vulkan implementation and implicitly enabled layers // via Vulkan implementation and implicitly enabled layers
{ {
uint32_t extensionCount = 0; uint32_t extensionCount = 0;
res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
return false; return false;
} }
VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
res = EnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions); res = grVkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
delete[] extensions; delete[] extensions;
return false; return false;
@ -207,14 +205,14 @@ static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
layerCount = instanceLayers->count(); layerCount = instanceLayers->count();
for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) { for (uint32_t layerIndex = 0; layerIndex < layerCount; ++layerIndex) {
uint32_t extensionCount = 0; uint32_t extensionCount = 0;
res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName, res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
&extensionCount, nullptr); &extensionCount, nullptr);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
return false; return false;
} }
VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount];
res = EnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName, res = grVkEnumerateInstanceExtensionProperties((*instanceLayers)[layerIndex].layerName,
&extensionCount, extensions); &extensionCount, extensions);
if (VK_SUCCESS != res) { if (VK_SUCCESS != res) {
delete[] extensions; delete[] extensions;
return false; return false;
@ -228,6 +226,8 @@ static bool init_instance_extensions_and_layers(GrVkGetProc getProc,
return true; return true;
} }
#define GET_PROC_LOCAL(F, inst, device) PFN_vk ## F F = (PFN_vk ## F) getProc("vk" #F, inst, device)
static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion, static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t specVersion,
VkInstance inst, VkPhysicalDevice physDev, VkInstance inst, VkPhysicalDevice physDev,
SkTArray<VkExtensionProperties>* deviceExtensions, SkTArray<VkExtensionProperties>* deviceExtensions,
@ -317,20 +317,36 @@ static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t spec
return true; return true;
} }
#define ACQUIRE_VK_INST_PROC_NOCHECK(name, instance) \
PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name))
#define ACQUIRE_VK_INST_PROC(name, instance) \
PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getInstProc(instance, "vk" #name)); \
do { \
if (grVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
if (inst != VK_NULL_HANDLE) { \
destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
} \
return false; \
} \
} while (0)
#define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \ #define ACQUIRE_VK_PROC_NOCHECK(name, instance, device) \
PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)) PFN_vk##name grVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device))
#define ACQUIRE_VK_PROC(name, instance, device) \ #define ACQUIRE_VK_PROC(name, instance, device) \
PFN_vk##name grVk##name = \ PFN_vk##name grVk##name = \
reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \ reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
do { \ do { \
if (grVk##name == nullptr) { \ if (grVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
if (device != VK_NULL_HANDLE) { \ if (inst != VK_NULL_HANDLE) { \
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); \ destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension); \
} \ } \
return false; \ return false; \
} \ } \
} while (0) } while (0)
#define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \ #define ACQUIRE_VK_PROC_LOCAL(name, instance, device) \
@ -339,19 +355,19 @@ static bool init_device_extensions_and_layers(GrVkGetProc getProc, uint32_t spec
do { \ do { \
if (grVk##name == nullptr) { \ if (grVk##name == nullptr) { \
SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \ SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
return false; \ return false; \
} \ } \
} while (0) } while (0)
static bool destroy_instance(GrVkGetProc getProc, VkInstance inst, static bool destroy_instance(PFN_vkGetInstanceProcAddr getInstProc, VkInstance inst,
VkDebugReportCallbackEXT* debugCallback, VkDebugReportCallbackEXT* debugCallback,
bool hasDebugExtension) { bool hasDebugExtension) {
if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) { if (hasDebugExtension && *debugCallback != VK_NULL_HANDLE) {
ACQUIRE_VK_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC_LOCAL(DestroyDebugReportCallbackEXT, inst);
grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr); grVkDestroyDebugReportCallbackEXT(inst, *debugCallback, nullptr);
*debugCallback = VK_NULL_HANDLE; *debugCallback = VK_NULL_HANDLE;
} }
ACQUIRE_VK_PROC_LOCAL(DestroyInstance, inst, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC_LOCAL(DestroyInstance, inst);
grVkDestroyInstance(inst, nullptr); grVkDestroyInstance(inst, nullptr);
return true; return true;
} }
@ -420,7 +436,7 @@ static bool setup_features(GrVkGetProc getProc, VkInstance inst, VkPhysicalDevic
// If we want to disable any extension features do so here. // If we want to disable any extension features do so here.
} }
bool CreateVkBackendContext(GrVkGetProc getProc, bool CreateVkBackendContext(PFN_vkGetInstanceProcAddr getInstProc,
GrVkBackendContext* ctx, GrVkBackendContext* ctx,
GrVkExtensions* extensions, GrVkExtensions* extensions,
VkPhysicalDeviceFeatures2* features, VkPhysicalDeviceFeatures2* features,
@ -430,7 +446,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
bool isProtected) { bool isProtected) {
VkResult err; VkResult err;
ACQUIRE_VK_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC_NOCHECK(EnumerateInstanceVersion, VK_NULL_HANDLE);
uint32_t instanceVersion = 0; uint32_t instanceVersion = 0;
if (!grVkEnumerateInstanceVersion) { if (!grVkEnumerateInstanceVersion) {
instanceVersion = VK_MAKE_VERSION(1, 0, 0); instanceVersion = VK_MAKE_VERSION(1, 0, 0);
@ -460,7 +476,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
VkPhysicalDevice physDev; VkPhysicalDevice physDev;
VkDevice device; VkDevice device;
VkInstance inst; VkInstance inst = VK_NULL_HANDLE;
const VkApplicationInfo app_info = { const VkApplicationInfo app_info = {
VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
@ -475,7 +491,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
SkTArray<VkLayerProperties> instanceLayers; SkTArray<VkLayerProperties> instanceLayers;
SkTArray<VkExtensionProperties> instanceExtensions; SkTArray<VkExtensionProperties> instanceExtensions;
if (!init_instance_extensions_and_layers(getProc, instanceVersion, if (!init_instance_extensions_and_layers(getInstProc, instanceVersion,
&instanceExtensions, &instanceExtensions,
&instanceLayers)) { &instanceLayers)) {
return false; return false;
@ -505,13 +521,22 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
bool hasDebugExtension = false; bool hasDebugExtension = false;
ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE); ACQUIRE_VK_INST_PROC(CreateInstance, VK_NULL_HANDLE);
err = grVkCreateInstance(&instance_create, nullptr, &inst); err = grVkCreateInstance(&instance_create, nullptr, &inst);
if (err < 0) { if (err < 0) {
SkDebugf("vkCreateInstance failed: %d\n", err); SkDebugf("vkCreateInstance failed: %d\n", err);
return false; return false;
} }
ACQUIRE_VK_INST_PROC(GetDeviceProcAddr, inst);
auto getProc = [getInstProc, grVkGetDeviceProcAddr](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return grVkGetDeviceProcAddr(device, proc_name);
}
return getInstProc(instance, proc_name);
};
#ifdef SK_ENABLE_VK_LAYERS #ifdef SK_ENABLE_VK_LAYERS
*debugCallback = VK_NULL_HANDLE; *debugCallback = VK_NULL_HANDLE;
for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) { for (int i = 0; i < instanceExtensionNames.count() && !hasDebugExtension; ++i) {
@ -551,12 +576,12 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr); err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
if (err) { if (err) {
SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
if (!gpuCount) { if (!gpuCount) {
SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n"); SkDebugf("vkEnumeratePhysicalDevices returned no supported devices.\n");
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
// Just returning the first physical device instead of getting the whole array. // Just returning the first physical device instead of getting the whole array.
@ -566,7 +591,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
// VK_INCOMPLETE is returned when the count we provide is less than the total device count. // VK_INCOMPLETE is returned when the count we provide is less than the total device count.
if (err && VK_INCOMPLETE != err) { if (err && VK_INCOMPLETE != err) {
SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -576,7 +601,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
if (isProtected && physDeviceVersion < VK_MAKE_VERSION(1, 1, 0)) { if (isProtected && physDeviceVersion < VK_MAKE_VERSION(1, 1, 0)) {
SkDebugf("protected requires vk physical device version 1.1\n"); SkDebugf("protected requires vk physical device version 1.1\n");
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -585,7 +610,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr); grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
if (!queueCount) { if (!queueCount) {
SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n"); SkDebugf("vkGetPhysicalDeviceQueueFamilyProperties returned no queues.\n");
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -605,7 +630,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
} }
if (graphicsQueueIndex == queueCount) { if (graphicsQueueIndex == queueCount) {
SkDebugf("Could not find any supported graphics queues.\n"); SkDebugf("Could not find any supported graphics queues.\n");
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -620,7 +645,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
} }
if (presentQueueIndex == queueCount) { if (presentQueueIndex == queueCount) {
SkDebugf("Could not find any supported present queues.\n"); SkDebugf("Could not find any supported present queues.\n");
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
*presentQueueIndexPtr = presentQueueIndex; *presentQueueIndexPtr = presentQueueIndex;
@ -636,7 +661,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
inst, physDev, inst, physDev,
&deviceExtensions, &deviceExtensions,
&deviceLayers)) { &deviceLayers)) {
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -695,8 +720,8 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) || if (physDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) { extensions->hasExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 1)) {
if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features, if (!setup_features(getProc, inst, physDev, physDeviceVersion, extensions, features,
isProtected)) { isProtected)) {
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }
@ -758,7 +783,7 @@ bool CreateVkBackendContext(GrVkGetProc getProc,
} }
if (err) { if (err) {
SkDebugf("CreateDevice failed: %d\n", err); SkDebugf("CreateDevice failed: %d\n", err);
destroy_instance(getProc, inst, debugCallback, hasDebugExtension); destroy_instance(getInstProc, inst, debugCallback, hasDebugExtension);
return false; return false;
} }

View File

@ -21,12 +21,12 @@ class GrVkExtensions;
struct GrVkBackendContext; struct GrVkBackendContext;
namespace sk_gpu_test { namespace sk_gpu_test {
bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr*, PFN_vkGetDeviceProcAddr*); bool LoadVkLibraryAndGetProcAddrFuncs(PFN_vkGetInstanceProcAddr*);
using CanPresentFn = std::function<bool(VkInstance, VkPhysicalDevice, using CanPresentFn = std::function<bool(VkInstance, VkPhysicalDevice,
uint32_t queueFamilyIndex)>; uint32_t queueFamilyIndex)>;
bool CreateVkBackendContext(GrVkGetProc getProc, bool CreateVkBackendContext(PFN_vkGetInstanceProcAddr getInstProc,
GrVkBackendContext* ctx, GrVkBackendContext* ctx,
GrVkExtensions*, GrVkExtensions*,
VkPhysicalDeviceFeatures2*, VkPhysicalDeviceFeatures2*,

View File

@ -24,16 +24,17 @@
#undef CreateSemaphore #undef CreateSemaphore
#endif #endif
#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fInstance, "vk" #F) #define GET_PROC(F) f ## F = \
#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fDevice, "vk" #F) (PFN_vk ## F) backendContext.fGetProc("vk" #F, fInstance, VK_NULL_HANDLE)
#define GET_DEV_PROC(F) f ## F = \
(PFN_vk ## F) backendContext.fGetProc("vk" #F, VK_NULL_HANDLE, fDevice)
namespace sk_app { namespace sk_app {
VulkanWindowContext::VulkanWindowContext(const DisplayParams& params, VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
CreateVkSurfaceFn createVkSurface, CreateVkSurfaceFn createVkSurface,
CanPresentFn canPresent, CanPresentFn canPresent,
PFN_vkGetInstanceProcAddr instProc, PFN_vkGetInstanceProcAddr instProc)
PFN_vkGetDeviceProcAddr devProc)
: WindowContext(params) : WindowContext(params)
, fCreateVkSurfaceFn(createVkSurface) , fCreateVkSurfaceFn(createVkSurface)
, fCanPresentFn(canPresent) , fCanPresentFn(canPresent)
@ -44,7 +45,6 @@ VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
, fSurfaces(nullptr) , fSurfaces(nullptr)
, fBackbuffers(nullptr) { , fBackbuffers(nullptr) {
fGetInstanceProcAddr = instProc; fGetInstanceProcAddr = instProc;
fGetDeviceProcAddr = devProc;
this->initializeContext(); this->initializeContext();
} }
@ -53,19 +53,12 @@ void VulkanWindowContext::initializeContext() {
// any config code here (particularly for msaa)? // any config code here (particularly for msaa)?
PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr; PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr getDeviceProc = fGetDeviceProcAddr;
auto getProc = [getInstanceProc, getDeviceProc](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return getDeviceProc(device, proc_name);
}
return getInstanceProc(instance, proc_name);
};
GrVkBackendContext backendContext; GrVkBackendContext backendContext;
GrVkExtensions extensions; GrVkExtensions extensions;
VkPhysicalDeviceFeatures2 features; VkPhysicalDeviceFeatures2 features;
if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, &extensions, &features, if (!sk_gpu_test::CreateVkBackendContext(getInstanceProc, &backendContext, &extensions,
&fDebugCallback, &fPresentQueueIndex, fCanPresentFn)) { &features, &fDebugCallback, &fPresentQueueIndex,
fCanPresentFn)) {
sk_gpu_test::FreeVulkanFeaturesStructs(&features); sk_gpu_test::FreeVulkanFeaturesStructs(&features);
return; return;
} }

View File

@ -48,7 +48,7 @@ public:
using CanPresentFn = sk_gpu_test::CanPresentFn; using CanPresentFn = sk_gpu_test::CanPresentFn;
VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn, VulkanWindowContext(const DisplayParams&, CreateVkSurfaceFn, CanPresentFn,
PFN_vkGetInstanceProcAddr, PFN_vkGetDeviceProcAddr); PFN_vkGetInstanceProcAddr);
private: private:
void initializeContext(); void initializeContext();
@ -73,9 +73,7 @@ private:
CreateVkSurfaceFn fCreateVkSurfaceFn; CreateVkSurfaceFn fCreateVkSurfaceFn;
CanPresentFn fCanPresentFn; CanPresentFn fCanPresentFn;
// Vulkan GetProcAddr functions
PFN_vkGetInstanceProcAddr fGetInstanceProcAddr = nullptr; PFN_vkGetInstanceProcAddr fGetInstanceProcAddr = nullptr;
PFN_vkGetDeviceProcAddr fGetDeviceProcAddr = nullptr;
// WSI interface functions // WSI interface functions
PFN_vkDestroySurfaceKHR fDestroySurfaceKHR = nullptr; PFN_vkDestroySurfaceKHR fDestroySurfaceKHR = nullptr;

View File

@ -21,8 +21,7 @@ namespace window_context_factory {
std::unique_ptr<WindowContext> MakeVulkanForAndroid(ANativeWindow* window, std::unique_ptr<WindowContext> MakeVulkanForAndroid(ANativeWindow* window,
const DisplayParams& params) { const DisplayParams& params) {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return nullptr; return nullptr;
} }
@ -50,7 +49,7 @@ std::unique_ptr<WindowContext> MakeVulkanForAndroid(ANativeWindow* window,
auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; }; auto canPresent = [](VkInstance, VkPhysicalDevice, uint32_t) { return true; };
std::unique_ptr<WindowContext> ctx( std::unique_ptr<WindowContext> ctx(
new VulkanWindowContext(params, createVkSurface, canPresent, instProc, devProc)); new VulkanWindowContext(params, createVkSurface, canPresent, instProc));
if (!ctx->isValid()) { if (!ctx->isValid()) {
return nullptr; return nullptr;
} }

View File

@ -25,8 +25,7 @@ namespace window_context_factory {
std::unique_ptr<WindowContext> MakeVulkanForXlib(const XlibWindowInfo& info, std::unique_ptr<WindowContext> MakeVulkanForXlib(const XlibWindowInfo& info,
const DisplayParams& displayParams) { const DisplayParams& displayParams) {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return nullptr; return nullptr;
} }
@ -75,7 +74,7 @@ std::unique_ptr<WindowContext> MakeVulkanForXlib(const XlibWindowInfo& info,
return (VK_FALSE != check); return (VK_FALSE != check);
}; };
std::unique_ptr<WindowContext> ctx( std::unique_ptr<WindowContext> ctx(
new VulkanWindowContext(displayParams, createVkSurface, canPresent, instProc, devProc)); new VulkanWindowContext(displayParams, createVkSurface, canPresent, instProc));
if (!ctx->isValid()) { if (!ctx->isValid()) {
return nullptr; return nullptr;
} }

View File

@ -25,8 +25,7 @@ namespace window_context_factory {
std::unique_ptr<WindowContext> MakeVulkanForWin(HWND hwnd, const DisplayParams& params) { std::unique_ptr<WindowContext> MakeVulkanForWin(HWND hwnd, const DisplayParams& params) {
PFN_vkGetInstanceProcAddr instProc; PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc; if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc)) {
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return nullptr; return nullptr;
} }
@ -70,7 +69,7 @@ std::unique_ptr<WindowContext> MakeVulkanForWin(HWND hwnd, const DisplayParams&
}; };
std::unique_ptr<WindowContext> ctx( std::unique_ptr<WindowContext> ctx(
new VulkanWindowContext(params, createVkSurface, canPresent, instProc, devProc)); new VulkanWindowContext(params, createVkSurface, canPresent, instProc));
if (!ctx->isValid()) { if (!ctx->isValid()) {
return nullptr; return nullptr;
} }