Skip to content

fix: GameProfilingSystem crashes on Vulkan (FastTextRenderer null command buffer)#3261

Merged
xen2 merged 3 commits into
stride3d:masterfrom
LazyWorksZA:fix/vulkan-gameprofiler-crash
Jul 10, 2026
Merged

fix: GameProfilingSystem crashes on Vulkan (FastTextRenderer null command buffer)#3261
xen2 merged 3 commits into
stride3d:masterfrom
LazyWorksZA:fix/vulkan-gameprofiler-crash

Conversation

@sasvdw

@sasvdw sasvdw commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

PR Details

Fixes a native crash (0xC0000005) on the Vulkan backend: enabling the on-screen game profiler (GameProfilingSystem, toggled with F7) crashes within a couple of frames inside FastTextRenderer.End.

Fatal error. 0xC0000005
   at Vortice.Vulkan.Vulkan.vkCmdBindVertexBuffers(...)   // on master; 4.3.x faults one call earlier at vkCmdBindPipeline
   at Stride.Graphics.CommandList.SetVertexBuffer(...)
   at Stride.Graphics.FastTextRenderer.End(...)
   at Stride.Profiling.GameProfilingSystem.Draw(...)

Root cause

GameProfilingSystem.Draw rendered FastTextRenderer through RenderContext.GetShared(Services).GetThreadContext(). On Vulkan that returns a thread-local pipeline-worker command list, which is Close()d during the compositor's parallel scene rendering (RenderSystem.Draw) and never re-begun afterwards — so its native VkCommandBuffer is null, and recording draw commands into it in FastTextRenderer.End dereferences a null handle → access violation.

It only worked on Direct3D11 because D3D11 records serially (IsDeferred == false) and its thread contexts alias the single main command list via GraphicsDevice.InternalMainCommandList — which Vulkan intentionally does not set, because it does genuine parallel command-buffer recording. So the profiler was the one GameSystem.Draw-level caller reaching into a pipeline-internal context that isn't valid outside the render pipeline.

Fix

Render through Game.GraphicsContext — the main, per-frame command list that GameBase.BeginDraw resets and begins every frame — exactly as DebugTextSystem (the other FastTextRenderer consumer) already does. Behaviour-preserving on Direct3D11 (that was already the main command list); fixes the crash on Vulkan. Single method changed; no FastTextRenderer change needed.

Validation

Built the engine at a single consistent version and A/B-tested a minimal real game: without the change it crashes 3/3, with it runs cleanly and the profiler overlay renders. Minimal self-contained reproduction (clone + dotnet run on a Vulkan GPU): https://github.com/sasvdw/stride-1020-vulkan-profiler-repro

Note / follow-up

This is the targeted caller fix. The deeper issue — GetThreadContext() silently handing a GameSystem.Draw an invalid (closed) command list on Vulkan, so any future out-of-pipeline drawing system is a latent crash — is a framework concern (DebugTextSystem even carries a // TODO GRAPHICS REFACTOR where to get command list from?). I've kept this PR minimal and low-risk and will raise that separately as a proposal.

Related Issue

Closes #1020. Related: #630 ([Vulkan] WriteDiscard support — same FastTextRenderer-on-Vulkan area).

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

…mand buffer)

The F7 GPU profiler hard-crashes with a native 0xC0000005 on Vulkan inside
FastTextRenderer.End (issue stride3d#1020). GameProfilingSystem.Draw rendered through
RenderContext.GetShared(Services).GetThreadContext(); on Vulkan that thread-local
command list is Close()d after the compositor's parallel scene rendering and never
re-begun, so its native VkCommandBuffer is null and recording draw commands into it
segfaults. It only worked on Direct3D11 because D3D11 records serially and its thread
contexts alias the main command list (InternalMainCommandList, unset on Vulkan).

Render through Game.GraphicsContext (the main per-frame command list, reset+begun each
frame in GameBase.BeginDraw), matching DebugTextSystem. Behaviour-preserving on D3D11.

Repro: https://github.com/sasvdw/stride-1020-vulkan-profiler-repro

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread sources/engine/Stride.Engine/Profiling/GameProfilingSystem.cs Outdated
Comment thread sources/engine/Stride.Engine/Profiling/GameProfilingSystem.cs Outdated
@xen2 xen2 merged commit 3a28fd0 into stride3d:master Jul 10, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Game Profiler does not work with Vulkan

3 participants