winevulkan: Implement device extension enumeration.
Signed-off-by: Roderick Colenbrander <thunderbird2k@gmail.com> Signed-off-by: Józef Kucia <jkucia@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
01abc2f8d2
commit
a7159e7c6a
|
@ -1803,6 +1803,26 @@ class VkGenerator(object):
|
||||||
f.write(" }\n")
|
f.write(" }\n")
|
||||||
f.write(" }\n")
|
f.write(" }\n")
|
||||||
f.write(" return NULL;\n")
|
f.write(" return NULL;\n")
|
||||||
|
f.write("}\n\n")
|
||||||
|
|
||||||
|
# Create array of device extensions.
|
||||||
|
f.write("static const char * const vk_device_extensions[] =\n{\n")
|
||||||
|
for ext in self.registry.extensions:
|
||||||
|
if ext["type"] != "device":
|
||||||
|
continue
|
||||||
|
|
||||||
|
f.write(" \"{0}\",\n".format(ext["name"]))
|
||||||
|
f.write("};\n\n")
|
||||||
|
|
||||||
|
f.write("BOOL wine_vk_device_extension_supported(const char *name)\n")
|
||||||
|
f.write("{\n")
|
||||||
|
f.write(" unsigned int i;\n")
|
||||||
|
f.write(" for (i = 0; i < ARRAY_SIZE(vk_device_extensions); i++)\n")
|
||||||
|
f.write(" {\n")
|
||||||
|
f.write(" if (strcmp(vk_device_extensions[i], name) == 0)\n")
|
||||||
|
f.write(" return TRUE;\n")
|
||||||
|
f.write(" }\n")
|
||||||
|
f.write(" return FALSE;\n")
|
||||||
f.write("}\n")
|
f.write("}\n")
|
||||||
|
|
||||||
def generate_thunks_h(self, f, prefix):
|
def generate_thunks_h(self, f, prefix):
|
||||||
|
@ -1820,6 +1840,8 @@ class VkGenerator(object):
|
||||||
f.write("void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;\n")
|
f.write("void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;\n")
|
||||||
f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
|
f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
|
||||||
|
|
||||||
|
f.write("BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;\n\n")
|
||||||
|
|
||||||
# Generate prototypes for device and instance functions requiring a custom implementation.
|
# Generate prototypes for device and instance functions requiring a custom implementation.
|
||||||
f.write("/* Functions for which we have custom implementations outside of the thunks. */\n")
|
f.write("/* Functions for which we have custom implementations outside of the thunks. */\n")
|
||||||
for vk_func in self.registry.funcs.values():
|
for vk_func in self.registry.funcs.values():
|
||||||
|
|
|
@ -46,6 +46,9 @@ struct wine_vk_structure_header
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *wine_vk_get_global_proc_addr(const char *name);
|
static void *wine_vk_get_global_proc_addr(const char *name);
|
||||||
|
static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstance_T *instance,
|
||||||
|
VkPhysicalDevice phys_dev_host);
|
||||||
|
static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev);
|
||||||
|
|
||||||
static const struct vulkan_funcs *vk_funcs = NULL;
|
static const struct vulkan_funcs *vk_funcs = NULL;
|
||||||
|
|
||||||
|
@ -170,7 +173,7 @@ static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *inst
|
||||||
/* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
|
/* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
|
||||||
for (i = 0; i < num_phys_devs; i++)
|
for (i = 0; i < num_phys_devs; i++)
|
||||||
{
|
{
|
||||||
struct VkPhysicalDevice_T *phys_dev = heap_alloc(sizeof(*phys_dev));
|
struct VkPhysicalDevice_T *phys_dev = wine_vk_physical_device_alloc(instance, tmp_phys_devs[i]);
|
||||||
if (!phys_dev)
|
if (!phys_dev)
|
||||||
{
|
{
|
||||||
ERR("Unable to allocate memory for physical device!\n");
|
ERR("Unable to allocate memory for physical device!\n");
|
||||||
|
@ -178,10 +181,6 @@ static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *inst
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_dev->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
|
|
||||||
phys_dev->instance = instance;
|
|
||||||
phys_dev->phys_dev = tmp_phys_devs[i];
|
|
||||||
|
|
||||||
instance->phys_devs[i] = phys_dev;
|
instance->phys_devs[i] = phys_dev;
|
||||||
instance->num_phys_devs = i + 1;
|
instance->num_phys_devs = i + 1;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +191,6 @@ static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *inst
|
||||||
|
|
||||||
err:
|
err:
|
||||||
heap_free(tmp_phys_devs);
|
heap_free(tmp_phys_devs);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +208,7 @@ static void wine_vk_instance_free(struct VkInstance_T *instance)
|
||||||
|
|
||||||
for (i = 0; i < instance->num_phys_devs; i++)
|
for (i = 0; i < instance->num_phys_devs; i++)
|
||||||
{
|
{
|
||||||
heap_free(&instance->phys_devs[i]);
|
wine_vk_physical_device_free(instance->phys_devs[i]);
|
||||||
}
|
}
|
||||||
heap_free(instance->phys_devs);
|
heap_free(instance->phys_devs);
|
||||||
}
|
}
|
||||||
|
@ -221,6 +219,99 @@ static void wine_vk_instance_free(struct VkInstance_T *instance)
|
||||||
heap_free(instance);
|
heap_free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstance_T *instance,
|
||||||
|
VkPhysicalDevice phys_dev)
|
||||||
|
{
|
||||||
|
struct VkPhysicalDevice_T *object;
|
||||||
|
uint32_t num_host_properties, num_properties = 0;
|
||||||
|
VkExtensionProperties *host_properties = NULL;
|
||||||
|
VkResult res;
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
object = heap_alloc_zero(sizeof(*object));
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
|
||||||
|
object->instance = instance;
|
||||||
|
object->phys_dev = phys_dev;
|
||||||
|
|
||||||
|
res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev,
|
||||||
|
NULL, &num_host_properties, NULL);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Failed to enumerate device extensions, res=%d\n", res);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
host_properties = heap_calloc(num_host_properties, sizeof(*host_properties));
|
||||||
|
if (!host_properties)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate memory for device properties!\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev,
|
||||||
|
NULL, &num_host_properties, host_properties);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Failed to enumerate device extensions, res=%d\n", res);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count list of extensions for which we have an implementation.
|
||||||
|
* TODO: perform translation for platform specific extensions.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < num_host_properties; i++)
|
||||||
|
{
|
||||||
|
if (wine_vk_device_extension_supported(host_properties[i].extensionName))
|
||||||
|
{
|
||||||
|
TRACE("Enabling extension '%s' for physical device %p\n", host_properties[i].extensionName, object);
|
||||||
|
num_properties++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties[i].extensionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties, num_properties);
|
||||||
|
|
||||||
|
object->properties = heap_calloc(num_properties, sizeof(*object->properties));
|
||||||
|
if (!object->properties)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate memory for device properties!\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < num_host_properties; i++)
|
||||||
|
{
|
||||||
|
if (wine_vk_device_extension_supported(host_properties[i].extensionName))
|
||||||
|
{
|
||||||
|
memcpy(&object->properties[j], &host_properties[i], sizeof(*object->properties));
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object->num_properties = num_properties;
|
||||||
|
|
||||||
|
heap_free(host_properties);
|
||||||
|
return object;
|
||||||
|
|
||||||
|
err:
|
||||||
|
wine_vk_physical_device_free(object);
|
||||||
|
heap_free(host_properties);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wine_vk_physical_device_free(struct VkPhysicalDevice_T *phys_dev)
|
||||||
|
{
|
||||||
|
if (!phys_dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heap_free(phys_dev->properties);
|
||||||
|
heap_free(phys_dev);
|
||||||
|
}
|
||||||
|
|
||||||
VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
|
VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain,
|
||||||
uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
|
uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *image_index)
|
||||||
{
|
{
|
||||||
|
@ -460,6 +551,9 @@ void WINAPI wine_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain
|
||||||
VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev,
|
VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev,
|
||||||
const char *layer_name, uint32_t *count, VkExtensionProperties *properties)
|
const char *layer_name, uint32_t *count, VkExtensionProperties *properties)
|
||||||
{
|
{
|
||||||
|
VkResult res;
|
||||||
|
unsigned int i, num_copies;
|
||||||
|
|
||||||
TRACE("%p, %p, %p, %p\n", phys_dev, layer_name, count, properties);
|
TRACE("%p, %p, %p, %p\n", phys_dev, layer_name, count, properties);
|
||||||
|
|
||||||
/* This shouldn't get called with layer_name set, the ICD loader prevents it. */
|
/* This shouldn't get called with layer_name set, the ICD loader prevents it. */
|
||||||
|
@ -471,16 +565,32 @@ VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_
|
||||||
|
|
||||||
if (!properties)
|
if (!properties)
|
||||||
{
|
{
|
||||||
*count = 0; /* No extensions yet. */
|
*count = phys_dev->num_properties;
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When properties is not NULL, we copy the extensions over and set count to
|
if (*count < phys_dev->num_properties)
|
||||||
* the number of copied extensions. For now we don't have much to do as we don't support
|
{
|
||||||
* any extensions yet.
|
/* Incomplete is a type of success used to signal the application
|
||||||
|
* that not all devices got copied.
|
||||||
*/
|
*/
|
||||||
*count = 0;
|
num_copies = *count;
|
||||||
return VK_SUCCESS;
|
res = VK_INCOMPLETE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
num_copies = phys_dev->num_properties;
|
||||||
|
res = VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_copies; i++)
|
||||||
|
{
|
||||||
|
memcpy(&properties[i], &phys_dev->properties[i], sizeof(phys_dev->properties[i]));
|
||||||
|
}
|
||||||
|
*count = num_copies;
|
||||||
|
|
||||||
|
TRACE("Result %d, extensions copied %u\n", res, num_copies);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkResult WINAPI wine_vkEnumerateInstanceExtensionProperties(const char *layer_name,
|
static VkResult WINAPI wine_vkEnumerateInstanceExtensionProperties(const char *layer_name,
|
||||||
|
|
|
@ -74,6 +74,10 @@ struct VkPhysicalDevice_T
|
||||||
{
|
{
|
||||||
struct wine_vk_base base;
|
struct wine_vk_base base;
|
||||||
struct VkInstance_T *instance; /* parent */
|
struct VkInstance_T *instance; /* parent */
|
||||||
|
|
||||||
|
uint32_t num_properties;
|
||||||
|
VkExtensionProperties *properties;
|
||||||
|
|
||||||
VkPhysicalDevice phys_dev; /* native physical device */
|
VkPhysicalDevice phys_dev; /* native physical device */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1073,3 +1073,19 @@ void *wine_vk_get_instance_proc_addr(const char *name)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char * const vk_device_extensions[] =
|
||||||
|
{
|
||||||
|
"VK_KHR_swapchain",
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL wine_vk_device_extension_supported(const char *name)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(vk_device_extensions); i++)
|
||||||
|
{
|
||||||
|
if (strcmp(vk_device_extensions[i], name) == 0)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;
|
void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;
|
||||||
void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
|
void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Functions for which we have custom implementations outside of the thunks. */
|
/* Functions for which we have custom implementations outside of the thunks. */
|
||||||
VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) DECLSPEC_HIDDEN;
|
VkResult WINAPI wine_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) DECLSPEC_HIDDEN;
|
||||||
VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN;
|
VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue