diff --git a/include/gpu/api/surface.h b/include/gpu/api/surface.h index d8dbcb9..b88e230 100644 --- a/include/gpu/api/surface.h +++ b/include/gpu/api/surface.h @@ -26,11 +26,12 @@ extern "C" { struct GPUApi; typedef struct GPUApiSurface { - GPUSurface *(*createSurface)(struct GPUApi * __restrict api, - struct GPUInstance * __restrict inst, - void * __restrict nativeHandle, - GPUSurfaceType type, - float scale); + GPUSurface *(*createSurface)(struct GPUApi * __restrict api, + struct GPUInstance * __restrict inst, + struct GPUPhysicalDevice * __restrict phyDevice, + void * __restrict nativeHandle, + GPUSurfaceType type, + float scale); } GPUApiSurface; #ifdef __cplusplus diff --git a/include/gpu/surface.h b/include/gpu/surface.h index bbc9fd2..e619586 100644 --- a/include/gpu/surface.h +++ b/include/gpu/surface.h @@ -34,9 +34,10 @@ typedef struct GPUSurface { GPU_EXPORT GPUSurface* -GPUCreateSurface(GPUInstance * __restrict inst, - void * __restrict nativeHandle, - GPUSurfaceType type, - float scale); +GPUCreateSurface(GPUInstance * __restrict inst, + GPUPhysicalDevice * __restrict phyDevice, + void * __restrict nativeHandle, + GPUSurfaceType type, + float scale); #endif /* gpu_surface */ diff --git a/src/api/surface.c b/src/api/surface.c index 406cc62..44dd658 100644 --- a/src/api/surface.c +++ b/src/api/surface.c @@ -18,14 +18,15 @@ GPU_EXPORT GPUSurface* -GPUCreateSurface(GPUInstance * __restrict inst, - void * __restrict nativeHandle, - GPUSurfaceType type, - float scale) { +GPUCreateSurface(GPUInstance * __restrict inst, + GPUPhysicalDevice * __restrict phyDevice, + void * __restrict nativeHandle, + GPUSurfaceType type, + float scale) { GPUApi *api; if (!(api = gpuActiveGPUApi())) return NULL; - return api->surface.createSurface(api, inst, nativeHandle, type, scale); + return api->surface.createSurface(api, inst, phyDevice, nativeHandle, type, scale); } diff --git a/src/backend/mt/impl/surface.c b/src/backend/mt/impl/surface.c index d3a72a2..6f6676c 100644 --- a/src/backend/mt/impl/surface.c +++ b/src/backend/mt/impl/surface.c @@ -17,11 +17,12 @@ #include "../common.h" GPUSurface* -mt_createSurface(struct GPUApi * __restrict api, - struct GPUInstance * __restrict inst, - void * __restrict nativeHandle, - GPUSurfaceType type, - float scale) { +mt_createSurface(GPUApi * __restrict api, + GPUInstance * __restrict inst, + GPUPhysicalDevice * __restrict phyDevice, + void * __restrict nativeHandle, + GPUSurfaceType type, + float scale) { GPUSurface *surface; return NULL; diff --git a/src/backend/vk/common.h b/src/backend/vk/common.h index e83cc11..51ece88 100644 --- a/src/backend/vk/common.h +++ b/src/backend/vk/common.h @@ -166,4 +166,33 @@ typedef struct GPUPhysicalDeviceVk { VkPhysicalDeviceFeatures physDevFeatures; } GPUPhysicalDeviceVk; + +typedef enum GPUQueueFlagBits { + GPU_QUEUE_GRAPHICS_BIT = 0x00000001, + GPU_QUEUE_COMPUTE_BIT = 0x00000002, + GPU_QUEUE_TRANSFER_BIT = 0x00000004, + GPU_QUEUE_SPARSE_BINDING_BIT = 0x00000008, + GPU_QUEUE_PROTECTED_BIT = 0x00000010, + + /* TODO: */ + GPU_QUEUE_VIDEO_DECODE_BIT_KHR = 0x00000020, + GPU_QUEUE_VIDEO_ENCODE_BIT_KHR = 0x00000040, + GPU_QUEUE_OPTICAL_FLOW_BIT_NV = 0x00000100, +} GPUQueueFlagBits; + +typedef struct GPUCommandQueueCreateInfo { + GPUQueueFlagBits flags; + uint32_t count; +} GPUCommandQueueCreateInfo; + +typedef struct GPUDeviceVk { + VkDevice device; + GPUCommandQueueCreateInfo *createCI; + GPUCommandQueue *createdQueues; +} GPUDeviceVk; + +typedef struct GPUSurfaceVk { + VkSurfaceKHR surface; +} GPUSurfaceVk; + #endif /* vk_common_h */ diff --git a/src/backend/vk/impl/device.c b/src/backend/vk/impl/device.c index 4dd458d..28d3c87 100644 --- a/src/backend/vk/impl/device.c +++ b/src/backend/vk/impl/device.c @@ -278,6 +278,103 @@ vk_getAvailablePhysicalDevicesBy(GPUApi * __restrict api, return phyDevice; } +GPU_HIDE +GPUDevice* +vk_createDevice(GPUApi * __restrict api, + GPUInstance * __restrict inst, + GPUPhysicalDevice * __restrict phyDevice, + GPUCommandQueueCreateInfo queueCI[], + uint32_t nQueueCI) { + GPUDevice *device; + GPUDeviceVk *deviceVk; + GPUPhysicalDeviceVk *phyDeviceVk; + GPUInstanceVk *instVk; + VkResult U_ASSERT_ONLY err; + float queue_priorities[1] = {0.0}; + VkDeviceQueueCreateInfo queues[nQueueCI]; + uint32_t i; + +// vk_createDevice(api, inst, phyDevice, (GPUCommandQueueCreateInfo[]){ +// [0] = { +// .flags = GPU_QUEUE_GRAPHICS_BIT, +// .count = 0 +// } +// }, 2); + + phyDeviceVk = phyDevice->priv; + instVk = inst->_priv; + deviceVk = calloc(1, sizeof(*deviceVk)); + + // Search for a graphics and a present queue in the array of queue + // families, try to find one that supports both + uint32_t graphicsQueueFamilyIndex = UINT32_MAX; + uint32_t presentQueueFamilyIndex = UINT32_MAX; + + for (i = 0; i < phyDeviceVk->queueFamilyCount; i++) { + if ((phyDeviceVk->queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) { + if (graphicsQueueFamilyIndex == UINT32_MAX) { + graphicsQueueFamilyIndex = i; + } + +// if (supportsPresent[i] == VK_TRUE) { +// graphicsQueueFamilyIndex = i; +// presentQueueFamilyIndex = i; +// break; +// } + } + } + +// if (presentQueueFamilyIndex == UINT32_MAX) { +// // If didn't find a queue that supports both graphics and present, then +// // find a separate present queue. +// for (uint32_t i = 0; i < phyDeviceVk->queueFamilyCount; ++i) { +// if (supportsPresent[i] == VK_TRUE) { +// presentQueueFamilyIndex = i; +// break; +// } +// } +// } + +// queues[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; +// queues[0].pNext = NULL; +// queues[0].queueFamilyIndex = demo->graphics_queue_family_index; +// queues[0].queueCount = 1; +// queues[0].pQueuePriorities = queue_priorities; +// queues[0].flags = 0; +// +// VkDeviceCreateInfo createInfoCI = { +// .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, +// .pNext = NULL, +// .queueCreateInfoCount = 1, +// .pQueueCreateInfos = queues, +// .enabledLayerCount = 0, +// .ppEnabledLayerNames = NULL, +// .enabledExtensionCount = instVk->nEnabledExtensions, +// .ppEnabledExtensionNames = (const char *const *)instVk->extensionNames, +// .pEnabledFeatures = NULL, // If specific features are required, pass them in here +// }; +// +// if (demo->separate_present_queue) { +// queues[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; +// queues[1].pNext = NULL; +// queues[1].queueFamilyIndex = demo->present_queue_family_index; +// queues[1].queueCount = 1; +// queues[1].pQueuePriorities = queue_priorities; +// queues[1].flags = 0; +// createInfoCI.queueCreateInfoCount = 2; +// } +// +// err = vkCreateDevice(phyDeviceVk->phyDevice, &createInfoCI, NULL, &deviceVk->device); +// assert(!err); +// +// device = calloc(1, sizeof(*device)); +// device->priv = NULL; +// +// /* TODO: select-phy device auto */ + + return device; +} + GPU_HIDE void vk_initDevice(GPUApiDevice* apiDevice) { diff --git a/src/backend/vk/impl/surface.c b/src/backend/vk/impl/surface.c index 907cda7..ccd618b 100644 --- a/src/backend/vk/impl/surface.c +++ b/src/backend/vk/impl/surface.c @@ -16,19 +16,172 @@ #include "../common.h" +/* TODO: cube.c, improve it if needed */ +#if defined(VK_USE_PLATFORM_DISPLAY_KHR) +GPU_HIDE +static +VkResult +vk_createDisplaySurface(GPUInstanceVk * __restrict inst, + GPUPhysicalDeviceVk * __restrict phyDevice, + GPUSurfaceVk * __restrict surface) { + VkDisplayPlanePropertiesKHR *plane_props; + VkDisplayPropertiesKHR display_props; + VkDisplayKHR display; + VkDisplayModePropertiesKHR mode_props; + VkBool32 found_plane = VK_FALSE; + VkExtent2D image_extent; + VkDisplaySurfaceCreateInfoKHR surfaceCI; + VkResult U_ASSERT_ONLY err; + uint32_t display_count, mode_count, plane_count, plane_index; + + // Get the first display + display_count = 1; + err = vkGetPhysicalDeviceDisplayPropertiesKHR(phyDevice->phyDevice, + &display_count, + &display_props); + assert(!err || (err == VK_INCOMPLETE)); + + display = display_props.display; + + // Get the first mode of the display + err = vkGetDisplayModePropertiesKHR(phyDevice->phyDevice, display, &mode_count, NULL); + assert(!err); + + if (mode_count == 0) { + printf("Cannot find any mode for the display!\n"); + fflush(stdout); + exit(1); + } + + mode_count = 1; + err = vkGetDisplayModePropertiesKHR(phyDevice->phyDevice, display, &mode_count, &mode_props); + assert(!err || (err == VK_INCOMPLETE)); + + // Get the list of planes + err = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phyDevice->phyDevice, &plane_count, NULL); + assert(!err); + + if (plane_count == 0) { + printf("Cannot find any plane!\n"); + fflush(stdout); + exit(1); + } + + plane_props = malloc(sizeof(VkDisplayPlanePropertiesKHR) * plane_count); + assert(plane_props); + + err = vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phyDevice->phyDevice, + &plane_count, + plane_props); + assert(!err); + + // Find a plane compatible with the display + for (plane_index = 0; plane_index < plane_count; plane_index++) { + uint32_t supported_count; + VkDisplayKHR *supported_displays; + + // Disqualify planes that are bound to a different display + if ((plane_props[plane_index].currentDisplay != VK_NULL_HANDLE) + && (plane_props[plane_index].currentDisplay != display)) { + continue; + } + + err = vkGetDisplayPlaneSupportedDisplaysKHR(phyDevice->phyDevice, + plane_index, + &supported_count, + NULL); + assert(!err); + + if (supported_count == 0) { + continue; + } + + supported_displays = malloc(sizeof(VkDisplayKHR) * supported_count); + assert(supported_displays); + + err = vkGetDisplayPlaneSupportedDisplaysKHR(phyDevice->phyDevice, + plane_index, + &supported_count, + supported_displays); + assert(!err); + + for (uint32_t i = 0; i < supported_count; i++) { + if (supported_displays[i] == display) { + found_plane = VK_TRUE; + break; + } + } + + free(supported_displays); + + if (found_plane) { + break; + } + } + + if (!found_plane) { + printf("Cannot find a plane compatible with the display!\n"); + fflush(stdout); + exit(1); + } + + free(plane_props); + + VkDisplayPlaneCapabilitiesKHR planeCaps; + vkGetDisplayPlaneCapabilitiesKHR(phyDevice->phyDevice, + mode_props.displayMode, + plane_index, + &planeCaps); + // Find a supported alpha mode + VkDisplayPlaneAlphaFlagBitsKHR alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; + VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = { + VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR, + VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR, + }; + + for (uint32_t i = 0; i < sizeof(alphaModes); i++) { + if (planeCaps.supportedAlpha & alphaModes[i]) { + alphaMode = alphaModes[i]; + break; + } + } + + image_extent.width = mode_props.parameters.visibleRegion.width; + image_extent.height = mode_props.parameters.visibleRegion.height; + + surfaceCI.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; + surfaceCI.pNext = NULL; + surfaceCI.flags = 0; + surfaceCI.displayMode = mode_props.displayMode; + surfaceCI.planeIndex = plane_index; + surfaceCI.planeStackIndex = plane_props[plane_index].currentStackIndex; + surfaceCI.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + surfaceCI.alphaMode = alphaMode; + surfaceCI.globalAlpha = 1.0f; + surfaceCI.imageExtent = image_extent; + + return vkCreateDisplayPlaneSurfaceKHR(inst->inst, &surfaceCI, NULL, &surface->surface); +} +#endif + GPU_HIDE GPUSurface* -vk_createSurface(struct GPUApi * __restrict api, - struct GPUInstance * __restrict inst, - void * __restrict nativeHandle, - GPUSurfaceType type, - float scale) { +vk_createSurface(GPUApi * __restrict api, + GPUInstance * __restrict inst, + GPUPhysicalDevice * __restrict phyDevice, + void * __restrict nativeHandle, + GPUSurfaceType type, + float scale) { GPUInstanceVk *instVk; + GPUPhysicalDeviceVk *phyDeviceVk; GPUSurface *gpuSurface; GPUSurfaceVk *surface; VkResult U_ASSERT_ONLY err; instVk = inst->_priv; + phyDeviceVk = phyDevice->priv; gpuSurface = calloc(1, sizeof(*gpuSurface)); gpuSurface->type = type; gpuSurface->scale = scale; @@ -91,7 +244,7 @@ vk_createSurface(struct GPUApi * __restrict api, err = vkCreateDirectFBSurfaceEXT(instVk->inst, &createInfo, NULL, &surface->surface); #elif defined(VK_USE_PLATFORM_DISPLAY_KHR) - err = demo_create_display_surface(demo); + err = vk_createDisplaySurface(instVk, phyDeviceVk, surface->surface); #elif defined(VK_USE_PLATFORM_METAL_EXT) VkMetalSurfaceCreateInfoEXT createInfo = {0}; createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;