Crystal Space
Welcome, Guest. Please login or register.
July 23, 2014, 11:17:40 am

Login with username, password and session length
Search:     Advanced search
9005 Posts in 2043 Topics by 8220 Members
Latest Member: Igymatta
* Home Help Search Login Register
+  Crystal Space
|-+  Crystal Space Development
| |-+  Support
| | |-+  PBO's in CS?
« previous next »
Pages: [1] Print
Author Topic: PBO's in CS?  (Read 3049 times)
rvhaasen
Jr. Member
**
Posts: 62


View Profile
« on: September 14, 2006, 04:21:06 pm »

I'm using the Texture::Blit() function to upload a texture each frame. This works fine, however it seriously impacts the framerate
( texture size = 2048x1024 )
PBO's (ARB_pixel_buffer_object OpenGL extension) would speed up the upload considerably.

Is there support for PBO's? As fas as i can see they are not supported.

In that case I'm considering changing the texture code to support PBO's (as far as i can see this is mainly involves gl_txtmgr.cpp)

Rick
Logged
res
Develazyoper
CS Developer
Full Member
*****
Posts: 206


View Profile Email
« Reply #1 on: September 14, 2006, 08:44:09 pm »

I'm using the Texture::Blit() function to upload a texture each frame. This works fine, however it seriously impacts the framerate
( texture size = 2048x1024 )
PBO's (ARB_pixel_buffer_object OpenGL extension) would speed up the upload considerably.

Is there support for PBO's? As fas as i can see they are not supported.

No.

In that case I'm considering changing the texture code to support PBO's (as far as i can see this is mainly involves gl_txtmgr.cpp)

Feel free. But also consider talking to me or thebolt before you jump into making the changes, so we have the chance to give some feedback wrt your planned changes.

NB, the tracker item for this is: http://trac.crystalspace3d.org/trac/CS/ticket/133
Logged
rvhaasen
Jr. Member
**
Posts: 62


View Profile
« Reply #2 on: September 15, 2006, 12:29:07 pm »

Ok, this is what i'm thinking of now

//--------------------------------------------
// Implementation 1, not so nice...

// From application setup create texture as usual:

iTextureWrapper  g_videoTexture = engine->CreateBlackTexture("videoTexture", 2048, 1024, 0, CS_TEXTURE_3D); 

// Now instantiate a csPBOimageMemory object which is a PBO implementation of the  csImageBase
// It will create 2 PBO's so the image could be used by glTexSubImage() and the application simultanuously (this
// is important if the "upload" by the application runs on another thread than the drawing thread.)

 csimageMemoryPBO* img = new csimageMemoryPBO(2048, 1024);

 g_videoTexture->SetImageFile(img);   // Connect to the texture


// Single thread example of CS frame  processing:

processFrame() {

  char* p = img->getImage();   // This will glMap 1 of the 2 PBO's and return the pointer so the application can store the
                                            // new image for this frame. The other PBO will be glUnmapped, so it can be used by
                                            // glTexSubimage() in the Blit() funtion of the texture.
  defineNewImage(p);             // Here the application updates the new Frame

  // Update the texture
  g_videoTexture->GetTextureHandle()->Blit(0, 0, 1280, 1024, 0);  // g_txtmgr.cpp has to be changed such that the blit function
                                                                                               // interpretes the null pointer as "use PBO as source".
                                                                                               // As such it will  glBind() the unmapped PBO,
                                                                                               // so glTexSubImage will use the PBO to upload the texture
}

A nicer approch would be to define a new texture class for this purpose.
In that case the engine interface must be extended. The application can then call something like

//------------------------------------
// Implementation 2, nicer...


iTextureWrapper  g_videoTexture = engine->CreatePBOtexture("videoTexture", 2048, 1024, 0, CS_TEXTURE_3D); 
 
// Single thread example

processFrame() {

  char* p = g_videoTexture->GetImage()->getImageData();

  updateNewImage(p);   

  g_videoTexture->GetTextureHandle()->Blit(0, 0, 1280, 1024); 
}

For multithreaded use, the glTexSubImage must be protected with a semaphore.
The glMap() and glUnmap()  funtions in g_videoTexture->GetImage()->getImageData() must also be protected.

There are other issues like signalling. The described implementation updates every frame which is fine for me now.
More in general updating should only be done when needed.
I don't know yet if i the  iEventHandler class could be used as another base class for the PBOtexture in order to do the uploading
in an event driven way.


Rick
Logged
res
Develazyoper
CS Developer
Full Member
*****
Posts: 206


View Profile Email
« Reply #3 on: September 15, 2006, 03:06:30 pm »

// Now instantiate a csPBOimageMemory object which is a PBO implementation of the  csImageBase
// It will create 2 PBO's so the image could be used by glTexSubImage() and the application simultanuously (this
// is important if the "upload" by the application runs on another thread than the drawing thread.)

 csimageMemoryPBO* img = new csimageMemoryPBO(2048, 1024);

Technically, this can be done. Practically, it's somewhat difficult to determine the type of an image at runtime - interfaces could be used, but that can get slow.

  g_videoTexture->GetTextureHandle()->Blit(0, 0, 1280, 1024, 0);  // g_txtmgr.cpp has to be changed such that the blit function
                                                                                               // interpretes the null pointer as "use PBO as source".
                                                                                               // As such it will  glBind() the unmapped PBO,
                                                                                               // so glTexSubImage will use the PBO to upload the texture
So either you'd only take the null pointer as "PBO source" indicator, taking away the ability to have an offset into the buffer, or you treat all pointers as buffer offsets (like GL does), losing the ability to Blit() arbitrary pointers.

