A real chain-aware Vulkan implicit layer the loader inserts at vkCreateInstance -- the reliable early-presence path for games that init Vulkan immediately, which the inline-hook vk_hook can't catch. It intercepts vkCreateInstance / Device / CreateSwapchainKHR / QueuePresentKHR via proper layer-chain dispatch and does the same read-back capture (vkCmdCopyImageToBuffer -> swizzle -> hook-owned D3D11 shared texture, with present-semaphore re-chaining) as vk_hook. The loader/layer link structs (VkLayer*CreateInfo, VkNegotiateLayerInterface) aren't in Vulkan-Headers, so they're hand-declared to interface version 2. Key gotcha found via tracing: the loader tags those link structs with small internal sType values (LOADER_INSTANCE_CREATE_INFO=47, _DEVICE=48), not the 1000000000 range -- matching the wrong value made the device-chain walk fail. Scoping: an implicit layer loads into every Vulkan app, so it only *captures* when COOP_VK_LAYER_FORCE is set (tests) or this process's image matches %TEMP%\coop_vk_target.txt (the host writes it); otherwise pure pass-through. mock_game_test registers it via VK_LAYER_PATH/VK_INSTANCE_LAYERS and decodes frames through it. Ships at the bin root with its JSON manifest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
15 lines
489 B
JSON
15 lines
489 B
JSON
{
|
|
"file_format_version": "1.2.0",
|
|
"layer": {
|
|
"name": "VK_LAYER_coop_capture",
|
|
"type": "GLOBAL",
|
|
"library_path": ".\\coop_vk_layer.dll",
|
|
"api_version": "1.1.0",
|
|
"implementation_version": "1",
|
|
"description": "CoopAllTheThings Vulkan capture layer (mirrors the swap-chain image into a shared texture; captures only the host's target process)",
|
|
"disable_environment": {
|
|
"COOP_VK_LAYER_DISABLE": "1"
|
|
}
|
|
}
|
|
}
|