Permalink
Browse files

Added warm-up functionality to TextureManager, to ensure texture data…

… is actually moved to the GPU (and doesn't keep sitting in the native heap), when the texture is loaded.
  • Loading branch information...
1 parent 69a2f8b commit 5e941a8fcfa3393d4ec2d80403241a8326060cbb Nicolas Gramlich committed May 15, 2012
@@ -37,6 +37,7 @@
private final ArrayList<ITexture> mTexturesToBeLoaded = new ArrayList<ITexture>();
private final ArrayList<ITexture> mTexturesToBeUnloaded = new ArrayList<ITexture>();
+ private TextureWarmUpVertexBufferObject mTextureWarmUpVertexBufferObject;
// ===========================================================
// Constructors
@@ -55,7 +56,7 @@
// ===========================================================
public synchronized void onCreate() {
-
+ this.mTextureWarmUpVertexBufferObject = new TextureWarmUpVertexBufferObject();
}
public synchronized void onReload() {
@@ -75,6 +76,8 @@ public synchronized void onReload() {
this.mTexturesManaged.removeAll(this.mTexturesToBeUnloaded); // TODO Check if removeAll uses iterator internally!
this.mTexturesToBeUnloaded.clear();
}
+
+ this.mTextureWarmUpVertexBufferObject.setNotLoadedToHardware();
}
public synchronized void onDestroy() {
@@ -87,6 +90,9 @@ public synchronized void onDestroy() {
this.mTexturesLoaded.clear();
this.mTexturesManaged.clear();
this.mTexturesMapped.clear();
+
+ this.mTextureWarmUpVertexBufferObject.dispose();
+ this.mTextureWarmUpVertexBufferObject = null;
}
public synchronized boolean hasMappedTexture(final String pID) {
@@ -245,6 +251,9 @@ public synchronized void updateTextures(final GLState pGLState) {
if(!textureToBeLoaded.isLoadedToHardware()) {
try {
textureToBeLoaded.loadToHardware(pGLState);
+
+ /* Execute the warm-up to ensure the texture data is actually moved to the GPU. */
+ this.mTextureWarmUpVertexBufferObject.warmup(pGLState, textureToBeLoaded);
@nicolasgramlich

nicolasgramlich May 15, 2012

Owner

To ensure Texture warmup actually works, replace the surrounding try-catch block with the following code:

try {
    System.gc();
    System.gc();

    Debug.i(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
    Debug.i("> Texture: " + textureToBeLoaded.toString() + "");
    Debug.i("> PRE");
    Debug.i("> Native memory allocated size: " + SystemUtils.getNativeHeapAllocatedSize() + " kB");

    textureToBeLoaded.loadToHardware(pGLState);
    System.gc();
    System.gc();

    Debug.i("> POST");
    Debug.i("> Native memory allocated size: " + SystemUtils.getNativeHeapAllocatedSize() + " kB");

    this.mTextureWarmUpVertexBufferObject.warmup(pGLState, textureToBeLoaded);

    Debug.i("> WARMED UP");
    Debug.i("> Native memory allocated size: " + SystemUtils.getNativeHeapAllocatedSize() + " kB");
    Debug.i(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
} catch (final IOException e) {
    Debug.e(e);
}

The output of that "Debug.i" statements should show the allocated native size go up first and the down, almost exactly to the initial amount.

} catch (final IOException e) {
Debug.e(e);
}
@@ -0,0 +1,82 @@
+package org.andengine.opengl.texture;
+
+import org.andengine.opengl.shader.PositionTextureCoordinatesShaderProgram;
+import org.andengine.opengl.shader.constants.ShaderProgramConstants;
+import org.andengine.opengl.util.GLState;
+import org.andengine.opengl.vbo.DrawType;
+import org.andengine.opengl.vbo.VertexBufferObject;
+import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributes;
+import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributesBuilder;
+
+import android.opengl.GLES20;
+
+/**
+ * (c) Zynga 2012
+ *
+ * @author Nicolas Gramlich <ngramlich@zynga.com>
+ * @since 15:11:05 - 15.05.2012
+ */
+public class TextureWarmUpVertexBufferObject extends VertexBufferObject {
+ // ===========================================================
+ // Constants
+ // ===========================================================
+
+ public static final int VERTEX_SIZE = 2 + 2;
+ public static final int VERTICES_PER_VERTEXBUFFEROBJECT_SIZE = 3;
+ public static final int VERTEXBUFFEROBJECT_SIZE = TextureWarmUpVertexBufferObject.VERTEX_SIZE * TextureWarmUpVertexBufferObject.VERTICES_PER_VERTEXBUFFEROBJECT_SIZE;
+
+ public static final VertexBufferObjectAttributes VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT = new VertexBufferObjectAttributesBuilder(2)
+ .add(ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION, 2, GLES20.GL_FLOAT, false)
+ .add(ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES, 2, GLES20.GL_FLOAT, false)
+ .build();
+
+ // ===========================================================
+ // Fields
+ // ===========================================================
+
+ // ===========================================================
+ // Constructors
+ // ===========================================================
+
+ public TextureWarmUpVertexBufferObject() {
+ super(null, VERTEXBUFFEROBJECT_SIZE, DrawType.STATIC, true, TextureWarmUpVertexBufferObject.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
+ }
+
+ // ===========================================================
+ // Getter & Setter
+ // ===========================================================
+
+ // ===========================================================
+ // Methods for/from SuperClass/Interfaces
+ // ===========================================================
+
+ @Override
+ public int getHeapMemoryByteSize() {
+ return 0;
+ }
+
+ @Override
+ public int getNativeHeapMemoryByteSize() {
+ return this.getByteCapacity();
+ }
+
+ @Override
+ protected void onBufferData() {
+ /* Nothing. */
+ }
+
+ public void warmup(final GLState pGLState, final ITexture pTexture) {
+ pTexture.bind(pGLState);
+ this.bind(pGLState, PositionTextureCoordinatesShaderProgram.getInstance());
+ this.draw(GLES20.GL_TRIANGLES, VERTICES_PER_VERTEXBUFFEROBJECT_SIZE);
+ this.unbind(pGLState, PositionTextureCoordinatesShaderProgram.getInstance());
+ }
+
+ // ===========================================================
+ // Methods
+ // ===========================================================
+
+ // ===========================================================
+ // Inner and Anonymous Classes
+ // ===========================================================
+}
@@ -48,7 +48,7 @@
// ===========================================================
/**
- * @param pVertexBufferObjectManager
+ * @param pVertexBufferObjectManager (optional, if you manage reloading on your own.)
* @param pCapacity
* @param pDrawType
* @param pAutoDispose when passing <code>true</code> this {@link VertexBufferObject} loads itself to the active {@link VertexBufferObjectManager}. <b><u>WARNING:</u></b> When passing <code>false</code> one needs to take care of that by oneself!
@@ -141,7 +141,9 @@ public void bind(final GLState pGLState) {
if(this.mHardwareBufferID == IVertexBufferObject.HARDWARE_BUFFER_ID_INVALID) {
this.loadToHardware(pGLState);
- this.mVertexBufferObjectManager.onVertexBufferObjectLoaded(this);
+ if(this.mVertexBufferObjectManager != null) {
+ this.mVertexBufferObjectManager.onVertexBufferObjectLoaded(this);
+ }
}
pGLState.bindArrayBuffer(this.mHardwareBufferID);
@@ -190,7 +192,9 @@ public void dispose() {
if(!this.mDisposed) {
this.mDisposed = true;
- this.mVertexBufferObjectManager.onUnloadVertexBufferObject(this);
+ if(this.mVertexBufferObjectManager != null) {
+ this.mVertexBufferObjectManager.onUnloadVertexBufferObject(this);
+ }
BufferUtils.freeDirectByteBuffer(this.mByteBuffer);
} else {

5 comments on commit 5e941a8

this gives strange behavior on Samsung S plus (i9001) ... sprites are invisible ... also some scenes dont load

Version 2.3.3

Can you update to adcc1a0 for obvious reasons?

Also, are there any (crash) logs?

it was with update adcc1a0

i dont have any logs at the moment because i reverted the changes

what i can tell you is that there were not any crash logs from what i remember .. but some sprites where invisible (not all sprites) ... i think most of the invisible sprites were the AnimatedSprites

i tested also on Samsung Google Nexus and there it was ok

Please sign in to comment.