0

I have a little game in C# which uses mainly fixed sprites (bitmaps loaded from disk) and some videos.

Now our current approach is

Loading:

texture.ID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.ID);

GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, w, h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);

GL.BindTexture(TextureTarget.Texture2D, 0);

Drawing

GL.BindTexture(TextureTarget.Texture2D, texture.ID);
GL.MatrixMode(MatrixMode.Texture);
GL.PushMatrix();
    GL.Begin(BeginMode.Quads);

    GL.TexCoord2(x1, y1);
    GL.Vertex3(rx1, ry1, rect.Z);

    GL.TexCoord2(x1, y2);
    GL.Vertex3(rx1, ry2, rect.Z);

    GL.TexCoord2(x2, y2);
    GL.Vertex3(rx2, ry2, rect.Z);

    GL.TexCoord2(x2, y1);
    GL.Vertex3(rx2, ry1, rect.Z);

    GL.End();
GL.PopMatrix();

GL.BindTexture(TextureTarget.Texture2D, 0);

And Updating:

GL.BindTexture(TextureTarget.Texture2D, texture.ID);

GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);

GL.BindTexture(TextureTarget.Texture2D, 0);

All the textures are kept till they are used, so loading is only done once at startup (in general) So first: Any comments on that method? Now I'd want to use PBO properly to update the textures (mainly for video) A) Is it a good idea to use a PBO to add the texture (from bmp)? I'd create a pbo, copy data from bmp to pbo and then use TexSubImage2D. Are there any performance points for that or is the overhead to high? B) Same for updating: Current Code:

GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);

IntPtr buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
Marshal.Copy(data, 0, buffer, data.Length);

GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);

GL.BindTexture(TextureTarget.Texture2D, texture.ID);

GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);

GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);

Does this actually work or is there no benefit with that?

I read http://www.opengl.org/wiki/Pixel_Buffer_Object and http://www.songho.ca/opengl/gl_pbo.html and the first article about the download-and-use suggest, that if I upload data and immediately draw that texture (or even use TexSubImage2D?) then I won't get any more speed by the PBO. Is this right? So if I use the PBO would I have to use a 2nd PBO and draw the frames a frame delayed?

My main-loop is like:

{
  DoSomeInputHandling();
  CopyDecodedVideoFrameToTexture();
  DrawTexture();
}

With video decoding in another thread.

Is a pretty naive approach but working. What's the correct/better way of doing this?

Flamefire
  • 5,313
  • 3
  • 35
  • 70

1 Answers1

0

Your texture creation and update code paths OK to me. One thing, though: you don't have to respecify the texture object parameters like filters and wrap modes int the update case, those states will stay as they are. Using immediate mode for drawing is also not likely to lead to optimal performance.

With PBOs one can avoid extra copies of the data. For example, your video decoding in another thread could directly write into mappend PBO memory (you will of course need some synchronization scheme to guarantee that the object is mapped when the thread wants to write to it), so eleminate the extra copy you are suggesting in your code. Implementing a PBO ping-pong (or ring buffer) approach might increase the performance and further disentangle the separate code parts, but at the cost of increaed latency. I don't know if this is a concern for your scenario.

derhass
  • 43,833
  • 2
  • 57
  • 78
  • So I also don't need the mipmap creation? Is it necessary at all? I just draw sprites (fixed bmps) with potentially different sizes. Is the mipmap handling actually used (and useful in this case)? Do you have an easy tutorial for an alternative to immediate? So basicly the PBOs are useless for texture creation in this case? (Memory copied twices) And for video: Basicly something like: { DoSomeInputHandling(); SwapVideoPBOs(); TexSubImage2D("old" PBOs) DrawTextures(); } If I cannot swap the PBO buffers, are they of any use at all (in this case)? – Flamefire May 10 '13 at 22:36
  • I don't know if you need mipmapps.Depens on how much you downscale when drawing. If you need them, you must also generate them. Concerning the PBOs: hard to tell what the real benefit is in your case. I observed significant improvements when using PBOs, even in the simple case with just doing BindBuffer, BufferData,Tex[Sub]Image, but you should benchmark/profile it to see if it helps. I once hacked together a small [texture update benchmark](http://www-user.tu-chemnitz.de/~heinm/tmp/test2.c), maybe you find it helpful. PBOs reduced the required update time by a factor of 4 for me. – derhass May 10 '13 at 23:38