mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2025-01-27 05:17:56 +01:00
Go through GlVertexArray
- VAO state is now handled by GlVertexArray objects - IndexedModel no longer inherits from VBOModel - BufferedModel doesn't need #clearState - Likely fixes crash on intel drivers
This commit is contained in:
parent
4c4d6b77fc
commit
b5a9741caf
11 changed files with 137 additions and 162 deletions
|
@ -18,9 +18,7 @@ public abstract class GlObject {
|
|||
|
||||
protected final void checkHandle() {
|
||||
if (this.isInvalid()) {
|
||||
String descriptor = getDescriptor();
|
||||
String message = (descriptor == null ? "" : (descriptor + " ")) + "handle is not valid.";
|
||||
throw new IllegalStateException(message);
|
||||
throw new IllegalStateException("handle is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,10 +31,8 @@ public abstract class GlObject {
|
|||
}
|
||||
|
||||
public void delete() {
|
||||
if (isInvalid()) {
|
||||
String descriptor = getDescriptor();
|
||||
String message = (descriptor == null ? "" : (descriptor + " ")) + "handle already deleted.";
|
||||
throw new IllegalStateException(message);
|
||||
if (this.isInvalid()) {
|
||||
throw new IllegalStateException("handle already deleted.");
|
||||
}
|
||||
|
||||
deleteInternal(handle);
|
||||
|
@ -45,7 +41,4 @@ public abstract class GlObject {
|
|||
|
||||
protected abstract void deleteInternal(int handle);
|
||||
|
||||
protected String getDescriptor() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.jozufozu.flywheel.backend.gl;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.layout.LayoutItem;
|
||||
import com.jozufozu.flywheel.mixin.BufferUploaderAccessor;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
||||
public class GlVertexArray extends GlObject {
|
||||
|
@ -20,11 +23,28 @@ public class GlVertexArray extends GlObject {
|
|||
BufferUploaderAccessor.flywheel$setLastVAO(0);
|
||||
}
|
||||
|
||||
public void enableArrays(int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
GL20.glEnableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void disableArrays(int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
GL20.glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void bindAttributes(int startIndex, BufferLayout type) {
|
||||
int offset = 0;
|
||||
for (LayoutItem spec : type.getLayoutItems()) {
|
||||
spec.vertexAttribPointer(type.getStride(), startIndex, offset);
|
||||
startIndex += spec.getAttributeCount();
|
||||
offset += spec.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
protected void deleteInternal(int handle) {
|
||||
GlStateManager._glDeleteVertexArrays(handle);
|
||||
}
|
||||
|
||||
public void enableArrays(int count) {
|
||||
AttribUtil.enableArrays(count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@ import com.jozufozu.flywheel.api.struct.Instanced;
|
|||
import com.jozufozu.flywheel.api.struct.StructWriter;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.instancing.AbstractInstancer;
|
||||
import com.jozufozu.flywheel.backend.model.BufferedModel;
|
||||
import com.jozufozu.flywheel.backend.model.ModelAllocator;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
|
||||
public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
||||
|
@ -73,14 +73,14 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
model = modelAllocator.alloc(modelData, arenaModel -> {
|
||||
vao.bind();
|
||||
|
||||
arenaModel.setupState();
|
||||
arenaModel.setupState(vao);
|
||||
});
|
||||
|
||||
vao.bind();
|
||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||
|
||||
instanceVBO = GlBuffer.requestPersistent(GlBufferType.ARRAY_BUFFER);
|
||||
instanceVBO.setGrowthMargin(instanceFormat.getStride() * 16);
|
||||
vao.enableArrays(model.getAttributeCount() + instanceFormat.getAttributeCount());
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
|
@ -180,19 +180,19 @@ public class GPUInstancer<D extends InstanceData> extends AbstractInstancer<D> {
|
|||
|
||||
glInstanceCount = size;
|
||||
|
||||
informAttribDivisors();
|
||||
bindInstanceAttributes();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void informAttribDivisors() {
|
||||
int staticAttributes = model.getAttributeCount();
|
||||
instanceFormat.vertexAttribPointers(staticAttributes);
|
||||
private void bindInstanceAttributes() {
|
||||
int attributeBaseIndex = model.getAttributeCount();
|
||||
vao.bindAttributes(attributeBaseIndex, instanceFormat);
|
||||
|
||||
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
|
||||
Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(i + staticAttributes, 1);
|
||||
Backend.getInstance().compat.instancedArrays.vertexAttribDivisor(attributeBaseIndex + i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,54 @@
|
|||
package com.jozufozu.flywheel.backend.model;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
|
||||
public class ArrayModelRenderer extends ModelRenderer {
|
||||
public class ArrayModelRenderer {
|
||||
|
||||
private final Model model;
|
||||
protected GlVertexArray vao;
|
||||
protected BufferedModel vbo;
|
||||
protected boolean initialized;
|
||||
|
||||
public ArrayModelRenderer(Supplier<Model> model) {
|
||||
super(model);
|
||||
public ArrayModelRenderer(Model model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Renders this model, checking first if there is anything to render.
|
||||
*/
|
||||
public void draw() {
|
||||
if (!initialized) init();
|
||||
if (!isValid()) return;
|
||||
|
||||
vao.bind();
|
||||
|
||||
model.drawCall();
|
||||
vbo.drawCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
initialized = true;
|
||||
Model model = modelSupplier.get();
|
||||
|
||||
if (model.empty()) return;
|
||||
|
||||
this.model = new IndexedModel(model);
|
||||
this.vbo = new IndexedModel(model);
|
||||
|
||||
vao = new GlVertexArray();
|
||||
|
||||
vao.bind();
|
||||
|
||||
// bind the model's vbo to our vao
|
||||
this.model.setupState();
|
||||
this.vbo.setupState(vao);
|
||||
|
||||
GlVertexArray.unbind();
|
||||
}
|
||||
|
||||
this.model.clearState();
|
||||
public void delete() {
|
||||
if (vbo != null)
|
||||
vbo.delete();
|
||||
}
|
||||
|
||||
protected boolean isValid() {
|
||||
return vbo != null && vbo.valid();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package com.jozufozu.flywheel.backend.model;
|
||||
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.core.layout.BufferLayout;
|
||||
|
||||
public interface BufferedModel {
|
||||
|
||||
|
@ -10,11 +11,9 @@ public interface BufferedModel {
|
|||
int getVertexCount();
|
||||
|
||||
/**
|
||||
* The VBO/VAO should be bound externally.
|
||||
* The VAO must be bound externally.
|
||||
*/
|
||||
void setupState();
|
||||
|
||||
void clearState();
|
||||
void setupState(GlVertexArray vao);
|
||||
|
||||
void drawCall();
|
||||
|
||||
|
@ -27,7 +26,7 @@ public interface BufferedModel {
|
|||
|
||||
void delete();
|
||||
|
||||
default BufferLayout getFormat() {
|
||||
default BufferLayout getLayout() {
|
||||
return getType().getLayout();
|
||||
}
|
||||
|
||||
|
@ -36,6 +35,6 @@ public interface BufferedModel {
|
|||
}
|
||||
|
||||
default int getAttributeCount() {
|
||||
return getFormat().getAttributeCount();
|
||||
return getType().getLayout().getAttributeCount();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,14 @@ package com.jozufozu.flywheel.backend.model;
|
|||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
|
||||
/**
|
||||
|
@ -11,26 +18,43 @@ import com.jozufozu.flywheel.core.model.Model;
|
|||
*
|
||||
* <br><em>This should be favored over a normal BufferedModel.</em>
|
||||
*/
|
||||
public class IndexedModel extends VBOModel {
|
||||
public class IndexedModel implements BufferedModel {
|
||||
|
||||
protected final Model model;
|
||||
protected final GlPrimitive primitiveMode;
|
||||
protected ElementBuffer ebo;
|
||||
protected GlBuffer vbo;
|
||||
protected boolean deleted;
|
||||
|
||||
public IndexedModel(Model model) {
|
||||
super(GlPrimitive.TRIANGLES, model);
|
||||
this.model = model;
|
||||
this.primitiveMode = GlPrimitive.TRIANGLES;
|
||||
|
||||
vbo = new MappedGlBuffer(GlBufferType.ARRAY_BUFFER);
|
||||
|
||||
vbo.bind();
|
||||
// allocate the buffer on the gpu
|
||||
vbo.ensureCapacity(model.size());
|
||||
|
||||
// mirror it in system memory, so we can write to it, and upload our model.
|
||||
try (MappedBuffer buffer = vbo.getBuffer()) {
|
||||
model.writeInto(buffer.unwrap());
|
||||
} catch (Exception e) {
|
||||
Flywheel.LOGGER.error(String.format("Error uploading model '%s':", model.name()), e);
|
||||
}
|
||||
|
||||
vbo.unbind();
|
||||
|
||||
this.ebo = model.createEBO();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupState() {
|
||||
super.setupState();
|
||||
ebo.bind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearState() {
|
||||
super.clearState();
|
||||
ebo.unbind();
|
||||
/**
|
||||
* The VBO/VAO should be bound externally.
|
||||
*/
|
||||
public void setupState(GlVertexArray vao) {
|
||||
vbo.bind();
|
||||
vao.enableArrays(getAttributeCount());
|
||||
vao.bindAttributes(0, getType().getLayout());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,6 +63,9 @@ public class IndexedModel extends VBOModel {
|
|||
GL20.glDrawElements(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws many instances of this model, assuming the appropriate state is already bound.
|
||||
*/
|
||||
@Override
|
||||
public void drawInstances(int instanceCount) {
|
||||
if (!valid()) return;
|
||||
|
@ -47,4 +74,24 @@ public class IndexedModel extends VBOModel {
|
|||
|
||||
GL31.glDrawElementsInstanced(primitiveMode.glEnum, ebo.elementCount, ebo.eboIndexType.getGlEnum(), 0, instanceCount);
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VertexType getType() {
|
||||
return model.getType();
|
||||
}
|
||||
|
||||
public int getVertexCount() {
|
||||
return model.vertexCount();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (deleted) return;
|
||||
|
||||
deleted = true;
|
||||
vbo.delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@ import java.util.List;
|
|||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexWriter;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
|
||||
public class ModelPool implements ModelAllocator {
|
||||
|
||||
|
@ -178,18 +178,10 @@ public class ModelPool implements ModelAllocator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setupState() {
|
||||
public void setupState(GlVertexArray vao) {
|
||||
vbo.bind();
|
||||
ebo.bind();
|
||||
AttribUtil.enableArrays(getAttributeCount());
|
||||
ModelPool.this.vertexType.getLayout().vertexAttribPointers(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearState() {
|
||||
AttribUtil.disableArrays(getAttributeCount());
|
||||
ebo.unbind();
|
||||
vbo.unbind();
|
||||
vao.enableArrays(getAttributeCount());
|
||||
vao.bindAttributes(0, vertexType.getLayout());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package com.jozufozu.flywheel.backend.model;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
|
||||
public class ModelRenderer {
|
||||
|
||||
protected Supplier<Model> modelSupplier;
|
||||
protected BufferedModel model;
|
||||
|
||||
protected boolean initialized;
|
||||
|
||||
public ModelRenderer(Supplier<Model> modelSupplier) {
|
||||
this.modelSupplier = modelSupplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders this model, checking first if there is anything to render.
|
||||
*/
|
||||
public void draw() {
|
||||
if (!initialized) init();
|
||||
if (!isValid()) return;
|
||||
|
||||
model.setupState();
|
||||
model.drawCall();
|
||||
model.clearState();
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (model != null)
|
||||
model.delete();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
initialized = true;
|
||||
Model model = modelSupplier.get();
|
||||
|
||||
if (model.empty()) return;
|
||||
|
||||
this.model = new IndexedModel(model);
|
||||
}
|
||||
|
||||
protected boolean isValid() {
|
||||
return model != null && model.valid();
|
||||
}
|
||||
}
|
|
@ -5,14 +5,14 @@ import static org.lwjgl.opengl.GL11.glDrawArrays;
|
|||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import com.jozufozu.flywheel.Flywheel;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.backend.gl.GlPrimitive;
|
||||
import com.jozufozu.flywheel.backend.gl.GlVertexArray;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer;
|
||||
import com.jozufozu.flywheel.backend.gl.buffer.MappedGlBuffer;
|
||||
import com.jozufozu.flywheel.core.model.Model;
|
||||
import com.jozufozu.flywheel.api.vertex.VertexType;
|
||||
import com.jozufozu.flywheel.util.AttribUtil;
|
||||
|
||||
public class VBOModel implements BufferedModel {
|
||||
|
||||
|
@ -57,15 +57,10 @@ public class VBOModel implements BufferedModel {
|
|||
/**
|
||||
* The VBO/VAO should be bound externally.
|
||||
*/
|
||||
public void setupState() {
|
||||
public void setupState(GlVertexArray vao) {
|
||||
vbo.bind();
|
||||
AttribUtil.enableArrays(getAttributeCount());
|
||||
getFormat().vertexAttribPointers(0);
|
||||
}
|
||||
|
||||
public void clearState() {
|
||||
AttribUtil.disableArrays(getAttributeCount());
|
||||
vbo.unbind();
|
||||
vao.enableArrays(getAttributeCount());
|
||||
vao.bindAttributes(0, getLayout());
|
||||
}
|
||||
|
||||
public void drawCall() {
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.jozufozu.flywheel.api.vertex.VertexType;
|
|||
* Classic Vertex Format struct with a clever name.
|
||||
*
|
||||
* <p>
|
||||
* Used for vertices and instance. Describes the layout of a datatype in a buffer object.
|
||||
* Used for vertices and instances. Describes the layout of a datatype in a buffer object.
|
||||
* </p>
|
||||
*
|
||||
* @see com.jozufozu.flywheel.api.struct.StructType
|
||||
|
@ -34,6 +34,10 @@ public class BufferLayout {
|
|||
this.stride = stride;
|
||||
}
|
||||
|
||||
public List<LayoutItem> getLayoutItems() {
|
||||
return allAttributes;
|
||||
}
|
||||
|
||||
public int getAttributeCount() {
|
||||
return numAttributes;
|
||||
}
|
||||
|
@ -42,15 +46,6 @@ public class BufferLayout {
|
|||
return stride;
|
||||
}
|
||||
|
||||
public void vertexAttribPointers(int index) {
|
||||
int offset = 0;
|
||||
for (LayoutItem spec : this.allAttributes) {
|
||||
spec.vertexAttribPointer(stride, index, offset);
|
||||
index += spec.getAttributeCount();
|
||||
offset += spec.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
// TODO: move this functionality into GlVertexArray and track it
|
||||
public class AttribUtil {
|
||||
|
||||
public static void enableArrays(int count) {
|
||||
enableArrays(0, count);
|
||||
}
|
||||
|
||||
public static void enableArrays(int fromInclusive, int toExclusive) {
|
||||
for (int i = fromInclusive; i < toExclusive; i++) {
|
||||
GL20.glEnableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableArrays(int count) {
|
||||
disableArrays(0, count);
|
||||
}
|
||||
|
||||
public static void disableArrays(int fromInclusive, int toExclusive) {
|
||||
for (int i = fromInclusive; i < toExclusive; i++) {
|
||||
GL20.glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue