Skip to content

Commit

Permalink
Merge pull request libgdx#6431 from mgsx-dev/fix/mesh-implicit-update
Browse files Browse the repository at this point in the history
Fix mesh implicit update when retrieving data for read only, fixes libgdx#6430
  • Loading branch information
Tom-Ski authored Nov 15, 2022
2 parents 9bbb1cf + 300d513 commit 02f4a0c
Show file tree
Hide file tree
Showing 29 changed files with 216 additions and 85 deletions.
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [BREAKING CHANGE] WidgetGroup#hit first validates the layout.
- [BREAKING CHANGE] Cell getters return object wrapper instead of primitives.
- [BREAKING CHANGE] MeshPartBuilder#lastIndex now returns int instead of short.
- [BREAKING CHANGE] Mesh#getVerticesBuffer, Mesh#getIndicesBuffer, VertexData#getBuffer, and IndexData#getBuffer are deprecated in favor to new methods with boolean parameter. If you subclassed some of these classes, you need to implement the new methods.
- iOS: Add new MobiVM MetalANGLE backend
- API Addition: Added Haptics API with 4 different Input#vibrate() methods with complete Android and iOS implementations.
- Fix: Fixed Android and iOS touch cancelled related issues, see #6871.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,20 @@ public void updateIndices (int targetOffset, short[] indices, int offset, int co
}
}

/**
* <p>
* Returns the underlying ShortBuffer. If you modify the buffer contents they wil be uploaded on the call to {@link #bind()}.
* If you need immediate uploading use {@link #setIndices(short[], int, int)}.
* </p>
*
* @return the underlying short buffer. */
/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public ShortBuffer getBuffer () {
isDirty = true;
return buffer;
}

@Override
public ShortBuffer getBuffer (boolean forWriting) {
isDirty |= forWriting;
return buffer;
}

/** Binds this IndexBufferObject for rendering with glDrawElements. */
public void bind () {
if (bufferHandle == 0) throw new GdxRuntimeException("No buffer allocated!");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,20 @@ public int getNumMaxInstances () {
return byteBuffer.capacity() / attributes.vertexSize;
}

/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public FloatBuffer getBuffer () {
isDirty = true;
return buffer;
}

@Override
public FloatBuffer getBuffer (boolean forWriting) {
isDirty |= forWriting;
return buffer;
}

/** Low level method to reset the buffer and attributes to the specified values. Use with care!
*
* @param data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,20 @@ public int getNumMaxVertices () {
return buffer.capacity() / (attributes.vertexSize / 4);
}

/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public FloatBuffer getBuffer () {
isDirty = true;
return buffer;
}

@Override
public FloatBuffer getBuffer (boolean forWriting) {
isDirty |= forWriting;
return buffer;
}

private void bufferChanged () {
if (isBound) {
Gdx.gl20.glBufferData(GL20.GL_ARRAY_BUFFER, buffer.limit(), buffer, usage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,20 @@ public int getNumMaxVertices () {
return buffer.capacity() * 4 / attributes.vertexSize;
}

/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public FloatBuffer getBuffer () {
isDirty = true;
return buffer;
}

@Override
public FloatBuffer getBuffer (boolean forWriting) {
isDirty |= forWriting;
return buffer;
}

private void bufferChanged () {
if (isBound) {
Gdx.gl20.glBufferData(GL20.GL_ARRAY_BUFFER, buffer.limit(), buffer, usage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ public void set (final Object tag, final Mesh mesh, int offset, int count) {

if (posAttr == null) throw new com.badlogic.gdx.utils.GdxRuntimeException("Mesh doesn't have a position attribute");

set(tag, mesh.getVerticesBuffer(), mesh.getVertexSize(), mesh.getNumVertices(), posAttr.offset, mesh.getIndicesBuffer(),
offset, count);
set(tag, mesh.getVerticesBuffer(false), mesh.getVertexSize(), mesh.getNumVertices(), posAttr.offset,
mesh.getIndicesBuffer(false), offset, count);
}

/** Convenience method to set this btIndexedMesh to the specified vertex and index data. The specified data must be indexed and
Expand Down
49 changes: 31 additions & 18 deletions gdx/src/com/badlogic/gdx/graphics/Mesh.java
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,11 @@ public float[] getVertices (int srcOffset, int count, float[] vertices, int dest
throw new IndexOutOfBoundsException();
if ((vertices.length - destOffset) < count) throw new IllegalArgumentException(
"not enough room in vertices array, has " + vertices.length + " floats, needs " + count);
int pos = getVerticesBuffer().position();
((Buffer)getVerticesBuffer()).position(srcOffset);
getVerticesBuffer().get(vertices, destOffset, count);
((Buffer)getVerticesBuffer()).position(pos);
FloatBuffer verticesBuffer = getVerticesBuffer(false);
int pos = verticesBuffer.position();
((Buffer)verticesBuffer).position(srcOffset);
verticesBuffer.get(vertices, destOffset, count);
((Buffer)verticesBuffer).position(pos);
return vertices;
}

Expand Down Expand Up @@ -454,10 +455,11 @@ public void getIndices (int srcOffset, int count, short[] indices, int destOffse
"Invalid range specified, offset: " + srcOffset + ", count: " + count + ", max: " + max);
if ((indices.length - destOffset) < count) throw new IllegalArgumentException(
"not enough room in indices array, has " + indices.length + " shorts, needs " + count);
int pos = getIndicesBuffer().position();
((Buffer)getIndicesBuffer()).position(srcOffset);
getIndicesBuffer().get(indices, destOffset, count);
((Buffer)getIndicesBuffer()).position(pos);
ShortBuffer indicesBuffer = getIndicesBuffer(false);
int pos = indicesBuffer.position();
((Buffer)indicesBuffer).position(srcOffset);
indicesBuffer.get(indices, destOffset, count);
((Buffer)indicesBuffer).position(pos);
}

/** @return the number of defined indices */
Expand Down Expand Up @@ -617,7 +619,7 @@ public void render (ShaderProgram shader, int primitiveType, int offset, int cou

if (isVertexArray) {
if (indices.getNumIndices() > 0) {
ShortBuffer buffer = indices.getBuffer();
ShortBuffer buffer = indices.getBuffer(false);
int oldPosition = buffer.position();
int oldLimit = buffer.limit();
((Buffer)buffer).position(offset);
Expand Down Expand Up @@ -679,9 +681,15 @@ public VertexAttributes getVertexAttributes () {
return vertices.getAttributes();
}

/** @return the backing FloatBuffer holding the vertices. Does not have to be a direct buffer on Android! */
/** @return the backing FloatBuffer holding the vertices. Does not have to be a direct buffer on Android!
* @deprecated use {@link #getVerticesBuffer(boolean)} instead */
@Deprecated
public FloatBuffer getVerticesBuffer () {
return vertices.getBuffer();
return vertices.getBuffer(true);
}

public FloatBuffer getVerticesBuffer (boolean forWriting) {
return vertices.getBuffer(forWriting);
}

/** Calculates the {@link BoundingBox} of the vertices contained in this mesh. In case no vertices are defined yet a
Expand All @@ -702,7 +710,7 @@ public void calculateBoundingBox (BoundingBox bbox) {
final int numVertices = getNumVertices();
if (numVertices == 0) throw new GdxRuntimeException("No vertices defined");

final FloatBuffer verts = vertices.getBuffer();
final FloatBuffer verts = vertices.getBuffer(false);
bbox.inf();
final VertexAttribute posAttrib = getVertexAttribute(Usage.Position);
final int offset = posAttrib.offset / 4;
Expand Down Expand Up @@ -772,8 +780,8 @@ public BoundingBox extendBoundingBox (final BoundingBox out, int offset, int cou
if (offset < 0 || count < 1 || offset + count > max)
throw new GdxRuntimeException("Invalid part specified ( offset=" + offset + ", count=" + count + ", max=" + max + " )");

final FloatBuffer verts = vertices.getBuffer();
final ShortBuffer index = indices.getBuffer();
final FloatBuffer verts = vertices.getBuffer(false);
final ShortBuffer index = indices.getBuffer(false);
final VertexAttribute posAttrib = getVertexAttribute(Usage.Position);
final int posoff = posAttrib.offset / 4;
final int vertexSize = vertices.getAttributes().vertexSize / 4;
Expand Down Expand Up @@ -847,8 +855,8 @@ public float calculateRadiusSquared (final float centerX, final float centerY, f
int numIndices = getNumIndices();
if (offset < 0 || count < 1 || offset + count > numIndices) throw new GdxRuntimeException("Not enough indices");

final FloatBuffer verts = vertices.getBuffer();
final ShortBuffer index = indices.getBuffer();
final FloatBuffer verts = vertices.getBuffer(false);
final ShortBuffer index = indices.getBuffer(false);
final VertexAttribute posAttrib = getVertexAttribute(Usage.Position);
final int posoff = posAttrib.offset / 4;
final int vertexSize = vertices.getAttributes().vertexSize / 4;
Expand Down Expand Up @@ -945,9 +953,14 @@ public float calculateRadius (final Vector3 center) {
return calculateRadius(center.x, center.y, center.z, 0, getNumIndices(), null);
}

/** @return the backing shortbuffer holding the indices. Does not have to be a direct buffer on Android! */
/** @return the backing shortbuffer holding the indices. Does not have to be a direct buffer on Android!
* @deprecated use {@link #getIndicesBuffer(boolean)} instead */
public ShortBuffer getIndicesBuffer () {
return indices.getBuffer();
return indices.getBuffer(true);
}

public ShortBuffer getIndicesBuffer (boolean forWriting) {
return indices.getBuffer(forWriting);
}

private static void addManagedMesh (Application app, Mesh mesh) {
Expand Down
5 changes: 3 additions & 2 deletions gdx/src/com/badlogic/gdx/graphics/g2d/SpriteBatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -956,8 +956,9 @@ public void flush () {
lastTexture.bind();
Mesh mesh = this.mesh;
mesh.setVertices(vertices, 0, idx);
((Buffer)mesh.getIndicesBuffer()).position(0);
((Buffer)mesh.getIndicesBuffer()).limit(count);
Buffer indicesBuffer = (Buffer)mesh.getIndicesBuffer(true);
indicesBuffer.position(0);
indicesBuffer.limit(count);

if (blendingDisabled) {
Gdx.gl.glDisable(GL20.GL_BLEND);
Expand Down
20 changes: 11 additions & 9 deletions gdx/src/com/badlogic/gdx/graphics/g2d/SpriteCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,10 @@ public void beginCache () {
if (drawing) throw new IllegalStateException("end must be called before beginCache");
if (currentCache != null) throw new IllegalStateException("endCache must be called before begin.");
int verticesPerImage = mesh.getNumIndices() > 0 ? 4 : 6;
currentCache = new Cache(caches.size, mesh.getVerticesBuffer().limit());
FloatBuffer verticesBuffer = mesh.getVerticesBuffer(true);
currentCache = new Cache(caches.size, verticesBuffer.limit());
caches.add(currentCache);
mesh.getVerticesBuffer().compact();
verticesBuffer.compact();
}

/** Starts the redefinition of an existing cache, allowing the add and {@link #endCache()} methods to be called. If this is not
Expand All @@ -182,21 +183,22 @@ public void beginCache () {
public void beginCache (int cacheID) {
if (drawing) throw new IllegalStateException("end must be called before beginCache");
if (currentCache != null) throw new IllegalStateException("endCache must be called before begin.");
Buffer verticesBuffer = (Buffer)mesh.getVerticesBuffer(true);
if (cacheID == caches.size - 1) {
Cache oldCache = caches.removeIndex(cacheID);
((Buffer)mesh.getVerticesBuffer()).limit(oldCache.offset);
verticesBuffer.limit(oldCache.offset);
beginCache();
return;
}
currentCache = caches.get(cacheID);
((Buffer)mesh.getVerticesBuffer()).position(currentCache.offset);
verticesBuffer.position(currentCache.offset);
}

/** Ends the definition of a cache, returning the cache ID to be used with {@link #draw(int)}. */
public int endCache () {
if (currentCache == null) throw new IllegalStateException("beginCache must be called before endCache.");
Cache cache = currentCache;
int cacheCount = mesh.getVerticesBuffer().position() - cache.offset;
int cacheCount = mesh.getVerticesBuffer(false).position() - cache.offset;
if (cache.textures == null) {
// New cache.
cache.maxCount = cacheCount;
Expand All @@ -206,7 +208,7 @@ public int endCache () {
for (int i = 0, n = counts.size; i < n; i++)
cache.counts[i] = counts.get(i);

((Buffer)mesh.getVerticesBuffer()).flip();
((Buffer)mesh.getVerticesBuffer(true)).flip();
} else {
// Redefine existing cache.
if (cacheCount > cache.maxCount) {
Expand All @@ -225,7 +227,7 @@ public int endCache () {
for (int i = 0, n = cache.textureCount; i < n; i++)
cache.counts[i] = counts.get(i);

FloatBuffer vertices = mesh.getVerticesBuffer();
FloatBuffer vertices = mesh.getVerticesBuffer(true);
((Buffer)vertices).position(0);
Cache lastCache = caches.get(caches.size - 1);
((Buffer)vertices).limit(lastCache.offset + lastCache.maxCount);
Expand All @@ -241,7 +243,7 @@ public int endCache () {
/** Invalidates all cache IDs and resets the SpriteCache so new caches can be added. */
public void clear () {
caches.clear();
((Buffer)mesh.getVerticesBuffer()).clear().flip();
((Buffer)mesh.getVerticesBuffer(true)).clear().flip();
}

/** Adds the specified vertices to the cache. Each vertex should have 5 elements, one for each of the attributes: x, y, color,
Expand All @@ -259,7 +261,7 @@ public void add (Texture texture, float[] vertices, int offset, int length) {
} else
counts.incr(lastIndex, count);

mesh.getVerticesBuffer().put(vertices, offset, length);
mesh.getVerticesBuffer(true).put(vertices, offset, length);
}

/** Adds the specified texture to the cache. */
Expand Down
10 changes: 6 additions & 4 deletions gdx/src/com/badlogic/gdx/graphics/g3d/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import com.badlogic.gdx.utils.ObjectMap;

import java.nio.Buffer;
import java.nio.ShortBuffer;

/** A model represents a 3D assets. It stores a hierarchy of nodes. A node has a transform and optionally a graphical part in form
* of a {@link MeshPart} and {@link Material}. Mesh parts reference subsets of vertices in one of the meshes of the model.
Expand Down Expand Up @@ -247,9 +248,10 @@ protected void convertMesh (ModelMesh modelMesh) {
meshes.add(mesh);
disposables.add(mesh);

BufferUtils.copy(modelMesh.vertices, mesh.getVerticesBuffer(), modelMesh.vertices.length, 0);
BufferUtils.copy(modelMesh.vertices, mesh.getVerticesBuffer(true), modelMesh.vertices.length, 0);
int offset = 0;
((Buffer)mesh.getIndicesBuffer()).clear();
ShortBuffer indicesBuffer = mesh.getIndicesBuffer(true);
((Buffer)indicesBuffer).clear();
for (ModelMeshPart part : modelMesh.parts) {
MeshPart meshPart = new MeshPart();
meshPart.id = part.id;
Expand All @@ -258,12 +260,12 @@ protected void convertMesh (ModelMesh modelMesh) {
meshPart.size = hasIndices ? part.indices.length : numVertices;
meshPart.mesh = mesh;
if (hasIndices) {
mesh.getIndicesBuffer().put(part.indices);
indicesBuffer.put(part.indices);
}
offset += meshPart.size;
meshParts.add(meshPart);
}
((Buffer)mesh.getIndicesBuffer()).position(0);
((Buffer)indicesBuffer).position(0);
for (MeshPart part : meshParts)
part.update();
}
Expand Down
15 changes: 8 additions & 7 deletions gdx/src/com/badlogic/gdx/graphics/glutils/IndexArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,18 @@ public void updateIndices (int targetOffset, short[] indices, int offset, int co
((Buffer)byteBuffer).position(pos);
}

/**
* <p>
* Returns the underlying ShortBuffer. If you modify the buffer contents they wil be uploaded on the call to {@link #bind()}.
* If you need immediate uploading use {@link #setIndices(short[], int, int)}.
* </p>
*
* @return the underlying short buffer. */
/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public ShortBuffer getBuffer () {
return buffer;
}

@Override
public ShortBuffer getBuffer (boolean forWriting) {
return buffer;
}

/** Binds this IndexArray for rendering with glDrawElements. */
public void bind () {
}
Expand Down
16 changes: 9 additions & 7 deletions gdx/src/com/badlogic/gdx/graphics/glutils/IndexBufferObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,20 @@ public void updateIndices (int targetOffset, short[] indices, int offset, int co
}
}

/**
* <p>
* Returns the underlying ShortBuffer. If you modify the buffer contents they wil be uploaded on the call to {@link #bind()}.
* If you need immediate uploading use {@link #setIndices(short[], int, int)}.
* </p>
*
* @return the underlying short buffer. */
/** @deprecated use {@link #getBuffer(boolean)} instead */
@Override
@Deprecated
public ShortBuffer getBuffer () {
isDirty = true;
return buffer;
}

@Override
public ShortBuffer getBuffer (boolean forWriting) {
isDirty |= forWriting;
return buffer;
}

/** Binds this IndexBufferObject for rendering with glDrawElements. */
public void bind () {
if (bufferHandle == 0) throw new GdxRuntimeException("No buffer allocated!");
Expand Down
Loading

0 comments on commit 02f4a0c

Please sign in to comment.