diff options
-rw-r--r-- | Makefile.am | 17 | ||||
-rw-r--r-- | src/vulkan-helpers.h | 57 | ||||
-rw-r--r-- | src/vulkan-renderer.c | 222 |
3 files changed, 296 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 62719c95..689132aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -215,6 +215,23 @@ gl_renderer_la_SOURCES = \ shared/helpers.h endif +if ENABLE_VULKAN +module_LTLIBRARIES += vulkan-renderer.la +vulkan_renderer_la_LDFLAGS = -module -avoid-version +vulkan_renderer_la_LIBADD = $(COMPOSITOR_LIBS) -lvulkan +vulkan_renderer_la_CFLAGS = \ + $(COMPOSITOR_CFLAGS) \ + $(VULKAN_RENDERER_CFLAGS) \ + $(AM_CFLAGS) +vulkan_renderer_la_SOURCES = \ + src/vulkan-helpers.h \ + src/vulkan-renderer.h \ + src/vulkan-renderer.c \ + src/vertex-clipping.c \ + src/vertex-clipping.h \ + shared/helpers.h +endif + if ENABLE_X11_COMPOSITOR module_LTLIBRARIES += x11-backend.la x11_backend_la_LDFLAGS = -module -avoid-version diff --git a/src/vulkan-helpers.h b/src/vulkan-helpers.h new file mode 100644 index 00000000..749d68af --- /dev/null +++ b/src/vulkan-helpers.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __VULKAN_HELPERS_H__ +#define __VULKAN_HELPERS_H__ + +#include <string.h> + +#define __VK_HELP_STRUCT_NAME(StructName, STRUCT_NAME) \ +static const VkStructureType __vulkan_helpers_##StructName##_type = \ + VK_STRUCTURE_TYPE_##STRUCT_NAME; + +__VK_HELP_STRUCT_NAME(ApplicationInfo, APPLICATION_INFO); +__VK_HELP_STRUCT_NAME(DeviceCreateInfo, DEVICE_CREATE_INFO); +__VK_HELP_STRUCT_NAME(MemoryAllocInfo, MEMORY_ALLOC_INFO); +__VK_HELP_STRUCT_NAME(ImageViewCreateInfo, IMAGE_VIEW_CREATE_INFO); + +__VK_HELP_STRUCT_NAME(InstanceCreateInfo, INSTANCE_CREATE_INFO); + +__VK_HELP_STRUCT_NAME(SurfaceDescriptionWindowWSI, SURFACE_DESCRIPTION_WINDOW_WSI); + +#define VK_STRUCT_DECL(StructName, name) \ +Vk##StructName name = { __vulkan_helpers_##StructName##_type, NULL } + +#define VK_STRUCT(StructName, name, ...) \ + Vk##StructName name; \ + do { \ + Vk##StructName s; \ + memset(&s, 0, sizeof(s)); \ + s.sType = __vulkan_helpers_##StructName##_type; \ + __VA_ARGS__; \ + name = s; \ + } while (0) + +#endif /* __VULKAN_HELPERS_H__ */ diff --git a/src/vulkan-renderer.c b/src/vulkan-renderer.c new file mode 100644 index 00000000..e0a9b03c --- /dev/null +++ b/src/vulkan-renderer.c @@ -0,0 +1,222 @@ +/* + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#define VK_PROTOTYPES + +#include <vulkan/vulkan.h> +#include <vulkan/vk_wsi_swapchain.h> +#include <vulkan/vk_wsi_device_swapchain.h> + +#include "shared/helpers.h" +#include "vulkan-renderer.h" +#include "vulkan-helpers.h" + +struct vk_renderer { + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + VkQueue queue; + + PFN_vkGetPhysicalDeviceSurfaceSupportWSI get_pd_surface_support; +}; + +static int +vk_renderer_output_create(struct weston_output *output, + VkSurfaceDescriptionWindowWSI *window, + VkFormat *formats, const int n_formats) +{ return -1; /* TODO */ } + +static void +vk_renderer_output_destroy(struct weston_output *output) +{ /* TODO */ } + +static void +vk_renderer_output_set_border(struct weston_output *output, + enum vk_renderer_border_side side, + int32_t width, int32_t height, + int32_t tex_width, unsigned char *data) +{ /* TODO */ } + +/* Chooses a physical device and queue family that should work */ +static int +vk_renderer_choose_physical_device(struct vk_renderer *r, + VkPlatformWSI platform, + void *native_platform_handle, + VkPhysicalDevice *physical_device, + uint32_t *queue_family) +{ + VkResult result; + uint32_t i, j, pd_count, queue_count; + VkPhysicalDevice *pdevs; + VkPhysicalDeviceQueueProperties *queue_props; + VkBool32 supported; + + result = vkEnumeratePhysicalDevices(r->instance, &pd_count, NULL); + if (result != VK_SUCCESS || pd_count == 0) + return -1; + + pdevs = malloc(pd_count * sizeof(*pdevs)); + if (pdevs == NULL) + return -1; + + result = vkEnumeratePhysicalDevices(r->instance, &pd_count, pdevs); + if (result != VK_SUCCESS) + goto fail; + + VK_STRUCT(SurfaceDescriptionWindowWSI, wsi_window, + s.platform = platform, + s.pPlatformHandle = native_platform_handle, + s.pPlatformWindow = NULL /* XXX: This shouldn't be needed? */ + ); + + /* Grab the first physical device that claims to have the WSI + * support that we need. + */ + for (i = 0; i < pd_count; i++) { + result = vkGetPhysicalDeviceQueueCount(pdevs[i], &queue_count); + if (result != VK_SUCCESS) + goto fail; + + queue_props = malloc(queue_count * sizeof(*queue_props)); + + result = vkGetPhysicalDeviceQueueProperties(pdevs[i], + queue_count, + queue_props); + if (result != VK_SUCCESS) { + free(queue_props); + goto fail; + } + + for (j = 0; j < queue_count; j++) { + if (!(queue_props[j].queueFlags & VK_QUEUE_GRAPHICS_BIT)) + continue; + + result = r->get_pd_surface_support(pdevs[i], j, + (void *)&wsi_window, + &supported); + if (supported) { + /* We've found a physical device and queue + * family that works. Let's go ahead and + * use that one. + */ + *physical_device = pdevs[i]; + *queue_family = j; + free(pdevs); + return 0; + } + } + } + +fail: + free(pdevs); + return -1; +} + +const char *instance_extensions[] = { + "VK_WSI_swapchain", +}; + +const char *device_extensions[] = { + "VK_WSI_device_swapchain", +}; + +static int +vk_renderer_create(struct weston_compositor *ec, VkPlatformWSI platform, + void *native_platform_handle) +{ + struct vk_renderer *r; + VkResult result; + uint32_t queue_family; + + r = zalloc(sizeof *r); + if (r == NULL) + return -1; + + VK_STRUCT(ApplicationInfo, app_info, + s.pAppName = "org.freedesktop.wayland.weston", + s.appVersion = 1, + s.pEngineName = "org.freedesktop.wayland.weston", + s.engineVersion = 1, + s.apiVersion = VK_MAKE_VERSION(0, 138, 2) + ); + + VK_STRUCT(InstanceCreateInfo, ic_info, + s.pAppInfo = &app_info, + s.pAllocCb = NULL, /* Use driver default */ + s.extensionCount = ARRAY_LENGTH(instance_extensions), + s.ppEnabledExtensionNames = instance_extensions + ); + + result = vkCreateInstance(&ic_info, &r->instance); + if (result != VK_SUCCESS) + goto fail_alloc; + + r->get_pd_surface_support = (PFN_vkGetPhysicalDeviceSurfaceSupportWSI) + vkGetInstanceProcAddr(r->instance, + "vkGetPhysicalDeviceSurfaceSupportWSI"); + + if (vk_renderer_choose_physical_device(r, platform, + native_platform_handle, + &r->physical_device, + &queue_family) < 0) { + goto fail_instance; + } + + VkDeviceQueueCreateInfo queue_info = { + queue_family, + 1 /* queue count */ + }; + + VK_STRUCT(DeviceCreateInfo, dev_info, + s.queueRecordCount = 1, + s.pRequestedQueues = &queue_info, + s.extensionCount = ARRAY_LENGTH(device_extensions), + s.ppEnabledExtensionNames = device_extensions + ); + + result = vkCreateDevice(r->physical_device, &dev_info, &r->device); + if (result != VK_SUCCESS) + goto fail_instance; + + result = vkGetDeviceQueue(r->device, queue_family, 0, &r->queue); + if (result != VK_SUCCESS) + goto fail_device; + +fail_device: + vkDestroyDevice(r->device); +fail_instance: + vkDestroyInstance(r->instance); +fail_alloc: + free(r); + + return -1; +} + +WL_EXPORT struct vulkan_renderer_interface vulkan_renderer_interface = { + .create = vk_renderer_create, + .output_create = vk_renderer_output_create, + .output_destroy = vk_renderer_output_destroy, + .output_set_border = vk_renderer_output_set_border, +}; |