From 07977d398cc257a88dff502e567e8bba570ee925 Mon Sep 17 00:00:00 2001 From: Ocelot Date: Tue, 26 Nov 2024 15:47:11 -0700 Subject: [PATCH] Added shader validation --- .../render/shader/ShaderProgramImpl.java | 9 +++- .../dynamicbuffer/ShaderInstanceMixin.java | 44 ++++++++++--------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/common/src/main/java/foundry/veil/impl/client/render/shader/ShaderProgramImpl.java b/common/src/main/java/foundry/veil/impl/client/render/shader/ShaderProgramImpl.java index c9d8e4ef..f8b6f587 100644 --- a/common/src/main/java/foundry/veil/impl/client/render/shader/ShaderProgramImpl.java +++ b/common/src/main/java/foundry/veil/impl/client/render/shader/ShaderProgramImpl.java @@ -26,6 +26,7 @@ import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.Resource; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -129,10 +130,16 @@ private void link() throws ShaderException { glLinkProgram(this.program); if (glGetProgrami(this.program, GL_LINK_STATUS) != GL_TRUE) { - String log = glGetProgramInfoLog(this.program); + String log = StringUtils.trim(glGetProgramInfoLog(this.program)); throw new ShaderException("Failed to link shader", log); } + glValidateProgram(this.program); + if (glGetProgrami(this.program, GL_VALIDATE_STATUS) != GL_TRUE) { + String log = StringUtils.trim(glGetProgramInfoLog(this.program)); + Veil.LOGGER.warn("Failed to validate shader ({}) : {}", this.id, log); + } + this.attachedShaders.values().forEach(shader -> { shader.apply(this); this.definitionDependencies.addAll(shader.definitionDependencies()); diff --git a/common/src/main/java/foundry/veil/mixin/client/dynamicbuffer/ShaderInstanceMixin.java b/common/src/main/java/foundry/veil/mixin/client/dynamicbuffer/ShaderInstanceMixin.java index fa3e25f8..98c05513 100644 --- a/common/src/main/java/foundry/veil/mixin/client/dynamicbuffer/ShaderInstanceMixin.java +++ b/common/src/main/java/foundry/veil/mixin/client/dynamicbuffer/ShaderInstanceMixin.java @@ -1,8 +1,6 @@ package foundry.veil.mixin.client.dynamicbuffer; -import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.shaders.Program; -import com.mojang.blaze3d.shaders.ProgramManager; import com.mojang.blaze3d.shaders.Shader; import com.mojang.blaze3d.shaders.Uniform; import com.mojang.blaze3d.vertex.VertexFormat; @@ -12,7 +10,6 @@ import foundry.veil.mixin.accessor.ProgramAccessor; import net.minecraft.client.renderer.ShaderInstance; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceProvider; import org.apache.commons.lang3.StringUtils; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; @@ -29,12 +26,10 @@ @Mixin(ShaderInstance.class) public abstract class ShaderInstanceMixin implements Shader, ShaderInstanceExtension { - @Mutable @Shadow @Final private Program vertexProgram; - @Mutable @Shadow @Final private Program fragmentProgram; @@ -77,38 +72,45 @@ public void apply(CallbackInfo ci) { try { ProgramAccessor vertexAccessor = (ProgramAccessor) this.vertexProgram; ProgramAccessor fragmentAccessor = (ProgramAccessor) this.fragmentProgram; + int vertexShader = vertexAccessor.getId(); + int fragmentShader = fragmentAccessor.getId(); - glDetachShader(this.programId, vertexAccessor.getId()); - glDetachShader(this.programId, fragmentAccessor.getId()); - - GlStateManager.glShaderSource(vertexAccessor.getId(), List.of(this.veil$vertexSource)); - GlStateManager.glCompileShader(vertexAccessor.getId()); - if (GlStateManager.glGetShaderi(vertexAccessor.getId(), GL_COMPILE_STATUS) != GL_TRUE) { - String error = StringUtils.trim(glGetShaderInfoLog(vertexAccessor.getId())); + glShaderSource(vertexShader, this.veil$vertexSource); + glCompileShader(vertexShader); + if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) != GL_TRUE) { + String error = StringUtils.trim(glGetShaderInfoLog(vertexShader)); throw new IOException("Couldn't compile vertex program (" + this.vertexProgram.getName() + ", " + this.name + ") : " + error); } - GlStateManager.glShaderSource(fragmentAccessor.getId(), List.of(this.veil$fragmentSource)); - GlStateManager.glCompileShader(fragmentAccessor.getId()); - if (GlStateManager.glGetShaderi(fragmentAccessor.getId(), GL_COMPILE_STATUS) != GL_TRUE) { - String error = StringUtils.trim(glGetShaderInfoLog(fragmentAccessor.getId())); + glShaderSource(fragmentShader, this.veil$fragmentSource); + glCompileShader(fragmentShader); + if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) != GL_TRUE) { + String error = StringUtils.trim(glGetShaderInfoLog(fragmentShader)); throw new IOException("Couldn't compile fragment program (" + this.fragmentProgram.getName() + ", " + this.name + ") : " + error); } int i = 0; for (String name : this.vertexFormat.getElementAttributeNames()) { - Uniform.glBindAttribLocation(this.programId, i, name); + glBindAttribLocation(this.programId, i, name); i++; } + glLinkProgram(this.programId); + if (glGetProgrami(this.programId, GL_LINK_STATUS) != GL_TRUE) { + String error = StringUtils.trim(glGetProgramInfoLog(this.programId)); + throw new IOException("Couldn't link shader (" + this.name + ") : " + error); + } + + glValidateProgram(this.programId); + if (glGetProgrami(this.programId, GL_VALIDATE_STATUS) != GL_TRUE) { + String log = StringUtils.trim(glGetProgramInfoLog(this.programId)); + Veil.LOGGER.warn("Couldn't validate shader ({}) : {}", this.name, log); + } + this.uniformLocations.clear(); this.samplerLocations.clear(); this.uniformMap.clear(); - - // Force re-link - ProgramManager.linkShader(this); this.updateLocations(); - this.markDirty(); } catch (Throwable t) { Veil.LOGGER.error("Failed to recompile vanilla shader: {}", this.name, t);