I want to improve glReadPixels() performance using PBO(for Android 4.3+), As glReadPixels takes about 30~50ms(1280*960) for each frame in my test device.But I can't use glReadPixels directly in Java, since the last param cannot be zero or "null". I also try to use ndk as mentioned here. But the last param needs to be (void*) either in my ndk's GLES3/gl3.h. So the question is how can I use glReadPixels to make PBO work? Is this the right solution for better performance?
You will need to cast the last parameter from int to void* explicitly in your c++ codes.
Related
I'm using OpenGL ES 2 via jni.
When going over the OpenGL Trace view of my frame rendering, I saw this error in the console:
error applying transformations for glUniform1f(location = 6, x = 1.000000)
java.lang.RuntimeException: No such property: PROGRAM_STATE/PROGRAMS/${program}/ACTIVE_UNIFORMS/6/UNIFORM_VALUE
It seems like I'm calling uniform for a non existing variable, so I went over all of the usages I have for this call, and also tried checking with 'glError', but I found nothing.
How can I know what is causing this?
I suspect you are trying to upload to a non-existent unifom in the current program.
Did you call glGetUniformLocation() on all the symbol names in this linked version of the program?
You can't safely make assumptions that, e.g. they increment, so you really do need to call glGetUniformLocation() for all of them (or set binding locations directly, but that's not available until OpenGL ES 3.x).
After a lot of reading I was able to understand the steps needed to load a texture in OpenGL ES 2.0, but some question are still not answered:
What's the code below is actually doing?
glUniform1i(sampler2DLocation, 0);
If I erase this line from my code, nothing changes. Some books describe it as "Tell the texture uniform sampler to use this texture in the shader by telling it to read from texture unit 0"
This is called after the line:
glActiveTexture(GL_TEXTURE0);
But as stated in khronos.org the default active texture is GL_TEXTURE0, so I guess the line "glActiveTexture(GL_TEXTURE0);" code is just written as a good practice?
One last thing, when I call:
glBindTexture(GL_TEXTURE_2D, genTextures[0]);
I'm saying that future calls that affect "GL_TEXTURE_2D" will affect the texture unit stored in genTextures[0], due the binding. But there is any relation between "GL_TEXTURE_2D" and the active texture unit? I mean, there is an intrinsic chain between the 03 "components"?
genTextures[0] <---> GL_TEXTURE_2D <---> the active texture unit
Thank you,
The reason why the code continues to work even if you remove the instruction "glUniform1i(sampler2DLocation, 0);" is due, possibly to the default value assigned by the driver when the uniform is not provided.
To better understand it I would need an example of the shared code and the way the uniform ID is taken but I am pretty sure that the instruction is there to say to the GPU through the shader to use the texture unit 0.
The effect of calling "glUniform1i(sampler2DLocation, 0);" says take texture unit 0.
The effect of not calling it, sets anyway the sampler uniform to 0 and therefore, even if not formally correct, has the same behavior.
According to OpenGL standard, you activate a texture unit with the glActivateTexture which requires the number of the texture unit and then you bind the texture with glbindtexture to that specific current texture unit.
In other words, first you set the texture unit you want to work on and then you tell to the driver which texture needs to be bound in it.
I hope this helps.
Maurizio
I have got some strange and unexpected results from my program in OpenGL ES for android for example in the code below:
matrix = ThisRot.get();
gl.glMultMatrixf(matrix, 0);
currentRotation.toMatrix(matrix);
temp.set(matrix);
I set the matrix value before I use it as an argument for gl.glMultMatrixf and after that I change the value of matrix and use it for another purpose, but it has effect an the way the object rotate so it should have effect on gl.glMultMatrixf(). and that's not the only one, some other places in my code I had this unexpected results. so I have thought maybe these happen due to mutual exclusion and multitreading and those kind of things.
am I right? should we worry about multithreading when we code in Opengl ES for android? How can I avoid these kind of problems.
Of course you should worry about multithreading. In particular, Android creates its own GLThread for rendering, when you attach a GLRenderer-derived class to a GLSurfaceView using the setRenderer() function.
In fact, multithreading can cause crashes (not only unexpected behavior) in your programs especially when you loop through arrays adding/removing objects and such.
Check if you are modifying the same data inside the onDrawFrame function of your GLRenderer and your own thread. If you are, try adding the following around the modified code (in both threads):
synchronize(variable) {
modify(variable);
}
This will lock the variable throughout the modify() function until it ends the block. Try not to overuse it, though, only in places where you need it. One thread will block the other one until it's finished!
I"m planning to store my data in a binary format as a resource, read it into an int buffer and basically pass it straight down to a native C++ function, which might cast it to a struct/class and work with it. No pointers, obviously, just ints and floats.
The question is - what kind of fixing up do I need to do? I suppose that I need to check ByteOrder.nativeOrder(), figure out if it's big endian or little endian, and perform byte-swapping if need be.
Other than that, floats are presumably guaranteed to be expected in IEEE 754 format? Are there any other caveats I'm completely overlooking here?
(Also - since I'm compiling using the NDK, I know what architecture it is already (ARMv7-A, in my case), so can I technically skip the endian shenanigans and just take the data the way it is?)
ARM support both big and little endian. This will most probably be set by the OS so it might be worth while checking this out beforehand.
There is also the issue of padding to word size in a struct:
struct st
{
char a;
int b;
};
will have a sizeof 8 and not the expected 5 bytes. This is so that the int will be word aligned. Generally align everything to 4 bytes and probably use the gcc packed attribute (struct my_packed_struct __attribute__ ((__packed__))
) as well. This will ensure that the internals of the struct are as you expect.
Alternatively use the Android Simulator to generate the data file for you.
I simply need to add floatArray1 to floatArray2 storing the result in floatArray2.. no third array.. all arrays are one dimensional but are very large... probibly as large as the os will let me get away with. Max i would need is two float arrays with 40,000 floats each... but i could get away with 1/10th that i suppose minimum.
Would love to do this in 1/30th or 1/60th of a second but that does not seem possible? Also if the code is JNI,NDK or OpenGL ES thats fine.. does android have an assembly language or like machine code i could use somehow?
Since a float is worth 32 bit and you have 40000 floats in each array you would need:
40000 * 32 * 2 = 2.560.000 bit
Which is 320.000 Byte. Not to much memory wise i would say since the default limit for an android app is 16MB.
Regarding performance you would definitely gain some speed using JNI. OpenGL would not give you enough benefit i would think since the OpenGL context creation takes some time as well.