// Spike S2: acquire the Bigscreen Beyond as a Vulkan direct-mode display and // present continuously. Decides ADR-0001's feasibility gate. // // s2 enumerate list physical devices, displays, modes // s2 present acquire Beyond, swapchain, animated clear loop // // Exit codes: 0 ok, 2 Beyond not found, 3 acquire failed, 10 other Vulkan fail. #include #define VK_NO_PROTOTYPES #define VK_USE_PLATFORM_WIN32_KHR #include #include #include #include #include #include #include #include static PFN_vkGetInstanceProcAddr gipa = nullptr; #define CHECK(call) \ do { \ VkResult r_ = (call); \ if (r_ != VK_SUCCESS) { \ fprintf(stderr, "FATAL %s = %d (line %d)\n", #call, (int)r_, __LINE__); \ return 10; \ } \ } while (0) #define IFN(name) PFN_##name name = (PFN_##name)gipa(inst, #name) #define DFN(name) PFN_##name name = (PFN_##name)vkGetDeviceProcAddr(dev, #name) struct FoundDisplay { VkPhysicalDevice phys = VK_NULL_HANDLE; uint32_t physIndex = 0; VkDisplayKHR display = VK_NULL_HANDLE; std::string name; VkExtent2D resolution{}; }; static bool looksLikeBeyond(const VkDisplayPropertiesKHR& p) { if (p.physicalResolution.width == 5088 || p.physicalResolution.height == 2544) return true; if (!p.displayName) return false; std::string n(p.displayName); for (auto& c : n) c = (char)tolower(c); return n.find("beyond") != std::string::npos || n.find("big") != std::string::npos; } int main(int argc, char** argv) { const char* cmd = argc > 1 ? argv[1] : "enumerate"; double seconds = argc > 2 ? atof(argv[2]) : 15.0; long targetId = argc > 3 ? atol(argv[3]) : -1; // WinRT DisplayAdapterTargetId bool doPresent = strcmp(cmd, "present") == 0; HMODULE vk = LoadLibraryA("vulkan-1.dll"); if (!vk) { fprintf(stderr, "FATAL: vulkan-1.dll not found\n"); return 10; } gipa = (PFN_vkGetInstanceProcAddr)GetProcAddress(vk, "vkGetInstanceProcAddr"); VkInstance inst = VK_NULL_HANDLE; { PFN_vkCreateInstance vkCreateInstance = (PFN_vkCreateInstance)gipa(nullptr, "vkCreateInstance"); PFN_vkEnumerateInstanceExtensionProperties enumExt = (PFN_vkEnumerateInstanceExtensionProperties)gipa( nullptr, "vkEnumerateInstanceExtensionProperties"); uint32_t n = 0; enumExt(nullptr, &n, nullptr); std::vector exts(n); enumExt(nullptr, &n, exts.data()); auto has = [&](const char* e) { for (auto& x : exts) if (strcmp(x.extensionName, e) == 0) return true; return false; }; std::vector want = {"VK_KHR_surface", "VK_KHR_display", "VK_EXT_direct_mode_display"}; for (auto e : want) if (!has(e)) { fprintf(stderr, "FATAL: instance ext %s missing\n", e); return 10; } printf("instance exts ok: surface, display, direct_mode_display\n"); VkApplicationInfo app{VK_STRUCTURE_TYPE_APPLICATION_INFO}; app.pApplicationName = "sauna-s2"; app.apiVersion = VK_API_VERSION_1_1; VkInstanceCreateInfo ci{VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; ci.pApplicationInfo = &app; ci.enabledExtensionCount = (uint32_t)want.size(); ci.ppEnabledExtensionNames = want.data(); CHECK(vkCreateInstance(&ci, nullptr, &inst)); } IFN(vkEnumeratePhysicalDevices); IFN(vkGetPhysicalDeviceProperties); IFN(vkEnumerateDeviceExtensionProperties); IFN(vkGetPhysicalDeviceQueueFamilyProperties); IFN(vkGetPhysicalDeviceDisplayPropertiesKHR); IFN(vkGetDisplayModePropertiesKHR); IFN(vkGetPhysicalDeviceDisplayPlanePropertiesKHR); IFN(vkGetDisplayPlaneSupportedDisplaysKHR); IFN(vkGetDisplayPlaneCapabilitiesKHR); IFN(vkCreateDisplayPlaneSurfaceKHR); IFN(vkReleaseDisplayEXT); IFN(vkAcquireWinrtDisplayNV); IFN(vkGetWinrtDisplayNV); IFN(vkGetPhysicalDeviceSurfaceSupportKHR); IFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); IFN(vkGetPhysicalDeviceSurfaceFormatsKHR); IFN(vkCreateDevice); IFN(vkGetDeviceProcAddr); IFN(vkDestroySurfaceKHR); IFN(vkDestroyInstance); uint32_t physCount = 0; CHECK(vkEnumeratePhysicalDevices(inst, &physCount, nullptr)); std::vector phys(physCount); CHECK(vkEnumeratePhysicalDevices(inst, &physCount, phys.data())); FoundDisplay found; for (uint32_t i = 0; i < physCount; i++) { VkPhysicalDeviceProperties pp; vkGetPhysicalDeviceProperties(phys[i], &pp); uint32_t extCount = 0; vkEnumerateDeviceExtensionProperties(phys[i], nullptr, &extCount, nullptr); std::vector dexts(extCount); vkEnumerateDeviceExtensionProperties(phys[i], nullptr, &extCount, dexts.data()); bool hasWinrtAcquire = false, hasSwapchain = false; for (auto& e : dexts) { if (strcmp(e.extensionName, "VK_NV_acquire_winrt_display") == 0) hasWinrtAcquire = true; if (strcmp(e.extensionName, "VK_KHR_swapchain") == 0) hasSwapchain = true; } printf("gpu[%u]: %s (winrt_acquire=%d swapchain=%d)\n", i, pp.deviceName, hasWinrtAcquire, hasSwapchain); uint32_t dn = 0; VkResult r = vkGetPhysicalDeviceDisplayPropertiesKHR(phys[i], &dn, nullptr); if (r != VK_SUCCESS) { printf(" display enum failed: %d\n", (int)r); continue; } std::vector dprops(dn); vkGetPhysicalDeviceDisplayPropertiesKHR(phys[i], &dn, dprops.data()); printf(" displays: %u\n", dn); for (uint32_t d = 0; d < dn; d++) { auto& p = dprops[d]; printf(" display[%u]: name='%s' physRes=%ux%u persistent=%d\n", d, p.displayName ? p.displayName : "(null)", p.physicalResolution.width, p.physicalResolution.height, p.persistentContent); uint32_t mn = 0; vkGetDisplayModePropertiesKHR(phys[i], p.display, &mn, nullptr); std::vector modes(mn); vkGetDisplayModePropertiesKHR(phys[i], p.display, &mn, modes.data()); for (uint32_t m = 0; m < mn; m++) printf(" mode[%u]: %ux%u @ %.3f Hz\n", m, modes[m].parameters.visibleRegion.width, modes[m].parameters.visibleRegion.height, modes[m].parameters.refreshRate / 1000.0); if (found.display == VK_NULL_HANDLE && hasWinrtAcquire && looksLikeBeyond(p)) { found = {phys[i], i, p.display, p.displayName ? p.displayName : "(null)", p.physicalResolution}; } } } if (found.display == VK_NULL_HANDLE && targetId >= 0) { // Not in the KHR enumeration — look it up by WinRT adapter-relative id. for (uint32_t i = 0; i < physCount; i++) { uint32_t extCount = 0; vkEnumerateDeviceExtensionProperties(phys[i], nullptr, &extCount, nullptr); std::vector dexts(extCount); vkEnumerateDeviceExtensionProperties(phys[i], nullptr, &extCount, dexts.data()); bool hasWinrt = false; for (auto& e : dexts) if (strcmp(e.extensionName, "VK_NV_acquire_winrt_display") == 0) hasWinrt = true; if (!hasWinrt) continue; VkDisplayKHR disp = VK_NULL_HANDLE; VkResult r = vkGetWinrtDisplayNV(phys[i], (uint32_t)targetId, &disp); printf("vkGetWinrtDisplayNV(gpu[%u], targetId=%ld) = %d, display=%p\n", i, targetId, (int)r, (void*)disp); if (r == VK_SUCCESS && disp != VK_NULL_HANDLE) { found = {phys[i], i, disp, "via-winrt-targetId", {}}; break; } } } if (found.display == VK_NULL_HANDLE) { printf("RESULT: Beyond not found among Vulkan displays\n"); vkDestroyInstance(inst, nullptr); return 2; } printf("RESULT: Beyond candidate on gpu[%u]: '%s' %ux%u\n", found.physIndex, found.name.c_str(), found.resolution.width, found.resolution.height); if (!doPresent) { vkDestroyInstance(inst, nullptr); return 0; } // ---- acquire ---- VkResult ar = vkAcquireWinrtDisplayNV(found.phys, found.display); printf("vkAcquireWinrtDisplayNV = %d\n", (int)ar); if (ar != VK_SUCCESS) return 3; // ---- pick mode: prefer max area, then refresh closest to 75 Hz ---- uint32_t mn = 0; vkGetDisplayModePropertiesKHR(found.phys, found.display, &mn, nullptr); std::vector modes(mn); vkGetDisplayModePropertiesKHR(found.phys, found.display, &mn, modes.data()); if (mn == 0) { fprintf(stderr, "FATAL: no display modes\n"); return 10; } uint32_t best = 0; auto score = [](const VkDisplayModePropertiesKHR& m) { double area = (double)m.parameters.visibleRegion.width * m.parameters.visibleRegion.height; double refPenalty = fabs(m.parameters.refreshRate / 1000.0 - 75.0); return area - refPenalty * 1e4; }; for (uint32_t m = 1; m < mn; m++) if (score(modes[m]) > score(modes[best])) best = m; VkDisplayModePropertiesKHR mode = modes[best]; VkExtent2D extent = mode.parameters.visibleRegion; printf("using mode[%u]: %ux%u @ %.3f Hz\n", best, extent.width, extent.height, mode.parameters.refreshRate / 1000.0); // ---- find a plane for this display ---- uint32_t pn = 0; vkGetPhysicalDeviceDisplayPlanePropertiesKHR(found.phys, &pn, nullptr); std::vector planes(pn); vkGetPhysicalDeviceDisplayPlanePropertiesKHR(found.phys, &pn, planes.data()); int planeIndex = -1; for (uint32_t p = 0; p < pn; p++) { if (planes[p].currentDisplay != VK_NULL_HANDLE && planes[p].currentDisplay != found.display) continue; uint32_t sn = 0; vkGetDisplayPlaneSupportedDisplaysKHR(found.phys, p, &sn, nullptr); std::vector sup(sn); vkGetDisplayPlaneSupportedDisplaysKHR(found.phys, p, &sn, sup.data()); for (auto s : sup) if (s == found.display) { planeIndex = (int)p; break; } if (planeIndex >= 0) break; } if (planeIndex < 0) { fprintf(stderr, "FATAL: no plane supports display\n"); return 10; } printf("using plane %d (of %u)\n", planeIndex, pn); VkDisplaySurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR}; sci.displayMode = mode.displayMode; sci.planeIndex = (uint32_t)planeIndex; sci.planeStackIndex = planes[planeIndex].currentStackIndex; sci.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; sci.globalAlpha = 1.0f; sci.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; sci.imageExtent = extent; VkSurfaceKHR surface; CHECK(vkCreateDisplayPlaneSurfaceKHR(inst, &sci, nullptr, &surface)); // ---- device + queue ---- uint32_t qn = 0; vkGetPhysicalDeviceQueueFamilyProperties(found.phys, &qn, nullptr); std::vector qf(qn); vkGetPhysicalDeviceQueueFamilyProperties(found.phys, &qn, qf.data()); uint32_t qi = UINT32_MAX; for (uint32_t q = 0; q < qn; q++) { VkBool32 sup = VK_FALSE; vkGetPhysicalDeviceSurfaceSupportKHR(found.phys, q, surface, &sup); if (sup && (qf[q].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { qi = q; break; } } if (qi == UINT32_MAX) { fprintf(stderr, "FATAL: no present+graphics queue\n"); return 10; } float prio = 1.0f; VkDeviceQueueCreateInfo qci{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}; qci.queueFamilyIndex = qi; qci.queueCount = 1; qci.pQueuePriorities = &prio; const char* devExts[] = {"VK_KHR_swapchain", "VK_NV_acquire_winrt_display"}; VkDeviceCreateInfo dci{VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; dci.queueCreateInfoCount = 1; dci.pQueueCreateInfos = &qci; dci.enabledExtensionCount = 2; dci.ppEnabledExtensionNames = devExts; VkDevice dev; CHECK(vkCreateDevice(found.phys, &dci, nullptr, &dev)); DFN(vkGetDeviceQueue); DFN(vkCreateSwapchainKHR); DFN(vkGetSwapchainImagesKHR); DFN(vkAcquireNextImageKHR); DFN(vkQueuePresentKHR); DFN(vkCreateCommandPool); DFN(vkAllocateCommandBuffers); DFN(vkBeginCommandBuffer); DFN(vkEndCommandBuffer); DFN(vkCmdPipelineBarrier); DFN(vkCmdClearColorImage); DFN(vkQueueSubmit); DFN(vkCreateSemaphore); DFN(vkCreateFence); DFN(vkWaitForFences); DFN(vkResetFences); DFN(vkResetCommandBuffer); DFN(vkDeviceWaitIdle); DFN(vkDestroySwapchainKHR); DFN(vkDestroyDevice); VkQueue queue; vkGetDeviceQueue(dev, qi, 0, &queue); VkSurfaceCapabilitiesKHR caps; CHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(found.phys, surface, &caps)); uint32_t fn = 0; vkGetPhysicalDeviceSurfaceFormatsKHR(found.phys, surface, &fn, nullptr); std::vector fmts(fn); vkGetPhysicalDeviceSurfaceFormatsKHR(found.phys, surface, &fn, fmts.data()); VkSurfaceFormatKHR fmt = fmts[0]; for (auto& f : fmts) if (f.format == VK_FORMAT_B8G8R8A8_UNORM) { fmt = f; break; } printf("surface: minImages=%u extent=%ux%u format=%d\n", caps.minImageCount, caps.currentExtent.width, caps.currentExtent.height, (int)fmt.format); VkSwapchainCreateInfoKHR sw{VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR}; sw.surface = surface; sw.minImageCount = caps.minImageCount > 2 ? caps.minImageCount : 2; sw.imageFormat = fmt.format; sw.imageColorSpace = fmt.colorSpace; sw.imageExtent = extent; sw.imageArrayLayers = 1; sw.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; sw.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; sw.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; sw.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; sw.presentMode = VK_PRESENT_MODE_FIFO_KHR; sw.clipped = VK_TRUE; VkSwapchainKHR swapchain; CHECK(vkCreateSwapchainKHR(dev, &sw, nullptr, &swapchain)); uint32_t imgCount = 0; vkGetSwapchainImagesKHR(dev, swapchain, &imgCount, nullptr); std::vector images(imgCount); vkGetSwapchainImagesKHR(dev, swapchain, &imgCount, images.data()); printf("swapchain: %u images\n", imgCount); VkCommandPoolCreateInfo cpci{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO}; cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; cpci.queueFamilyIndex = qi; VkCommandPool pool; CHECK(vkCreateCommandPool(dev, &cpci, nullptr, &pool)); const int FRAMES = 2; VkCommandBuffer cb[FRAMES]; VkSemaphore semAcq[FRAMES], semDone[FRAMES]; VkFence fence[FRAMES]; VkCommandBufferAllocateInfo cbai{VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO}; cbai.commandPool = pool; cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cbai.commandBufferCount = FRAMES; CHECK(vkAllocateCommandBuffers(dev, &cbai, cb)); for (int f = 0; f < FRAMES; f++) { VkSemaphoreCreateInfo si{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}; CHECK(vkCreateSemaphore(dev, &si, nullptr, &semAcq[f])); CHECK(vkCreateSemaphore(dev, &si, nullptr, &semDone[f])); VkFenceCreateInfo fi{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}; fi.flags = VK_FENCE_CREATE_SIGNALED_BIT; CHECK(vkCreateFence(dev, &fi, nullptr, &fence[f])); } auto t0 = std::chrono::steady_clock::now(); uint64_t frames = 0, presentErrors = 0; double worstDt = 0, lastT = 0; while (true) { double t = std::chrono::duration(std::chrono::steady_clock::now() - t0).count(); if (t >= seconds) break; int f = (int)(frames % FRAMES); CHECK(vkWaitForFences(dev, 1, &fence[f], VK_TRUE, UINT64_MAX)); CHECK(vkResetFences(dev, 1, &fence[f])); uint32_t idx = 0; VkResult r = vkAcquireNextImageKHR(dev, swapchain, UINT64_MAX, semAcq[f], VK_NULL_HANDLE, &idx); if (r != VK_SUCCESS && r != VK_SUBOPTIMAL_KHR) { fprintf(stderr, "acquireNextImage = %d at frame %llu\n", (int)r, (unsigned long long)frames); presentErrors++; break; } // animated, dim hue sweep — burn-in-safe moving content float hue = (float)fmod(t * 0.2, 1.0) * 6.0f; float x = 1 - fabsf(fmodf(hue, 2.0f) - 1); float rr = 0, gg = 0, bb = 0; switch ((int)hue) { case 0: rr = 1; gg = x; break; case 1: rr = x; gg = 1; break; case 2: gg = 1; bb = x; break; case 3: gg = x; bb = 1; break; case 4: rr = x; bb = 1; break; default: rr = 1; bb = x; break; } VkClearColorValue color{{rr * 0.25f, gg * 0.25f, bb * 0.25f, 1.0f}}; VkCommandBufferBeginInfo bi{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; CHECK(vkBeginCommandBuffer(cb[f], &bi)); VkImageSubresourceRange range{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; VkImageMemoryBarrier b1{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER}; b1.srcAccessMask = 0; b1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; b1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; b1.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; b1.srcQueueFamilyIndex = b1.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; b1.image = images[idx]; b1.subresourceRange = range; vkCmdPipelineBarrier(cb[f], VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &b1); vkCmdClearColorImage(cb[f], images[idx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &range); VkImageMemoryBarrier b2 = b1; b2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; b2.dstAccessMask = 0; b2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; b2.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; vkCmdPipelineBarrier(cb[f], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &b2); CHECK(vkEndCommandBuffer(cb[f])); VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_TRANSFER_BIT; VkSubmitInfo si{VK_STRUCTURE_TYPE_SUBMIT_INFO}; si.waitSemaphoreCount = 1; si.pWaitSemaphores = &semAcq[f]; si.pWaitDstStageMask = &waitStage; si.commandBufferCount = 1; si.pCommandBuffers = &cb[f]; si.signalSemaphoreCount = 1; si.pSignalSemaphores = &semDone[f]; CHECK(vkQueueSubmit(queue, 1, &si, fence[f])); VkPresentInfoKHR pi{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; pi.waitSemaphoreCount = 1; pi.pWaitSemaphores = &semDone[f]; pi.swapchainCount = 1; pi.pSwapchains = &swapchain; pi.pImageIndices = &idx; r = vkQueuePresentKHR(queue, &pi); if (r != VK_SUCCESS && r != VK_SUBOPTIMAL_KHR) { fprintf(stderr, "queuePresent = %d at frame %llu\n", (int)r, (unsigned long long)frames); presentErrors++; break; } frames++; if (lastT > 0 && t - lastT > worstDt) worstDt = t - lastT; lastT = t; if (frames % 300 == 0) printf(" t=%6.1fs frames=%llu avg=%.2f fps\n", t, (unsigned long long)frames, frames / t); } vkDeviceWaitIdle(dev); double total = std::chrono::duration(std::chrono::steady_clock::now() - t0).count(); printf("PRESENT RESULT: %llu frames in %.1fs = %.2f fps avg, worst gap %.1f ms, errors %llu\n", (unsigned long long)frames, total, frames / total, worstDt * 1000.0, (unsigned long long)presentErrors); vkDestroySwapchainKHR(dev, swapchain, nullptr); vkDestroyDevice(dev, nullptr); vkDestroySurfaceKHR(inst, surface, nullptr); vkReleaseDisplayEXT(found.phys, found.display); printf("display released\n"); vkDestroyInstance(inst, nullptr); bool pass = frames > 0 && presentErrors == 0 && frames / total > 70.0; printf("VERDICT: %s\n", pass ? "PASS" : (frames > 0 ? "MARGINAL" : "FAIL")); return 0; }