A nicer approch would be to define a new texture class for this purpose.
In that case the engine interface must be extended. The application can then call something like
Well, PBO is something provided by the renderer, not the engine, so the engine shouldn't be touched.
Currently there are no "special" renderable textures, you can just take a normal texture and Blit() to it - so why start adding one now?

For multithreaded use, the glTexSubImage must be protected with a semaphore.
The glMap() and glUnmap()  funtions in g_videoTexture->GetImage()->getImageData() must also be protected.

There are other issues like signalling. The described implementation updates every frame which is fine for me now.
More in general updating should only be done when needed.
I don't know yet if i the  iEventHandler class could be used as another base class for the PBOtexture in order to do the uploading
in an event driven way.

CS doesn't bother much with threading. It's essentially single-threaded. If you want to generate the image data in a multi-threaded fashion, it's probably better to let your application handle the necessary synchronization.

Did you look at the link I posted above? The suggestion in there essentially works without defining special image or texture classes and is fully backwards compatible.

Logged
rvhaasen
Jr. Member
**
Posts: 62


View Profile
« Reply #4 on: September 15, 2006, 04:09:26 pm »

i guess you are referring to the suggestion from the ticket:

>> To avoid blocking rendering when procedural textures are used, support a kind of "async" upload would be nice.
>> It probably means that two memory buffers for the pixel data would be needed, one that is uploaded, and one that is changed.
>> Interface-wise, dfryer suggested to add a method to query a buffer that can be filled with pixel buffer, and passing it to Blit() later
>> signals that the modification is complete. Implementation-wise, the APPLE_client_storage and EXT_pixel_buffer_object extensions
>> could be utilized

What would be interface to add the mentioned function?
I guess not the iTexture interface because it should not contain implementation specific methods.

So it could be added it to the csGLTexHandle interface. The application could then <dynamic_cast> the iTexture pointer
(as returned from  engine->CreateBlackTexture("videoTexture", 2048, 1024, 0, CS_TEXTURE_3D); )
to a csGLTextureHandle pointer. At least this would be a type-safe way.

The new functions would then be:

char* csGLTexHandle::getImage(void); // Returns pointer of mapped PBO
char* csGLTexHandle::Blit(...);             // New blit function specific for PBO's

Rick


Logged
res
Develazyoper
CS Developer
Full Member
*****
Posts: 206


View Profile Email
« Reply #5 on: September 15, 2006, 06:05:50 pm »

i guess you are referring to the suggestion from the ticket:

>> To avoid blocking rendering when procedural textures are used, support a kind of "async" upload would be nice.
>> It probably means that two memory buffers for the pixel data would be needed, one that is uploaded, and one that is changed.
>> Interface-wise, dfryer suggested to add a method to query a buffer that can be filled with pixel buffer, and passing it to Blit() later
>> signals that the modification is complete. Implementation-wise, the APPLE_client_storage and EXT_pixel_buffer_object extensions
>> could be utilized

What would be interface to add the mentioned function?
I guess not the iTexture interface because it should not contain implementation specific methods.


The interface would be iTextureHandle. The methods would look like:
virtual uint8* GetBlitBuffer(size_t size) = 0;
virtual void DiscardBlitBuffer(uint8* buffer) = 0;


GetBlitBuffer()'s behaviour would return a pointer that can be filled by the application with pixel data for the texture, and then passed to Blit() for blitting (which will invalidate the pointer). DiscardBlitBuffer() would discard that buffer without blitting. For PBO, GetBlitBuffer() could return a mapped pointer. When PBO is not available, or some other ext is used (like APPLE_client_storage), the pointer could e.g. be a simple heap-allocated block of memory. Blit() should, for compatibility purposes, also accept a buffer that was not created by GetBlitBuffer() - thsi requires a bit of housekeeping but is not difficult. All in all, these changes would be backward compatible and transparent to the application - things will Just Work whether PBO is used or not or some completely different extension.

So it could be added it to the csGLTexHandle interface. The application could then <dynamic_cast> the iTexture pointer
(as returned from  engine->CreateBlackTexture("videoTexture", 2048, 1024, 0, CS_TEXTURE_3D); )
to a csGLTextureHandle pointer. At least this would be a type-safe way.

The new functions would then be:

char* csGLTexHandle::getImage(void); // Returns pointer of mapped PBO
char* csGLTexHandle::Blit(...);             // New blit function specific for PBO's

This is impossible, since csGLTexHandle is private to the gl3d plugin. Communication between plugins and the application can only go through interfaces.

-f.r.
Logged
rvhaasen
Jr. Member
**
Posts: 62


View Profile
« Reply #6 on: September 15, 2006, 08:30:32 pm »

Sounds good!
Next week I will start with an implementation of the 2 functions
The interface would be iTextureHandle. The methods would look like:
virtual uint8* GetBlitBuffer(size_t size) = 0;
virtual void DiscardBlitBuffer(uint8* buffer) = 0;
The only thing I have to find out is where to query/activate for the PBO-extension. As far as I can see the constructor
of csGLTextureManager is a suitable place:

Code:
  G3D->ext->InitGL_ARB_pixel_buffer_object ();
  if (G3D->ext->CS_GL_ARB_pixel_buffer_object)
    G3D->ext->InitGL_pixel_buffer_object ();

many thanks,
Rick
Logged
res
Develazyoper
CS Developer
Full Member
*****
Posts: 206


View Profile Email
« Reply #7 on: September 16, 2006, 12:31:48 am »

Code:
  G3D->ext->InitGL_ARB_pixel_buffer_object ();
  if (G3D->ext->CS_GL_ARB_pixel_buffer_object)
    G3D->ext->InitGL_pixel_buffer_object ();

You're on the right track here.
Logged
Pages: [1] Print 
« previous next »
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.2 | SMF © 2006-2007, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 8.268 seconds with 16 queries.