Fabric API

Fabric API

106M Downloads

CoreShaderRegistrationCallback is called multiple times on shader reload in 1.20.x

Draylar opened this issue ยท 0 comments

commented

Issue

CoreShaderRegistrationCallback class docs:

Called when core shaders ({@linkplain ShaderProgram shader programs} loaded from {@code assets/<namespace>/shaders/core})
are loaded to register custom modded shaders.

My understanding of this callback is that it should run once when core shader assets are reloaded - but in 1.20.1, it seems to trigger every time a core vanilla shader is loaded in GameRenderer#loadPrograms. In the following test suite example, the shader is actually loaded about 60 times in a vanilla environment. You can verify this by writing a core shader file with an unreferenced uniform - the game will spit out a warning ~60 times (equal to the number of vanilla core shaders loaded in the inject method target).

CoreShaderRegistrationCallback.EVENT.register(context -> {
// Register a custom shader taking POSITION vertices.
Identifier id = new Identifier("fabric-rendering-v1-testmod", "test");
context.register(id, VertexFormats.POSITION, program -> testShader = program);
});

You can also stick a breakpoint in here & see that any custom program is added to programs ~60 times:

private void registerShaders(ResourceFactory factory, CallbackInfo info, List<?> shaderStages, List<Pair<ShaderProgram, Consumer<ShaderProgram>>> programs) throws IOException {
CoreShaderRegistrationCallback.RegistrationContext context = (id, vertexFormat, loadCallback) -> {
ShaderProgram program = new FabricShaderProgram(factory, id, vertexFormat);
programs.add(Pair.of(program, loadCallback));
};
CoreShaderRegistrationCallback.EVENT.invoker().registerShaders(context);

Solution

I think the Slice is messed up in the inject, but I don't know enough about them to propose a fix. I personally would drop the Slice and inject at List#add, ordinal 0 (which would give the expected behavior of the callback only running once) - or inject at the clearPrograms call, which would let modded core shaders load after vanilla core shaders.

Versions

minecraft_version=1.20.1
yarn_mappings=1.20.1+build.8
loader_version=0.14.21