How to add uniform buffer to glsl shader?

I’ve been working on a GLSL shader and am trying to figure out how to add a uniform buffer so I can pass more uniform parameters to it. I had been using push constants up until now, but didn’t realize there was a 128 byte limit.

When I tried to add my latest uniform, I went over that limit and thought maybe adding a uniform buffer would let me do that. While I was able to adapt my shader and it compiles and runs, there seems to be a lot of memory corruption going on. I’m wondering if I’ve done something wrong. I’ve not added any code yet to pass new things to the shader, only added code to my previously working glsl shader.

The head of my shader is

#[compute]
#version 450

#include "res://shaders/simplex_noise_2.gdshaderinc"
#include "res://shaders/custom_math.gdshaderinc"
#include "res://shaders/biome_table.gdshaderinc"

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

layout(rgba32f, set = 0, binding = 0) uniform restrict writeonly image2D output_image;

layout(set = 0, binding = 1) uniform sampler2D elevation_latitude_tex;
layout(set = 0, binding = 2) uniform sampler2D elevation_color_tex;
layout(set = 0, binding = 3) uniform sampler2D heat_latitude_tex;
layout(set = 0, binding = 4) uniform sampler2D elevation_to_moisture_tex;
layout(set = 0, binding = 5) uniform sampler2D biome_color_lookup_tex;
layout(set = 0, binding = 6) uniform sampler2D land_color_lookup_tex;



layout(push_constant, std430) uniform Params {
	int seed;
	int octaves;
	float gain;
	float lacunarity;

        ...
	
} params;

//Methods below here
...

I tried adding this underneath my push constant block:


layout(set = 1, binding = 0, std140) uniform Param2Block {
	float elevation_color_max;
} params2;

I had tried added a bare uniform, but that was causing an error and the forums I consulted said it need to be in a block. Not sure why the sampler uniforms don’t seem to need that - they were written that way in the shader I was referencing and seem to work. But after I add the uniform block, they seem to be referencing data from the wrong images. I also tried putting elevation_color_max in set 0, but I’m still getting the same issue.

You need to allocate data for uniform buffer object and use it in C++ code:

unsigned int uboExampleBlock;
glGenBuffers(1, &uboExampleBlock);
glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
glBufferData(GL_UNIFORM_BUFFER, 152, NULL, GL_STATIC_DRAW); // allocate 152 bytes of memory
glBindBuffer(GL_UNIFORM_BUFFER, 0);

There’s a tutorial on learnopengl about this.

You can look at the Dynamic Uniform Buffers example for how this works in general.

What is the validation layer saying? Also, reading this makes me wonder if you synchronize correctly between writing data to the uniform buffer and the computer shader invocation(s) that read from it?
Beyond that it’s a little difficult to say because you are only giving a pretty vague description of the problem you are seeing - with Vulkan in particular that makes it hard to say anything more useful than “yup, you’ve likely got a bug somewhere”; but you kinda knew that already… :wink:

1 Like

I’m actually trying to get something working for the Godot game engine, so I can’t call Vulkan methods directly. Everything goes through their custom GDScript language, so it’s hard to tell what’s going on. I’m not even sure if I can use Vulkan’s layers.

I was hoping that I had just messed up the syntax in the GLSL shader somehow since it seems to be compiling and running, but corrupting memory. I had thought that the shader would still work since I’m not using the variable in the new section right now, just declaring it as an experiment.

I was pretty good with OpenGL years ago, but am new to Vulkan, so I’m reading a book on it. Hopefully it will clear things up.

AFAIK Godot uses a variation of GLSL with elements/annotations that the engine requires added on top of it - it probably also has it’s own set of limitations. What they also have is a tutorial for a compute shader that accesses uniform buffer. Does that tutorial work for you? Have you examined how your code differs from the tutorial?
Beyond that you may have better luck on a godot forum since what you want to do has to respect the rules of the engine for accessing resources (e.g. textures/buffers) and the synchronization between GPU and CPU. Depending on how godot abstracts/hides the details of the underlying graphics APIs those may be quite different from what “raw” Vulkan requires.

Looks like you were right. My app did need to supply a uniform buffer to get things to work.