Hot links

- Do not specify layout qualifier for vertex attributes
- Bind attribute locations before linking programs
- Delete gl programs when linking fails
This commit is contained in:
Jozufozu 2024-02-22 14:02:16 -06:00
parent c6ed7c4132
commit a504aa1862
6 changed files with 41 additions and 16 deletions

View file

@ -81,7 +81,7 @@ public class IndirectPrograms extends AbstractPrograms {
.withComponent(IndirectComponent::create) .withComponent(IndirectComponent::create)
.withResource(InstanceType::cullShader) .withResource(InstanceType::cullShader)
.withResource(CULL_SHADER_MAIN)) .withResource(CULL_SHADER_MAIN))
.then((key, program) -> program.setUniformBlockBinding("_FlwFrameUniforms", 0)) .postLink((key, program) -> program.setUniformBlockBinding("_FlwFrameUniforms", 0))
.harness("culling", sources); .harness("culling", sources);
} }

View file

@ -50,7 +50,14 @@ public class PipelineCompiler {
.withResource(key -> key.contextShader() .withResource(key -> key.contextShader()
.fragmentShader()) .fragmentShader())
.withResource(pipeline.fragmentMain())) .withResource(pipeline.fragmentMain()))
.then((key, program) -> { .preLink((key, program) -> {
program.bindAttribLocation("_flw_a_pos", 0);
program.bindAttribLocation("_flw_a_color", 1);
program.bindAttribLocation("_flw_a_texCoord", 2);
program.bindAttribLocation("_flw_a_overlay_light", 3);
program.bindAttribLocation("_flw_a_normal", 4);
})
.postLink((key, program) -> {
program.setUniformBlockBinding("_FlwFrameUniforms", 0); program.setUniformBlockBinding("_FlwFrameUniforms", 0);
program.setUniformBlockBinding("_FlwFogUniforms", 1); program.setUniformBlockBinding("_FlwFogUniforms", 1);

View file

@ -42,7 +42,10 @@ public class Compile<K> {
public static class ProgramStitcher<K> implements CompilationHarness.KeyCompiler<K> { public static class ProgramStitcher<K> implements CompilationHarness.KeyCompiler<K> {
private final Map<ShaderType, ShaderCompiler<K>> compilers = new EnumMap<>(ShaderType.class); private final Map<ShaderType, ShaderCompiler<K>> compilers = new EnumMap<>(ShaderType.class);
private BiConsumer<K, GlProgram> onLink = (k, p) -> { private BiConsumer<K, GlProgram> postLink = (k, p) -> {
};
private BiConsumer<K, GlProgram> preLink = (k, p) -> {
}; };
public CompilationHarness<K> harness(String marker, ShaderSources sources) { public CompilationHarness<K> harness(String marker, ShaderSources sources) {
@ -57,8 +60,13 @@ public class Compile<K> {
return this; return this;
} }
public ProgramStitcher<K> then(BiConsumer<K, GlProgram> onLink) { public ProgramStitcher<K> postLink(BiConsumer<K, GlProgram> postLink) {
this.onLink = onLink; this.postLink = postLink;
return this;
}
public ProgramStitcher<K> preLink(BiConsumer<K, GlProgram> preLink) {
this.preLink = preLink;
return this; return this;
} }
@ -84,10 +92,10 @@ public class Compile<K> {
return null; return null;
} }
var out = programLinker.link(shaders); var out = programLinker.link(shaders, p -> preLink.accept(key, p));
if (out != null) { if (out != null) {
onLink.accept(key, out); postLink.accept(key, out);
} }
return out; return out;

View file

@ -9,6 +9,7 @@ import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glLinkProgram; import static org.lwjgl.opengl.GL20.glLinkProgram;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -23,26 +24,30 @@ public class ProgramLinker {
} }
@Nullable @Nullable
public GlProgram link(List<GlShader> shaders) { public GlProgram link(List<GlShader> shaders, Consumer<GlProgram> preLink) {
// this probably doesn't need caching // this probably doesn't need caching
var linkResult = linkInternal(shaders); var linkResult = linkInternal(shaders, preLink);
stats.linkResult(linkResult); stats.linkResult(linkResult);
return linkResult.unwrap(); return linkResult.unwrap();
} }
private LinkResult linkInternal(List<GlShader> shaders) { private LinkResult linkInternal(List<GlShader> shaders, Consumer<GlProgram> preLink) {
int handle = glCreateProgram(); int handle = glCreateProgram();
var out = new GlProgram(handle);
for (GlShader shader : shaders) { for (GlShader shader : shaders) {
glAttachShader(handle, shader.handle()); glAttachShader(handle, shader.handle());
} }
preLink.accept(out);
glLinkProgram(handle); glLinkProgram(handle);
String log = glGetProgramInfoLog(handle); String log = glGetProgramInfoLog(handle);
if (linkSuccessful(handle)) { if (linkSuccessful(handle)) {
return LinkResult.success(new GlProgram(handle), log); return LinkResult.success(out, log);
} else { } else {
out.delete();
return LinkResult.failure(log); return LinkResult.failure(log);
} }
} }

View file

@ -1,5 +1,6 @@
package com.jozufozu.flywheel.backend.gl.shader; package com.jozufozu.flywheel.backend.gl.shader;
import static org.lwjgl.opengl.GL20.glBindAttribLocation;
import static org.lwjgl.opengl.GL20.glDeleteProgram; import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glGetUniformLocation; import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glUniform1f; import static org.lwjgl.opengl.GL20.glUniform1f;
@ -170,6 +171,10 @@ public class GlProgram extends GlObject implements Shader {
glUniformBlockBinding(handle(), index, binding); glUniformBlockBinding(handle(), index, binding);
} }
public void bindAttribLocation(String attribute, int binding) {
glBindAttribLocation(handle(), binding, attribute);
}
@Override @Override
protected void deleteInternal(int handle) { protected void deleteInternal(int handle) {
glDeleteProgram(handle); glDeleteProgram(handle);

View file

@ -1,8 +1,8 @@
layout(location = 0) in vec3 _flw_a_pos; in vec3 _flw_a_pos;
layout(location = 1) in vec4 _flw_a_color; in vec4 _flw_a_color;
layout(location = 2) in vec2 _flw_a_texCoord; in vec2 _flw_a_texCoord;
layout(location = 3) in ivec4 _flw_a_overlay_light; in ivec4 _flw_a_overlay_light;
layout(location = 4) in vec3 _flw_a_normal; in vec3 _flw_a_normal;
void _flw_layoutVertex() { void _flw_layoutVertex() {
flw_vertexPos = vec4(_flw_a_pos, 1.0); flw_vertexPos = vec4(_flw_a_pos, 1.0);