diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-25 23:58:35 +0100 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-25 23:58:35 +0100 |
| commit | 1ef541f3cb94bf0bf508afab3ad86aa1e4914705 (patch) | |
| tree | a52f4a9968a6342e464f6cc73dbf639c1f190316 /samples/SampleApp.cpp | |
| parent | 4c3777527cea4c360b0832a772d6796d81e64c90 (diff) | |
add support for khrDisplay in sample app
Diffstat (limited to 'samples/SampleApp.cpp')
| -rw-r--r-- | samples/SampleApp.cpp | 254 |
1 files changed, 210 insertions, 44 deletions
diff --git a/samples/SampleApp.cpp b/samples/SampleApp.cpp index bec9a97..422013a 100644 --- a/samples/SampleApp.cpp +++ b/samples/SampleApp.cpp @@ -9,6 +9,8 @@ #include <iostream> #include <stdio.h> #include <chrono> +#include <unistd.h> +#include <fcntl.h> bool SampleApp::try_get_phyinfo(VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDeviceType gpuType, VkhPhyInfo* phy) { for (uint32_t i = 0; i < phyCount; i++) { @@ -40,17 +42,45 @@ static void mouse_move_callback(GLFWwindow* window, double x, double y) {} static void scroll_callback(GLFWwindow* window, double x, double y) {} static void mouse_button_callback(GLFWwindow* window, int but, int state, int modif) {} -void SampleApp::Init() { - glfwSetErrorCallback(glfw_error_callback); +static bool is_desktop_environment_available(void) { +#if defined(__ANDROID__) + // Android always runs inside an active graphical framework handled by SurfaceFlinger. + // If the binary compiles for Android, a display context is inherently present. + return true; +#elif defined(_WIN32) || defined(_WIN64) + // Windows always has a desktop environment unless running as a headless NT Service. + return getenv("SystemRoot") != NULL; - if (!glfwInit()) { - perror("glfwInit failed"); - exit(-1); +#elif defined(__APPLE__) && defined(__MACH__) + // macOS always runs within a Quartz GUI session. + return getenv("HOME") != NULL; + +#else + // Linux/Unix (Debian, etc.) + // Check for active X11 display handles or Wayland compositor paths + bool has_x11 = getenv("DISPLAY") != NULL; + bool has_wayland = getenv("WAYLAND_DISPLAY") != NULL; + return (has_x11 || has_wayland); +#endif } - if (!glfwVulkanSupported()) { - perror("glfwVulkanSupported return false."); - exit(-1); +void SampleApp::Init() { + //vkh_log_level = VKH_LOG_FULL; + + displayMode = !is_desktop_environment_available(); + + if (!displayMode) { + glfwSetErrorCallback(glfw_error_callback); + + if (!glfwInit()) { + perror("glfwInit failed"); + exit(-1); + } + + if (!glfwVulkanSupported()) { + perror("glfwVulkanSupported return false."); + exit(-1); + } } const char* enabledLayers[10]; @@ -73,14 +103,18 @@ void SampleApp::Init() { #endif vkh_layers_check_release(); - uint32_t glfwReqExtsCount = 0; - const char** gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount); - vkvg_get_required_instance_extensions(enabledExts, &enabledExtsCount); - for (uint32_t i = 0; i < glfwReqExtsCount; i++) - enabledExts[i + enabledExtsCount] = gflwExts[i]; - enabledExtsCount += glfwReqExtsCount; + if (displayMode) { + enabledExts[enabledExtsCount++] = VK_KHR_SURFACE_EXTENSION_NAME; + enabledExts[enabledExtsCount++] = VK_KHR_DISPLAY_EXTENSION_NAME; + } else { + uint32_t glfwReqExtsCount = 0; + const char** gflwExts = glfwGetRequiredInstanceExtensions(&glfwReqExtsCount); + for (uint32_t i = 0; i < glfwReqExtsCount; i++) + enabledExts[i + enabledExtsCount] = gflwExts[i]; + enabledExtsCount += glfwReqExtsCount; + } app = vkh_app_create(1, 2, "vkvg", enabledLayersCount, enabledLayers, enabledExtsCount, enabledExts); @@ -92,16 +126,8 @@ void SampleApp::Init() { vkh_app_enable_debug_messenger(app, (VkDebugUtilsMessageTypeFlagBitsEXT)logType, (VkDebugUtilsMessageSeverityFlagBitsEXT)severity, NULL); #endif - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - glfwWindowHint(GLFW_FLOATING, GLFW_FALSE); - glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); - win = glfwCreateWindow((int)width, (int)height, "Window Title", NULL, NULL); - - glfwCreateWindowSurface(vkh_app_get_inst(app), win, NULL, &vkSurf); - - VkhPhyInfo* phys = vkh_app_get_phyinfos(app, &phyCount, vkSurf); + VkhPhyInfo* phys = vkh_app_get_phyinfos(app, &phyCount, NULL); if (listGpus) { std::cout << "Available GPU's:" << std::endl; @@ -110,15 +136,24 @@ void SampleApp::Init() { std::cout << "\t" << i << ": " << phys[i]->properties.deviceName << std::endl; } vkh_app_free_phyinfos(phyCount, phys); - vkDestroySurfaceKHR(vkh_app_get_inst(app), vkSurf, NULL); - glfwDestroyWindow(win); vkh_app_destroy(app); glfwTerminate(); exit(0); } + if (!displayMode) { + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + glfwWindowHint(GLFW_FLOATING, GLFW_FALSE); + glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); + + win = glfwCreateWindow((int)width, (int)height, "Window Title", NULL, NULL); + + glfwCreateWindowSurface(vkh_app_get_inst(app), win, NULL, &vkSurf); + } + VkhPhyInfo pi = 0; - if (gpuIndex > 0 && gpuIndex < phyCount) { + if (gpuIndex >= 0 && gpuIndex < phyCount) { pi = phys[gpuIndex]; } else { if (!try_get_phyinfo(phys, phyCount, preferedGPU, &pi) && @@ -128,6 +163,107 @@ void SampleApp::Init() { } assert(pi && "No vulkan physical device found."); + VkPhysicalDevice phy = vkh_phyinfo_get_phy(pi); + vkh_app_free_phyinfos (phyCount, phys); + + if (displayMode) { + uint32_t display_count = 0; + vkGetPhysicalDeviceDisplayPropertiesKHR(phy, &display_count, NULL); + + if (display_count == 0) { + perror("No dispaly found.\n"); + return; + } + + VkDisplayPropertiesKHR* display_props = + (VkDisplayPropertiesKHR*)malloc(display_count * sizeof(VkDisplayPropertiesKHR)); + vkGetPhysicalDeviceDisplayPropertiesKHR(phy, &display_count, display_props); + std::cout << "Available Vulkan Displays:" << std::endl; + std::cout << "=========================" << std::endl; + for (uint32_t i = 0; i < display_count; i++) { + std::cout << i << ": " << display_props[i].displayName << std::endl; + std::cout << "\tResolution:" << display_props[i].physicalDimensions.width << + " X " << display_props[i].physicalDimensions.height << std::endl; + } + int dispIdx; + while (std::cout << "Enter (0-" << display_count - 1 << "): " && + (!(std::cin >> dispIdx) || dispIdx < 0 || dispIdx >= display_count)) { + std::cin.clear(); std::cin.ignore(256, '\n'); + } + VkDisplayKHR native_display = display_props[dispIdx].display; + uint32_t mode_count = 0; + vkGetDisplayModePropertiesKHR(phy, native_display, &mode_count, NULL); + + VkDisplayModePropertiesKHR* mode_props = (VkDisplayModePropertiesKHR*) + malloc(mode_count * sizeof(VkDisplayModePropertiesKHR)); + vkGetDisplayModePropertiesKHR(phy, native_display, &mode_count, mode_props); + + std::cout << "Available Modes:" << std::endl; + std::cout << "================" << std::endl; + for (uint32_t i = 0; i < mode_count; i++) { + VkDisplayModeParametersKHR params = mode_props[i].parameters; + // Refresh rate is stored as millihertz (mHz), divide by 1000 for standard Hz + float refresh_rate = (float)params.refreshRate / 1000.0f; + std::cout << i << ": " << params.visibleRegion.width << " X " << + params.visibleRegion.height << " @ " << refresh_rate << std::endl; + } + int modeIdx; + while (std::cout << "Enter (0-" << mode_count - 1 << "): " && + (!(std::cin >> modeIdx) || modeIdx < 0 || modeIdx >= mode_count)) { + std::cin.clear(); std::cin.ignore(256, '\n'); + } + VkDisplayModeKHR display_mode = mode_props[modeIdx].displayMode; + uint32_t plane_count = 0; + vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phy, &plane_count, NULL); + VkDisplayPlanePropertiesKHR* plane_props = (VkDisplayPlanePropertiesKHR*) + malloc(plane_count * sizeof(VkDisplayPlanePropertiesKHR)); + vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phy, &plane_count, plane_props); + uint32_t active_plane_index = 0; + VkBool32 plane_supported = VK_FALSE; + for (uint32_t p = 0; p < plane_count; p++) { + vkGetDisplayPlaneSupportedDisplaysKHR(phy, p, &display_count, NULL); + if (display_count > 0) { + VkDisplayKHR* supported_displays = (VkDisplayKHR*) + malloc(display_count * sizeof(VkDisplayKHR)); + vkGetDisplayPlaneSupportedDisplaysKHR(phy, p, &display_count, supported_displays); + for (uint32_t d = 0; d < display_count; d++) { + if (supported_displays[d] == native_display) { + active_plane_index = p; + plane_supported = VK_TRUE; + break; + } + } + free(supported_displays); + } + if (plane_supported) break; + } + if (!plane_supported) { + fprintf(stderr, "Critical Error: Could not resolve a hardware plane that supports the selected display!\n"); + return; + } + VkExtent2D extent = mode_props[modeIdx].parameters.visibleRegion; + VkDisplaySurfaceCreateInfoKHR surface_info = { + .sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR, + .displayMode = display_mode, + .planeIndex = active_plane_index, + .planeStackIndex = 0, + .transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, + .globalAlpha = 1.0f, + .alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR, + .imageExtent = extent + }; + + vkCreateDisplayPlaneSurfaceKHR(vkh_app_get_inst(app), &surface_info, NULL, &vkSurf); + width = extent.width; + height = extent.height; + + free(plane_props); + free(mode_props); + free(display_props); + } + + pi = vkh_phyinfo_create(phy, vkSurf); + memory_properties = pi->memProps; gpu_props = pi->properties; @@ -137,10 +273,6 @@ void SampleApp::Init() { VkDeviceQueueCreateInfo pQueueInfos[] = {{}, {}, {}}; if (vkh_phyinfo_create_presentable_queues(pi, 1, qPriorities, &pQueueInfos[qCount])) qCount++; - /*if (vkh_phyinfo_create_compute_queues (pi, 1, qPriorities, &pQueueInfos[qCount])) - qCount++; - if (vkh_phyinfo_create_transfer_queues (pi, 1, qPriorities, &pQueueInfos[qCount])) - qCount++;*/ enabledExtsCount = 0; @@ -164,14 +296,29 @@ void SampleApp::Init() { }; vkhDev = vkh_device_create(app, pi, &device_info); - presentQIndex = (uint32_t)pi->pQueue; - renderer = vkh_presenter_create(vkhDev, presentQIndex, vkSurf, width, height, VK_FORMAT_B8G8R8A8_SRGB, presentMode); + int32_t gQFamIdx; + vkh_phyinfo_get_queue_fam_indices(pi, &gQFamIdx, NULL, NULL, NULL); + presentQIndex = gQFamIdx; + vkh_phyinfo_destroy (pi); - vkh_app_free_phyinfos(phyCount, phys); + VkFormat targetFormat = VK_FORMAT_B8G8R8A8_SRGB; + if (displayMode) { + uint32_t formatCount = 0; + vkGetPhysicalDeviceSurfaceFormatsKHR(phy, vkSurf, &formatCount, NULL); + VkSurfaceFormatKHR* formats = (VkSurfaceFormatKHR* + )malloc(formatCount * sizeof(VkSurfaceFormatKHR)); + vkGetPhysicalDeviceSurfaceFormatsKHR(phy, vkSurf, &formatCount, formats); + targetFormat = formats[0].format; + free(formats); + } + + renderer = vkh_presenter_create(vkhDev, presentQIndex, vkSurf, width, height, targetFormat, presentMode); - glfwSetKeyCallback(win, key_callback); - glfwSetMouseButtonCallback(win, mouse_button_callback); - glfwSetCursorPosCallback(win, mouse_move_callback); + if (!displayMode) { + glfwSetKeyCallback(win, key_callback); + glfwSetMouseButtonCallback(win, mouse_button_callback); + glfwSetCursorPosCallback(win, mouse_move_callback); + } } void SampleApp::Run() { @@ -193,13 +340,26 @@ void SampleApp::Run() { curTest = VkvgTest::tests[testsToRun[testIdx]]; } - glfwSetWindowTitle(win, curTest->name.c_str()); + if (displayMode) + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + else + glfwSetWindowTitle(win, curTest->name.c_str()); curTest->initTest(this); curTest->performTest(testIdx);//warm-up - while (!glfwWindowShouldClose(win)) { - glfwPollEvents(); + while (true) { + if (displayMode) { + char ch; + if (read(STDIN_FILENO, &ch, 1) > 0) { + if (ch == 'q') break; + printf("Key pressed: %c\r\n", ch); + } + } else { + glfwPollEvents(); + if (glfwWindowShouldClose(win)) + break; + } int idx = testIdx; auto start = std::chrono::steady_clock::now(); @@ -247,7 +407,10 @@ void SampleApp::Run() { totTime = 0; run_time_values.clear(); run_time_values.reserve(iterations); - glfwSetWindowTitle(win, curTest->name.c_str()); + + if (!displayMode) + glfwSetWindowTitle(win, curTest->name.c_str()); + curTest->initTest(this); curTest->performTest(testIdx);//warm-up } @@ -263,8 +426,11 @@ void SampleApp::CleanUp() { vkDestroySurfaceKHR(vkh_app_get_inst(app), vkSurf, NULL); vkh_device_destroy(vkhDev); - glfwDestroyWindow(win); - vkh_app_destroy(app); - - glfwTerminate(); + if (displayMode) { + vkh_app_destroy(app); + } else { + glfwDestroyWindow(win); + vkh_app_destroy(app); + glfwTerminate(); + } } |