Compute shader with current version of OF

Hi forum,

I am going through the book “Mastering openFrameworks” and on page 214 it is mentioned that compute shader can be used for universal computation along with OF. So far as i know compute shader is supported in opengl 4.3 and OF uses opengl 3 if the programmable renderer is used.

In that case i do not understand how to use the compute shader with the existing version of OF.

Thanks

you can’t, it’s actually relatively easy to change the core to support any other version of openGL just edit ofAppRunner to change the version of openGL and then the programmable GL renderer to change the default shader versions to the corresponding GLSL version. even with that ofShader doesn’t support compute shaders yet although it should be easy to hack it as well. but no in principle there’s no support for compute shaders or anything beyond openGL 3.2

2 Likes

Ok @arturo , I want to work based on at least OpenGL 3.3. Which files i have to edit and then compile from the following

  1. ofAppRunner.

  2. programmable GL renderer … any specific file names ?

  3. We have to extend the ofShader class to to support the compute shader ?

ofAppRunner and ofGLProgrammableRenderer, i’m looking at ofShader and it’s possible that you won’t need to change it if you use setupShaderFromSource instead of load.

1 Like

Hi @arturo,

I managed to change some of the parameters within the file you suggested and it is as follows

//--------------------------------------
void ofSetupOpenGL(ofPtr<ofAppBaseWindow> windowPtr, int w, int h, int screenMode){

   //if the current renderer is not found
    if(!ofGetCurrentRenderer()) {
	#ifdef USE_PROGRAMMABLE_GL
       //if the programmable renderer is defined create a new instance of it
	    ofPtr<ofBaseRenderer> renderer(new ofGLProgrammableRenderer(false));
	#else
	    //otherwise create a normal renderer instance
	    ofPtr<ofBaseRenderer> renderer(new ofGLRenderer(false));
	#endif

	    //set the newly created renderer as the current one
	    ofSetCurrentRenderer(renderer,false);
    }

	window = windowPtr;

	//IF WE DEAL WITH PROGRAMMABLE PIPELINE ONY
	//WHICH VERSION SHOULD WE CONSIDER
	if(ofIsGLProgrammableRenderer())
	{
#if defined(TARGET_RASPBERRY_PI)
	   static_cast<ofAppEGLWindow*>(window.get())->setGLESVersion(2);
#elif defined(TARGET_LINUX_ARM)
	   static_cast<ofAppGLFWWindow*>(window.get())->setOpenGLVersion(2,0);
#elif !defined(TARGET_OPENGLES)

	   //THIS IS WHERE I EDIT - SAJJAD****************** previous one - (3,2)
	   static_cast<ofAppGLFWWindow*>(window.get())->setOpenGLVersion(4,3);
#endif
	}
	else
	{

And inside the ofGLProgrammableRenderer i did not find anything else to change other than altering the version string as follows:

#version 430 core

What do i have to look into ? I build the library again after the changes and it build fine.

Now it is time to test. Any hint to get started with ?

Thanks

yes that should be it, never used compute shaders but would be curious to know if post any examples

Hi @arturo

I guess that there are more to be done other than extending the ofShader to compute shader. Now it is mandatory to create vertex array object in the OpenGL 4.3 core profile irrespective of the fact one is using the vbo or not.

glGenVertexArrays(...)

I think i have to do some more changes within the ofGLProgrammableRenderer and ofVbo classes. It will be nice if you could suggest me which functions i should look into within these two classes or if i have to look into somewhere else.

Thanks
Sajjadul

VAO’s are mandatory since 3.0 we always use them when the programmable renderer is enabled.

i’ve been working on a branch that will allow you to set up any openGL version in case you want to try it:

https://github.com/arturoc/openFrameworks/tree/feature-moreProgrammableGL

in main before calling ofSetupOpenGL just call ofSetGLVersion(4,4); or whatever version you want to use

Really? It means that if i use your branch i do not have to make those changes with in the API that have been discussed from the beginning of this thread.

And again, i checked the ofShader and ofGLProgrammableRenderer class of this branch and i do not see where you incorporated the provision of tesselation control shader and tesselation evaluation shader which are part of the opengl 4.3 core profile. Yes, they could be written , but we have avoid using the ofShader::load(…) function.

Let me know if i missed it.

Thanks

yes with that branch you don’t need to do any changes.

and no, i haven’t done any change to ofShader since it’ll complicate the load function a lot so you’ll need to load the shaders using setupShaderFromSource instead of load

1 Like

Do i have to include some more file inside the main.cpp . I am getting error with the following snippet:

#include "ofMain.h"
#include "ofApp.h"

// comment out the line below if you want to use a fixed pipeline opengl renderer,
// otherwise leave this line uncommented if you want to use a programmable pipeline opengl renderer.
#define USE_PROGRAMMABLE_RENDERER

#ifdef USE_PROGRAMMABLE_RENDERER
#include "ofGLProgrammableRenderer.h"
#endif
//========================================================================
int main( )
{
#ifdef USE_PROGRAMMABLE_RENDERER
   ofSetCurrentRenderer(ofGLProgrammableRenderer::TYPE);
#endif      
   //ofSetupOpenGL(1024,768,OF_WINDOW);			// <-------- setup the GL context
   ofSetGLVersion(4,3);
   ofSetupOpenGL(1024,768, OF_FULLSCREEN);   
   
   // this kicks off the running of my app
   // can be OF_WINDOW or OF_FULLSCREEN
   // pass in width and height too:
   ofRunApp(new ofApp());

}

And i am getting the error

src/main.cpp: In function ‘int main()’:
src/main.cpp:18:22: error: ‘ofSetGLVersion’ was not declared in this scope
    ofSetGLVersion(4,3);

Any idea?

Thanks

yeah sorry, it’s ofSetOpenGLVersion, you don’t need to set the programmable renderer anymore just the GL version

None of the shaders app works with the new programmable branch. I am getting the following error:

sajjad@sajjad-G74Sx:~/Downloads/openFrameworks/moreProgrammable/openFrameworks-feature-moreProgrammableGL/apps/myApps/myShaderRimLight$ [verbose] ofxAssimpModelLoader: loadModel(): loading "buddha.obj" from "/home/sajjad/Downloads/openFrameworks/moreProgrammable/openFrameworks-feature-moreProgrammableGL/apps/myApps/myShaderRimLight/bin/data/"
[verbose] ofxAssimpModelLoader: calculateDimensions(): inited scene with 2 meshes & 0 animations
[verbose] ofxAssimpModelLoader: loadGLResources(): starting
[verbose] ofxAssimpModelLoader: loadGLResources(): loading mesh 0
[verbose] ofxAssimpModelLoader: loadGLResources(): loading mesh 1
[verbose] ofxAssimpModelLoader: loadGLResource(): finished
[verbose] ofxAssimpModelLoader: loadMode(): no animations
[verbose] ofShader: checkAndCreateProgram(): creating GLSL program
[verbose] ofShader: setupShaderFromSource(): GL_VERTEX_SHADER shader compiled
[verbose] ofShader: setupShaderFromSource(): GL_FRAGMENT_SHADER shader compiled
[verbose] linkProgram(): attaching GL_FRAGMENT_SHADER shader to program 22
[verbose] linkProgram(): attaching GL_VERTEX_SHADER shader to program 22
[verbose] ofShader: checkProgramLinkStatus(): program 22linked
[verbose] ofTrueTypeFont: loadFontFace(): "sans-serif" not a file in data loading system font from "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
[verbose] ofTrueTypeFont: loadFontFace(): "sans-serif" not a file in data loading system font from "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
[verbose] ofTrueTypeFont: loadFontFace(): "sans-serif" not a file in data loading system font from "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
[verbose] ofShader: checkAndCreateProgram(): creating GLSL program
[verbose] ofShader: setupShaderFromSource(): GL_VERTEX_SHADER shader compiled
[ error ] ofShader: setupShaderFromSource(): GL_FRAGMENT_SHADER shader failed to compile
[ error ] ofShader: GL_FRAGMENT_SHADER shader reports:
0(10) : error C1043: size of dimension cannot be less than 1

[verbose] linkProgram(): attaching GL_VERTEX_SHADER shader to program 25
[verbose] ofShader: checkProgramLinkStatus(): program 25linked
[verbose] ofShader: checkAndCreateProgram(): creating GLSL program
[verbose] ofShader: setupShaderFromSource(): GL_VERTEX_SHADER shader compiled
[ error ] ofShader: setupShaderFromSource(): GL_FRAGMENT_SHADER shader failed to compile
[ error ] ofShader: GL_FRAGMENT_SHADER shader reports:
0(11) : error C1043: size of dimension cannot be less than 1

[verbose] linkProgram(): attaching GL_VERTEX_SHADER shader to program 28
[verbose] ofShader: checkProgramLinkStatus(): program 28linked
[verbose] ofShader: checkAndCreateProgram(): creating GLSL program
[verbose] ofShader: setupShaderFromSource(): GL_VERTEX_SHADER shader compiled
[ error ] ofShader: setupShaderFromSource(): GL_FRAGMENT_SHADER shader failed to compile
[ error ] ofShader: GL_FRAGMENT_SHADER shader reports:
0(11) : error C1043: size of dimension cannot be less than 1

[verbose] linkProgram(): attaching GL_VERTEX_SHADER shader to program 31
[verbose] ofShader: checkProgramLinkStatus(): program 31linked

And getting the following output

http://imgur.com/4BANDJ4

The expected output is

http://imgur.com/eV3NOzb

I got immediate above output with the release version of OF.

What does it mean with the following

0(10) : error C1043: size of dimension cannot be less than 1 

Do you mean that we do not have to call the glGenVertexArrays() since it is called by default ?

I tried it and i do not see any output at all and i do get the expected output with the following snippet:

void ofApp::setup()
{
   //now load the shaders
   if(ofIsGLProgrammableRenderer())
   {
      if(!shader.setupShaderFromFile(GL_VERTEX_SHADER,"shaders/triangle-tesselation.vert") ||
	 !shader.setupShaderFromFile(GL_TESS_CONTROL_SHADER,"shaders/triangle-tesselation.tcs") ||
	 !shader.setupShaderFromFile(GL_TESS_EVALUATION_SHADER,"shaders/triangle-tesselation.tes") ||
	 !shader.setupShaderFromFile(GL_FRAGMENT_SHADER,"shaders/triangle-tesselation.frag"))
      {
	 std::cerr << "Shaders could not be loaded from the source files." << std::endl;
	 OF_EXIT_APP(1);
      }

      if(!shader.linkProgram())
      {
	 std::cerr << "Shaders could not be linked" << std::endl;
	 OF_EXIT_APP(1);	 
      }      
   }
   else
   {
      std::cout << "Programmable Shading is not supported. " << std::endl;
      OF_EXIT_APP(1);
   }

   glGenVertexArrays(1,&vertex_array_object);
   glBindVertexArray(vertex_array_object);
   
   glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
}



void ofApp::draw()
{
   static const GLfloat green[] = {0.0f,0.25f,0.0f,1.0f};

   glClearBufferfv(GL_COLOR,0,green);

   shader.begin();
   glDrawArrays(GL_PATCHES,0,3);
   shader.end();
}

are you using materials? in that case you need at least a light enabled for them to work, i’ll fix this so it reports an error or the shader doesn’t fail to compile, but the error C1043: size of dimension cannot be less than 1 seems related to that, unless it comes from your own shaders

Did you mean ofLight ? I have a point light defined inside shader and i wanted to preserve it. If it has to be programmable pipeline, would it not be better to remove the some fixed-pipeline stuff ?

ofLight and ofMaterial are based on shaders in that branch, but anyway, it you are not using ofMaterial the problem might be somewhere else

Currently compute shaders are not supported in Mac OS X -
http://www.opengl.org/discussion_boards/showthread.php/183385-Compute-shaders-on-MacOS-X

#ifndef GL_COMPUTE_SHADER
#define GL_COMPUTE_SHADER                 0x91B9
#endif

...
    GLuint ShaderID = glCreateShader( GL_COMPUTE_SHADER );
    if ( !ShaderID ) {
        cout << "ERROR: Failed creating compute shader instance" << endl;
        return 0;
    }
....
  • on Mac OS X ShaderID is equal to 0 - it means that shader is not created here.