InDSAanced vertex arrays

- Make GlCompat static
- Expand InstancedArrays compat to encompass all vertex array ops
- GlVertexArray calls into VertexArray compat layer
- VertexAttributes still use 2 separate interface methods
This commit is contained in:
Jozufozu 2023-04-24 21:54:59 -07:00
parent 128a77275a
commit 684d9c7913
13 changed files with 221 additions and 188 deletions

View file

@ -32,8 +32,7 @@ public class Backends {
.engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Instancing Engine").withStyle(ChatFormatting.GREEN))
.engineFactory(level -> new InstancingEngine(256, Contexts.WORLD)) .engineFactory(level -> new InstancingEngine(256, Contexts.WORLD))
.fallback(() -> Backends.BATCHING) .fallback(() -> Backends.BATCHING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsInstancing() && InstancingPrograms.allLoaded())
.instancedArraysSupported() && InstancingPrograms.allLoaded())
.register(Flywheel.rl("instancing")); .register(Flywheel.rl("instancing"));
/** /**
@ -43,8 +42,7 @@ public class Backends {
.engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN)) .engineMessage(new TextComponent("Using Indirect Engine").withStyle(ChatFormatting.GREEN))
.engineFactory(level -> new IndirectEngine(256)) .engineFactory(level -> new IndirectEngine(256))
.fallback(() -> Backends.INSTANCING) .fallback(() -> Backends.INSTANCING)
.supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.getInstance() .supported(() -> !ShadersModHandler.isShaderPackInUse() && GlCompat.supportsIndirect() && IndirectPrograms.allLoaded())
.supportsIndirect() && IndirectPrograms.allLoaded())
.register(Flywheel.rl("indirect")); .register(Flywheel.rl("indirect"));
public static void init() { public static void init() {

View file

@ -1,15 +1,10 @@
package com.jozufozu.flywheel.backend.engine.indirect; package com.jozufozu.flywheel.backend.engine.indirect;
import static org.lwjgl.opengl.GL30.glBindVertexArray; import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT; import static org.lwjgl.opengl.GL42.GL_COMMAND_BARRIER_BIT;
import static org.lwjgl.opengl.GL42.glMemoryBarrier; import static org.lwjgl.opengl.GL42.glMemoryBarrier;
import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT; import static org.lwjgl.opengl.GL43.GL_SHADER_STORAGE_BARRIER_BIT;
import static org.lwjgl.opengl.GL43.glDispatchCompute; import static org.lwjgl.opengl.GL43.glDispatchCompute;
import static org.lwjgl.opengl.GL45.glCreateVertexArrays;
import static org.lwjgl.opengl.GL45.glEnableVertexArrayAttrib;
import static org.lwjgl.opengl.GL45.glVertexArrayElementBuffer;
import static org.lwjgl.opengl.GL45.glVertexArrayVertexBuffer;
import com.jozufozu.flywheel.api.event.RenderStage; import com.jozufozu.flywheel.api.event.RenderStage;
import com.jozufozu.flywheel.api.instance.Instance; import com.jozufozu.flywheel.api.instance.Instance;
@ -17,6 +12,7 @@ import com.jozufozu.flywheel.api.instance.InstanceType;
import com.jozufozu.flywheel.api.vertex.VertexType; import com.jozufozu.flywheel.api.vertex.VertexType;
import com.jozufozu.flywheel.backend.compile.IndirectPrograms; import com.jozufozu.flywheel.backend.compile.IndirectPrograms;
import com.jozufozu.flywheel.backend.engine.UniformBuffer; import com.jozufozu.flywheel.backend.engine.UniformBuffer;
import com.jozufozu.flywheel.gl.array.GlVertexArray;
import com.jozufozu.flywheel.gl.shader.GlProgram; import com.jozufozu.flywheel.gl.shader.GlProgram;
import com.jozufozu.flywheel.lib.context.Contexts; import com.jozufozu.flywheel.lib.context.Contexts;
import com.jozufozu.flywheel.lib.util.QuadConverter; import com.jozufozu.flywheel.lib.util.QuadConverter;
@ -35,7 +31,7 @@ public class IndirectCullingGroup<I extends Instance> {
final IndirectMeshPool meshPool; final IndirectMeshPool meshPool;
private final int elementBuffer; private final int elementBuffer;
int vertexArray; GlVertexArray vertexArray;
final IndirectDrawSet<I> drawSet = new IndirectDrawSet<>(); final IndirectDrawSet<I> drawSet = new IndirectDrawSet<>();
@ -55,7 +51,7 @@ public class IndirectCullingGroup<I extends Instance> {
meshPool = new IndirectMeshPool(vertexType, 1024); meshPool = new IndirectMeshPool(vertexType, 1024);
vertexArray = glCreateVertexArrays(); vertexArray = new GlVertexArray();
elementBuffer = QuadConverter.getInstance() elementBuffer = QuadConverter.getInstance()
.quads2Tris(2048).glBuffer; .quads2Tris(2048).glBuffer;
@ -67,21 +63,8 @@ public class IndirectCullingGroup<I extends Instance> {
} }
private void setupVertexArray() { private void setupVertexArray() {
glVertexArrayElementBuffer(vertexArray, elementBuffer); vertexArray.setElementBuffer(elementBuffer);
vertexArray.bindAttributes(vertexType.getLayout(), meshPool.vbo, 0, 0);
var meshLayout = vertexType.getLayout();
var meshAttribs = meshLayout.getAttributeCount();
var attributes = meshLayout.attributes();
long offset = 0;
for (int i = 0; i < meshAttribs; i++) {
var attribute = attributes.get(i);
glEnableVertexArrayAttrib(vertexArray, i);
glVertexArrayVertexBuffer(vertexArray, i, meshPool.vbo, offset, meshLayout.getStride());
attribute.format(vertexArray, i);
offset += attribute.getByteWidth();
}
} }
void beginFrame() { void beginFrame() {
@ -127,7 +110,7 @@ public class IndirectCullingGroup<I extends Instance> {
} }
UniformBuffer.syncAndBind(draw); UniformBuffer.syncAndBind(draw);
glBindVertexArray(vertexArray); vertexArray.bindForDraw();
buffers.bindForDraw(); buffers.bindForDraw();
memoryBarrier(); memoryBarrier();
@ -180,7 +163,7 @@ public class IndirectCullingGroup<I extends Instance> {
} }
public void delete() { public void delete() {
glDeleteVertexArrays(vertexArray); vertexArray.delete();
buffers.delete(); buffers.delete();
meshPool.delete(); meshPool.delete();
} }

View file

@ -16,7 +16,6 @@ public class DrawCall {
meshAttributes = this.mesh.getAttributeCount(); meshAttributes = this.mesh.getAttributeCount();
vao = new GlVertexArray(); vao = new GlVertexArray();
vao.enableArrays(meshAttributes + this.instancer.getAttributeCount());
} }
public boolean isInvalid() { public boolean isInvalid() {

View file

@ -90,7 +90,7 @@ public class GPUInstancer<I extends Instance> extends AbstractInstancer<I> {
return; return;
} }
vao.bindAttributes(vbo, attributeOffset, instanceFormat, 0L); vao.bindAttributes(instanceFormat, vbo.handle(), attributeOffset, 0L);
for (int i = 0; i < instanceFormat.getAttributeCount(); i++) { for (int i = 0; i < instanceFormat.getAttributeCount(); i++) {
vao.setAttributeDivisor(attributeOffset + i, 1); vao.setAttributeDivisor(attributeOffset + i, 1);

View file

@ -221,11 +221,10 @@ public class InstancedMeshPool {
private void setup(GlVertexArray vao) { private void setup(GlVertexArray vao) {
if (boundTo.add(vao)) { if (boundTo.add(vao)) {
vao.enableArrays(getAttributeCount()); vao.bindAttributes(vertexType.getLayout(), InstancedMeshPool.this.vbo.handle(), 0, byteIndex);
vao.bindAttributes(InstancedMeshPool.this.vbo, 0, vertexType.getLayout(), byteIndex); vao.setElementBuffer(ebo.glBuffer);
} }
vao.bindElementArray(ebo.glBuffer); vao.bindForDraw();
vao.bind();
} }
private void draw(int instanceCount) { private void draw(int instanceCount) {

View file

@ -1,13 +1,12 @@
package com.jozufozu.flywheel.gl.array; package com.jozufozu.flywheel.gl.array;
import org.lwjgl.opengl.GL20; import java.util.List;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
import com.jozufozu.flywheel.api.layout.BufferLayout; import com.jozufozu.flywheel.api.layout.BufferLayout;
import com.jozufozu.flywheel.gl.GlObject; import com.jozufozu.flywheel.gl.GlObject;
import com.jozufozu.flywheel.gl.GlStateTracker; import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.buffer.GlBuffer;
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.jozufozu.flywheel.gl.versioned.GlCompat; import com.jozufozu.flywheel.gl.versioned.GlCompat;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
@ -24,22 +23,18 @@ public class GlVertexArray extends GlObject {
* Each attribute's divisor. * Each attribute's divisor.
*/ */
private final int[] divisors = new int[MAX_ATTRIBS]; private final int[] divisors = new int[MAX_ATTRIBS];
/**
* The VBO to which each attribute is bound.
*/
private final int[] targets = new int[MAX_ATTRIBS];
/** /**
* Each attribute's data type. * Each attribute's data type.
*/ */
private final VertexAttribute[] attributes = new VertexAttribute[MAX_ATTRIBS]; private final VertexAttribute[] attributes = new VertexAttribute[MAX_ATTRIBS];
/**
* The VBO to which each attribute is bound.
*/
private final int[] targets = new int[MAX_ATTRIBS];
/** /**
* Each attribute's offset. * Each attribute's offset.
*/ */
private final long[] offsets = new long[MAX_ATTRIBS]; private final long[] offsets = new long[MAX_ATTRIBS];
/** /**
* Each attribute's stride. * Each attribute's stride.
*/ */
@ -49,16 +44,16 @@ public class GlVertexArray extends GlObject {
public GlVertexArray() { public GlVertexArray() {
setHandle(GlStateManager._glGenVertexArrays()); setHandle(GlCompat.vertexArray.create());
} }
public void bind() { public void bindForDraw() {
if (!isBound()) { if (!isBound()) {
GlStateManager._glBindVertexArray(handle()); GlStateManager._glBindVertexArray(handle());
} }
} }
public boolean isBound() { private boolean isBound() {
return handle() == GlStateTracker.getVertexArray(); return handle() == GlStateTracker.getVertexArray();
} }
@ -66,62 +61,21 @@ public class GlVertexArray extends GlObject {
GlStateManager._glBindVertexArray(0); GlStateManager._glBindVertexArray(0);
} }
/** public void bindAttributes(BufferLayout type, int vbo, int startAttrib, long startOffset) {
* @param buffer The buffer where the data is stored.
* @param startAttrib The first attribute to be used by the data.
* @param type The format of the attributes.
* @param offset The offset in bytes to the start of the data.
*/
public void bindAttributes(GlBuffer buffer, int startAttrib, BufferLayout type, long offset) {
bind();
int targetBuffer = buffer.handle();
GlBufferType.ARRAY_BUFFER.bind(targetBuffer);
int i = startAttrib;
final int stride = type.getStride(); final int stride = type.getStride();
for (var attribute : type.attributes()) { List<VertexAttribute> vertexAttributes = type.attributes();
targets[i] = targetBuffer; for (int i = 0; i < vertexAttributes.size(); i++) {
attributes[i] = attribute; var attribute = vertexAttributes.get(i);
offsets[i] = offset; int index = i + startAttrib;
strides[i] = stride; targets[index] = vbo;
attributes[index] = attribute;
offsets[index] = startOffset;
strides[index] = stride;
attribute.pointer(offset, i, stride); GlCompat.vertexArray.setupAttrib(handle(), stride, vbo, startOffset, attribute, index);
i++; startOffset += attribute.getByteWidth();
offset += attribute.getByteWidth();
}
}
public void enableArrays(int count) {
bind();
for (int i = 0; i < count; i++) {
enable(i);
}
}
public void disableArrays(int count) {
bind();
for (int i = 0; i < count; i++) {
disable(i);
}
}
private void enable(int i) {
if (!enabled[i]) {
GL20.glEnableVertexAttribArray(i);
enabled[i] = true;
}
}
private void disable(int i) {
if (enabled[i]) {
GL20.glDisableVertexAttribArray(i);
enabled[i] = false;
} }
} }
@ -131,16 +85,14 @@ public class GlVertexArray extends GlObject {
public void setAttributeDivisor(int index, int divisor) { public void setAttributeDivisor(int index, int divisor) {
if (divisors[index] != divisor) { if (divisors[index] != divisor) {
bind(); GlCompat.vertexArray.setAttribDivisor(handle(), index, divisor);
GlCompat.getInstance().instancedArrays.vertexAttribDivisor(index, divisor);
divisors[index] = divisor; divisors[index] = divisor;
} }
} }
public void bindElementArray(int ebo) { public void setElementBuffer(int ebo) {
if (elementBufferBinding != ebo) { if (elementBufferBinding != ebo) {
bind(); GlCompat.vertexArray.setElementBuffer(handle(), ebo);
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(ebo);
elementBufferBinding = ebo; elementBufferBinding = ebo;
} }
} }

View file

@ -5,16 +5,18 @@ public interface VertexAttribute {
/** /**
* Apply this vertex attribute to the bound vertex array. * Apply this vertex attribute to the bound vertex array.
*
* @param offset The byte offset to the first element of the attribute. * @param offset The byte offset to the first element of the attribute.
* @param i The attribute index. * @param i The attribute index.
* @param stride The byte stride between consecutive elements of the attribute. * @param stride The byte stride between consecutive elements of the attribute.
*/ */
void pointer(long offset, int i, int stride); void setup(long offset, int i, int stride);
/** /**
* Use DSA to apply this vertex attribute to the given vertex array. * Use DSA to apply this vertex attribute to the given vertex array.
*
* @param vaobj The vertex array object to modify. * @param vaobj The vertex array object to modify.
* @param i The attribute index. * @param i The attribute index.
*/ */
void format(int vaobj, int i); void setupDSA(int vaobj, int i);
} }

