From 6f06283f6fb8e22c5652d2c635b350d89b2bb4ee Mon Sep 17 00:00:00 2001 From: Jozufozu Date: Mon, 19 Jul 2021 13:44:49 -0700 Subject: [PATCH] Instancers like suppliers - Instancers accept model suppliers instead of models directly - gpu resource allocation is deferred until render time --- .../backend/instancing/InstanceMaterial.java | 4 +- .../backend/instancing/Instancer.java | 63 +++++++++++-------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java index ea46a0de4..4a2823432 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstanceMaterial.java @@ -59,7 +59,7 @@ public class InstanceMaterial { return models.size() > 0 && models.asMap() .values() .stream() - .allMatch(Instancer::empty); + .allMatch(Instancer::isEmpty); } public void delete() { @@ -100,7 +100,7 @@ public class InstanceMaterial { public Instancer get(Object key, Supplier supplier) { try { - return models.get(key, () -> new Instancer<>(supplier.get(), originCoordinate, spec)); + return models.get(key, () -> new Instancer<>(supplier, originCoordinate, spec)); } catch (ExecutionException e) { e.printStackTrace(); return null; diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java index 43d657350..31f1103d8 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/Instancer.java @@ -20,7 +20,8 @@ public class Instancer { public final Supplier originCoordinate; - protected final BufferedModel model; + protected Supplier gen; + protected BufferedModel model; protected final VertexFormat instanceFormat; protected final IInstanceFactory factory; @@ -35,31 +36,15 @@ public class Instancer { boolean anyToRemove; boolean anyToUpdate; - public Instancer(BufferedModel model, Supplier originCoordinate, MaterialSpec spec) { - this.model = model; + public Instancer(Supplier model, Supplier originCoordinate, MaterialSpec spec) { + this.gen = model; this.factory = spec.getInstanceFactory(); this.instanceFormat = spec.getInstanceFormat(); this.originCoordinate = originCoordinate; - - if (model.getVertexCount() <= 0) - throw new IllegalArgumentException("Refusing to instance a model with no vertices."); - - vao = new GlVertexArray(); - instanceVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER); - - vao.bind(); - - // bind the model's vbo to our vao - model.setupState(); - - AttribUtil.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount()); - - vao.unbind(); - - model.clearState(); } public void render() { + if (!isInitialized()) init(); if (deleted) return; vao.bind(); @@ -82,7 +67,33 @@ public class Instancer { return instanceData; } - public boolean empty() { + private void init() { + model = gen.get(); + gen = null; + + if (model.getVertexCount() <= 0) + throw new IllegalArgumentException("Refusing to instance a model with no vertices."); + + vao = new GlVertexArray(); + instanceVBO = new GlBuffer(GlBufferType.ARRAY_BUFFER); + + vao.bind(); + + // bind the model's vbo to our vao + model.setupState(); + + AttribUtil.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount()); + + vao.unbind(); + + model.clearState(); + } + + public boolean isInitialized() { + return gen != null; + } + + public boolean isEmpty() { return !anyToUpdate && !anyToRemove && glInstanceCount == 0; } @@ -95,17 +106,19 @@ public class Instancer { } /** - * Free acquired resources. Attempting to use this after calling delete is undefined behavior. + * Free acquired resources. All other Instancer methods are undefined behavior after calling delete. */ public void delete() { if (deleted) return; deleted = true; - model.delete(); + if (isInitialized()) { + model.delete(); - instanceVBO.delete(); - vao.delete(); + instanceVBO.delete(); + vao.delete(); + } } protected void renderSetup() {