diff --git a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java index 9abdebfed..c44355940 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java +++ b/src/main/java/com/jozufozu/flywheel/backend/gl/versioned/GlCompat.java @@ -9,6 +9,8 @@ import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; +import net.minecraft.Util; + /** * An instance of this class stores information about what OpenGL features are available. *
@@ -19,13 +21,27 @@ public class GlCompat { public final InstancedArrays instancedArrays; public final BufferStorage bufferStorage; + public final boolean amd; public GlCompat(GLCapabilities caps) { instancedArrays = getLatest(InstancedArrays.class, caps); bufferStorage = getLatest(BufferStorage.class, caps); + + + if (Util.getPlatform() == Util.OS.WINDOWS) { + String vendor = GL20C.glGetString(GL20C.GL_VENDOR); + // vendor string I got was "ATI Technologies Inc." + amd = vendor.contains("ATI") || vendor.contains("AMD"); + } else { + amd = false; + } } - public boolean instancedArraysSupported() { + public boolean onAMDWindows() { + return amd; + } + + public boolean instancedArraysSupported() { return instancedArrays != InstancedArrays.UNSUPPORTED; } diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java index efc77ce9a..a2c0075d3 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/GPUInstancer.java @@ -77,7 +77,7 @@ public class GPUInstancer extends AbstractInstancer { model = modelAllocator.alloc(modelData, arenaModel -> { vao.bind(); - model.setupState(); + arenaModel.setupState(); }); vao.bind(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java index dc8678362..791dea79d 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterial.java @@ -5,10 +5,13 @@ import java.util.function.Supplier; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.RenderWork; import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.Instancer; import com.jozufozu.flywheel.api.Material; +import com.jozufozu.flywheel.backend.model.ImmediateAllocator; +import com.jozufozu.flywheel.backend.model.ModelAllocator; import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.api.struct.StructType; import com.jozufozu.flywheel.core.Formats; @@ -20,14 +23,18 @@ import com.jozufozu.flywheel.core.model.Model; */ public class InstancedMaterial implements Material { - final ModelPool modelPool; + final ModelAllocator allocator; protected final Cache> models; protected final StructType type; public InstancedMaterial(StructType spec) { this.type = spec; - modelPool = new ModelPool(Formats.UNLIT_MODEL, 64); + if (Backend.getInstance().compat.onAMDWindows()) { + allocator = ImmediateAllocator.INSTANCE; + } else { + allocator = new ModelPool(Formats.UNLIT_MODEL, 64); + } this.models = CacheBuilder.newBuilder() .removalListener(notification -> { GPUInstancer instancer = (GPUInstancer) notification.getValue(); @@ -46,7 +53,7 @@ public class InstancedMaterial implements Material { @Override public Instancer model(Object key, Supplier modelSupplier) { try { - return models.get(key, () -> new GPUInstancer<>(type, modelSupplier.get(), modelPool)); + return models.get(key, () -> new GPUInstancer<>(type, modelSupplier.get(), allocator)); } catch (ExecutionException e) { throw new RuntimeException("error creating instancer", e); } @@ -61,7 +68,7 @@ public class InstancedMaterial implements Material { public void delete() { models.invalidateAll(); - modelPool.delete(); + if (allocator instanceof ModelPool pool) pool.delete(); } /** diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialRenderer.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialRenderer.java index 9d52ea695..a6ab47680 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialRenderer.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/instancing/InstancedMaterialRenderer.java @@ -4,6 +4,7 @@ import java.util.Collection; import java.util.function.Consumer; import java.util.function.Supplier; +import com.jozufozu.flywheel.backend.model.ModelPool; import com.jozufozu.flywheel.core.shader.WorldProgram; import com.mojang.math.Matrix4f; @@ -28,8 +29,10 @@ public class InstancedMaterialRenderer

{ // initialize all uninitialized instancers... instancers.forEach(GPUInstancer::init); - // ...and then flush the model arena in case anything was marked for upload - material.modelPool.flush(); + if (material.allocator instanceof ModelPool pool) { + // ...and then flush the model arena in case anything was marked for upload + pool.flush(); + } P program = this.program.get(); diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java index f22818d32..02ab9606b 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/IndexedModel.java @@ -43,6 +43,8 @@ public class IndexedModel extends BufferedModel { public void drawInstances(int instanceCount) { if (!valid()) return; + ebo.bind(); + GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount); } } diff --git a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java index 5a1d033f6..72f7973e2 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java +++ b/src/main/java/com/jozufozu/flywheel/backend/model/ModelPool.java @@ -120,9 +120,12 @@ public class ModelPool implements ModelAllocator { VecBufferWriter consumer = new VecBufferWriter(buffer); + int vertices = 0; for (PooledModel model : models) { + model.first = vertices; model.model.buffer(consumer); if (model.callback != null) model.callback.onAlloc(model); + vertices += model.getVertexCount(); } } catch (Exception e) { diff --git a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java index 674f48255..1935c5406 100644 --- a/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java +++ b/src/main/java/com/jozufozu/flywheel/vanilla/ChestInstance.java @@ -125,80 +125,76 @@ public class ChestInstance extends TileE private ModelPart getBaseModel() { - switch (chestType) { - case LEFT: - return ModelPart.builder("chest_base_left", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 19) - .start(0, 0, 1) - .size(15, 10, 14) - .endCuboid() - .build(); - case RIGHT: - return ModelPart.builder("chest_base_right", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 19) - .start(1, 0, 1) - .size(15, 10, 14) - .endCuboid() - .build(); - } + return switch (chestType) { + case LEFT -> ModelPart.builder("chest_base_left", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 19) + .start(0, 0, 1) + .size(15, 10, 14) + .endCuboid() + .build(); + case RIGHT -> ModelPart.builder("chest_base_right", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 19) + .start(1, 0, 1) + .size(15, 10, 14) + .endCuboid() + .build(); + default -> ModelPart.builder("chest_base", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 19) + .start(1, 0, 1) + .end(15, 10, 15) + .endCuboid() + .build(); + }; - return ModelPart.builder("chest_base", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 19) - .start(1, 0, 1) - .end(15, 10, 15) - .endCuboid() - .build(); } private ModelPart getLidModel() { - switch (chestType) { - case LEFT: - return ModelPart.builder("chest_lid_left", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 0) - .start(0, 0, 1) - .size(15, 5, 14) - .endCuboid() - .cuboid() - .start(0, -2, 15) - .size(1, 4, 1) - .endCuboid() - .build(); - case RIGHT: - return ModelPart.builder("chest_lid_right", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 0) - .start(1, 0, 1) - .size(15, 5, 14) - .endCuboid() - .cuboid() - .start(15, -2, 15) - .size(1, 4, 1) - .endCuboid() - .build(); - } + return switch (chestType) { + case LEFT -> ModelPart.builder("chest_lid_left", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 0) + .start(0, 0, 1) + .size(15, 5, 14) + .endCuboid() + .cuboid() + .start(0, -2, 15) + .size(1, 4, 1) + .endCuboid() + .build(); + case RIGHT -> ModelPart.builder("chest_lid_right", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 0) + .start(1, 0, 1) + .size(15, 5, 14) + .endCuboid() + .cuboid() + .start(15, -2, 15) + .size(1, 4, 1) + .endCuboid() + .build(); + default -> ModelPart.builder("chest_lid", 64, 64) + .sprite(renderMaterial.sprite()) + .cuboid() + .textureOffset(0, 0) + .start(1, 0, 1) + .size(14, 5, 14) + .endCuboid() + .cuboid() + .start(7, -2, 15) + .size(2, 4, 1) + .endCuboid() + .build(); + }; - return ModelPart.builder("chest_lid", 64, 64) - .sprite(renderMaterial.sprite()) - .cuboid() - .textureOffset(0, 0) - .start(1, 0, 1) - .size(14, 5, 14) - .endCuboid() - .cuboid() - .start(7, -2, 15) - .size(2, 4, 1) - .endCuboid() - .build(); } public static boolean isChristmas() {