Commit a7159e7c authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Alexandre Julliard

winevulkan: Implement device extension enumeration.

parent 01abc2f8
......@@ -1803,6 +1803,26 @@ class VkGenerator(object):
f.write(" }\n")
f.write(" }\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")
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_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.
f.write("/* Functions for which we have custom implementations outside of the thunks. */\n")
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 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;
......@@ -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. */
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)
{
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;
}
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->num_phys_devs = i + 1;
}
......@@ -192,7 +191,6 @@ static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *inst
err:
heap_free(tmp_phys_devs);
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++)
{
heap_free(&instance->phys_devs[i]);
wine_vk_physical_device_free(instance->phys_devs[i]);
}
heap_free(instance->phys_devs);
}
......@@ -221,6 +219,99 @@ static void wine_vk_instance_free(struct VkInstance_T *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,
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,
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);
/* 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)
{
*count = 0; /* No extensions yet. */
*count = phys_dev->num_properties;
return VK_SUCCESS;
}
/* When properties is not NULL, we copy the extensions over and set count to
* the number of copied extensions. For now we don't have much to do as we don't support
* any extensions yet.
*/
*count = 0;
return VK_SUCCESS;
if (*count < phys_dev->num_properties)
{
/* Incomplete is a type of success used to signal the application
* that not all devices got copied.
*/
num_copies = *count;
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,
......
......@@ -74,6 +74,10 @@ struct VkPhysicalDevice_T
{
struct wine_vk_base base;
struct VkInstance_T *instance; /* parent */
uint32_t num_properties;
VkExtensionProperties *properties;
VkPhysicalDevice phys_dev; /* native physical device */
};
......
......@@ -1073,3 +1073,19 @@ void *wine_vk_get_instance_proc_addr(const char *name)
}
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_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. */
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment