zink: fix instance/device versioning (for real this time)

the maximum allowable runtime version of vk can be computed by MIN(instance_version, device_version)

despite this, instances and devices can be created using the maximum version available
for each respective type. the restriction is applied only at the point of
enabling/applying features and extensions, meaning that to correctly handle this,
zink must:

1. create an instance using the maximum allowable version
2. select a physical device using the instance
3. compute MIN(instance_version, device_version)
4. only now begin to enable/use features requiring vk 1.1+

ref #4392

Reviewed-by: Adam Jackson <ajax@redhat.com>
Acked-by: Hoe Hao Cheng <haochengho12907@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9479>
This commit is contained in:
Mike Blumenkrantz
2021-03-09 09:54:01 -05:00
committed by Marge Bot
parent 1d70863c12
commit 5945d7d2e9
4 changed files with 33 additions and 39 deletions

View File

@@ -247,10 +247,6 @@ zink_get_physical_device_info(struct zink_screen *screen)
%endfor
uint32_t num_extensions = 0;
// get device API support
vkGetPhysicalDeviceProperties(screen->pdev, &info->props);
info->device_version = info->props.apiVersion;
// get device memory properties
vkGetPhysicalDeviceMemoryProperties(screen->pdev, &info->mem_props);
@@ -268,7 +264,7 @@ zink_get_physical_device_info(struct zink_screen *screen)
%if ext.core_since:
%for version in versions:
%if ext.core_since.struct_version == version.struct_version:
if (${version.version()} >= info->device_version) {
if (${version.version()} >= screen->vk_version) {
%if not (ext.has_features or ext.has_properties):
info->have_${ext.name_with_vendor()} = true;
%else:
@@ -305,7 +301,7 @@ zink_get_physical_device_info(struct zink_screen *screen)
info->feats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
%for version in versions:
if (${version.version()} <= info->device_version) {
if (${version.version()} <= screen->vk_version) {
info->feats${version.struct()}.sType = ${version.stype("FEATURES")};
info->feats${version.struct()}.pNext = info->feats.pNext;
info->feats.pNext = &info->feats${version.struct()};
@@ -336,7 +332,7 @@ zink_get_physical_device_info(struct zink_screen *screen)
props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
%for version in versions:
if (${version.version()} <= info->device_version) {
if (${version.version()} <= screen->vk_version) {
info->props${version.struct()}.sType = ${version.stype("PROPERTIES")};
info->props${version.struct()}.pNext = props.pNext;
props.pNext = &info->props${version.struct()};

View File

@@ -133,21 +133,10 @@ zink_create_instance(struct zink_instance_info *instance_info)
if (vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extension_props) == VK_SUCCESS) {
for (uint32_t i = 0; i < extension_count; i++) {
%for ext in extensions:
%if not ext.core_since:
if (!strcmp(extension_props[i].extensionName, ${ext.extension_name_literal()})) {
have_${ext.name_with_vendor()} = true;
extensions[num_extensions++] = ${ext.extension_name_literal()};
}
%else:
if (instance_info->loader_version < ${ext.core_since.version()}) {
if (!strcmp(extension_props[i].extensionName, ${ext.extension_name_literal()})) {
have_${ext.name_with_vendor()} = true;
extensions[num_extensions++] = ${ext.extension_name_literal()};
}
} else {
have_${ext.name_with_vendor()} = true;
}
%endif
%endfor
}
}
@@ -213,7 +202,7 @@ zink_create_instance(struct zink_instance_info *instance_info)
ai.pApplicationName = "unknown";
ai.pEngineName = "mesa zink";
ai.apiVersion = VK_MAKE_VERSION(1, 0, 0);
ai.apiVersion = instance_info->loader_version;
VkInstanceCreateInfo ici = {};
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@@ -248,10 +237,11 @@ zink_load_instance_extensions(struct zink_screen *screen)
}
%elif bool(ext.instance_funcs):
if (screen->instance_info.have_${ext.name_with_vendor()}) {
if (screen->instance_info.loader_version < ${ext.core_since.version()}) {
if (screen->vk_version < ${ext.core_since.version()}) {
%for func in ext.instance_funcs:
GET_PROC_ADDR_INSTANCE_LOCAL(screen->instance, ${func}${ext.vendor()});
screen->vk_${func} = vk_${func}${ext.vendor()};
if (!screen->vk_${func}) return false;
%endfor
} else {
%for func in ext.instance_funcs:
@@ -318,6 +308,9 @@ if __name__ == "__main__":
error_count += 1
print("The instance function {} is not added by the extension {}.".format(func, ext.name))
if entry.promoted_in:
ext.core_since = Version((*entry.promoted_in, 0))
if error_count > 0:
print("zink_instance.py: Found {} error(s) in total. Quitting.".format(error_count))
exit(1)

View File

@@ -852,43 +852,47 @@ zink_destroy_screen(struct pipe_screen *pscreen)
FREE(screen);
}
static VkPhysicalDevice
choose_pdev(const VkInstance instance)
static void
choose_pdev(struct zink_screen *screen)
{
uint32_t i, pdev_count;
VkPhysicalDevice *pdevs, pdev = NULL;
VkResult result = vkEnumeratePhysicalDevices(instance, &pdev_count, NULL);
VkPhysicalDevice *pdevs;
VkResult result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, NULL);
if (result != VK_SUCCESS)
return VK_NULL_HANDLE;
return;
assert(pdev_count > 0);
pdevs = malloc(sizeof(*pdevs) * pdev_count);
result = vkEnumeratePhysicalDevices(instance, &pdev_count, pdevs);
result = vkEnumeratePhysicalDevices(screen->instance, &pdev_count, pdevs);
assert(result == VK_SUCCESS);
assert(pdev_count > 0);
VkPhysicalDeviceProperties *props = &screen->info.props;
for (i = 0; i < pdev_count; ++i) {
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(pdevs[i], &props);
vkGetPhysicalDeviceProperties(pdevs[i], props);
#ifdef ZINK_WITH_SWRAST_VK
char *use_lavapipe = getenv("ZINK_USE_LAVAPIPE");
if (use_lavapipe) {
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
pdev = pdevs[i];
if (props->deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
screen->pdev = pdevs[i];
screen->info.device_version = props->apiVersion;
break;
} else
continue;
}
continue;
}
#endif
if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) {
pdev = pdevs[i];
if (props->deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) {
screen->pdev = pdevs[i];
screen->info.device_version = props->apiVersion;
break;
}
}
free(pdevs);
return pdev;
/* runtime version is the lesser of the instance version and device version */
screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version);
}
static void
@@ -1260,13 +1264,10 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
if (!screen->instance)
goto fail;
if (!zink_load_instance_extensions(screen))
goto fail;
if (screen->instance_info.have_EXT_debug_utils && !create_debug(screen))
debug_printf("ZINK: failed to setup debug utils\n");
screen->pdev = choose_pdev(screen->instance);
choose_pdev(screen);
if (screen->pdev == VK_NULL_HANDLE)
goto fail;
@@ -1277,6 +1278,9 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
screen->have_D24_UNORM_S8_UINT = zink_is_depth_format_supported(screen,
VK_FORMAT_D24_UNORM_S8_UINT);
if (!zink_load_instance_extensions(screen))
goto fail;
if (!zink_get_physical_device_info(screen)) {
debug_printf("ZINK: failed to detect features\n");
goto fail;

View File

@@ -66,6 +66,7 @@ struct zink_screen {
struct zink_instance_info instance_info;
VkPhysicalDevice pdev;
uint32_t vk_version;
struct zink_device_info info;
struct nir_shader_compiler_options nir_options;