winevulkan: Add instance funcs stubs.
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
75b68a8585
commit
586a18995f
|
@ -2,6 +2,7 @@ MODULE = winevulkan.dll
|
|||
IMPORTS = user32 gdi32
|
||||
|
||||
C_SRCS = \
|
||||
vulkan.c
|
||||
vulkan.c \
|
||||
vulkan_thunks.c
|
||||
|
||||
RC_SRCS = version.rc
|
||||
|
|
|
@ -65,6 +65,8 @@ LOGGER.addHandler(logging.StreamHandler())
|
|||
# Filenames to create.
|
||||
WINE_VULKAN_H = "../../include/wine/vulkan.h"
|
||||
WINE_VULKAN_DRIVER_H = "../../include/wine/vulkan_driver.h"
|
||||
WINE_VULKAN_THUNKS_C = "vulkan_thunks.c"
|
||||
WINE_VULKAN_THUNKS_H = "vulkan_thunks.h"
|
||||
|
||||
|
||||
# Functions part of our winevulkan graphics driver interface.
|
||||
|
@ -76,15 +78,18 @@ DRIVER_VERSION = 1
|
|||
# This are regular device / instance functions for which we need
|
||||
# to more work compared to a regular thunk or because they are
|
||||
# part of the driver interface.
|
||||
# - dispatch set whether we need a function pointer in the device
|
||||
# / instance dispatch table.
|
||||
# - driver sets whether the api is part of the driver interface.
|
||||
# - thunk sets whether to create a thunk in vulkan_thunks.c.
|
||||
FUNCTION_OVERRIDES = {
|
||||
# Global functions
|
||||
"vkCreateInstance" : {"driver" : True},
|
||||
"vkEnumerateInstanceExtensionProperties" : {"driver" : True},
|
||||
"vkGetInstanceProcAddr": {"driver" : True},
|
||||
"vkCreateInstance" : {"dispatch" : False, "driver" : True, "thunk" : False},
|
||||
"vkEnumerateInstanceExtensionProperties" : {"dispatch" : False, "driver" : True, "thunk" : False},
|
||||
"vkGetInstanceProcAddr": {"dispatch" : False, "driver" : True, "thunk" : False},
|
||||
|
||||
# Instance functions
|
||||
"vkDestroyInstance" : {"driver" : True},
|
||||
"vkDestroyInstance" : {"dispatch" : True, "driver" : True, "thunk" : True },
|
||||
}
|
||||
|
||||
|
||||
|
@ -256,7 +261,9 @@ class VkFunction(object):
|
|||
|
||||
# For some functions we need some extra metadata from FUNCTION_OVERRIDES.
|
||||
func_info = FUNCTION_OVERRIDES.get(self.name, None)
|
||||
self.dispatch = func_info["dispatch"] if func_info is not None else True
|
||||
self.driver = func_info["driver"] if func_info is not None else False
|
||||
self.thunk_needed = func_info["thunk"] if func_info is not None else True
|
||||
|
||||
# Required is set while parsing which APIs and types are required
|
||||
# and is used by the code generation.
|
||||
|
@ -303,6 +310,12 @@ class VkFunction(object):
|
|||
def is_required(self):
|
||||
return self.required
|
||||
|
||||
def needs_dispatch(self):
|
||||
return self.dispatch
|
||||
|
||||
def needs_thunk(self):
|
||||
return self.thunk_needed
|
||||
|
||||
def pfn(self, call_conv=None, conv=False):
|
||||
""" Create function pointer. """
|
||||
|
||||
|
@ -359,6 +372,48 @@ class VkFunction(object):
|
|||
|
||||
return proto
|
||||
|
||||
def stub(self, call_conv=None, prefix=None):
|
||||
stub = self.prototype(call_conv=call_conv, prefix=prefix)
|
||||
stub += "\n{\n"
|
||||
stub += " {0}".format(self.trace(message="stub: ", trace_func="FIXME"))
|
||||
|
||||
if self.type == "VkResult":
|
||||
stub += " return VK_ERROR_OUT_OF_HOST_MEMORY;\n"
|
||||
elif self.type == "VkBool32":
|
||||
stub += " return VK_FALSE;\n"
|
||||
|
||||
stub += "}\n\n"
|
||||
return stub
|
||||
|
||||
def trace(self, message=None, trace_func=None):
|
||||
""" Create a trace string including all parameters.
|
||||
|
||||
Args:
|
||||
message (str, optional): text to print at start of trace message e.g. 'stub: '
|
||||
trace_func (str, optional): used to override trace function e.g. FIXME, printf, etcetera.
|
||||
"""
|
||||
if trace_func is not None:
|
||||
trace = "{0}(\"".format(trace_func)
|
||||
else:
|
||||
trace = "TRACE(\""
|
||||
|
||||
if message is not None:
|
||||
trace += message
|
||||
|
||||
# First loop is for all the format strings.
|
||||
trace += ", ".join([p.format_string() for p in self.params])
|
||||
trace += "\\n\""
|
||||
|
||||
# Second loop for parameter names and optional conversions.
|
||||
for param in self.params:
|
||||
if param.format_conv is not None:
|
||||
trace += ", " + param.format_conv.format(param.name)
|
||||
else:
|
||||
trace += ", {0}".format(param.name)
|
||||
trace += ");\n"
|
||||
|
||||
return trace
|
||||
|
||||
|
||||
class VkFunctionPointer(object):
|
||||
def __init__(self, _type, name, members):
|
||||
|
@ -628,6 +683,8 @@ class VkParam(object):
|
|||
self.handle = type_info["data"] if type_info["category"] == "handle" else None
|
||||
self.struct = type_info["data"] if type_info["category"] == "struct" else None
|
||||
|
||||
self._set_format_string()
|
||||
|
||||
def __repr__(self):
|
||||
return "{0} {1} {2} {3} {4}".format(self.const, self.type, self.pointer, self.name, self.array_len, self.dyn_array_len)
|
||||
|
||||
|
@ -663,6 +720,49 @@ class VkParam(object):
|
|||
|
||||
return VkParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len)
|
||||
|
||||
def _set_format_string(self):
|
||||
""" Internal helper function to be used by constructor to set format string. """
|
||||
|
||||
# Determine a format string used by code generation for traces.
|
||||
# 64-bit types need a conversion function.
|
||||
self.format_conv = None
|
||||
if self.is_static_array() or self.is_pointer():
|
||||
self.format_str = "%p"
|
||||
else:
|
||||
if self.type_info["category"] == "bitmask":
|
||||
self.format_str = "%#x"
|
||||
elif self.type_info["category"] == "enum":
|
||||
self.format_str = "%d"
|
||||
elif self.is_handle():
|
||||
# We use uint64_t for non-dispatchable handles as opposed to pointers
|
||||
# for dispatchable handles.
|
||||
if self.handle.is_dispatchable():
|
||||
self.format_str = "%p"
|
||||
else:
|
||||
self.format_str = "0x%s"
|
||||
self.format_conv = "wine_dbgstr_longlong({0})"
|
||||
elif self.type == "float":
|
||||
self.format_str = "%f"
|
||||
elif self.type == "int":
|
||||
self.format_str = "%d"
|
||||
elif self.type == "int32_t":
|
||||
self.format_str = "%d"
|
||||
elif self.type == "size_t":
|
||||
self.format_str = "0x%s"
|
||||
self.format_conv = "wine_dbgstr_longlong({0})"
|
||||
elif self.type in ["uint32_t", "VkBool32"]:
|
||||
self.format_str = "%u"
|
||||
elif self.type in ["uint64_t", "VkDeviceSize"]:
|
||||
self.format_str = "0x%s"
|
||||
self.format_conv = "wine_dbgstr_longlong({0})"
|
||||
elif self.type == "HANDLE":
|
||||
self.format_str = "%p"
|
||||
elif self.type in ["VisualID", "xcb_visualid_t", "RROutput"]:
|
||||
# Don't care about Linux specific types.
|
||||
self.format_str = ""
|
||||
else:
|
||||
LOGGER.warn("Unhandled type: {0}".format(self.type_info))
|
||||
|
||||
def definition(self, postfix=None):
|
||||
""" Return prototype for the parameter. E.g. 'const char *foo' """
|
||||
|
||||
|
@ -687,6 +787,17 @@ class VkParam(object):
|
|||
|
||||
return proto
|
||||
|
||||
def direction(self):
|
||||
""" Returns parameter direction: input, output, input_output.
|
||||
|
||||
Parameter direction in Vulkan is not straight-forward, which this function determines.
|
||||
"""
|
||||
|
||||
return self._direction
|
||||
|
||||
def format_string(self):
|
||||
return self.format_str
|
||||
|
||||
def is_const(self):
|
||||
return self.const is not None
|
||||
|
||||
|
@ -854,6 +965,75 @@ class VkGenerator(object):
|
|||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
|
||||
def generate_thunks_c(self, f, prefix):
|
||||
f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
|
||||
|
||||
f.write("#include \"config.h\"\n")
|
||||
f.write("#include \"wine/port.h\"\n\n")
|
||||
|
||||
f.write("#include \"wine/debug.h\"\n")
|
||||
f.write("#include \"wine/vulkan.h\"\n")
|
||||
f.write("#include \"wine/vulkan_driver.h\"\n")
|
||||
f.write("#include \"vulkan_private.h\"\n\n")
|
||||
|
||||
f.write("WINE_DEFAULT_DEBUG_CHANNEL(vulkan);\n\n")
|
||||
|
||||
# Create thunks for instance functions.
|
||||
# Global functions don't go through the thunks.
|
||||
for vk_func in self.registry.funcs.values():
|
||||
if not vk_func.is_required():
|
||||
continue
|
||||
|
||||
if vk_func.is_global_func():
|
||||
continue
|
||||
|
||||
# We don't support device functions yet as other plumbing
|
||||
# is needed first.
|
||||
if vk_func.is_device_func():
|
||||
continue
|
||||
|
||||
if not vk_func.needs_thunk():
|
||||
continue
|
||||
|
||||
f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
|
||||
|
||||
f.write("static const struct vulkan_func vk_instance_dispatch_table[] =\n{\n")
|
||||
for vk_func in self.registry.instance_funcs:
|
||||
if not vk_func.is_required():
|
||||
continue
|
||||
|
||||
if not vk_func.needs_dispatch():
|
||||
LOGGER.debug("skipping {0} in instance dispatch table".format(vk_func.name))
|
||||
continue
|
||||
|
||||
f.write(" {{\"{0}\", &{1}{0}}},\n".format(vk_func.name, prefix))
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("void *wine_vk_get_instance_proc_addr(const char *name)\n")
|
||||
f.write("{\n")
|
||||
f.write(" unsigned int i;\n")
|
||||
f.write(" for (i = 0; i < ARRAY_SIZE(vk_instance_dispatch_table); i++)\n")
|
||||
f.write(" {\n")
|
||||
f.write(" if (strcmp(vk_instance_dispatch_table[i].name, name) == 0)\n")
|
||||
f.write(" {\n")
|
||||
f.write(" TRACE(\"Found pName=%s in instance table\\n\", name);\n")
|
||||
f.write(" return vk_instance_dispatch_table[i].func;\n")
|
||||
f.write(" }\n")
|
||||
f.write(" }\n")
|
||||
f.write(" return NULL;\n")
|
||||
f.write("}\n")
|
||||
|
||||
def generate_thunks_h(self, f, prefix):
|
||||
f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
|
||||
|
||||
f.write("#ifndef __WINE_VULKAN_THUNKS_H\n")
|
||||
f.write("#define __WINE_VULKAN_THUNKS_H\n\n")
|
||||
|
||||
f.write("/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */\n")
|
||||
f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
|
||||
|
||||
f.write("#endif /* __WINE_VULKAN_THUNKS_H */\n")
|
||||
|
||||
def generate_vulkan_h(self, f):
|
||||
f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
|
||||
f.write("#ifndef __WINE_VULKAN_H\n")
|
||||
|
@ -1245,5 +1425,11 @@ def main():
|
|||
with open(WINE_VULKAN_DRIVER_H, "w") as f:
|
||||
generator.generate_vulkan_driver_h(f)
|
||||
|
||||
with open(WINE_VULKAN_THUNKS_H, "w") as f:
|
||||
generator.generate_thunks_h(f, "wine_")
|
||||
|
||||
with open(WINE_VULKAN_THUNKS_C, "w") as f:
|
||||
generator.generate_thunks_c(f, "wine_")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -38,16 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
|
|||
*/
|
||||
#define WINE_VULKAN_ICD_VERSION 4
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
struct vulkan_func
|
||||
{
|
||||
const char *name;
|
||||
void *func;
|
||||
};
|
||||
|
||||
static void *wine_vk_get_global_proc_addr(const char *name);
|
||||
|
||||
static const struct vulkan_funcs *vk_funcs = NULL;
|
||||
|
@ -148,6 +138,9 @@ static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
func = wine_vk_get_instance_proc_addr(name);
|
||||
if (func) return func;
|
||||
|
||||
FIXME("Unsupported device or instance function: '%s'\n", debugstr_a(name));
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,21 @@
|
|||
#ifndef __WINE_VULKAN_PRIVATE_H
|
||||
#define __WINE_VULKAN_PRIVATE_H
|
||||
|
||||
#include "vulkan_thunks.h"
|
||||
|
||||
/* Magic value defined by Vulkan ICD / Loader spec */
|
||||
#define VULKAN_ICD_MAGIC_VALUE 0x01CDC0DE
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
struct vulkan_func
|
||||
{
|
||||
const char *name;
|
||||
void *func;
|
||||
};
|
||||
|
||||
/* Base 'class' for our Vulkan dispatchable objects such as VkDevice and VkInstance.
|
||||
* This structure MUST be the first element of a dispatchable object as the ICD
|
||||
* loader depends on it. For now only contains loader_magic, but over time more common
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */
|
||||
|
||||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/vulkan.h"
|
||||
#include "wine/vulkan_driver.h"
|
||||
#include "vulkan_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
|
||||
|
||||
static VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p, %p\n", physicalDevice, pCreateInfo, pAllocator, pDevice);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
FIXME("stub: %p, %p\n", instance, pAllocator);
|
||||
}
|
||||
|
||||
static VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p, %p\n", physicalDevice, pLayerName, pPropertyCount, pProperties);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
static VkResult WINAPI wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p\n", physicalDevice, pPropertyCount, pProperties);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
static VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p\n", instance, pPhysicalDeviceCount, pPhysicalDevices);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
|
||||
{
|
||||
FIXME("stub: %p, %p\n", physicalDevice, pFeatures);
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties)
|
||||
{
|
||||
FIXME("stub: %p, %d, %p\n", physicalDevice, format, pFormatProperties);
|
||||
}
|
||||
|
||||
static VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties)
|
||||
{
|
||||
FIXME("stub: %p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties)
|
||||
{
|
||||
FIXME("stub: %p, %p\n", physicalDevice, pMemoryProperties);
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
|
||||
{
|
||||
FIXME("stub: %p, %p\n", physicalDevice, pProperties);
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
|
||||
}
|
||||
|
||||
static void WINAPI wine_vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties)
|
||||
{
|
||||
FIXME("stub: %p, %d, %d, %d, %#x, %d, %p, %p\n", physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
|
||||
}
|
||||
|
||||
static const struct vulkan_func vk_instance_dispatch_table[] =
|
||||
{
|
||||
{"vkCreateDevice", &wine_vkCreateDevice},
|
||||
{"vkDestroyInstance", &wine_vkDestroyInstance},
|
||||
{"vkEnumerateDeviceExtensionProperties", &wine_vkEnumerateDeviceExtensionProperties},
|
||||
{"vkEnumerateDeviceLayerProperties", &wine_vkEnumerateDeviceLayerProperties},
|
||||
{"vkEnumeratePhysicalDevices", &wine_vkEnumeratePhysicalDevices},
|
||||
{"vkGetPhysicalDeviceFeatures", &wine_vkGetPhysicalDeviceFeatures},
|
||||
{"vkGetPhysicalDeviceFormatProperties", &wine_vkGetPhysicalDeviceFormatProperties},
|
||||
{"vkGetPhysicalDeviceImageFormatProperties", &wine_vkGetPhysicalDeviceImageFormatProperties},
|
||||
{"vkGetPhysicalDeviceMemoryProperties", &wine_vkGetPhysicalDeviceMemoryProperties},
|
||||
{"vkGetPhysicalDeviceProperties", &wine_vkGetPhysicalDeviceProperties},
|
||||
{"vkGetPhysicalDeviceQueueFamilyProperties", &wine_vkGetPhysicalDeviceQueueFamilyProperties},
|
||||
{"vkGetPhysicalDeviceSparseImageFormatProperties", &wine_vkGetPhysicalDeviceSparseImageFormatProperties},
|
||||
};
|
||||
|
||||
void *wine_vk_get_instance_proc_addr(const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < ARRAY_SIZE(vk_instance_dispatch_table); i++)
|
||||
{
|
||||
if (strcmp(vk_instance_dispatch_table[i].name, name) == 0)
|
||||
{
|
||||
TRACE("Found pName=%s in instance table\n", name);
|
||||
return vk_instance_dispatch_table[i].func;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */
|
||||
|
||||
#ifndef __WINE_VULKAN_THUNKS_H
|
||||
#define __WINE_VULKAN_THUNKS_H
|
||||
|
||||
/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */
|
||||
void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __WINE_VULKAN_THUNKS_H */
|
Loading…
Reference in New Issue