Skip to content

Pass each streamed EFF frame's own bit depth to gr_update_texture - #7882

Open
dustinspace217 wants to merge 1 commit into
scp-fs2open:masterfrom
dustinspace217:graphics/vulkan-eff-dds
Open

dustinspace217 wants to merge 1 commit into
scp-fs2open:masterfrom
dustinspace217:graphics/vulkan-eff-dds

Conversation

@dustinspace217

@dustinspace217 dustinspace217 commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #7701

What?

Streamed EFF animations now tell the renderer each frame's real bit depth instead of always 32.

Why?

Under Vulkan, main hall and other streamed animations made of 24-bit frames draw as garbage, and the game can crash at random. WCS's uncompressed DDS frames hit it, and so do 24-bit JPG, PNG and TGA frames, which are common in mods.

How?

generic_render_eff_stream passed 32 bpp for every frame, but 24-bit frames keep 3 bytes per pixel after locking. OpenGL takes the depth from the texture, so it was unaffected. Vulkan trusted the 32 and copied 4 bytes per pixel, which scrambled the image and read past the end of the frame buffer; that over-read is the likely cause of the crashes. The caller now passes the locked frame's own bpp. HUD-colored animations still pass 8, so their path is unchanged.

Screenshots?

A test mod replaces the main hall's 2_maincrane with an EFF of 20 frames (256x128, color bars and a moving marker), one row per frame format:

EFF frame formats, OpenGL master, Vulkan master, Vulkan with this PR

Testing?

Retail FS2 data, 1024x768, Linux, Debug builds. "Master" is a build whose generic.cpp, Vulkan texture and bmpman code is identical to master. Seven frame formats (DDS, JPG, PNG and TGA at 24 bits; DDS, PNG and TGA at 32 bits) on both renderers, master and this branch:

  • OpenGL: master and this branch are pixel-identical for every format.
  • Vulkan with this branch: pixel-identical to OpenGL for every format.
  • Vulkan on master: every 24-bit format is broken; the 32-bit ones are fine.

Also on both renderers: the retail main hall, a color and a grayscale EFF played from a script with gr.loadStreamingAnim, and SM1-01 in flight. All behave as on master except the color script EFF, which this fixes on Vulkan. I don't have WCS, so it's untested there.

Anything Else?

Two older problems turned up that this doesn't touch. A grayscale (HUD-colored) streamed EFF draws as a plain block on Vulkan, before and after this change. An EFF whose frames grow after the first (a 32-bit frame after a 24-bit one) corrupts the heap with either renderer; that one is #7883. Written with Claude Code; the investigation, review and testing ran on my machine.

generic_render_eff_stream told the renderer every streamed EFF frame was
32 bpp. Frames from uncompressed 24-bit DDS, JPG or 24-bit TGA files keep
3 bytes per pixel after locking. OpenGL takes the depth from the texture
and was unaffected, but Vulkan trusted the 32 and copied 4 bytes per pixel:
the animation was drawn as garbage and the copy read past the end of the
frame's buffer. HUD-colored animations still pass 8.
@dustinspace217

dustinspace217 commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Overlap note: #7886 gives EFF streams their own buffer and no longer uploads the raw locked frame, so it also fixes the 24-bit case this PR addresses. Either merge order works: if #7886 lands first, this one can be closed in its favor; if this one lands first, #7886 hits one small conflict on the line changed here and resolves it by keeping its own version, since it replaces that upload.

@BMagnu BMagnu added the LLM-authored For PR's mainly created through LLMs and NOT submitted by badged developers label Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LLM-authored For PR's mainly created through LLMs and NOT submitted by badged developers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Vulkan: Corrupted mainhall EFF animations and potential crash on WCS

2 participants