Skip to content

Support for shader_explicit_arithmetic_types and shader_16bit_storage - #1001

Merged
bjornbytes merged 1 commit into
bjornbytes:devfrom
SK83RJOSH:feat-storage-extensions
Aug 9, 2026
Merged

Support for shader_explicit_arithmetic_types and shader_16bit_storage#1001
bjornbytes merged 1 commit into
bjornbytes:devfrom
SK83RJOSH:feat-storage-extensions

Conversation

@SK83RJOSH

Copy link
Copy Markdown
Contributor

These two extensions are useful when working with compute shaders, and by extension raster shaders if they're fed packed data.

My specific use case was doing some mesh generation in a compute pass where I needed atomics to write packed data. Using shader_8bit_storage: require allows me to remove all atomics by ensuring each byte is only touched by up to at most one thread. So it's a fairly good win, especially considering 8-bit / 16-bit storage has been fairly well supported for the last ~10 years.

Some early feedback received, but not yet address:

  1. vec3 types are not widely supported for vertex attributes, and are not supported by wgpu at all
  2. It may be worthwhile merging storage / uniform features

Please note, I have not tested the wgpu backend yet, but I imagine it works just fine since the changes are fairly mechanical. One thing to call out there is the explicit errors added if you manage to break alignment rules for vertex attributes. Ostensibly this means, you're fine to use types like u16vec3 if you're not using scalar / packed rules - the padding saves your bacon. Otherwise, you'll hit these new errors.

@SK83RJOSH

SK83RJOSH commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

On 1:
I believe rgb8 is widely supported for vertex attributes. rgb16 on the other hand, is not, but should we remove support altogether?

storage8/16 support is fairly universal, so they still have wide applicability outside that use case, though VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT are used in tandem so maybe this is moot if this will block their use regardless.

On 2:
While storage8/16 is near universal on desktop, uniform8/16 is not. I suspect tethering the two would mean you don't get to benefit from these types in a lot of scenarios.

Perhaps storage8/16 could be merged, and uniform8/16 as well? I would presume these two features coincide with one another a great deal so that may be a win - but I'd want to get some numbers on that from somewhere.

Alternatively, would you be opposed to a bitmask for Float, Int, and Storage / Uniform support? Something like 1/2/4 signal 8/16/32 support? They could use the same underlying type / enum and we can avoid bit field support for now just to keep things simple.

enum {
   GPU_FEATURE_SUPPORT_8 = (1 << 0),
   GPU_FEATURE_SUPPORT_16 = (1 << 1),
   GPU_FEATURE_SUPPORT_32 = (1 << 2),
   GPU_FEATURE_SUPPORT_64 = (1 << 3),
};

// All support 32-bit, and you would never query this, but nice from a "correctness" POV
uint8 integer = GPU_FEATURE_SUPPORT_32;
uint8 float = GPU_FEATURE_SUPPORT_32;
uint8 storage = GPU_FEATURE_SUPPORT_32;
uint8 uniform = GPU_FEATURE_SUPPORT_32;

Of course, with bit fields, this becomes more compact and all four of these fit in 2 bytes.

Comment thread src/core/gpu_web.c Outdated
Comment thread src/modules/graphics/graphics.c Outdated
Comment thread src/modules/graphics/graphics.h
Comment thread src/core/gpu_vk.c Outdated
@bjornbytes

Copy link
Copy Markdown
Owner

One idea to simplify the graphics features a bit might be to document them as like:

All the "type" features, like float16, int8, etc. indicate support for using the type as variables in shader functions and in storage buffers. Uniform buffers and in/out don't support these types.

That way there can just be top-level float16 and int8 features, similar to WebGPU. They indicate that you can use the types for most of the common uses, without bundling them with the other features that have less-broad support.

@SK83RJOSH

SK83RJOSH commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

All the "type" features, like float16, int8, etc. indicate support for using the type as variables in shader functions and in storage buffers. Uniform buffers and in/out don't support these types.

I'm okay with this, but for clarity, this feature in WGPU essentially checks for storageBuffer16BitAccess + uniformAndStorageBuffer16BitAccess.

