From 9aebf20aad1c1b12d2558d955041f426e22cf162 Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Sat, 1 Nov 2025 01:17:18 +1000 Subject: [PATCH] fix dynamic unifomrs not being exposed --- .../iris/IrisVoxyRenderPipelineData.java | 149 ++++++++++++++---- 1 file changed, 116 insertions(+), 33 deletions(-) diff --git a/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java b/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java index 792af065..fa17dd7d 100644 --- a/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java +++ b/src/main/java/me/cortex/voxy/client/iris/IrisVoxyRenderPipelineData.java @@ -3,6 +3,7 @@ package me.cortex.voxy.client.iris; import com.google.common.collect.ImmutableSet; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectFunction; import kroppeb.stareval.function.FunctionReturn; import kroppeb.stareval.function.Type; import me.cortex.voxy.client.core.IrisVoxyRenderPipeline; @@ -28,9 +29,7 @@ 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.function.*; import java.util.stream.Collectors; import static org.lwjgl.opengl.ARBDirectStateAccess.glBindTextureUnit; @@ -116,40 +115,55 @@ public class IrisVoxyRenderPipelineData { return targetTextures; } + + private static String convertToGlslType(UniformType type) { + return switch (type) { + case INT -> "int"; + case FLOAT -> "float"; + case MAT3 -> "mat3"; + case MAT4 -> "mat4"; + case VEC2 -> "vec2"; + case VEC2I -> "ivec2"; + case VEC3 -> "vec3"; + case VEC3I -> "ivec3"; + case VEC4 -> "vec4"; + case VEC4I -> "ivec4"; + }; + } public record StructLayout(int size, String layout, LongConsumer updater) {} - private static StructLayout createUniformLayoutStructAndUpdater(CachedUniform[] uniforms) { - if (uniforms.length == 0) { + private static StructLayout createUniformLayoutStructAndUpdater(List uniforms) { + if (uniforms.size() == 0) { return null; } - List[] ordering = new List[]{new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()}; + List[] ordering = new List[]{new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>()}; //Creates an optimial struct layout for the uniforms for (var uniform : uniforms) { - int order = getUniformOrdering(Type.convert(uniform.getType())); + int order = getUniformOrdering(uniform.type); ordering[order].add(uniform); } //Emit the ordering, note this is not optimial, but good enough, e.g. if have even number of align 2, emit that after align 4 int pos = 0; - Int2ObjectLinkedOpenHashMap layout = new Int2ObjectLinkedOpenHashMap<>(); + Int2ObjectLinkedOpenHashMap layout = new Int2ObjectLinkedOpenHashMap<>(); for (var uniform : ordering[0]) {//Emit exact align 4 - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; } if (!ordering[1].isEmpty() && (ordering[1].size()&1)==0) { //Emit all the align 2 as there is an even number of them for (var uniform : ordering[1]) { - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; } ordering[1].clear(); } //Emit align 3 for (var uniform : ordering[2]) {//Emit size odd, alignment must be 4 - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; //We must get a size 1 to pad to align 4 if (!ordering[3].isEmpty()) {//Size 1 uniform = ordering[3].removeFirst(); - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; } else {//Padding must be injected pos += 1; } @@ -157,15 +171,15 @@ public class IrisVoxyRenderPipelineData { //Emit align 2 for (var uniform : ordering[1]) { - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; } //Emit align 1 for (var uniform : ordering[3]) { - layout.put(pos, uniform); pos += getSizeAndAlignment(Type.convert(uniform.getType()))>>5; + layout.put(pos, uniform); pos += getSizeAndAlignment(uniform.type)>>5; } - if (layout.size()!=uniforms.length) { + if (layout.size()!=uniforms.size()) { throw new IllegalStateException(); } @@ -175,7 +189,7 @@ public class IrisVoxyRenderPipelineData { { StringBuilder struct = new StringBuilder("{\n"); for (var pair : layout.int2ObjectEntrySet()) { - struct.append("\t").append(pair.getValue().getType().toString()).append(" ").append(pair.getValue().getName()).append(";\n"); + struct.append("\t").append(convertToGlslType(pair.getValue().type)).append(" ").append(pair.getValue().name).append(";\n"); } struct.append("}"); structLayout = struct.toString(); @@ -183,11 +197,10 @@ public class IrisVoxyRenderPipelineData { LongConsumer updater; { - FunctionReturn cacheRetObj = new FunctionReturn(); - LongConsumer[] updaters = new LongConsumer[uniforms.length]; + LongConsumer[] updaters = new LongConsumer[uniforms.size()]; int i = 0; for (var pair : layout.int2ObjectEntrySet()) { - updaters[i++] = createWriter(pair.getIntKey()*4L, cacheRetObj, pair.getValue()); + updaters[i++] = pair.getValue().writingFactory.get(pair.getIntKey()*4L); } updater = ptr -> { @@ -273,14 +286,81 @@ public class IrisVoxyRenderPipelineData { }; } - private static CachedUniform[] createUniformSet(CustomUniforms cu, IrisShaderPatch patch) { + private record UniformWritingHolder(String name, UniformType type, Long2ObjectFunction writingFactory) { + + } + private static List createUniformSet(CustomUniforms cu, IrisShaderPatch patch) { //This is a fking awful hack... but it works thinks + + List uniforms = new ArrayList<>(); + Set seenUniforms = new HashSet<>(); DynamicLocationalUniformHolder uniformBuilder = new DynamicLocationalUniformHolder() { @Override - public DynamicLocationalUniformHolder addDynamicUniform(Uniform uniform, ValueUpdateNotifier valueUpdateNotifier) { + public DynamicLocationalUniformHolder uniform1i(UniformUpdateFrequency updateFrequency, String name, IntSupplier value) { + return this.uniform1i(name, value, null); + } + + @Override + public DynamicLocationalUniformHolder uniform1i(String name, IntSupplier value, ValueUpdateNotifier notifier) { + this.injectDynamicUniformType(name, UniformType.INT, offset->{ + return ptr->{ + MemoryUtil.memPutInt(ptr+offset, value.getAsInt()); + }; + }); return this; } + + @Override + public DynamicLocationalUniformHolder uniform1f(UniformUpdateFrequency updateFrequency, String name, FloatSupplier value) { + return this.uniform1f(name, value, null); + } + + @Override + public DynamicLocationalUniformHolder uniform1f(String name, FloatSupplier value, ValueUpdateNotifier notifier) { + this.injectDynamicUniformType(name, UniformType.FLOAT, offset->{ + return ptr->{ + MemoryUtil.memPutFloat(ptr+offset, value.getAsFloat()); + }; + }); + return this; + } + + + @Override + public DynamicLocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value) { + return this.uniform3f(name, value, null); + } + + @Override + public DynamicLocationalUniformHolder uniform3f(String name, Supplier value, ValueUpdateNotifier notifier) { + this.injectDynamicUniformType(name, UniformType.VEC3, offset->{ + return ptr->{ + value.get().getToAddress(ptr+offset); + }; + }); + return this; + } + + private void injectDynamicUniformType(String name, UniformType type, Long2ObjectFunction supplier) { + var names = patch.getUniformList(); + for (int i = 0; i < names.length; i++) { + if (names[i].equals(name)) { + if (!seenUniforms.add(name)) { + throw new IllegalArgumentException("Already added uniform: " + name); + } + uniforms.add(new UniformWritingHolder(name, type, supplier)); + break; + } + } + } + + @Override + public DynamicLocationalUniformHolder addDynamicUniform(Uniform uniform, ValueUpdateNotifier valueUpdateNotifier) { + throw new IllegalStateException("Type not implemented for uniform: " + uniform); + //return this; + } + @Override public LocationalUniformHolder addUniform(UniformUpdateFrequency uniformUpdateFrequency, Uniform uniform) { return this; @@ -303,24 +383,27 @@ public class IrisVoxyRenderPipelineData { return null; } }; - //CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_FRAGMENT); + CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_FRAGMENT); cu.assignTo(uniformBuilder); cu.mapholderToPass(uniformBuilder, patch); - CachedUniform[] uniforms = new CachedUniform[patch.getUniformList().length]; - ((CustomUniformsAccessor)cu).getLocationMap().get(patch).object2IntEntrySet().forEach(entry->uniforms[entry.getIntValue()] = entry.getKey()); - int i = 0; - int j = 0; - for (var uniform : uniforms) { - if (uniform == null) { - Logger.error("Unknown uniform at location "+j + " skipping, uniform name: " + patch.getUniformList()[j]); - } else { - uniforms[i++] = uniform;//This shuffles the uniforms down till its compacted + FunctionReturn cachedReturn = new FunctionReturn(); + ((CustomUniformsAccessor)cu).getLocationMap().get(patch).object2IntEntrySet().forEach(entry-> { + if (!seenUniforms.add(entry.getKey().getName())) { + throw new IllegalArgumentException("Already added uniform: " + entry.getKey().getName()); } - j++; + uniforms.add(new UniformWritingHolder(entry.getKey().getName(), Type.convert(entry.getKey().getType()),offset->createWriter(offset, cachedReturn, entry.getKey()))); + }); + + if (uniforms.size() != patch.getUniformList().length) { + Set uniformsUnseen = new HashSet<>(List.of(patch.getUniformList())); + for (var uniform : uniforms) { + uniformsUnseen.remove(uniform.name); + } + Logger.error("The following uniforms could not be found: [" + uniformsUnseen.stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(","))+"]"); } //In _theory_ this should work? - return Arrays.copyOf(uniforms, i); + return uniforms; } private record TextureWSampler(String name, IntSupplier texture, int sampler) { }