Skip to content

Commit

Permalink
Crude drawlist concept to batch draw calls by program
Browse files Browse the repository at this point in the history
  • Loading branch information
ultraq committed Jun 28, 2024
1 parent 6947ef5 commit 6f221e5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ abstract class Shader implements GraphicsResource {
}

/**
* Enable the use of this shader for the next rendering commands.
* Enable the use of this shader for all of the rendering commands within the
* given closure.
*/
abstract void use()
abstract void use(Closure closure)
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory
import static org.lwjgl.opengl.GL11C.*
import static org.lwjgl.opengl.GL20C.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
import static org.lwjgl.opengl.GL20C.glUseProgram
import static org.lwjgl.opengl.GL30C.GL_FRAMEBUFFER
import static org.lwjgl.opengl.GL30C.glBindFramebuffer
import static org.lwjgl.opengl.GL31C.*
Expand Down Expand Up @@ -292,37 +291,50 @@ class OpenGLRenderer implements GraphicsRenderer {
}
}

private static class DrawList {
Shader shader
final List<Closure> drawCommands = []

void flush() {
shader?.use { ->
drawCommands*.call()
}
shader = null
drawCommands.clear()
}
}

private final DrawList drawList = new DrawList()

@Override
void draw(Mesh mesh, Matrix4f transform, Shader shader, Material material = null) {

averageNanos('draw', 1f, logger) { ->
shader.use()
shader.applyUniforms(transform, material, window)
mesh.bind()
if (mesh.indices) {
glDrawElements(mesh.vertexType, mesh.indices.size(), GL_UNSIGNED_INT, 0)
}
else {
glDrawArrays(mesh.vertexType, 0, mesh.vertices.size())
}
if (shader != drawList.shader) {
drawList.flush()
drawList.shader = shader
}

trigger(new DrawEvent())

// For an error w/ nVidia on Windows, where the program state seems to
// linger when creating a shader with a different layout, eg: we last used
// the Sharp Upscaling shader which has all of colour, position, and
// texcoord attributes, then try to create the Primitives shader which has
// only colour and position. This then manifests as an error on the next
// frame when we call glClear() 🤔
// "Program/shader state performance warning: Vertex shader in program X
// is being recompiled based on GL state"
glUseProgram(0)
drawList.drawCommands << { ->
averageNanos('draw', 1f, logger) { ->
shader.applyUniforms(transform, material, window)
mesh.bind()
if (mesh.indices) {
glDrawElements(mesh.vertexType, mesh.indices.size(), GL_UNSIGNED_INT, 0)
}
else {
glDrawArrays(mesh.vertexType, 0, mesh.vertices.size())
}

trigger(new DrawEvent())
}
}
}

@Override
void setRenderTarget(Framebuffer framebuffer) {

drawList.flush()

if (framebuffer) {
framebuffer.bind()
glViewport(0, 0, framebuffer.texture.width, framebuffer.texture.height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,10 @@ class OpenGLShader extends Shader {
}

@Override
void use() {
void use(Closure closure) {

glUseProgram(programId)
closure()
glUseProgram(0)
}
}

0 comments on commit 6f221e5

Please sign in to comment.