Skip to content

Handle Vulkan float-to-integer color attachment format mismatch#2702

Closed
Icehunter wants to merge 1 commit intoKhronosGroup:mainfrom
Icehunter:fix/vulkan-integer-float-format-mismatch
Closed

Handle Vulkan float-to-integer color attachment format mismatch#2702
Icehunter wants to merge 1 commit intoKhronosGroup:mainfrom
Icehunter:fix/vulkan-integer-float-format-mismatch

Conversation

@Icehunter
Copy link
Copy Markdown

Some Vulkan applications write float data to integer color attachments (e.g. VK_FORMAT_R16G16B16A16_UINT), which is undefined behavior per the Vulkan spec but works on most hardware. Metal requires the shader output type to exactly match the color attachment pixel format and rejects the pipeline with "output of type float4 is not compatible with a MTLPixelFormatRGBA16Uint color attachment".

This change adds per-location format matching by reflecting fragment shader SPIR-V outputs to determine each location's base type (float vs uint). When a mismatch is detected (float shader output to integer attachment), the pipeline descriptor's color attachment format is swapped to the corresponding float format (e.g. RGBA16Uint to RGBA16Float) before compilation.

Only mismatched locations are swapped, preserving correct behavior for shaders that legitimately output integer types.

Known limitation: the pipeline descriptor format may differ from the render pass attachment format. Metal tolerates this for same-size formats but the data may be reinterpreted incorrectly by composition passes that read the attachment as a sampled texture.

Some Vulkan applications write float data to integer color attachments
(e.g. VK_FORMAT_R16G16B16A16_UINT), which is undefined behavior per
the Vulkan spec but works on most hardware. Metal requires the shader
output type to exactly match the color attachment pixel format and
rejects the pipeline with "output of type float4 is not compatible
with a MTLPixelFormatRGBA16Uint color attachment".

This change adds per-location format matching by reflecting fragment
shader SPIR-V outputs to determine each location's base type (float
vs uint). When a mismatch is detected (float shader output to integer
attachment), the pipeline descriptor's color attachment format is
swapped to the corresponding float format (e.g. RGBA16Uint to
RGBA16Float) before compilation.

Only mismatched locations are swapped, preserving correct behavior
for shaders that legitimately output integer types.

Known limitation: the pipeline descriptor format may differ from the
render pass attachment format. Metal tolerates this for same-size
formats but the data may be reinterpreted incorrectly by composition
passes that read the attachment as a sampled texture.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 26, 2026

CLA assistant check
All committers have signed the CLA.

@cdavis5e
Copy link
Copy Markdown
Collaborator

Some Vulkan applications write float data to integer color attachments (e.g. VK_FORMAT_R16G16B16A16_UINT), which is undefined behavior per the Vulkan spec [emphasis added]

Then I'm afraid those applications are broken. "Undefined" means undefined. Literally anything can happen. When you violate the spec, it is legal for the ICD to delete the entire contents of your SSD, and make demons fly out of your nose.

What happens when you run Minecraft under the validation layer?

See also: KhronosGroup/SPIRV-Cross#2562, which, by the way, is a change that I wrote. It was rejected for this very same reason.

@Icehunter
Copy link
Copy Markdown
Author

Some Vulkan applications write float data to integer color attachments (e.g. VK_FORMAT_R16G16B16A16_UINT), which is undefined behavior per the Vulkan spec [emphasis added]

Then I'm afraid those applications are broken. "Undefined" means undefined. Literally anything can happen. When you violate the spec, it is legal for the ICD to delete the entire contents of your SSD, and make demons fly out of your nose.

What happens when you run Minecraft under the validation layer?

See also: KhronosGroup/SPIRV-Cross#2562, which, by the way, is a change that I wrote. It was rejected for this very same reason.

It quite literally just crashes dead in the water. I've been fighting with it all day, for the insane reason of running bedrock on MacOS.

My last hurray tonight well be to enable volumetric lighting and getting realistic waves to render like it does on a mobile phone, but at this point I'm thinking it's just beyond fixes and going into unrealistic patches.

@billhollings
Copy link
Copy Markdown
Contributor

Then I'm afraid those applications are broken.

I assume we don't want to deliberately bring in a fix to make the behaviour de facto defined, per the other implementations?

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.

4 participants