godotengine / godotengine/godot
Uniform array of textures/images using specialization constant as array length ignores provided constant value and uses the default value as length
- Dominant language
- C++
- Stars
- 117k
- Forks
- 26.8k
- PR merge metrics
- PR metrics pending
Description
### Tested versions
- Reproduced in: v4.6.stable.mono.official [89cea1439], v4.5.1.stable.mono.official [f62fdbde1]
### System information
Windows 10, Vulkan (Forward+), Nvidia RTX 3070, driver - GeForce Game Ready 591.86
### Issue description
When using specialization constant (`RDPipelineSpecializationConstant`) in GLSL compute shaders in order to have an array of textures or images with variable size,
```glsl
layout(constant_id = 0)const int IMAGE_COUNT = 3;
layout(rgba32f, set = 0, binding = 0)uniform image2D images[IMAGE_COUNT];
```
provided specialization constant value is ignored and instead the default constant value is used as array length. Specialization constant value is however correctly set for the rest of the shader, i.e. while uniform array length is equal to constant's default value, during runtime shader execution the correctly set value of the specialization constant is visible.
When attempting to set specialization constant value (to something else other than its default) and provide the same number of textures/images, the following errors are displayed (attempting to provide 2 images and set spec. constant to 2 while 3 is its default value)
```
E 0:00:01:216 script.gd:45 @ _test_values(): Image (binding: 0) is an array of (3) textures, so it should be provided equal number of texture IDs to satisfy it (IDs provided: 2).
Method/function failed. Returning: RID()
servers/rendering/rendering_device.cpp:3865 @ uniform_set_create()
script.gd:45 @ _test_values()
script.gd:70 @ _ready()
E 0:00:01:216 script.gd:49 @ _test_values(): Parameter "uniform_set" is null.
servers/rendering/rendering_device.cpp:5473 @ compute_list_bind_uniform_set()
script.gd:49 @ _test_values()
script.gd:70 @ _ready()
E 0:00:01:216 script.gd:50 @ _test_values(): Uniforms were never supplied for set (0) at the time of drawing, which are required by the pipeline.
Method/function failed.
servers/rendering/rendering_device.cpp:5562 @ compute_list_dispatch()
script.gd:50 @ _test_values()
script.gd:70 @ _ready()
```
### Steps to reproduce
- Open the attached MRP project and run it in the editor, observe debug output and errors
- See `script.gd` for code and detailed instructions (relevant info also pasted below)
Relevant portion of `script.gd`:
```gdscript
func _ready() -> void:
# Supply 3 textures (3 is the default specialization constant value set in the shader) but pass an incorrect spec constant value of 404
_test_values(3, 404)
# Expected: errors due to image array buffer requiring 404 images but only having 3 supplied
# Actual result: passes and prints "First image data: 123.456001, Second image data: 123.456001, IMAGE_COUNT value: 404"
# Supply 2 textures and pass 2 as spec constant value
_test_values(2, 2)
# Expected result: it will work and print "First image data: 123.456001, Second image data: 123.456001, IMAGE_COUNT value: 2"
# Actual result: prints "First image data: 0.000000, Second image data: 0.000000, IMAGE_COUNT value: 0"
# and displays an error, since the provided spec constant value is ignored and instead tne default value is used as array buffer element count
```
### Minimal reproduction project (MRP)
[spec_constant_bug_mrp.zip](https://github.com/user-attachments/files/25216251/spec_constant_bug_mrp.zip)
Contributor guide
Assessment
This issue has not been assessed yet.