Skip to content

FastTextRenderer reads a Vulkan mapping after it has been unmapped #3375

Description

@BenjaBobs

Release Type: GitHub source

Version: 4.4.0-dev at commit 2f6f79b

Platform(s): Linux/Vulkan

Describe the bug

On the first frame that draws debug text, Linux/Vulkan terminates with an AccessViolationException.
When FastTextRenderer initializes, it creates the index data for the character quads in a mapped temporary buffer and saves a pointer to that data.
It then unmaps the buffer before passing the pointer to Buffer.Index.New, which reads from it to initialize the final index buffer.
The pointer is no longer valid after the Vulkan buffer has been unmapped.

To Reproduce

  1. Build a code-only game against Stride source packages from commit 2f6f79b.
  2. Select Vulkan.
  3. Queue one debug message with game.DebugTextSystem.Print(...).
  4. Start the game.
  5. Observe a fatal access violation while constructing the index buffer.

Expected behavior

The debug text should render without accessing unmapped memory.

Screenshots

Not applicable because the process terminates.

Log and callstacks

Fatal error.
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.SpanHelpers.Memmove(Byte ByRef, Byte ByRef, UIntPtr)
   at System.Buffer.MemoryCopy(Void*, Void*, Int64, Int64)
   at Stride.Core.MemoryUtilities.CopyWithAlignmentFallback(Void*, Void*, UInt32)
   at Stride.Graphics.Buffer.Recreate(IntPtr)
   at Stride.Graphics.Buffer.InitializeFromImpl(Stride.Graphics.BufferDescription ByRef, Stride.Graphics.BufferFlags, Stride.Graphics.PixelFormat, IntPtr)
   at Stride.Graphics.Buffer.InitializeFrom(System.ReadOnlySpan`1<Byte>, Int32, Stride.Graphics.BufferFlags, Stride.Graphics.PixelFormat, Stride.Graphics.GraphicsResourceUsage)
   at Stride.Graphics.Buffer.New(Stride.Graphics.GraphicsDevice, System.ReadOnlySpan`1<Byte>, Int32, Stride.Graphics.BufferFlags, Stride.Graphics.PixelFormat, Stride.Graphics.GraphicsResourceUsage)
   at Stride.Graphics.Buffer+Index.New(Stride.Graphics.GraphicsDevice, System.ReadOnlySpan`1<Byte>, Stride.Graphics.GraphicsResourceUsage)
   at Stride.Graphics.FastTextRenderer.Initialize(Stride.Graphics.GraphicsContext, Int32)
   at Stride.Graphics.FastTextRenderer..ctor(Stride.Graphics.GraphicsContext, Int32)
   at Stride.Profiling.DebugTextSystem.Draw(Stride.Games.GameTime)
   at Stride.Games.GameSystemCollection.Draw(Stride.Games.GameTime)
   at Stride.Games.GameBase.Draw(Stride.Games.GameTime)
   at Stride.Games.GameBase.RawTick(System.TimeSpan, Int32, Single, Boolean)
   at Stride.Games.GameBase.RawTickProducer()
   at Stride.Games.GameBase.Tick()
   at Stride.Games.GamePlatform.Tick()
   at Stride.Games.GamePlatform.OnRunCallback()
   at Stride.Games.GameWindowSDL+<>c__DisplayClass17_0.<Run>b__0()
   at Stride.Games.SDLMessageLoop.Run(Stride.Graphics.SDL.Window, RenderCallback)
   at Stride.Games.GameWindowSDL.Run()
   at Stride.Games.GamePlatform.Run(Stride.Games.GameContext)
   at Stride.Games.GameBase.Run(Stride.Games.GameContext)
   at Stride.CommunityToolkit.Engine.GameExtensions.Run(Stride.Engine.Game, Stride.Games.GameContext, System.Action`1<Stride.Engine.Scene>, System.Action`2<Stride.Engine.Scene,Stride.Games.GameTime>)
   at Program.<Main>$(System.String[])

Additional context

I fixed this locally by building the indices in a managed int[] and passing that array directly to Buffer.Index.New.
This removes the temporary buffer and keeps the index data alive for the entire call.
The method no longer uses pointers after this change, so I also removed its unsafe modifier.
I rebuilt the local Stride packages and confirmed that the game now renders successfully on Linux/Vulkan.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions