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

Open
#116,145 2 comments 0 reactions 0 assignees View on GitHub
bug topic:shaders
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.