View file

@ -20,12 +20,12 @@ public record VertexAttributeF(GlNumericType type, int size, boolean normalized)
} }
@Override @Override
public void pointer(long offset, int i, int stride) { public void setup(long offset, int i, int stride) {
GL32.glVertexAttribPointer(i, size(), type().getGlEnum(), normalized(), stride, offset); GL32.glVertexAttribPointer(i, size(), type().getGlEnum(), normalized(), stride, offset);
} }
@Override @Override
public void format(int vaobj, int i) { public void setupDSA(int vaobj, int i) {
GL45.glVertexArrayAttribFormat(vaobj, i, size(), type().getGlEnum(), normalized(), 0); GL45.glVertexArrayAttribFormat(vaobj, i, size(), type().getGlEnum(), normalized(), 0);
} }
} }

View file

@ -19,12 +19,12 @@ public record VertexAttributeI(GlNumericType type, int size) implements VertexAt
} }
@Override @Override
public void pointer(long offset, int i, int stride) { public void setup(long offset, int i, int stride) {
GL32.glVertexAttribIPointer(i, size(), type().getGlEnum(), stride, offset); GL32.glVertexAttribIPointer(i, size(), type().getGlEnum(), stride, offset);
} }
@Override @Override
public void format(int vaobj, int i) { public void setupDSA(int vaobj, int i) {
GL45.glVertexArrayAttribIFormat(vaobj, i, size(), type().getGlEnum(), 0); GL45.glVertexArrayAttribIFormat(vaobj, i, size(), type().getGlEnum(), 0);
} }
} }

