Context
The texture-pipeline redesign (PR #751) added real device-layer logic — VulkanDevice::ReconstructTexture, DestroyTexture, the timeline-gated TextureHandleToDispose drain — that today is only verified by static/adversarial review and a manual Obelisk resize stress test, not by an automated test. It also left RenderResourceManagerHotReloadTest.cpp's 4 tests permanently GTEST_SKIP()'d:
SlotGenerationIsMonotonicAcrossReuse
StaleHandleAfterReleaseAndReuseFailsGetBuffer
HotReloadSwapUpdatesMeshOffsetsNextFrame
ScheduleSwapIsThreadSafeFromNonRenderThread
Both are blocked on the same thing: no test anywhere in the repo constructs a real VulkanDevice. VulkanDevice::Initialize unconditionally calls window->CreateSurface(...), so it's never been tried without a window/surface.
What exists already
GpuAllocatorTest.cpp's HeadlessVulkan fixture proves a minimal headless Vulkan context works locally (confirmed via ctest on macOS — raw vkCreateInstance/vkCreateDevice, no window). But it deliberately bypasses VulkanDevice entirely — it only needs a VkPhysicalDevice/VkDevice/VkInstance for GpuAllocator, not the full device wrapper.
What's needed
Extend that pattern far enough to construct a minimal, real VulkanDevice — GlobalTextures, ImageBufferManager, CreateTexture, ReconstructTexture, DestroyTexture, a timeline semaphore for Present()'s drain gating — without a window, surface, or swapchain. This unlocks:
- The 4 skip-gated tests above.
- New GPU-level tests for
ReconstructTexture (preserves Index/Generation across a resize) and DestroyTexture (doesn't reclaim the slot before the stamped timeline value is reached).
Not this issue
Issue #627 (Linux CI plumbing for an already-written headless swapchain-resize test suite) is a related but separate problem — that's about the CI Vulkan loader not finding an ICD on Linux runners for tests that already run locally. This issue is about the local capability to construct a VulkanDevice at all without a window, which is a prerequisite everywhere (including local dev on macOS), not a CI-specific gap.
References
ZEngine/ZEngine/Hardwares/VulkanDevice.cpp (Initialize)
ZEngine/tests/Rendering/GpuAllocatorTest.cpp (the HeadlessVulkan pattern to extend)
ZEngine/tests/Rendering/RenderResourceManagerHotReloadTest.cpp (the 4 skip-gated tests)
Context
The texture-pipeline redesign (PR #751) added real device-layer logic —
VulkanDevice::ReconstructTexture,DestroyTexture, the timeline-gatedTextureHandleToDisposedrain — that today is only verified by static/adversarial review and a manual Obelisk resize stress test, not by an automated test. It also leftRenderResourceManagerHotReloadTest.cpp's 4 tests permanentlyGTEST_SKIP()'d:SlotGenerationIsMonotonicAcrossReuseStaleHandleAfterReleaseAndReuseFailsGetBufferHotReloadSwapUpdatesMeshOffsetsNextFrameScheduleSwapIsThreadSafeFromNonRenderThreadBoth are blocked on the same thing: no test anywhere in the repo constructs a real
VulkanDevice.VulkanDevice::Initializeunconditionally callswindow->CreateSurface(...), so it's never been tried without a window/surface.What exists already
GpuAllocatorTest.cpp'sHeadlessVulkanfixture proves a minimal headless Vulkan context works locally (confirmed viacteston macOS — rawvkCreateInstance/vkCreateDevice, no window). But it deliberately bypassesVulkanDeviceentirely — it only needs aVkPhysicalDevice/VkDevice/VkInstanceforGpuAllocator, not the full device wrapper.What's needed
Extend that pattern far enough to construct a minimal, real
VulkanDevice—GlobalTextures,ImageBufferManager,CreateTexture,ReconstructTexture,DestroyTexture, a timeline semaphore forPresent()'s drain gating — without a window, surface, or swapchain. This unlocks:ReconstructTexture(preservesIndex/Generationacross a resize) andDestroyTexture(doesn't reclaim the slot before the stamped timeline value is reached).Not this issue
Issue #627 (Linux CI plumbing for an already-written headless swapchain-resize test suite) is a related but separate problem — that's about the CI Vulkan loader not finding an ICD on Linux runners for tests that already run locally. This issue is about the local capability to construct a
VulkanDeviceat all without a window, which is a prerequisite everywhere (including local dev on macOS), not a CI-specific gap.References
ZEngine/ZEngine/Hardwares/VulkanDevice.cpp(Initialize)ZEngine/tests/Rendering/GpuAllocatorTest.cpp(theHeadlessVulkanpattern to extend)ZEngine/tests/Rendering/RenderResourceManagerHotReloadTest.cpp(the 4 skip-gated tests)