Compute utility
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
27
src/main/resources/assets/voxy/shaders/util/set.comp
Normal file
27
src/main/resources/assets/voxy/shaders/util/set.comp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user