Skip to content

Vulkan: draw decals, and draw them like OpenGL does - #7879

Open
dustinspace217 wants to merge 3 commits into
scp-fs2open:masterfrom
dustinspace217:graphics/vulkan-decals
Open

dustinspace217 wants to merge 3 commits into
scp-fs2open:masterfrom
dustinspace217:graphics/vulkan-decals

Conversation

@dustinspace217

Copy link
Copy Markdown
Contributor

What?

Decals now render on Vulkan, matching OpenGL. Two one-line causes: the shader input mask dropped three of four per-instance matrix columns, and the decal pipeline lacked the material's shader flags. The mask now comes from one helper, shader_vertex_input_mask() in shader_types.

Why?

On Vulkan, decals from Lua or a weapon's $Impact Decal: never showed up, while the same table lit the ship in OpenGL. Fixes #7866.

How?

The Vulkan pipeline keeps one bit per vertex attribute a shader type lists, and the decal shader lists VATTRIB_MODEL_MATRIX once. A mat4 takes four locations (8 to 11), so three columns read unbound inputs and decals landed nowhere on screen. The helper gives the matrix four bits for both Vulkan call sites. OpenGL binds by name and is unchanged.

Vulkan decals then drew two to fifteen times brighter and wider than OpenGL's: the variant without USE_NORMAL_MAP fell back to screen-space derivative normals for angle rejection. The decal pipeline config now takes the material's flags, like the other draw paths.

Testing?

Linux, headless, Release and Debug with fatal warnings. Vulkan on NVIDIA, OpenGL on Mesa's software renderer. Base b477dd5 vs this branch, MediaVPs 5.0.2, SM1-01, 1280x720, plus a two-table mod: a decal ($Decal: vkdecaltest, +Diffuse: beamglow1, +Glow: beamglow1) and an $On Mission Start: hook giving every ship a ship-sized one (def:create(radius, radius, -1, -1, ship, ship.Class.Model:getDetailRoot())).

Before, only OpenGL lit the ships. After, both do, and halo brightness at three ships stays inside OpenGL's range over four frames each. Without the mod, frames match the base build within run scatter. Frame times are flat: Vulkan 11.9 ms with decals on both builds, OpenGL 45.6 vs 45.4 ms. Decals draw under MSAA 4x, a normal-mapped decal draws on both renderers, and the Debug build's validation layer reports the same pre-existing messages with and without decals, none from the decal pass. Three new unit tests cover the input mask per shader type (old code: mask 257, locations 9 to 11 missing), the matrix locations and the decal flag polarity. Both suites pass in Release and Debug.

Anything Else?

The Vulkan decal fragment shader samples all three maps through one sampler2DArray binding, so a glow or normal bitmap different from the diffuse reads the diffuse. With a thruster01 glow, OpenGL shows a bluish halo, Vulkan the old white one. That path was unreachable until now. I left it for a separate PR. Written with Claude Code; the investigation, review and testing ran on my machine.

The Vulkan shader input mask had one bit per listed attribute, so the
pipeline dropped the MATRIX4 attributes at locations 9-11 and the decal
vertex shader read three of its four instance-matrix columns from unbound
inputs. No decal was ever drawn in Vulkan.

The mask now covers four locations for VATTRIB_MODEL_MATRIX. It is built
by shader_vertex_input_mask() in shader_types so both Vulkan call sites
share it and a unit test covers it without a Vulkan build.

Fixes scp-fs2open#7866
The decal pipeline config set the shader type but not the flags, so the
decal shader variant was always compiled without USE_NORMAL_MAP and fell
back to screen-space derivative normals for angle rejection. Far more of
the decal volume passed the angle test than in OpenGL, which lit the
decals brighter and wider. The pipeline now takes the flags the material
reports, as the other draw paths already do.
…idth check

Pin the full mask per shader type instead of the presence of the matrix
bits, so an expansion of any other attribute fails; pin that a decal
without a normal map is the one that reads the scene normal buffer; add a
compile-time bound on the mask width; trim two comments.
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.

Vulkan: decals are not drawn

1 participant