2 * Copyright 2018 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wine/port.h"
21 #include "wined3d_private.h"
23 #include "wine/vulkan_driver.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
27 #ifdef USE_WIN32_VULKAN
28 static BOOL
wined3d_load_vulkan(struct wined3d_vk_info
*vk_info
)
30 struct vulkan_ops
*vk_ops
= &vk_info
->vk_ops
;
32 if (!(vk_info
->vulkan_lib
= LoadLibraryA("vulkan-1.dll")))
34 WARN("Failed to load vulkan-1.dll.\n");
38 vk_ops
->vkGetInstanceProcAddr
= (void *)GetProcAddress(vk_info
->vulkan_lib
, "vkGetInstanceProcAddr");
39 if (!vk_ops
->vkGetInstanceProcAddr
)
41 FreeLibrary(vk_info
->vulkan_lib
);
48 static void wined3d_unload_vulkan(struct wined3d_vk_info
*vk_info
)
50 if (vk_info
->vulkan_lib
)
52 FreeLibrary(vk_info
->vulkan_lib
);
53 vk_info
->vulkan_lib
= NULL
;
57 static BOOL
wined3d_load_vulkan(struct wined3d_vk_info
*vk_info
)
59 struct vulkan_ops
*vk_ops
= &vk_info
->vk_ops
;
60 const struct vulkan_funcs
*vk_funcs
;
64 vk_funcs
= __wine_get_vulkan_driver(dc
, WINE_VULKAN_DRIVER_VERSION
);
70 vk_ops
->vkGetInstanceProcAddr
= (void *)vk_funcs
->p_vkGetInstanceProcAddr
;
74 static void wined3d_unload_vulkan(struct wined3d_vk_info
*vk_info
) {}
77 static void adapter_vk_destroy(struct wined3d_adapter
*adapter
)
79 struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk(adapter
);
80 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
82 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
83 wined3d_unload_vulkan(vk_info
);
84 wined3d_adapter_cleanup(&adapter_vk
->a
);
85 heap_free(adapter_vk
);
88 static BOOL
adapter_vk_create_context(struct wined3d_context
*context
,
89 struct wined3d_texture
*target
, const struct wined3d_format
*ds_format
)
94 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter
*adapter
, struct wined3d_caps
*caps
)
98 static BOOL
adapter_vk_check_format(const struct wined3d_adapter
*adapter
,
99 const struct wined3d_format
*adapter_format
, const struct wined3d_format
*rt_format
,
100 const struct wined3d_format
*ds_format
)
105 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops
=
108 adapter_vk_create_context
,
109 adapter_vk_get_wined3d_caps
,
110 adapter_vk_check_format
,
113 static unsigned int wined3d_get_wine_vk_version(void)
115 const char *ptr
= PACKAGE_VERSION
;
120 while (isdigit(*ptr
) || *ptr
== '.')
125 return VK_MAKE_VERSION(major
, minor
, 0);
128 static BOOL
wined3d_init_vulkan(struct wined3d_vk_info
*vk_info
)
130 struct vulkan_ops
*vk_ops
= &vk_info
->vk_ops
;
131 VkInstance instance
= VK_NULL_HANDLE
;
132 VkInstanceCreateInfo instance_info
;
133 VkApplicationInfo app_info
;
134 char app_name
[MAX_PATH
];
137 if (!wined3d_load_vulkan(vk_info
))
140 if (!(vk_ops
->vkCreateInstance
= (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkCreateInstance"))))
142 ERR("Could not get 'vkCreateInstance'.\n");
146 memset(&app_info
, 0, sizeof(app_info
));
147 app_info
.sType
= VK_STRUCTURE_TYPE_APPLICATION_INFO
;
148 if (wined3d_get_app_name(app_name
, ARRAY_SIZE(app_name
)))
149 app_info
.pApplicationName
= app_name
;
150 app_info
.pEngineName
= "Damavand";
151 app_info
.engineVersion
= wined3d_get_wine_vk_version();
152 app_info
.apiVersion
= VK_API_VERSION_1_0
;
154 memset(&instance_info
, 0, sizeof(instance_info
));
155 instance_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
156 instance_info
.pApplicationInfo
= &app_info
;
157 if ((vr
= VK_CALL(vkCreateInstance(&instance_info
, NULL
, &instance
))) < 0)
159 WARN("Failed to create Vulkan instance, vr %d.\n", vr
);
163 TRACE("Created Vulkan instance %p.\n", instance
);
165 #define LOAD_INSTANCE_PFN(name) \
166 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
168 WARN("Could not get instance proc addr for '" #name "'.\n"); \
171 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
172 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
175 #undef VK_INSTANCE_PFN
178 vk_info
->instance
= instance
;
183 if (vk_ops
->vkDestroyInstance
)
184 VK_CALL(vkDestroyInstance(instance
, NULL
));
185 wined3d_unload_vulkan(vk_info
);
189 static VkPhysicalDevice
get_vulkan_physical_device(struct wined3d_vk_info
*vk_info
)
191 VkPhysicalDevice physical_devices
[1];
195 if ((vr
= VK_CALL(vkEnumeratePhysicalDevices(vk_info
->instance
, &count
, NULL
))) < 0)
197 WARN("Failed to enumerate physical devices, vr %d.\n", vr
);
198 return VK_NULL_HANDLE
;
202 WARN("No physical device.\n");
203 return VK_NULL_HANDLE
;
207 /* TODO: Create wined3d_adapter for each device. */
208 FIXME("Multiple physical devices available.\n");
212 if ((vr
= VK_CALL(vkEnumeratePhysicalDevices(vk_info
->instance
, &count
, physical_devices
))) < 0)
214 WARN("Failed to get physical devices, vr %d.\n", vr
);
215 return VK_NULL_HANDLE
;
218 return physical_devices
[0];
221 const struct wined3d_gpu_description
*get_vulkan_gpu_description(const struct wined3d_vk_info
*vk_info
,
222 VkPhysicalDevice physical_device
)
224 const struct wined3d_gpu_description
*description
;
225 VkPhysicalDeviceProperties properties
;
227 VK_CALL(vkGetPhysicalDeviceProperties(physical_device
, &properties
));
229 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
230 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties
.vendorID
, properties
.deviceID
);
231 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
232 TRACE("API version: %u.%u.%u.\n", VK_VERSION_MAJOR(properties
.apiVersion
),
233 VK_VERSION_MINOR(properties
.apiVersion
), VK_VERSION_PATCH(properties
.apiVersion
));
235 if ((description
= wined3d_get_gpu_description(properties
.vendorID
, properties
.deviceID
)))
238 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
239 debugstr_a(properties
.deviceName
), properties
.vendorID
, properties
.deviceID
);
241 return wined3d_get_gpu_description(HW_VENDOR_AMD
, CARD_AMD_RADEON_RX_VEGA
);
244 static BOOL
wined3d_adapter_vk_init(struct wined3d_adapter_vk
*adapter_vk
,
245 unsigned int ordinal
, unsigned int wined3d_creation_flags
)
247 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
248 const struct wined3d_gpu_description
*gpu_description
;
249 struct wined3d_adapter
*adapter
= &adapter_vk
->a
;
251 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
252 adapter_vk
, ordinal
, wined3d_creation_flags
);
254 if (!wined3d_adapter_init(adapter
, ordinal
))
257 if (!wined3d_init_vulkan(vk_info
))
259 WARN("Failed to initialize Vulkan.\n");
263 if (!(adapter_vk
->physical_device
= get_vulkan_physical_device(vk_info
)))
266 if (!(gpu_description
= get_vulkan_gpu_description(vk_info
, adapter_vk
->physical_device
)))
268 ERR("Failed to get GPU description.\n");
271 wined3d_driver_info_init(&adapter
->driver_info
, gpu_description
, wined3d_settings
.emulated_textureram
);
273 if (!wined3d_adapter_vk_init_format_info(adapter
))
276 adapter
->vertex_pipe
= &none_vertex_pipe
;
277 adapter
->fragment_pipe
= &none_fragment_pipe
;
278 adapter
->shader_backend
= &none_shader_backend
;
279 adapter
->adapter_ops
= &wined3d_adapter_vk_ops
;
281 adapter
->d3d_info
.wined3d_creation_flags
= wined3d_creation_flags
;
286 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
287 wined3d_unload_vulkan(vk_info
);
289 wined3d_adapter_cleanup(adapter
);
293 struct wined3d_adapter
*wined3d_adapter_vk_create(unsigned int ordinal
,
294 unsigned int wined3d_creation_flags
)
296 struct wined3d_adapter_vk
*adapter_vk
;
298 if (!(adapter_vk
= heap_alloc_zero(sizeof(*adapter_vk
))))
301 if (!wined3d_adapter_vk_init(adapter_vk
, ordinal
, wined3d_creation_flags
))
303 heap_free(adapter_vk
);
307 TRACE("Created adapter %p.\n", adapter_vk
);
309 return &adapter_vk
->a
;