How to let a vertex shader in OpenGL ES 2.0 perform GPGPU computing? - opengl-es

I'm doing a project using OpenCL and thought it can work on Mali 400 GPU. But I recently found that Mali 400 GPU only support OpenGL ES 2.0 standard.
I still have to use this GPU, So is there any way to let a shader act nearly the same as OpenCL kernel or CUDA kernel?
There are some main features I expect but not sure glsl will support:
For example, I created a global memory for GPU, and I want to read/write the global memory in shader, how should I pass the variable from host to vertex shader, can I expect that data be both 'in and out' like this?
layout (location = 0) inout vec3 a_Data;
I want to fetch a_Data as 64 float values, is there a easy way to declare it like vec64 or float[64], or I have to use multiple vec4 to assemble it?

So is there any way to let a vertex shader act nearly the same as OpenCL kernel or CUDA kernel?
No.
In ES 2.0, vertex shaders have no mechanism to write to memory. At all. All of their output variables go to the rasterizer to generate fragments to be processed by the fragment shader.
The only way to do GPGPU processing on such hardware is to use the fragment shader to write data. That means you have to manipulate your data to look like a rendering operation. Your vertex positions needs to set up your fragment shader to be able to write values to the appropriate places. And your fragment shader needs to be able to acquire whatever information it needs based on what the VS provides (which is at a per-vertex granularity and interpolated for each fragment).

Related

culling instanced meshes without geometry shader

Whats an effective way to cull instanced meshes
(f.e. 2000 trees, each with ~ 17 triangles) without using the geometry shader ?
Unfortunately my software supports only OpenGL ES 3.0, so have to cull in the vertex shader or somewhere else.
Another solution would be to rearrange the instance buffer in each frame.
GPU culling is pointless if it cannot be done efficiently; that is, after all, the whole point of putting culling on the GPU to begin with.
Efficient GPU culling requires the following:
A way to conditionally write data to GPU memory from a shader, and with a controllable format.
A way to have rendering commands executed based on data stored entirely within GPU memory, without CPU/GPU synchronization.
OpenGL ES 3.0 lacks a mechanism for doing either of these. Geometry shaders and transform feedback are the older means for doing #1, but it could also be done with compute shaders and SSBOs/image load/store. Of course, ES 3.0 has neither sets of functionality; you'd need ES 3.1 for that.
ES 3.0 also has no indirect rendering features, which could be used to actually render with the GPU-generated data without any read-back of data from the CPU. So even if you had a way to do #1, you'd have to read the data back on the CPU to be able to use it in a rendering command.
So unless CPU culling is somehow more expensive than doing a full GPU/CPU sync (it almost certainly isn't), it's best to just do the culling on the CPU.

In opengl ES can I use a vertex buffer array buffer etc for shader shared matrices?

As OpenGL ES does not support shared "uniform blocks" I was wondering if there is a way I can put matrices that can be referenced by a number of different shaders, a simple example would be a worldToViewport or worldToEye which would not change for an entire frame and which all shaders would reference. I saw one post where one uses 3 or 4 dot calls on a vertex to transform it from 4 "column vectors", but wondering if there is a way to assign the buffer data to a "mat4" in the shader.
Ah yes the need for this is webGL which at the moment it seems only to support openGLES 2.0.
I wonder if it supports indexed attribute buffers as I assume they don't need to be any specified size relative to the size of the position vertex array.
Then if one can use a hard coded or calculated index into the attribute buffer ( in the shader ) and if one can bind more than one attribute buffer at a time, and access all "bound to the shader" buffers simultaneously in a shader ...
I see if all true might work. I need a good language/architecture reference on shaders as I am somewhat new to shader programming as I I'm trying to deign a wall without knowing the shapes of the bricks :)
Vertex attributes are per-vertex, so there is no way so share vertex attributes amongst multiple vertices.
OpenGL ES 2.0 upwards has CPU-side uniforms, which must be uploaded individually from the CPU at draw time. Uniforms belong to the program object, so for uniforms which are constant for a frame you only have to modify each program once, so the cost isn't necessarily proportional to draw count.
OpenGL ES 3.0 onwards has Uniform Buffer Objects (UBOs) which allow you to load uniforms from a buffer in memory.
I'm not sure what you mean by "doesn't support shared uniform blocks", as that's pretty much what a UBO is, albeit it won't work on older hardware which only supports OpenGL ES 2.x.

OpenGL ES 3.0: writing to multiple buffers

One section of the OpenGL ES 3.0 spec is not completely clear to me.
https://www.khronos.org/registry/Ope...s_spec_3.0.pdf, page 185:
If an OpenGL ES Shading Language 1.00 fragment shader writes to
gl_FragColor or gl_FragData, DrawBuffers specifies the draw buffer, if
any, into which the single fragment color defined by gl_FragColor or
gl_FragData[0] is written. If an OpenGL ES Shading Language 3.00
fragment shader writes a user-defined varying out variable,
DrawBuffers specifies a set of draw buffers into which each of the
multiple output colors defined by these variables are separately
written.
I understand this the following way:
1) If I use OpenGL ES 3.0 and write shaders using GLSL 1.0, then the only way I can write to 2 buffers at once (COLOR0 and COLOR1) is to manually specify what gets written to gl_FragData[0] and gl_FragData[1] in my fragment shader. If I then want to get back to writing only to COLOR0, I must switch glPrograms to one that only writes to gl_FragData[0] (or gl_FragColor).
2) If on the other hand I use OpenGL ES 3.0 and write my shaders using GLSL 3.0, then I can write a single fragment shader with output defined to be a single varying out variable, and dynamically switch on and off writing to COLOR1 with calls to DrawBuffers() and with no need to swap glPrograms.
Is the above correct?
Is the above correct?
No. In ESSL 1.0 shaders you can only write to a single color buffer gl_FragData, or it's alias gl_FragData[0]. There is no such thing as gl_FragData[1] in ESSL 1.0.
and dynamically switch on and off writing to COLOR1 with calls to DrawBuffers() and with no need to swap glPrograms.
Yes, this is how it works in ESSL 3.x.
However, in most cases it's far more efficient just to swap programs. You execute the shader program millions of times (once per fragment), so having one program containing all of the code for all color targets and just masking out output writes is horribly inefficient. Don't do it. You want you shader programs to be as close to optimal as possible - that's where your GPU runtime goes ...

