Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a940aca
chore: remove ApiStatus.Internal in mixin classes, add ApiStatus.Inte…
ZhuRuoLing Aug 7, 2026
6ca7cd7
feat(rendering): add occlusion culling part 1
ZhuRuoLing Aug 7, 2026
fb6fea0
feat(rendering): migrate GL calls in ALRComputeCapabilities to ALRHIC…
ZhuRuoLing Aug 11, 2026
8f2358f
feat(opts-hiz-occlusion): 感谢amd开源
ZhuRuoLing Aug 11, 2026
4cdf68c
feat(rendering): batch GPU occlusion queries with dynamic uniforms
ZhuRuoLing Aug 13, 2026
6a630c8
feat(rendering): add Hi-Z texture culling foundation
ZhuRuoLing Aug 14, 2026
a385c94
feat(rendering): cull occluded feature submits
ZhuRuoLing Aug 28, 2026
cd3f9f6
fix: gradle does not sync
ZhuRuoLing Aug 28, 2026
109d21f
feat(rendering): make gpu query occlusion culling work
ZhuRuoLing Aug 29, 2026
c643033
feat(rendering): move matrix mul to gpu
ZhuRuoLing Aug 29, 2026
5d9ccce
fix(rendering): fix some compute bugs
ZhuRuoLing Aug 29, 2026
cd257f3
feat(rendering): implement hiz depth convert
ZhuRuoLing Sep 1, 2026
56219c1
feat(rendering): make it compile
ZhuRuoLing Sep 1, 2026
fd1dbfd
feat(rendering): bindless texture
ZhuRuoLing Sep 1, 2026
cb62b72
feat(rendering): make it compile x2
ZhuRuoLing Sep 1, 2026
87e7728
feat(rendering): it does not compile
ZhuRuoLing Sep 3, 2026
0c0cff6
feat(rendering): add bindless texturing support
ZhuRuoLing Sep 4, 2026
4e596f7
feat(rendering): make ffx spd bindless working
ZhuRuoLing Sep 4, 2026
c46da48
feat(rendering): std140可以停更吗 这个好难看
ZhuRuoLing Sep 4, 2026
820669f
feat(rendering): std140可以停更吗 这个好难看
ZhuRuoLing Sep 4, 2026
621a9cb
feat(rendering): 很有可能是外星文明的伪装
ZhuRuoLing Sep 5, 2026
8748bdf
feat(rendering): 找一车kipfel弄你
ZhuRuoLing Sep 8, 2026
6ef7ff2
feat(rendering): 也不是不能用
ZhuRuoLing Sep 8, 2026
298d8d9
feat(rendering): 大脑升级 就绪
ZhuRuoLing Sep 8, 2026
8db5d12
feat(rendering): 对不起我把电脑玩炸了
ZhuRuoLing Sep 8, 2026
3249356
feat(rendering): add no lds ffx spd
ZhuRuoLing Sep 8, 2026
7fda223
feat(rendering): SO AMD FUCK U
ZhuRuoLing Sep 8, 2026
29e0ae2
feat(rendering): add ApiStatus.Internal annotation and cache disposing
ZhuRuoLing Sep 9, 2026
5a16c60
feat(rendering): fix ai slop
ZhuRuoLing Sep 9, 2026
d76bccc
feat(rendering): add more @ApiStatus.Internal
ZhuRuoLing Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 54 additions & 49 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,59 @@ repositories {

dependencies {}

tasks.register("createModule") {
if (!project.hasProperty('id')) {
throw new GradleException("Id property is required. Use -Pid=<id> to specify the version.")
}
String id = project.property("id")
if (id.matches("[A-Z]+")) {
throw new GradleException("Id cannot be all uppercase.")
}
String underlinedId = id.replace('-', '_')
String mod_id = "anvillib_$underlinedId"
String bigHumpName = id.split('-').collect { it.substring(0, 1).toUpperCase() + it.substring(1) }.join()
String mod_name = "AnvilLib-$bigHumpName"
String class_name = "AnvilLib$bigHumpName"
File buildGradle = file("module.$id/build.gradle")
File gradleProperties = file("module.$id/gradle.properties")
File mainClass = file("module.$id/src/main/java/dev/anvilcraft/lib/v2/$underlinedId/${class_name}.java")
File packageInfo = file("module.$id/src/main/java/dev/anvilcraft/lib/v2/$underlinedId/package-info.java")
File modInfoPath = file("module.$id/src/main/resources/META-INF/")
File mixinConfig = file("module.$id/src/main/resources/${mod_id}.mixins.json")
buildGradle.parentFile.mkdirs()
mainClass.parentFile.mkdirs()
modInfoPath.mkdirs()
buildGradle.createNewFile()
gradleProperties.createNewFile()
mainClass.createNewFile()
mixinConfig.createNewFile()
copy {
from file("module.main/src/main/resources/META-INF/neoforge.mods.toml")
into modInfoPath
}
copy {
from file("module.main/src/main/resources/icon.png")
into file("module.$id/src/main/resources/")
}
class CreateModuleTask extends DefaultTask {
@TaskAction
void onCreateModule() {
if (!project.hasProperty('id')) {
throw new GradleException("Id property is required. Use -Pid=<id> to specify the version.")
}
String id = project.property("id")
if (id.matches("[A-Z]+")) {
throw new GradleException("Id cannot be all uppercase.")
}
String underlinedId = id.replace('-', '_')
String mod_id = "anvillib_$underlinedId"
String bigHumpName = id.split('-').collect { it.substring(0, 1).toUpperCase() + it.substring(1) }.join()
String mod_name = "AnvilLib-$bigHumpName"
String class_name = "AnvilLib$bigHumpName"
File buildGradle = file("module.$id/build.gradle")
File gradleProperties = file("module.$id/gradle.properties")
File mainClass = file("module.$id/src/main/java/dev/anvilcraft/lib/v2/$underlinedId/${class_name}.java")
File packageInfo = file("module.$id/src/main/java/dev/anvilcraft/lib/v2/$underlinedId/package-info.java")
File modInfoPath = file("module.$id/src/main/resources/META-INF/")
File mixinConfig = file("module.$id/src/main/resources/${mod_id}.mixins.json")
buildGradle.parentFile.mkdirs()
mainClass.parentFile.mkdirs()
modInfoPath.mkdirs()
buildGradle.createNewFile()
gradleProperties.createNewFile()
mainClass.createNewFile()
mixinConfig.createNewFile()
copy {
from file("module.main/src/main/resources/META-INF/neoforge.mods.toml")
into modInfoPath
}
copy {
from file("module.main/src/main/resources/icon.png")
into file("module.$id/src/main/resources/")
}

buildGradle.write(
"""
buildGradle.write(
"""
dependencies {
}
""".stripIndent().trim()
)
gradleProperties.write(
"""
)
gradleProperties.write(
"""
## Mod Properties
mod_id=$mod_id
mod_name=$mod_name
mod_description=
""".stripIndent().trim()
)
mainClass.write(
"""
)
mainClass.write(
"""
package dev.anvilcraft.lib.v2.$underlinedId;

import net.minecraft.resources.Identifier;
Expand All @@ -82,17 +84,17 @@ tasks.register("createModule") {
}
}
""".stripIndent().trim()
)
packageInfo.write(
"""
)
packageInfo.write(
"""
@NullMarked
package dev.anvilcraft.lib.v2.$underlinedId;

import org.jspecify.annotations.NullMarked;
""".stripIndent().trim()
)
mixinConfig.write(
"""
)
mixinConfig.write(
"""
{
"required": true,
"minVersion": "0.8",
Expand All @@ -108,9 +110,12 @@ tasks.register("createModule") {
}
}
""".stripIndent().trim()
)
)
}
}

tasks.register("createModule", CreateModuleTask)

subprojects {
if (it.name == "renderdoc-loader-internal") return
if (it.name == "anvillib-sync-processor-neoforge-26.1") return
Expand Down
8 changes: 7 additions & 1 deletion module.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ neoForge {
clientIrisWorkaround {
client()
systemProperty('neoforge.enabledGameTestNamespaces', project.mod_id)
systemProperty("neoforge.disableGlValidation", "true")
systemProperty('neoforge.enabledGameTestNamespaces', project.mod_id)
systemProperty("alrTextureDebugClear", "true")
jvmArgument("-XX:+UseParallelGC")
jvmArgument("-XX:+UnlockDiagnosticVMOptions")
jvmArgument("-XX:+DebugNonSafepoints")
programArgument("--renderDebugLabels")

}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package dev.anvilcraft.lib.v2.rendering;

import dev.anvilcraft.lib.v2.rendering.event.RegisterComputePipelinesEvent;
import dev.anvilcraft.lib.v2.rendering.extension.blaze3d.compute.pipeline.ALRComputePipeline;
import net.minecraft.client.renderer.ShaderDefines;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;

@EventBusSubscriber(Dist.CLIENT)
public class ALRComputePipelines {
public static final ALRComputePipeline FFX_SPD_DOWNSAMPLE_PASS = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("ffx_spd_downsample_pass"))
.withShader(AnvilLibRendering.location("compute/ffx_spd_downsample_pass.csh"))
.withDefines(
ShaderDefines.builder()
// .define("SPD_MAX_MIP_LEVELS", 5) // minium required value in spec of GL_MAX_IMAGE_UNITS is 8, spd use one for input tex, one for mid tex
.define("FFX_SPD_OPTION_DOWNSAMPLE_FILTER", "2") // use max for HZB
.define("FFX_SPD_OPTION_WAVE_INTEROP_LDS", 0) // weird inverted
.build()
)
.withUniformBlock("cbFSR1")
.withTexture("r_input_downsample_src")
.withShaderStorage("rw_internal_global_atomic")
.withReadWriteImage("rw_input_downsample_src_mid_mip")
.withArrayOfImage("rw_input_downsample_src_mips", true, true, 13)
.build();

public static final ALRComputePipeline FFX_SPD_DOWNSAMPLE_PASS_BINDLESS = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("ffx_spd_downsample_pass_bindless"))
.withShader(AnvilLibRendering.location("compute/ffx_spd_downsample_pass_bindless.csh"))
.withDefines(
ShaderDefines.builder()
// .define("SPD_MAX_MIP_LEVELS", 4) // minium required value in spec of GL_MAX_IMAGE_UNITS is 8, spd use one for input tex
.define("FFX_SPD_OPTION_DOWNSAMPLE_FILTER", "2") // use max for HZB
.define("FFX_SPD_OPTION_WAVE_INTEROP_LDS", 0) // weird inverted
.build()
)
.withUniformBlock("cbFSR1")
.withTexture("r_input_downsample_src")
.withShaderStorage("rw_internal_global_atomic")
.withReadWriteImage("rw_input_downsample_src_mid_mip")
.withBindlessArrayOfImage("rw_input_downsample_src_mips", true, true, 13)
.build();

public static final ALRComputePipeline FFX_SPD_DOWNSAMPLE_PASS_NO_LDS = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("ffx_spd_downsample_pass_no_lds"))
.withShader(AnvilLibRendering.location("compute/ffx_spd_downsample_pass.csh"))
.withDefines(
ShaderDefines.builder()
// .define("SPD_MAX_MIP_LEVELS", 5) // minium required value in spec of GL_MAX_IMAGE_UNITS is 8, spd use one for input tex, one for mid tex
.define("FFX_SPD_OPTION_DOWNSAMPLE_FILTER", "2") // use max for HZB
.define("FFX_SPD_OPTION_WAVE_INTEROP_LDS", 1) // weird inverted
.build()
)
.withUniformBlock("cbFSR1")
.withTexture("r_input_downsample_src")
.withShaderStorage("rw_internal_global_atomic")
.withReadWriteImage("rw_input_downsample_src_mid_mip")
.withArrayOfImage("rw_input_downsample_src_mips", true, true, 13)
.build();

public static final ALRComputePipeline FFX_SPD_DOWNSAMPLE_PASS_BINDLESS_NO_LDS = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("ffx_spd_downsample_pass_bindless_no_lds"))
.withShader(AnvilLibRendering.location("compute/ffx_spd_downsample_pass_bindless.csh"))
.withDefines(
ShaderDefines.builder()
// .define("SPD_MAX_MIP_LEVELS", 4) // minium required value in spec of GL_MAX_IMAGE_UNITS is 8, spd use one for input tex
.define("FFX_SPD_OPTION_DOWNSAMPLE_FILTER", "2") // use max for HZB
.define("FFX_SPD_OPTION_WAVE_INTEROP_LDS", 1) // weird inverted
.build()
)
.withUniformBlock("cbFSR1")
.withTexture("r_input_downsample_src")
.withShaderStorage("rw_internal_global_atomic")
.withReadWriteImage("rw_input_downsample_src_mid_mip")
.withBindlessArrayOfImage("rw_input_downsample_src_mips", true, true, 13)
.build();

public static final ALRComputePipeline DEPTH_CONVERT = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("depth_convert"))
.withShader(AnvilLibRendering.location("compute/depth_convert.csh"))
.withUniformBlock("ConvertParam")
.withTexture("Input")
.withWriteOnlyImage("Output")
.build();

public static final ALRComputePipeline HIZ_OCCLUSION_TEST = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("hiz_occlusion_test"))
.withShader(AnvilLibRendering.location("compute/hiz_occlusion_test.csh"))
.withUniformBlock("cbOcclusionTest")
.withShaderStorage("ShaderInput")
.withShaderStorage("ShaderOutput")
.withArrayOfImage("uInputs", true, false, 13)
.build();

public static final ALRComputePipeline HIZ_OCCLUSION_TEST_BINDLESS = ALRComputePipeline.builder()
.withName(AnvilLibRendering.location("hiz_occlusion_test_bindless"))
.withShader(AnvilLibRendering.location("compute/hiz_occlusion_test_bindless.csh"))
.withUniformBlock("cbOcclusionTest")
.withShaderStorage("ShaderInput")
.withShaderStorage("ShaderOutput")
.withBindlessArrayOfImage("uInputs", true, false, 13)
.build();

@SubscribeEvent
public static void on(RegisterComputePipelinesEvent event) {
event.registerPipeline(FFX_SPD_DOWNSAMPLE_PASS);
event.registerPipeline(FFX_SPD_DOWNSAMPLE_PASS_BINDLESS);
event.registerPipeline(FFX_SPD_DOWNSAMPLE_PASS_BINDLESS_NO_LDS);
event.registerPipeline(FFX_SPD_DOWNSAMPLE_PASS_NO_LDS);

event.registerPipeline(DEPTH_CONVERT);
event.registerPipeline(HIZ_OCCLUSION_TEST);
event.registerPipeline(HIZ_OCCLUSION_TEST_BINDLESS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.anvilcraft.lib.v2.rendering;

import dev.anvilcraft.lib.v2.rendering.debug.OcclusionCullingDebugEntry;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RegisterDebugEntriesEvent;

@EventBusSubscriber(Dist.CLIENT)
public class ALRDebugEntries {
@SubscribeEvent
public static void on(RegisterDebugEntriesEvent event) {
event.register(OcclusionCullingDebugEntry.LOCATION, new OcclusionCullingDebugEntry());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.anvilcraft.lib.v2.rendering;

import com.mojang.blaze3d.systems.RenderSystem;
import dev.anvilcraft.lib.v2.rendering.optimization.occlusion.OcclusionCuller;
import org.jspecify.annotations.Nullable;

public class ALROptimizations {
private static OcclusionCuller occlusionCuller;

public static OcclusionCuller getOcclusionCuller() {
if (occlusionCuller == null) {
occlusionCuller = OcclusionCuller.createInstance(RenderSystem.getDevice());
}
return occlusionCuller;
}

public static void create() {
occlusionCuller = OcclusionCuller.createInstance(RenderSystem.getDevice());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.anvilcraft.lib.v2.rendering;

import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.Nullable;

@SuppressWarnings("SameParameterValue")
@Slf4j
public class ALROptions {
public static final boolean SPD_OPTION_WAVE_INTEROP_LDS = getPropertyBoolean("alrSpdOptionUseWaveInteropLds");
public static final boolean OCCLUSION_QUERY_USE_FRUSTUM_PRE_PASS = getPropertyBoolean("alrOcclusionQueryUseFrustumPrePass", false);
public static final String OCCLUSION_CULLING_FORCE_IMPL = getProperty("alrOcclusionCullingForceImplementation", null);
public static final boolean TEXTURE_DEBUG_CLEAR = getPropertyBoolean("alrTextureDebugClear", false);

public static void logAllOptions() {
log.info("ALR options: SPD_OPTION_WAVE_INTEROP_LDS={}, OCCLUSION_QUERY_USE_FRUSTUM_PRE_PASS={}, OCCLUSION_CULLING_FORCE_IMPL={}, TEXTURE_DEBUG_CLEAR={}",
SPD_OPTION_WAVE_INTEROP_LDS,
OCCLUSION_QUERY_USE_FRUSTUM_PRE_PASS,
OCCLUSION_CULLING_FORCE_IMPL,
TEXTURE_DEBUG_CLEAR
);
}

private static String getProperty(String key, @Nullable String defaultValue) {
return System.getProperty(key, defaultValue);
}

private static boolean getPropertyBoolean(String key, boolean defaultValue) {
String prop = System.getProperty(key);
if (prop == null) {
return defaultValue;
}
return !"false".equals(prop);
}

private static boolean getPropertyBoolean(String key) {
String prop = System.getProperty(key);
return !"false".equals(prop);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

import com.mojang.blaze3d.pipeline.BlendFunction;
import com.mojang.blaze3d.pipeline.ColorTargetState;
import com.mojang.blaze3d.pipeline.DepthStencilState;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import com.mojang.blaze3d.platform.CompareOp;
import com.mojang.blaze3d.shaders.UniformType;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormatElement;
import dev.anvilcraft.lib.v2.rendering.bloom.TransformsUbo;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.RegisterRenderPipelinesEvent;
import org.jetbrains.annotations.ApiStatus;

import java.util.Optional;

@EventBusSubscriber(Dist.CLIENT)
public class ALRPipelines {
public static final RenderPipeline.Snippet POST_PASS = RenderPipeline.builder()
Expand Down Expand Up @@ -76,6 +81,17 @@ public class ALRPipelines {
.withCull(false)
.build();

public static final RenderPipeline OCCLUSION_QUERY = RenderPipeline.builder()
.withLocation(AnvilLibRendering.location("occlusion_query"))
.withVertexFormat(DefaultVertexFormat.POSITION, VertexFormat.Mode.QUADS)
.withUniform("Transforms", UniformType.UNIFORM_BUFFER)
.withVertexShader(AnvilLibRendering.location("core/occlusion_query"))
.withFragmentShader(AnvilLibRendering.location("core/occlusion_query"))
.withColorTargetState(new ColorTargetState(Optional.empty(), ColorTargetState.WRITE_NONE))
.withDepthStencilState(new DepthStencilState(CompareOp.LESS_THAN_OR_EQUAL, false))
.withCull(false)
.build();


@ApiStatus.Internal
@SubscribeEvent
Expand All @@ -86,5 +102,7 @@ public static void on(RegisterRenderPipelinesEvent event) {
event.registerPipeline(UPSAMPLE);

event.registerPipeline(SDF_GRAPHICS);

event.registerPipeline(OCCLUSION_QUERY);
}
}
Loading
Loading