Update #53 - Improved FPS, reduced WebGL context loss crashes

This commit is contained in:
lax1dude
2025-07-06 12:31:55 -07:00
parent f3281c037f
commit 332a7bb11f
53 changed files with 568 additions and 383 deletions

View File

@ -26,7 +26,6 @@ class DisplayList {
int attribs = -1;
int mode = -1;
int count = 0;
boolean bindQuad16 = false;
boolean bindQuad32 = false;
byte bindQuad = 0;
}

View File

@ -40,7 +40,7 @@ import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
public class EaglercraftGPU {
static final GLObjectRecycler<IBufferGL> arrayBufferRecycler = new GLObjectRecycler<IBufferGL>(32) {
static final GLObjectRecycler<IBufferGL> arrayBufferRecycler = new GLObjectRecycler<IBufferGL>(256) {
@Override
protected IBufferGL create() {
@ -49,7 +49,14 @@ public class EaglercraftGPU {
@Override
protected void invalidate(IBufferGL object) {
// Don't bother
IBufferGL old = currentArrayBuffer;
if (old != object) {
_wglBindBuffer(GL_ARRAY_BUFFER, object);
}
_wglBufferData(GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
if (old != object) {
_wglBindBuffer(GL_ARRAY_BUFFER, old);
}
}
@Override
@ -59,7 +66,7 @@ public class EaglercraftGPU {
};
static final GLObjectRecycler<IBufferGL> elementArrayBufferRecycler = new GLObjectRecycler<IBufferGL>(32) {
static final GLObjectRecycler<IBufferGL> elementArrayBufferRecycler = new GLObjectRecycler<IBufferGL>(256) {
@Override
protected IBufferGL create() {
@ -68,7 +75,22 @@ public class EaglercraftGPU {
@Override
protected void invalidate(IBufferGL object) {
// Don't bother
IVertexArrayGL oldArray = currentVertexArray;
boolean vao = !emulatedVAOs;
if (vao && vertexArrayCapable && oldArray != null) {
_wglBindVertexArray(null);
}
IBufferGL old = currentEmulatedVAOIndexBuffer;
if (vao || old != object) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, object);
}
_wglBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, GL_STATIC_DRAW);
if (!vao && old != object) {
_wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, old);
}
if (vao && vertexArrayCapable && oldArray != null) {
_wglBindVertexArray(oldArray);
}
}
@Override
@ -211,8 +233,7 @@ public class EaglercraftGPU {
if(dp.vertexArray == null) {
dp.vertexArray = createGLVertexArray();
dp.bindQuad16 = false;
dp.bindQuad32 = false;
dp.bindQuad = 0;
}
if(dp.vertexBuffer == null) {
dp.vertexBuffer = createGLArrayBuffer();
@ -252,8 +273,7 @@ public class EaglercraftGPU {
if(dp.vertexArray == null) {
dp.vertexArray = createGLVertexArray();
dp.bindQuad16 = false;
dp.bindQuad32 = false;
dp.bindQuad = 0;
}
if(dp.vertexBuffer == null) {
dp.vertexBuffer = createGLArrayBuffer();
@ -280,21 +300,19 @@ public class EaglercraftGPU {
if(dp.mode == GL_QUADS) {
int cnt = dp.count;
if(cnt > quad16MaxVertices) {
if(!dp.bindQuad32) {
dp.bindQuad16 = false;
dp.bindQuad32 = true;
if(dp.bindQuad != 32) {
dp.bindQuad = 32;
attachQuad32EmulationBuffer(cnt, true);
}else {
attachQuad32EmulationBuffer(cnt, false);
}
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_INT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, cnt - 1, (cnt >> 2) * 6, GL_UNSIGNED_INT, 0);
}else {
if(!dp.bindQuad16) {
dp.bindQuad16 = true;
dp.bindQuad32 = false;
if(dp.bindQuad != 16) {
dp.bindQuad = 16;
attachQuad16EmulationBuffer(true);
}
p.drawElements(GL_TRIANGLES, (cnt >> 2) * 6, GL_UNSIGNED_SHORT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, cnt - 1, (cnt >> 2) * 6, GL_UNSIGNED_SHORT, 0);
}
}else {
p.drawArrays(dp.mode, 0, dp.count);
@ -560,6 +578,21 @@ public class EaglercraftGPU {
_wglDrawElements(mode, count, type, offset);
}
public static void drawRangeElements(int mode, int start, int end, int count, int type, int offset) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
logger.warn("Skipping draw call with emulated VAO because no known VAO is bound!");
return;
}
((SoftGLVertexArray)currentVertexArray).transitionToState(emulatedVAOState, true);
}
if(glesVers >= 300) {
_wglDrawRangeElements(mode, start, end, count, type, offset);
}else {
_wglDrawElements(mode, count, type, offset);
}
}
public static void drawArraysInstanced(int mode, int first, int count, int instances) {
if(emulatedVAOs) {
if(currentVertexArray == null) {
@ -768,7 +801,7 @@ public class EaglercraftGPU {
displayListBuffer.put(buffer);
lastRender = null;
}else {
lastRender = FixedFunctionPipeline.setupDirect(buffer, attrib).update();
lastRender = FixedFunctionPipeline.setupDirect(buffer, attrib, mode == GL_QUADS).update();
lastRender.drawDirectArrays(mode, 0, count);
lastMode = mode;
lastCount = count;
@ -845,7 +878,7 @@ public class EaglercraftGPU {
v3 = v2 + 1;
v4 = v3 + 1;
buf.put(v1 | (v2 << 16));
buf.put(v4 | (v2 << 16));
buf.put(v3 | (v1 << 16));
buf.put(v3 | (v4 << 16));
}
buf.flip();
@ -862,7 +895,7 @@ public class EaglercraftGPU {
v3 = v2 + 1;
v4 = v3 + 1;
buf.put(v1); buf.put(v2);
buf.put(v4); buf.put(v2);
buf.put(v3); buf.put(v1);
buf.put(v3); buf.put(v4);
}
buf.flip();
@ -891,7 +924,7 @@ public class EaglercraftGPU {
}
FixedFunctionPipeline p = FixedFunctionPipeline.setupRenderDisplayList(mesh.getAttribBits()).update();
EaglercraftGPU.bindGLVertexArray(mesh.vertexArray);
p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
p.drawRangeElements(GL_TRIANGLES, 0, mesh.vertexCount - 1, mesh.indexCount, GL_UNSIGNED_SHORT, 0);
}
static int glesVers = -1;

View File

@ -30,12 +30,9 @@ import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IProgramGL;
import net.lax1dude.eaglercraft.v1_8.internal.IShaderGL;
import net.lax1dude.eaglercraft.v1_8.internal.IUniformGL;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.opengl.StreamBuffer.StreamBufferInstance;
import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f;
import net.lax1dude.eaglercraft.v1_8.vector.Vector4f;
import net.minecraft.util.MathHelper;
@ -61,7 +58,7 @@ public class FixedFunctionPipeline {
(GlStateManager.stateEnableShaderBlendColor ? STATE_ENABLE_BLEND_ADD : 0);
}
static FixedFunctionPipeline setupDirect(ByteBuffer buffer, int attrib) {
static FixedFunctionPipeline setupDirect(ByteBuffer buffer, int attrib, boolean quads) {
FixedFunctionPipeline self;
int baseState = attrib | getFragmentState();
if(GlStateManager.stateUseExtensionPipeline) {
@ -74,13 +71,13 @@ public class FixedFunctionPipeline {
self = getPipelineInstanceCore(baseState);
}
StreamBufferInstance sb = self.streamBuffer.getBuffer(buffer.remaining());
self.currentVertexArray = sb;
EaglercraftGPU.bindGLVertexArray(self.getDirectModeVertexArray());
EaglercraftGPU.bindGLVertexArray(sb.getVertexArray());
EaglercraftGPU.bindGLArrayBuffer(sb.getVertexBuffer());
int off = StreamBuffer.uploadData(self.attribStride, buffer.remaining() / self.attribStride, quads);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, buffer);
_wglBufferSubData(GL_ARRAY_BUFFER, off * self.attribStride, buffer);
self.directBaseOffset = off;
return self;
}
@ -132,16 +129,19 @@ public class FixedFunctionPipeline {
}
static FixedFunctionPipeline setupRenderDisplayList(int attribs) {
FixedFunctionPipeline self;
int baseState = attribs | getFragmentState();
if(GlStateManager.stateUseExtensionPipeline) {
if(extensionProvider != null) {
return getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState));
self = getPipelineInstanceExt(baseState, extensionProvider.getCurrentExtensionStateBits(baseState));
}else {
throw new IllegalStateException("No extension pipeline is available!");
}
}else {
return getPipelineInstanceCore(baseState);
self = getPipelineInstanceCore(baseState);
}
return self;
}
void drawArrays(int mode, int offset, int count) {
@ -151,24 +151,26 @@ public class FixedFunctionPipeline {
void drawDirectArrays(int mode, int offset, int count) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
offset += directBaseOffset;
if(mode == GL_QUADS) {
StreamBufferInstance sb = currentVertexArray;
if(count > EaglercraftGPU.quad16MaxVertices) {
if(!sb.bindQuad32) {
sb.bindQuad16 = false;
sb.bindQuad32 = true;
int offset2 = (offset >> 2) * 6;
int count2 = (count >> 2) * 6;
if(offset + count > EaglercraftGPU.quad16MaxVertices) {
if(directQuads != 32) {
directQuads = 32;
EaglercraftGPU.attachQuad32EmulationBuffer(count, true);
}else {
EaglercraftGPU.attachQuad32EmulationBuffer(count, false);
}
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_INT, 0);
EaglercraftGPU.drawRangeElements(GL_TRIANGLES, offset, offset + count - 1, count2, GL_UNSIGNED_INT,
offset2 << 2);
}else {
if(!sb.bindQuad16) {
sb.bindQuad16 = true;
sb.bindQuad32 = false;
if(directQuads != 16) {
directQuads = 16;
EaglercraftGPU.attachQuad16EmulationBuffer(true);
}
EaglercraftGPU.drawElements(GL_TRIANGLES, (count >> 2) * 6, GL_UNSIGNED_SHORT, 0);
EaglercraftGPU.drawRangeElements(GL_TRIANGLES, offset, offset + count - 1, count2, GL_UNSIGNED_SHORT,
offset2 << 1);
}
}else {
EaglercraftGPU.drawArrays(mode, offset, count);
@ -180,6 +182,11 @@ public class FixedFunctionPipeline {
EaglercraftGPU.drawElements(mode, count, type, offset);
}
void drawRangeElements(int mode, int start, int end, int count, int type, int offset) {
EaglercraftGPU.bindGLShaderProgram(shaderProgram);
EaglercraftGPU.drawRangeElements(mode, start, end, count, type, offset);
}
private static IExtPipelineCompiler extensionProvider;
public static void loadExtensionPipeline(IExtPipelineCompiler provider) {
@ -423,9 +430,9 @@ public class FixedFunctionPipeline {
private float stateAlphaTestRef = -999.0f;
private final IUniformGL stateLightsEnabledUniform1i;
private final IUniformGL[] stateLightsVectorsArrayUniform4f = new IUniformGL[4];
private final IUniformGL[] stateLightsVectorsArrayUniform4f = new IUniformGL[2];
private int stateLightsEnabled = -1;
private final Vector4f[] stateLightsVectors = new Vector4f[4];
private final Vector4f[] stateLightsVectors = new Vector4f[2];
private int stateLightingSerial = -1;
private final IUniformGL stateLightingAmbientUniform3f;
@ -496,8 +503,9 @@ public class FixedFunctionPipeline {
private float stateAnisotropicFixH = -999.0f;
private float stateAnisotropicFixSerial = 0;
private final StreamBuffer streamBuffer;
private StreamBufferInstance currentVertexArray = null;
private IVertexArrayGL directVertexArray;
private int directBaseOffset;
private byte directQuads;
private static FloatBuffer matrixCopyBuffer = null;
@ -572,39 +580,6 @@ public class FixedFunctionPipeline {
}
throw new IllegalStateException("Program could not be linked!");
}
streamBuffer = new StreamBuffer((vertexArray, vertexBuffer) -> {
EaglercraftGPU.bindGLVertexArray(vertexArray);
EaglercraftGPU.bindVAOGLArrayBuffer(vertexBuffer);
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
if(attribTextureIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
}
if(attribColorIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
}
if(attribNormalIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
}
if(attribLightmapIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
}
});
stateEnableTexture2D = (bits & STATE_ENABLE_TEXTURE2D) != 0;
stateEnableLightmap = (bits & STATE_ENABLE_LIGHTMAP) != 0;
@ -899,9 +874,7 @@ public class FixedFunctionPipeline {
_wglUniform3f(stateLightingAmbientUniform3f, r, g, b);
}
}
}
if(stateEnableMCLighting || DynamicLightsStateManager.isInDynamicLightsPass()) {
if(!stateHasAttribNormal) {
serial = GlStateManager.stateNormalSerial;
if(stateNormalSerial != serial) {
@ -1089,13 +1062,51 @@ public class FixedFunctionPipeline {
}
pipelineListTracker.clear();
}
public void destroy() {
PlatformOpenGL._wglDeleteProgram(shaderProgram);
streamBuffer.destroy();
}
public IVertexArrayGL getDirectModeVertexArray() {
return currentVertexArray.vertexArray;
if (directVertexArray == null) {
directVertexArray = EaglercraftGPU.createGLVertexArray();
EaglercraftGPU.bindGLVertexArray(directVertexArray);
EaglercraftGPU.bindVAOGLArrayBuffer(StreamBuffer.getBuffer());
EaglercraftGPU.enableVertexAttribArray(0);
EaglercraftGPU.vertexAttribPointer(0, VertexFormat.COMPONENT_POSITION_SIZE,
VertexFormat.COMPONENT_POSITION_FORMAT, false, attribStride, 0);
if (attribTextureIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribTextureIndex);
EaglercraftGPU.vertexAttribPointer(attribTextureIndex, VertexFormat.COMPONENT_TEX_SIZE,
VertexFormat.COMPONENT_TEX_FORMAT, false, attribStride, attribTextureOffset);
}
if (attribColorIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribColorIndex);
EaglercraftGPU.vertexAttribPointer(attribColorIndex, VertexFormat.COMPONENT_COLOR_SIZE,
VertexFormat.COMPONENT_COLOR_FORMAT, true, attribStride, attribColorOffset);
}
if (attribNormalIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribNormalIndex);
EaglercraftGPU.vertexAttribPointer(attribNormalIndex, VertexFormat.COMPONENT_NORMAL_SIZE,
VertexFormat.COMPONENT_NORMAL_FORMAT, true, attribStride, attribNormalOffset);
}
if (attribLightmapIndex != -1) {
EaglercraftGPU.enableVertexAttribArray(attribLightmapIndex);
EaglercraftGPU.vertexAttribPointer(attribLightmapIndex, VertexFormat.COMPONENT_LIGHTMAP_SIZE,
VertexFormat.COMPONENT_LIGHTMAP_FORMAT, false, attribStride, attribLightmapOffset);
}
return directVertexArray;
}
return directVertexArray;
}
public void destroy() {
_wglDeleteProgram(shaderProgram);
if (directVertexArray != null) {
EaglercraftGPU.destroyGLVertexArray(directVertexArray);
}
}
}

View File

@ -44,7 +44,7 @@ public class FixedFunctionShader {
public static final String FILENAME_VSH = "/assets/eagler/glsl/core.vsh";
public static final String FILENAME_FSH = "/assets/eagler/glsl/core.fsh";
public static final String PRECISION_INT = "lowp";
public static final String PRECISION_INT = "mediump";
public static final String PRECISION_FLOAT = "highp";
public static final String PRECISION_SAMPLER = "mediump";

View File

@ -76,9 +76,9 @@ public class GlStateManager {
static boolean stateMaterial = false;
static boolean stateLighting = false;
static int stateLightsStackPointer = 0;
static final boolean[][] stateLightsEnabled = new boolean[4][8];
static final Vector4f[][] stateLightsStack = new Vector4f[4][8];
static final int[] stateLightingSerial = new int[4];
static final boolean[][] stateLightsEnabled = new boolean[2][8];
static final Vector4f[][] stateLightsStack = new Vector4f[2][8];
static final int[] stateLightingSerial = new int[2];
static float stateLightingAmbientR = 0.0f;
static float stateLightingAmbientG = 0.0f;

View File

@ -206,8 +206,7 @@ public class InstancedFontRenderer {
EaglercraftGPU.vertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
EaglercraftGPU.bindVAOGLArrayBuffer(instancesBuffer);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 2, GL_SHORT, false, 10, 0);
@ -381,7 +380,7 @@ public class InstancedFontRenderer {
int l = fontDataBuffer.limit();
fontDataBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, fontDataBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (fontDataBuffer.remaining() + 0x3FF) & 0xFFFFFC00, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontDataBuffer);
fontDataBuffer.position(p);
@ -395,7 +394,7 @@ public class InstancedFontRenderer {
int l = fontBoldDataBuffer.limit();
fontBoldDataBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, fontBoldDataBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (fontBoldDataBuffer.remaining() + 0x3FF) & 0xFFFFFC00, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, fontBoldDataBuffer);
fontBoldDataBuffer.position(p);

View File

@ -187,8 +187,7 @@ public class InstancedParticleRenderer {
EaglercraftGPU.vertexAttribPointer(0, 2, GL_FLOAT, false, 8, 0);
EaglercraftGPU.vertexAttribDivisor(0, 0);
EaglercraftGPU.bindVAOGLArrayBufferNow(instancesBuffer);
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
EaglercraftGPU.bindVAOGLArrayBuffer(instancesBuffer);
EaglercraftGPU.enableVertexAttribArray(1);
EaglercraftGPU.vertexAttribPointer(1, 3, GL_FLOAT, false, 24, 0);
@ -315,7 +314,7 @@ public class InstancedParticleRenderer {
int l = particleBuffer.limit();
particleBuffer.flip();
_wglBufferData(GL_ARRAY_BUFFER, particleBuffer.capacity(), GL_STREAM_DRAW);
_wglBufferData(GL_ARRAY_BUFFER, (particleBuffer.remaining() + 0xFFF) & 0xFFFFF000, GL_STREAM_DRAW);
_wglBufferSubData(GL_ARRAY_BUFFER, 0, particleBuffer);
particleBuffer.position(p);

View File

@ -16,108 +16,53 @@
package net.lax1dude.eaglercraft.v1_8.opengl;
import net.lax1dude.eaglercraft.v1_8.internal.IVertexArrayGL;
import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL;
import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*;
import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*;
/**
* This streaming implementation was designed by reverse engineering the OpenGL
* driver that powers most Intel-based Chromebooks, performance may vary on
* other platforms
*/
public class StreamBuffer {
public static final int poolSize = 4;
protected static IBufferGL buffer = null;
protected static final PoolInstance[] pool = new PoolInstance[poolSize];
protected static int poolBufferID = 0;
protected static int currentOffset = 0;
protected static int currentSize = 0;
static {
for(int i = 0; i < poolSize; ++i) {
pool[i] = new PoolInstance();
}
}
protected static class PoolInstance {
protected IBufferGL vertexBuffer = null;
protected int vertexBufferSize = 0;
}
private static void resizeInstance(PoolInstance instance, int requiredMemory) {
IBufferGL buffer = instance.vertexBuffer;
public static IBufferGL getBuffer() {
if (buffer == null) {
buffer = _wglGenBuffers();
instance.vertexBuffer = buffer;
return buffer = _wglGenBuffers();
}
int newSize = instance.vertexBufferSize;
if (newSize < requiredMemory) {
newSize = (requiredMemory + 0xFFFF) & 0xFFFF0000;
instance.vertexBufferSize = newSize;
}
EaglercraftGPU.bindGLArrayBuffer(buffer);
_wglBufferData(GL_ARRAY_BUFFER, newSize, GL_STREAM_DRAW);
return buffer;
}
protected StreamBufferInstance[] buffers;
protected final IStreamBufferInitializer initializer;
public static class StreamBufferInstance {
protected PoolInstance poolInstance = null;
protected IVertexArrayGL vertexArray = null;
public boolean bindQuad16 = false;
public boolean bindQuad32 = false;
public IVertexArrayGL getVertexArray() {
return vertexArray;
public static int uploadData(int elSize, int elCount, boolean quads) {
EaglercraftGPU.bindGLArrayBuffer(getBuffer());
int off = (currentOffset + elSize - 1) / elSize;
if (quads) {
off = (off + 3) & -4;
}
public IBufferGL getVertexBuffer() {
return poolInstance.vertexBuffer;
}
}
public static interface IStreamBufferInitializer {
void initialize(IVertexArrayGL vertexArray, IBufferGL vertexBuffer);
}
public StreamBuffer(IStreamBufferInitializer initializer) {
this.buffers = new StreamBufferInstance[poolSize];
for(int i = 0; i < this.buffers.length; ++i) {
StreamBufferInstance j = new StreamBufferInstance();
j.poolInstance = pool[i];
this.buffers[i] = j;
}
this.initializer = initializer;
}
public StreamBufferInstance getBuffer(int requiredMemory) {
StreamBufferInstance next = buffers[poolBufferID++ % buffers.length];
resizeInstance(next.poolInstance, requiredMemory);
if(next.vertexArray == null) {
next.vertexArray = EaglercraftGPU.createGLVertexArray();
initializer.initialize(next.vertexArray, next.poolInstance.vertexBuffer);
}
return next;
}
public void destroy() {
for(int i = 0; i < buffers.length; ++i) {
StreamBufferInstance next = buffers[i];
if(next.vertexArray != null) {
EaglercraftGPU.destroyGLVertexArray(next.vertexArray);
}
int offBytes = off * elSize;
int reqBytes = elCount * elSize;
if (currentSize - offBytes >= reqBytes) {
currentOffset = offBytes + reqBytes;
return off;
} else {
currentOffset = 0;
currentSize = (reqBytes + 0xFFFF) & 0xFFFFF000;
_wglBufferData(GL_ARRAY_BUFFER, currentSize, GL_STREAM_DRAW);
return 0;
}
}
public static void destroyPool() {
for(int i = 0; i < pool.length; ++i) {
if(pool[i].vertexBuffer != null) {
_wglDeleteBuffers(pool[i].vertexBuffer);
pool[i].vertexBuffer = null;
}
if (buffer != null) {
_wglDeleteBuffers(buffer);
buffer = null;
}
}

View File

@ -316,7 +316,8 @@ public class LensFlareMeshRenderer {
_wglUniform3f(streaksProgram.uniforms.u_flareColor3f, v.x * mag * 0.5f, v.y * mag * 0.5f, v.z * mag * 0.5f);
EaglercraftGPU.bindGLVertexArray(streaksVertexArray);
_wglDrawElements(GL_TRIANGLES, streaksVertexCount + (streaksVertexCount >> 1), GL_UNSIGNED_SHORT, 0);
_wglDrawRangeElements(GL_TRIANGLES, 0, streaksVertexCount - 1, streaksVertexCount + (streaksVertexCount >> 1),
GL_UNSIGNED_SHORT, 0);
ghostsProgram.useProgram();

View File

@ -46,8 +46,8 @@ public class DynamicLightBucketLoader {
private int currentLightSourceBucketId = -1;
private int lightingBufferSliceLength = -1;
public static final int MAX_LIGHTS_PER_CHUNK = 12;
public static final int LIGHTING_BUFFER_LENGTH = 16 * MAX_LIGHTS_PER_CHUNK + 16;
public static final int MAX_LIGHTS_PER_CHUNK = 8;
public static final int LIGHTING_BUFFER_LENGTH = 8 * MAX_LIGHTS_PER_CHUNK + 16;
private final int lightSourceBucketsWidth;
private final int lightSourceBucketsHeight;
@ -114,26 +114,36 @@ public class DynamicLightBucketLoader {
int ser = currentLightSourceBucket.getEaglerSerial();
int max = currentLightSourceBucket.size();
if(max > 0) {
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
EaglercraftGPU.bindGLUniformBuffer(buffer_chunkLightingData);
int offset = currentLightSourceBucketId * lightingBufferSliceLength;
if (lightSourceBucketsSerials[currentLightSourceBucketId] != ser
|| lightSourceRenderPosSerials[currentLightSourceBucketId] != currentRenderPosSerial) {
lightSourceBucketsSerials[currentLightSourceBucketId] = ser;
lightSourceRenderPosSerials[currentLightSourceBucketId] = currentRenderPosSerial;
if(max > MAX_LIGHTS_PER_CHUNK) {
max = MAX_LIGHTS_PER_CHUNK;
}
int bucketXOff = -relativeBlockX & -16;
int bucketYOff = -relativeBlockY & -16;
int bucketZOff = -relativeBlockZ & -16;
chunkLightingDataCopyBuffer.clear();
chunkLightingDataCopyBuffer.putInt(
((bucketXOff & 0xFF) << 8) |
((bucketYOff & 0xFF) << 16) |
((bucketZOff & 0xFF) << 24)
);
chunkLightingDataCopyBuffer.putInt(max);
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); //padding
chunkLightingDataCopyBuffer.putInt(0); // padding
chunkLightingDataCopyBuffer.putInt(0); // padding
for(int i = 0; i < max; ++i) {
DynamicLightInstance dl = currentLightSourceBucket.get(i);
chunkLightingDataCopyBuffer.putFloat((float)(dl.posX - currentRenderX));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posY - currentRenderY));
chunkLightingDataCopyBuffer.putFloat((float)(dl.posZ - currentRenderZ));
chunkLightingDataCopyBuffer.putFloat(dl.radius);
int x = (int)((dl.posX - currentRenderX + bucketXOff) * (1.0f / 0.0009765923f));
int y = (int)((dl.posY - currentRenderY + bucketYOff) * (1.0f / 0.0009765923f));
int z = (int)((dl.posZ - currentRenderZ + bucketZOff) * (1.0f / 0.0009765923f));
int r = (int)(dl.radius * (1.0f / 0.0009765923f));
if (r > 32767) r = 32767;
chunkLightingDataCopyBuffer.putInt((x & 0xFFFF) | (z << 16));
chunkLightingDataCopyBuffer.putInt((y & 0xFFFF) | (r << 16));
}
chunkLightingDataCopyBuffer.flip();
_wglBufferSubData(_GL_UNIFORM_BUFFER, offset, chunkLightingDataCopyBuffer);