How can I perform arbitrary computation in OpenGL ES 3.0 (prior to compute shaders)

Prior to the introduction of compute shaders in OpenGL ES 3.1, what techniques or tricks can be used to perform general computations on the GPU? e.g. I am animating a particle system and I'd like to farm out some work to the GPU. Can I make use of vertex shaders with "fake" vertex data somehow?
EDIT:
I found this example which looks helpful: http://ciechanowski.me/blog/2014/01/05/exploring_gpgpu_on_ios/
You can use vertex shaders and transform feedback to output the results to an application accessible buffer. The main downside is that you can't have cross-thread data sharing between "work items" like you can with a compute shader, so they are not 100% equivalent.

is it possible to read data from vertex shader?

I am trying to write a simple GPGPU benchmark. To load the data into vertex buffer array, do some computation in the vertex shader, and read the data back. Is it possible? I am planning to run this on SGX GPUs.
Is there any way to do that? I dont want it to go through the transformation, clipping, Tiling phases, and pixel processing. that incurs additional overhead, and changes my data.
can I read back the data and examine it in the CPU? is there anyway in opengl es?
I can do the computations in pixel shader aswell, by sending data through a texture and multiplying with some constants and writing it to another frame buffer. but how do I get it back? i dont really want to present it to the screen.
is there anyway to do that? can somebody point me to some tutorials if available?
Reading Vertex output: Look for Transform Feedback - But you will have to have OpenGL ES 3.0 to use this.
For ES2.0 I suggest using fragment shader and Render To Texture techniques. Here is some link with tutorial
After rendering to texture you basically have to read pixels of the texture.
Nice tutorial on reading the data here
tutorial about feedback: http://open.gl/feedback
You cannot read data from vertex shader directly in OpenGL ES 2.0.
So, you can sed your data to pixel/fragment shader, attach it to Frame Buffer Object(FBO) and then use glReadPixels to get the data as texture in your CPU.
This link discribes the concept and code snnipet:
here.
Hope this might help.
"...computation in the vertex shader, and read the data back. Is it possible? I am planning to run this on SGX GPUs."
As SGX supports Opengles 2.0 not 3.0, PowerVR SGX doesn't support reading vertex shader output.(OpenGL ES 2.0 spec doesn't include such functionality).
"can I read back the data and examine it in the CPU? is there anyway in opengl es?"
You can use framebuffer objects and read the same using glRead API. You can read about FrameBuffer Objects here
Ref: http://en.wikipedia.org/wiki/Framebuffer_Object
Ref: Reading the pixels values from the Frame Buffer Object (FBO) using Pixel Buffer Object (PBO)
If GPGPU calculation you are after, then i recommend you should go for OpenCL.
SGX Supports OpenCL EP 1.1.
While writing from vertex shader to offscreen is not possible in OpenGL ES2, you can do that from pixel shader.
First you need to render to the offscreen buffer, then you can either render that as a texture to another object on screen, or you can read it back using readPixels the usual way. A simple list of steps is given in https://gist.github.com/prabindh/9201855.

Resources