Image and ssbo bindings

This commit is contained in:
mcrcortex
2025-08-20 13:44:31 +10:00
parent 9c74f92147
commit cc609bbb07
3 changed files with 107 additions and 28 deletions

View File

@@ -137,20 +137,28 @@ public class IrisVoxyRenderPipeline extends AbstractRenderPipeline {
glColorMask(true, true, true, true);
}
@Override
public void setupAndBindOpaque(Viewport<?> viewport) {
this.fb.bind();
private void doBindings() {
if (this.shaderUniforms != null) {
GL30.glBindBufferBase(GL_UNIFORM_BUFFER, 5, this.shaderUniforms.id);// todo: dont randomly select this to 5
}
if (this.data.getSsboSet() != null) {
this.data.getSsboSet().bindingFunction().accept(10);
}
if (this.data.getImageSet() != null) {
this.data.getImageSet().bindingFunction().accept(6);
}
}
@Override
public void setupAndBindOpaque(Viewport<?> viewport) {
this.fb.bind();
this.doBindings();
}
@Override
public void setupAndBindTranslucent(Viewport<?> viewport) {
this.fbTranslucent.bind();
if (this.shaderUniforms != null) {
GL30.glBindBufferBase(GL_UNIFORM_BUFFER, 5, this.shaderUniforms.id);// todo: dont randomly select this to 5
}
this.doBindings();
if (this.data.getBlender() != null) {
this.data.getBlender().run();
}
@@ -162,17 +170,33 @@ public class IrisVoxyRenderPipeline extends AbstractRenderPipeline {
super.addDebug(debug);
}
@Override
public String patchOpaqueShader(AbstractSectionRenderer<?, ?> renderer, String input) {
private StringBuilder buildGenericShaderHeader(AbstractSectionRenderer<?, ?> renderer, String input) {
StringBuilder builder = new StringBuilder(input).append("\n\n\n");
if (this.data.getUniforms() != null) {
//TODO make ths binding point... not randomly 5
builder.append("layout(binding = 5, std140) uniform ShaderUniformBindings ")
.append(this.data.getUniforms().layout())
.append(";\n\n\n");
.append(";\n\n");
}
if (this.data.getSsboSet() != null) {
builder.append("#define BUFFER_BINDING_INDEX_BASE 10\n");//TODO: DONT RANDOMLY MAKE THIS 10
builder.append(this.data.getSsboSet().layout()).append("\n\n");
}
if (this.data.getImageSet() != null) {
builder.append("#define BASE_SAMPLER_BINDING_INDEX 6\n");//TODO: DONT RANDOMLY MAKE THIS 6
builder.append(this.data.getImageSet().layout()).append("\n\n");
}
return builder.append("\n\n");
}
@Override
public String patchOpaqueShader(AbstractSectionRenderer<?, ?> renderer, String input) {
var builder = this.buildGenericShaderHeader(renderer, input);
builder.append(this.data.opaqueFragPatch());
return builder.toString();
@@ -182,17 +206,8 @@ public class IrisVoxyRenderPipeline extends AbstractRenderPipeline {
public String patchTranslucentShader(AbstractSectionRenderer<?, ?> renderer, String input) {
if (this.data.translucentFragPatch() == null) return null;
StringBuilder builder = new StringBuilder(input).append("\n\n\n");
if (this.data.getUniforms() != null) {
//TODO make ths binding point... not randomly 5
builder.append("layout(binding = 5, std140) uniform ShaderUniformBindings ")
.append(this.data.getUniforms().layout())
.append(";\n\n\n");
}
var builder = this.buildGenericShaderHeader(renderer, input);
builder.append(this.data.translucentFragPatch());
return builder.toString();
}
}

View File

@@ -2,6 +2,7 @@ package me.cortex.voxy.client.iris;
import com.google.gson.*;
import com.google.gson.annotations.JsonAdapter;
import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import me.cortex.voxy.common.Logger;
@@ -137,7 +138,7 @@ public class IrisShaderPatch {
}
public Int2ObjectMap<String> getSSBOs() {
return this.ssbos;
return new Int2ObjectLinkedOpenHashMap<>(this.ssbos);
}
public String getPatchOpaqueSource() {
return String.join("\n", this.patchData.opaquePatchData);

View File

@@ -26,10 +26,16 @@ import org.joml.*;
import org.lwjgl.system.MemoryUtil;
import java.util.*;
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.LongConsumer;
import java.util.stream.Collectors;
import static org.lwjgl.opengl.ARBDirectStateAccess.glBindTextureUnit;
import static org.lwjgl.opengl.ARBUniformBufferObject.glBindBufferBase;
import static org.lwjgl.opengl.GL33C.glBindSampler;
import static org.lwjgl.opengl.GL43C.GL_SHADER_STORAGE_BUFFER;
public class IrisVoxyRenderPipelineData {
public IrisVoxyRenderPipeline thePipeline;
public final int[] opaqueDrawTargets;
@@ -38,13 +44,25 @@ public class IrisVoxyRenderPipelineData {
private final String translucentPatch;
private final StructLayout uniforms;
private final Runnable blendingSetup;
private IrisVoxyRenderPipelineData(IrisShaderPatch patch, int[] opaqueDrawTargets, int[] translucentDrawTargets, StructLayout uniformSet, Runnable blendingSetup) {
private final ImageSet imageSet;
private final SSBOSet ssboSet;
private IrisVoxyRenderPipelineData(IrisShaderPatch patch, int[] opaqueDrawTargets, int[] translucentDrawTargets, StructLayout uniformSet, Runnable blendingSetup, ImageSet imageSet, SSBOSet ssboSet) {
this.opaqueDrawTargets = opaqueDrawTargets;
this.translucentDrawTargets = translucentDrawTargets;
this.opaquePatch = patch.getPatchOpaqueSource();
this.translucentPatch = patch.getPatchTranslucentSource();
this.uniforms = uniformSet;
this.blendingSetup = blendingSetup;
this.imageSet = imageSet;
this.ssboSet = ssboSet;
}
public SSBOSet getSsboSet() {
return this.ssboSet;
}
public ImageSet getImageSet() {
return this.imageSet;
}
public StructLayout getUniforms() {
@@ -60,12 +78,13 @@ public class IrisVoxyRenderPipelineData {
return this.translucentPatch;
}
public static IrisVoxyRenderPipelineData buildPipeline(IrisRenderingPipeline ipipe, IrisShaderPatch patch, CustomUniforms cu, ShaderStorageBufferHolder ssboHolder) {
var uniforms = createUniformLayoutStructAndUpdater(createUniformSet(cu, patch));
createImageSet(ipipe, patch);
var imageSet = createImageSet(ipipe, patch);
createSSBOLayouts(patch.getSSBOs(), ssboHolder);
var ssboSet = createSSBOLayouts(patch.getSSBOs(), ssboHolder);
var opaqueDrawTargets = getDrawBuffers(patch.getOpqaueTargets(), ipipe.getFlippedAfterPrepare(), ((IrisRenderingPipelineAccessor)ipipe).getRenderTargets());
var translucentDrawTargets = getDrawBuffers(patch.getTranslucentTargets(), ipipe.getFlippedAfterPrepare(), ((IrisRenderingPipelineAccessor)ipipe).getRenderTargets());
@@ -73,7 +92,7 @@ public class IrisVoxyRenderPipelineData {
//TODO: need to transform the string patch with the uniform decleration aswell as sampler declerations
return new IrisVoxyRenderPipelineData(patch, opaqueDrawTargets, translucentDrawTargets, uniforms, patch.createBlendSetup());
return new IrisVoxyRenderPipelineData(patch, opaqueDrawTargets, translucentDrawTargets, uniforms, patch.createBlendSetup(), imageSet, ssboSet);
}
private static int[] getDrawBuffers(int[] targets, ImmutableSet<Integer> stageWritesToAlt, RenderTargets rt) {
@@ -277,11 +296,13 @@ public class IrisVoxyRenderPipelineData {
return uniforms;
}
private record TextureWSampler(String name, IntSupplier texture, int sampler) {
private record TextureWSampler(String name, IntSupplier texture, int sampler) { }
public record ImageSet(String layout, IntConsumer bindingFunction) {
}
private static void createImageSet(IrisRenderingPipeline ipipe, IrisShaderPatch patch) {
private static ImageSet createImageSet(IrisRenderingPipeline ipipe, IrisShaderPatch patch) {
Set<String> samplerNameSet = new LinkedHashSet<>(List.of(patch.getSamplerList()));
if (samplerNameSet.isEmpty()) return null;
Set<TextureWSampler> samplerSet = new LinkedHashSet<>();
SamplerHolder samplerBuilder = new SamplerHolder() {
@Override
@@ -350,10 +371,52 @@ public class IrisVoxyRenderPipelineData {
//TODO: generate a layout (defines) for all the samplers with the correct types
StringBuilder builder = new StringBuilder();
TextureWSampler[] samplers = new TextureWSampler[samplerSet.size()];
int i = 0;
for (var entry : samplerSet) {
samplers[i]=entry;
builder.append("layout(binding=(BASE_SAMPLER_BINDING_INDEX+").append(i).append(")) uniform sampler2D ").append(entry.name).append(";\n");
i++;
}
private static void createSSBOLayouts(Int2ObjectMap<String> ssbos, ShaderStorageBufferHolder ssboStore) {
IntConsumer bindingFunction = base->{
for (int j = 0; j < samplers.length; j++) {
int unit = j+base;
var ts = samplers[j];
glBindTextureUnit(unit, ts.texture.getAsInt());
if (ts.sampler != -1) {
glBindSampler(unit, ts.sampler);
}//TODO: might need to bind sampler 0
}
};
return new ImageSet(builder.toString(), bindingFunction);
}
public record SSBOSet(String layout, IntConsumer bindingFunction){}
private record SSBOBinding(int irisIndex, int bindingOffset) {}
private static SSBOSet createSSBOLayouts(Int2ObjectMap<String> ssbos, ShaderStorageBufferHolder ssboStore) {
if (ssbos.isEmpty()) return null;
String header = "";
if (ssbos.containsKey(-1)) header = ssbos.remove(-1);
StringBuilder builder = new StringBuilder(header);
builder.append("\n");
SSBOBinding[] bindings = new SSBOBinding[ssbos.size()];
int i = 0;
for (var entry : ssbos.int2ObjectEntrySet()) {
var val = entry.getValue();
bindings[i] = new SSBOBinding(entry.getIntKey(), i);
builder.append("layout(binding = (BUFFER_BINDING_INDEX_BASE+").append(i).append(")) restrict buffer IrisBufferBinding").append(i);
builder.append(" ").append(val).append(";\n");
i++;
}
//ssboStore.getBufferIndex()
IntConsumer bindingFunction = base->{
for (var binding : bindings) {
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, base+binding.bindingOffset, ssboStore.getBufferIndex(binding.irisIndex));
}
};
return new SSBOSet(builder.toString(), bindingFunction);
}
}