So I guess for true parity, we may as well do the same. Bit of a shame, since I think this limits 100% support to Nvidia RTX and forward or ~8 years vs. ~11 years.

@SK83RJOSH
SK83RJOSH force-pushed the feat-storage-extensions branch from 1286a1a to 7792ccf Compare August 9, 2026 18:44
@SK83RJOSH

SK83RJOSH commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

All feedback addressed, only change worth noting, is I made int16 align with the rest here, which is a breaking change. I don't know how many people use lovr on mobile, but support for i16 types and storage/uniform buffer support is probably the worst on those devices.

I presume this wouldn't be the case on stuff like the Quest and other standalone headsets though. So it may be worth regression testing if you've got anything to test on (I've a Quest 3 lying around, but no projects to test with).

Granted, I suspect not many people were using that anyway.

@bjornbytes

Copy link
Copy Markdown
Owner

It's fine to make int16 a little more restrictive.

Since we get to decide between:

  1. Make float16 etc. also indicate support for uniform buffers. Match WebGPU, but feature is unsupported more.
  2. Make float16 etc. only indicate support for storage buffers, and document it as not working for uniform buffers.

I think I'd probably pick (2) here? It seems better to advertise the feature more (esp. on Quest) rather than strictly follow WebGPU's semantics. Either way, it's definitely niche.

Comment thread src/core/gpu_vk.c Outdated
@bjornbytes

bjornbytes commented Aug 9, 2026

Copy link
Copy Markdown
Owner

l_lovrGraphicsGetFeatures in l_graphics.c should also add the new float16 and int8 features to the table.

@SK83RJOSH

Copy link
Copy Markdown
Contributor Author

I think I'd probably pick (2) here? It seems better to advertise the feature more (esp. on Quest) rather than strictly follow WebGPU's semantics. Either way, it's definitely niche.

Here's what support looks like right now:

Oculus Go:

shaderInt16

Oculus Quest 2 / Pro:

shaderInt8, shaderInt16, shaderFloat16, storageBuffer16BitAccess

Oculus Quest 3 / 3S:

shaderInt8, shaderInt16, shaderInt64, shaderFloat16, storageBuffer8BitAccess, storageBuffer16BitAccess

Apple Vision Pro (M2):

shaderInt8, shaderInt16, shaderFloat16, storageBuffer8BitAccess, uniformAndStorageBuffer8BitAccess, storageBuffer16BitAccess, uniformAndStorageBuffer16BitAccess

Apple Vision Pro (M5):

shaderInt8, shaderInt16, shaderInt64, shaderFloat16, storageBuffer8BitAccess, uniformAndStorageBuffer8BitAccess, storageBuffer16BitAccess, uniformAndStorageBuffer16BitAccess

Interestingly Qualcomm GPUs do not support uniformAndStorageBuffer at all - so if mobile is a big area for y'all I think that seals the deal as the minimum target.

@SK83RJOSH
SK83RJOSH force-pushed the feat-storage-extensions branch from 7792ccf to e80b1a9 Compare August 9, 2026 21:01
Comment thread src/core/spv.c Outdated
@SK83RJOSH
SK83RJOSH force-pushed the feat-storage-extensions branch from e80b1a9 to eb2837e Compare August 9, 2026 21:36
@SK83RJOSH

SK83RJOSH commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

I don't think you need to run checks for this one, but decided to resolve that / code style issues in spv.c, and I updated the errors in graphics.c to handle storage/uniform correctly.

Think this is ready to merge, so I'll restrain myself from further code golfing. :)

@SK83RJOSH
SK83RJOSH force-pushed the feat-storage-extensions branch from eb2837e to 6ec0895 Compare August 9, 2026 21:43
@bjornbytes

Copy link
Copy Markdown
Owner

Looks good, thanks for the PR!

@bjornbytes
bjornbytes merged commit f8465dd into bjornbytes:dev Aug 9, 2026
@bjornbytes

Copy link
Copy Markdown
Owner

(Added support for reading back the new formats in Buffer:getData + friends, and golfed the spir-v parsing a bit more)

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.

2 participants