Skip to content

vk: vkCmdBlitImage and the device procs SDL_GPU resolves (MARVEL Cosmic Invasion) - #2598

Open
bensaadmucret wants to merge 1 commit into
seedds:mainfrom
bensaadmucret:pr-vk-blit-swapchain
Open

bensaadmucret wants to merge 1 commit into
seedds:mainfrom
bensaadmucret:pr-vk-blit-swapchain

Conversation

@bensaadmucret

Copy link
Copy Markdown

What and why

SDL_GPU resolves every Vulkan entry point through vkGetInstanceProcAddr / vkGetDeviceProcAddr and calls some of them unchecked: lookups the layer did not implement returned null, and the game crashed on a blr to 0 right after "Setting backbuffer" (FNA's SDL_GPU backend, MARVEL Cosmic Invasion 010059D020C26000 v0, build D6A37DEAFF3F5AEA).

Two parts:

  1. The procs SDL_GPU calls get an implementation or a safe landing. vkCmdSetBlendConstants, vkCmdSetDepthBias, vkCmdSetDepthBounds, vkCmdClearAttachments, vkCmdResolveImage, vkCmdDispatch, vkCmdDispatchIndirect, vkCmdDrawIndirect, vkCmdDrawIndexedIndirect, vkCreateComputePipelines and the VK_EXT_debug_utils label calls are listed so the lookup answers something real — no-ops, logged, until each gets its Metal implementation (the unimplemented ones already warn, e.g. dynamic state 4 not implemented).
  2. vkCmdBlitImage is real (C_BLIT). An unscaled same-format region replays through the blit encoder, as vkCmdCopyImage does; what a copy cannot do — a blit between different formats, scaled or flipped — is drawn with the draw_tex builtin: a fullscreen triangle samples the source, and the linear mapping carries a flip on its own. This was the black window: SDL_GPU renders its frame into an R8G8B8A8_UNORM image and blits it into the B8G8R8A8_UNORM swap chain image, which no Metal texture copy can do. A blit inside a render pass splits the encoder and the pass resumes, as copies do; the occlusion slot counting includes C_BLIT.

Adds the findings to docs/reference/rendering.md (Vulkan layer: device procs a Vulkan library calls without checking; vkCmdBlitImage to the swap chain).

Checked

  • Tests: python3 -m unittest dm.tools.tests.test_docs (6 tests); make -C dm/host GAME=010099C022B96000 builds clean on this base
  • Games run, with title ID and version: MARVEL Cosmic Invasion 010059D020C26000 v0: before, the run reached 60 fps with real draws but the window stayed black; after, the intro video plays at 60 fps with audio (~870 draws/frame, presents at every display-link tick)
  • Devices and OS: Apple M6, macOS 27.0
  • regress.py check --games was not run: regress.py impact reaches api:vulkan for the change, but every added path was unreachable before — a game that had called vkCmdBlitImage or one of these procs would have crashed on the null lookup, so no profiled game's behavior changes. Open: vkCmdSetBlendConstants still warns as unimplemented; the render-encoder split for mid-pass blits is exercised only by the game this was found on.
  • One of four PRs from the same bring-up (the others: EOS platform handle, vk_shaders entry point, profile_guess detection).

Docs

  • The finding is in its game note or its docs/reference/<subsystem>.md entry, and python3 dm/tools/docs_symptoms.py was run (the symptom index)
  • A chain tool changed: dmsh_chain.py --header was run and dm/gfx/nvn/dmsh_chain.h is part of the change
  • No game files, keys or data extracted from a game in the change or the attachments

…ic Invasion)

SDL_GPU resolves every Vulkan entry point through vkGetDeviceProcAddr and calls some of them unchecked: lookups the
host did not implement returned null and the game crashed on a blr to 0 right after 'Setting backbuffer'. The
lookup now finds the calls SDL_GPU uses: vkCmdSetBlendConstants, vkCmdSetDepthBias, vkCmdSetDepthBounds,
vkCmdClearAttachments, vkCmdResolveImage, vkCmdDispatch, vkCmdDispatchIndirect, vkCmdDrawIndirect,
vkCmdDrawIndexedIndirect, vkCreateComputePipelines and the VK_EXT_debug_utils entry points — no-ops that keep the
call landing somewhere real until each gets its Metal implementation.

vkCmdBlitImage is real: an unscaled same-format region goes through the blit encoder like vkCmdCopyImage, and what
a copy cannot do — a blit between different formats, scaled or flipped — is drawn with the draw_tex builtin, which
samples the source through a fullscreen triangle whose linear mapping takes a flip into account on its own. This
was the black screen: SDL_GPU renders its frame to an R8G8B8A8 texture and blits it into the B8G8R8A8 swapchain
image, which no Metal copy can do.

Checked: dmhost builds; MARVEL Cosmic Invasion plays its intro video in a window at 60 FPS with audio (was a black
screen before).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation vulkan Vulkan on Metal (dm/gfx/vk)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant