Stephen Seo
dfc78540db
This commit does some preparation for a new Vulkan compute shader "blue_noise_filter.glsl". Note that every call of "filter" is followed by a call to "min_max". The goal is to combine a single invocation of Vulkan "filter" and log(n) invocations of Vulkan "min_max" in the same command buffer, which may help with performance. This will be achieved by passing the "max_in_buf" to the new "filter" compute shader, which will hold the results of applying the precomputed-gaussian. This buffer will then be copied to "min_in_buf", and then all is set to call the Vulkan "min_max" compute shader log(n) times. Note that log(n) comes from the fact that the Vulkan "min_max" compute shader does a "reduce" on the input buffers where each SIMD invocation compares two values and reduces it to 1. Doing this approximately log(n) (log base 2) times will reduce the input gradually into a single minimum and single maximum. This works due to having two separate "layouts" for the same "min_max" shader where the "in" and "out" buffers are swapped per "layout", and so by calling the other layout each time ensures that the proper buffers are reduced. (This work has already been done. What's left is to combine the "filter" and "min_max" Vulkan compute shaders into the same Vulkan command buffer. But first, the actual setup for the new Vulkan "filter" compute shader still has some work to do.)
58 lines
1.2 KiB
GLSL
58 lines
1.2 KiB
GLSL
#version 450
|
|
|
|
struct FloatAndIndex {
|
|
float value;
|
|
int pbp;
|
|
int idx;
|
|
};
|
|
|
|
int twoToOne(int x, int y, int width, int height) {
|
|
while (x < 0) {
|
|
x += width;
|
|
}
|
|
while (y < 0) {
|
|
y += height;
|
|
}
|
|
x = x % width;
|
|
y = y % height;
|
|
return x + y * width;
|
|
}
|
|
|
|
layout(binding = 0) readonly buffer PreComputed { float precomputed[]; };
|
|
|
|
layout(binding = 1) writeonly buffer FilterInOut {
|
|
FloatAndIndex filter_in_out[];
|
|
};
|
|
|
|
layout(binding = 2) readonly buffer Other {
|
|
int width;
|
|
int height;
|
|
int filter_size;
|
|
};
|
|
|
|
layout(local_size_x = 256) in;
|
|
|
|
void main() {
|
|
uint index = gl_GlobalInvocationID.x;
|
|
if (index >= width * height) {
|
|
return;
|
|
}
|
|
|
|
filter_in_out[index].idx = index;
|
|
|
|
int x = int(index % width);
|
|
int y = int(index / width);
|
|
|
|
filter_in_out[index].value = 0.0F;
|
|
for (int q = 0; q < filter_size; ++q) {
|
|
int q_prime = height - filter_size / 2 + y + q;
|
|
for (int p = 0; p < filter_size; ++p) {
|
|
int p_prime = width - filter_size / 2 + x + p;
|
|
if (filter_in_out[twoToOne(p_prime, q_prime, width, height)].pbp != 0) {
|
|
filter_in_out[index].value +=
|
|
precomputed[twoToOne(p, q, filter_size, filter_size)];
|
|
}
|
|
}
|
|
}
|
|
}
|