View file

@ -18,40 +18,35 @@ import net.minecraft.Util;
* system. * system.
*/ */
public class GlCompat { public class GlCompat {
public static final VertexArray vertexArray;
public static final BufferStorage bufferStorage;
public static final boolean amd;
public static final boolean supportsIndirect;
private static GlCompat instance; static {
public static GlCompat getInstance() {
if (instance == null) {
instance = new GlCompat();
}
return instance;
}
public final InstancedArrays instancedArrays;
public final BufferStorage bufferStorage;
public final boolean amd;
public final boolean supportsIndirect;
private GlCompat() {
GLCapabilities caps = GL.createCapabilities(); GLCapabilities caps = GL.createCapabilities();
instancedArrays = getLatest(InstancedArrays.class, caps);
bufferStorage = getLatest(BufferStorage.class, caps); bufferStorage = getLatest(BufferStorage.class, caps);
vertexArray = getLatest(VertexArray.class, caps);
supportsIndirect = true; supportsIndirect = caps.OpenGL46;
amd = _isAmdWindows(); amd = _isAmdWindows();
} }
public boolean onAMDWindows() { private GlCompat() {
}
public static boolean onAMDWindows() {
return amd; return amd;
} }
public boolean instancedArraysSupported() { public static boolean supportsInstancing() {
return instancedArrays != InstancedArrays.UNSUPPORTED; return vertexArray != VertexArray.UNSUPPORTED;
} }
public boolean bufferStorageSupported() { public static boolean supportsIndirect() {
return supportsIndirect;
}
public static boolean bufferStorageSupported() {
return bufferStorage != BufferStorage.UNSUPPORTED; return bufferStorage != BufferStorage.UNSUPPORTED;
} }
@ -63,7 +58,7 @@ public class GlCompat {
* @param <V> The type of the versioning enum. * @param <V> The type of the versioning enum.
* @return The first defined enum variant to return true. * @return The first defined enum variant to return true.
*/ */
public static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz, GLCapabilities caps) { private static <V extends Enum<V> & GlVersioned> V getLatest(Class<V> clazz, GLCapabilities caps) {
V[] constants = clazz.getEnumConstants(); V[] constants = clazz.getEnumConstants();
V last = constants[constants.length - 1]; V last = constants[constants.length - 1];
if (!last.supported(caps)) { if (!last.supported(caps)) {
@ -111,9 +106,5 @@ public class GlCompat {
// vendor string I got was "ATI Technologies Inc." // vendor string I got was "ATI Technologies Inc."
return vendor.contains("ATI") || vendor.contains("AMD"); return vendor.contains("ATI") || vendor.contains("AMD");
} }
public boolean supportsIndirect() {
return supportsIndirect;
}
} }

View file

@ -1,43 +0,0 @@
package com.jozufozu.flywheel.gl.versioned;
import org.lwjgl.opengl.ARBInstancedArrays;
import org.lwjgl.opengl.GL33;
import org.lwjgl.opengl.GLCapabilities;
public enum InstancedArrays implements GlVersioned {
GL33_INSTANCED_ARRAYS {
@Override
public boolean supported(GLCapabilities caps) {
return caps.OpenGL33;
}
@Override
public void vertexAttribDivisor(int index, int divisor) {
GL33.glVertexAttribDivisor(index, divisor);
}
},
ARB_INSTANCED_ARRAYS {
@Override
public boolean supported(GLCapabilities caps) {
return caps.GL_ARB_instanced_arrays;
}
@Override
public void vertexAttribDivisor(int index, int divisor) {
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
}
},
UNSUPPORTED {
@Override
public boolean supported(GLCapabilities caps) {
return true;
}
@Override
public void vertexAttribDivisor(int index, int divisor) {
throw new UnsupportedOperationException();
}
};
public abstract void vertexAttribDivisor(int index, int divisor);
}

View file

@ -0,0 +1,154 @@
package com.jozufozu.flywheel.gl.versioned;
import org.lwjgl.opengl.ARBInstancedArrays;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL33;
import org.lwjgl.opengl.GL45C;
import org.lwjgl.opengl.GLCapabilities;
import com.jozufozu.flywheel.gl.GlStateTracker;
import com.jozufozu.flywheel.gl.array.VertexAttribute;
import com.jozufozu.flywheel.gl.buffer.GlBufferType;
import com.mojang.blaze3d.platform.GlStateManager;
public enum VertexArray implements GlVersioned {
DSA {
@Override
public boolean supported(GLCapabilities caps) {
// The static methods from GL45 and ARBDirectStateAccess all point to GL45C.
return caps.OpenGL45 || caps.GL_ARB_direct_state_access;
}
@Override
public int create() {
return GL45C.glCreateVertexArrays();
}
@Override
public void setElementBuffer(int vao, int elementBuffer) {
GL45C.glVertexArrayElementBuffer(vao, elementBuffer);
}
@Override
public void setupAttrib(int vao, int stride, int vbo, long offset, VertexAttribute attribute, int index) {
GL45C.glEnableVertexArrayAttrib(vao, index);
GL45C.glVertexArrayVertexBuffer(vao, index, vbo, offset, stride);
attribute.setupDSA(vao, index);
}
@Override
public void setAttribDivisor(int vao, int attrib, int divisor) {
GL45C.glVertexArrayBindingDivisor(vao, attrib, divisor);
}
},
GL_33 {
@Override
public boolean supported(GLCapabilities caps) {
return caps.OpenGL33;
}
@Override
public int create() {
return GL33.glGenVertexArrays();
}
@Override
public void setElementBuffer(int vao, int elementBuffer) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(elementBuffer);
}
@Override
public void setupAttrib(int vao, int stride, int vbo, long offset, VertexAttribute attribute, int index) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
GlBufferType.ARRAY_BUFFER.bind(vbo);
GL33.glEnableVertexAttribArray(index);
attribute.setup(offset, index, stride);
}
@Override
public void setAttribDivisor(int vao, int attrib, int divisor) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
GL33.glVertexAttribDivisor(attrib, divisor);
}
},
ARB_INSTANCED_ARRAYS {
@Override
public boolean supported(GLCapabilities caps) {
return caps.GL_ARB_instanced_arrays;
}
@Override
public int create() {
return GL30.glGenVertexArrays();
}
@Override
public void setElementBuffer(int vao, int elementBuffer) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
GlBufferType.ELEMENT_ARRAY_BUFFER.bind(elementBuffer);
}
@Override
public void setupAttrib(int vao, int stride, int vbo, long offset, VertexAttribute attribute, int index) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
GlBufferType.ARRAY_BUFFER.bind(vbo);
GL30.glEnableVertexAttribArray(index);
attribute.setup(offset, index, stride);
}
@Override
public void setAttribDivisor(int vao, int attrib, int divisor) {
if (vao != GlStateTracker.getVertexArray()) {
GlStateManager._glBindVertexArray(vao);
}
ARBInstancedArrays.glVertexAttribDivisorARB(attrib, divisor);
}
},
UNSUPPORTED {
@Override
public boolean supported(GLCapabilities caps) {
return true;
}
@Override
public int create() {
throw new UnsupportedOperationException("Cannot use vertex arrays");
}
@Override
public void setElementBuffer(int vao, int elementBuffer) {
throw new UnsupportedOperationException("Cannot use vertex arrays");
}
@Override
public void setupAttrib(int vao, int stride, int vbo, long offset, VertexAttribute attribute, int index) {
throw new UnsupportedOperationException("Cannot use vertex arrays");
}
@Override
public void setAttribDivisor(int vao, int attrib, int divisor) {
throw new UnsupportedOperationException("Cannot use vertex arrays");
}
};
public abstract int create();
public abstract void setElementBuffer(int vao, int elementBuffer);
public abstract void setupAttrib(int vao, int stride, int vbo, long offset, VertexAttribute attribute, int index);
public abstract void setAttribDivisor(int vao, int attrib, int divisor);
}

View file

@ -50,14 +50,12 @@ public class FullscreenQuad {
vao = new GlVertexArray(); vao = new GlVertexArray();
vao.enableArrays(1); vao.bindAttributes(LAYOUT, vbo.handle(), 0, 0L);
vao.bindAttributes(vbo, 0, LAYOUT, 0L);
} }
} }
public void draw() { public void draw() {
vao.bind(); vao.bindForDraw();
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);
GlVertexArray.unbind(); GlVertexArray.unbind();
} }