render/vulkan: relax minimum Vulkan API version to 1.0

This allows using the vulkan renderer on platforms that provide all
the necessary Vulkan extensions.

Tested on a Mali G52 platform with Mesa 26.0.0 and 25.3.5, which only
support Vulkan API 1.0.
This commit is contained in:
hrdl 2026-02-19 20:18:16 +00:00
parent 67ce318b1f
commit 3dafaa4df3
4 changed files with 32 additions and 32 deletions

View file

@ -56,6 +56,10 @@ struct wlr_vk_device {
PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR;
PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR;
PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
} api;
uint32_t format_prop_count;

View file

@ -1188,7 +1188,7 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
vkDestroyPipelineLayout(dev->dev, pipeline_layout->vk, NULL);
vkDestroyDescriptorSetLayout(dev->dev, pipeline_layout->ds, NULL);
vkDestroySampler(dev->dev, pipeline_layout->sampler, NULL);
vkDestroySamplerYcbcrConversion(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
renderer->dev->api.vkDestroySamplerYcbcrConversionKHR(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
free(pipeline_layout);
}
@ -2049,10 +2049,10 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
.chromaFilter = VK_FILTER_LINEAR,
};
res = vkCreateSamplerYcbcrConversion(renderer->dev->dev,
res = renderer->dev->api.vkCreateSamplerYcbcrConversionKHR(renderer->dev->dev,
&conversion_create_info, NULL, &pipeline_layout->ycbcr.conversion);
if (res != VK_SUCCESS) {
wlr_vk_error("vkCreateSamplerYcbcrConversion", res);
wlr_vk_error("vkCreateSamplerYcbcrConversionKHR", res);
free(pipeline_layout);
return NULL;
}

View file

@ -653,7 +653,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
};
vkGetImageMemoryRequirements2(dev, &memri, &memr);
renderer->dev->api.vkGetImageMemoryRequirements2KHR(dev, &memri, &memr);
int mem = vulkan_find_mem_type(renderer->dev, 0,
memr.memoryRequirements.memoryTypeBits & fdp.memoryTypeBits);
if (mem < 0) {
@ -712,7 +712,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
}
}
res = vkBindImageMemory2(dev, mem_count, bindi);
res = renderer->dev->api.vkBindImageMemory2KHR(dev, mem_count, bindi);
if (res != VK_SUCCESS) {
wlr_vk_error("vkBindMemory failed", res);
goto error_image;

View file

@ -81,21 +81,6 @@ static VKAPI_ATTR VkBool32 debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT
}
struct wlr_vk_instance *vulkan_instance_create(bool debug) {
// we require vulkan 1.1
PFN_vkEnumerateInstanceVersion pfEnumInstanceVersion =
(PFN_vkEnumerateInstanceVersion)
vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion");
if (!pfEnumInstanceVersion) {
wlr_log(WLR_ERROR, "wlroots requires vulkan 1.1 which is not available");
return NULL;
}
uint32_t ini_version;
if (pfEnumInstanceVersion(&ini_version) != VK_SUCCESS ||
ini_version < VK_API_VERSION_1_1) {
wlr_log(WLR_ERROR, "wlroots requires vulkan 1.1 which is not available");
return NULL;
}
uint32_t avail_extc = 0;
VkResult res;
@ -125,7 +110,18 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
}
size_t extensions_len = 0;
const char *extensions[1] = {0};
const char *extensions[8] = {0};
extensions[extensions_len++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
extensions[extensions_len++] = VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME;
extensions[extensions_len++] = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME;
for (size_t i = 0; i < extensions_len; i++) {
if (!check_extension(avail_ext_props, avail_extc, extensions[i])) {
wlr_log(WLR_ERROR, "vulkan: required instance extension %s not found",
extensions[i]);
goto error;
}
}
bool debug_utils_found = false;
if (debug && check_extension(avail_ext_props, avail_extc,
@ -140,7 +136,7 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pEngineName = "wlroots",
.engineVersion = WLR_VERSION_NUM,
.apiVersion = VK_API_VERSION_1_1,
.apiVersion = VK_API_VERSION_1_0,
};
VkInstanceCreateInfo instance_info = {
@ -282,20 +278,10 @@ VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd)
for (uint32_t i = 0; i < num_phdevs; ++i) {
VkPhysicalDevice phdev = phdevs[i];
// check whether device supports vulkan 1.1, needed for
// vkGetPhysicalDeviceProperties2
VkPhysicalDeviceProperties phdev_props;
vkGetPhysicalDeviceProperties(phdev, &phdev_props);
log_phdev(&phdev_props);
if (phdev_props.apiVersion < VK_API_VERSION_1_1) {
// NOTE: we could additionally check whether the
// VkPhysicalDeviceProperties2KHR extension is supported but
// implementations not supporting 1.1 are unlikely in future
continue;
}
// check for extensions
uint32_t avail_extc = 0;
res = vkEnumerateDeviceExtensionProperties(phdev, NULL,
@ -474,6 +460,12 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
extensions[extensions_len++] = VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME;
extensions[extensions_len++] = VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME; // or vulkan 1.2
extensions[extensions_len++] = VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME; // or vulkan 1.3
extensions[extensions_len++] = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME; // or vulkan 1.1
extensions[extensions_len++] = VK_KHR_BIND_MEMORY_2_EXTENSION_NAME; // or vulkan 1.1
extensions[extensions_len++] = VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME; // or vulkan 1.1
extensions[extensions_len++] = VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME; // or vulkan 1.1
extensions[extensions_len++] = VK_KHR_MAINTENANCE_1_EXTENSION_NAME; // or vulkan 1.1
extensions[extensions_len++] = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME; // or vulkan 1.1
for (size_t i = 0; i < extensions_len; i++) {
if (!check_extension(avail_ext_props, avail_extc, extensions[i])) {
@ -630,6 +622,10 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
load_device_proc(dev, "vkGetSemaphoreCounterValueKHR",
&dev->api.vkGetSemaphoreCounterValueKHR);
load_device_proc(dev, "vkQueueSubmit2KHR", &dev->api.vkQueueSubmit2KHR);
load_device_proc(dev, "vkBindImageMemory2KHR", &dev->api.vkBindImageMemory2KHR);
load_device_proc(dev, "vkCreateSamplerYcbcrConversionKHR", &dev->api.vkCreateSamplerYcbcrConversionKHR);
load_device_proc(dev, "vkDestroySamplerYcbcrConversionKHR", &dev->api.vkDestroySamplerYcbcrConversionKHR);
load_device_proc(dev, "vkGetImageMemoryRequirements2KHR", &dev->api.vkGetImageMemoryRequirements2KHR);
if (has_external_semaphore_fd) {
load_device_proc(dev, "vkGetSemaphoreFdKHR", &dev->api.vkGetSemaphoreFdKHR);