Compute utility

This commit is contained in:
mcrcortex
2024-12-24 12:56:30 +10:00
parent 663a352586
commit df2611f0b7
2 changed files with 125 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
package me.cortex.voxy.client.core.rendering.util;
import me.cortex.voxy.client.core.gl.GlBuffer;
import me.cortex.voxy.client.core.gl.shader.Shader;
import me.cortex.voxy.client.core.gl.shader.ShaderType;
import org.lwjgl.system.MemoryUtil;
import java.util.function.Supplier;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL20.glUniform1i;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL30.glBindBufferBase;
import static org.lwjgl.opengl.GL30.glUniform1ui;
import static org.lwjgl.opengl.GL31.GL_UNIFORM_BUFFER;
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BUFFER;
import static org.lwjgl.opengl.GL43C.glDispatchCompute;
//Utilities for common operations not suited for basic gl functions
// such as sparse memory setting
//TODO CLEAN THIS SHIT UP
public class ComputeUtils {
private ComputeUtils() {}
public static ComputeUtils INSTANCE = new ComputeUtils();
private static final int SETTING_BUFFER_BINDING = 1;
private static final int ENTRY_BUFFER_BINDING = 2;
//TODO: FIXME! This should itself be just a raw streaming buffer/mapped ptr (probably)
private final GlBuffer SCRATCH = new GlBuffer(1<<20);//1 MB scratch buffer... this should be enough.. right?
private int maxCount;
private int count;
private long ptr;
private final Supplier<Shader> uintSetShader = makeCacheSetShader("uint");
public void prepSetUint(int maxCount) {
if (this.count != 0 || this.maxCount != 0 || this.ptr != 0) {
throw new IllegalStateException();
}
this.ptr = UploadStream.INSTANCE.upload(SCRATCH, 0, maxCount*8L);
this.maxCount = maxCount;
}
public void pushSetUint(int index, int value) {
//For uint it goes
// {uint value; uint index;}
if (this.maxCount <= this.count++) {
throw new IllegalStateException("Pushed to many values to prepared set");
}
MemoryUtil.memPutInt(this.ptr, value); this.ptr += 4;
MemoryUtil.memPutInt(this.ptr, index); this.ptr += 4;
}
public void finishSetUint(GlBuffer dst) {
UploadStream.INSTANCE.commit();
this.uintSetShader.get().bind();
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, SETTING_BUFFER_BINDING, dst.id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ENTRY_BUFFER_BINDING, this.SCRATCH.id);
glUniform1i(0, this.count);
glDispatchCompute((this.count+127)/128, 1, 1);
this.ptr = 0;
this.maxCount = 0;
this.count = 0;
}
private static Supplier<Shader> makeCacheSetShader(String type) {
return makeAndCache(()->makeSetShader(type));
}
private static Shader makeSetShader(String type) {
return Shader.make()
.define("TYPE", type)
.define("SETTING_BUFFER_BINDING", SETTING_BUFFER_BINDING)
.define("ENTRY_BUFFER_BINDING", ENTRY_BUFFER_BINDING)
.add(ShaderType.COMPUTE, "voxy:util/set.comp")
.compile();
}
private static <T> Supplier<T> makeAndCache(Supplier<T> maker) {
Object[] value = new Object[1];
boolean[] hasSet = new boolean[1];
return ()->{
if (hasSet[0]) {
return (T) value[0];
} else {
var val = maker.get();
hasSet[0] = true;
value[0] = val;
return val;
}
};
}
}

View File

@@ -0,0 +1,27 @@
#version 460 core
layout(local_size_x=128) in;
layout(binding = SETTING_BUFFER_BINDING, std430) restrict writeonly buffer SetDataBuffer {
TYPE[] setting;
};
struct Entry {
TYPE value;
uint index;
};
layout(binding = ENTRY_BUFFER_BINDING, std430) restrict readonly buffer EntryBuffer {
Entry[] entries;
};
layout(location=0) uniform uint count;
void main() {
uint id = gl_GlobalInvocationID.x;
if (count <= id) {
return;
}
Entry entry = entries[id];
setting[entry.index] = entry.value;
}