Loading a texture in OpenGL

Using the OpenGL package on Hackage, how do I load a texture from an array? In the red book[1], I see their code using glGenTextures and glBindTexture, but I can't find these in the documentation. Are there different functions I should be calling? [1] http://glprogramming.com/red/chapter09.html

On Mon, Feb 6, 2012 at 12:00 PM, Clark Gaebel
Using the OpenGL package on Hackage, how do I load a texture from an array?
The answer will depend on a few things: * Which OpenGL package you use, for example OpenGL vs. OpenGLRaw * What type of 'array' you use. In the case of the OpenGL package you need to create a PixelData value and pass that on. You can find example code here: https://github.com/dagit/nehe-tuts/blob/447f5471f3e7fe07b44dc5d2d87c4a95be35... https://github.com/dagit/nehe-tuts/blob/447f5471f3e7fe07b44dc5d2d87c4a95be35...
In the red book[1], I see their code using glGenTextures and glBindTexture, but I can't find these in the documentation. Are there different functions I should be calling?
Yes. As you've noticed the API of the OpenGL package sometimes (often?) differs from that of the C OpenGL api. If that's what you're more familiar with then take a look at OpenGLRaw. Here is how to do the same thing as the previous two links but using OpenGLRaw: https://github.com/dagit/nehe-tuts/blob/master/lesson06.hs https://github.com/dagit/nehe-tuts/blob/master/Util.hs Instead of using Arrays as defined by Haskell98, I would recommend using something else like Data.Vector. The standard arrays must be converted to something else to work with OpenGL. Data.Vector on the other hand allows direct access to the pinned pointer and is thus suitable for use with OpenGL as is. Have you seen JuicyPixels? The version on hackage uses arrays, but the version in github uses vector. I'd recommend using the version from github. It's faster and it will be easier to pass the data to OpenGL: https://github.com/Twinside/Juicy.Pixels Good luck! Jason

Thank you both. I'll be sure to try these out.
As a matter of fact, I _am_ using JuicyPixels. I didn't realize there was a
version on github which uses Vector. Thanks for letting me know.
Regards,
- clark
On Mon, Feb 6, 2012 at 5:55 PM, Jason Dagit
On Mon, Feb 6, 2012 at 12:00 PM, Clark Gaebel
wrote: Using the OpenGL package on Hackage, how do I load a texture from an array?
The answer will depend on a few things: * Which OpenGL package you use, for example OpenGL vs. OpenGLRaw * What type of 'array' you use.
In the case of the OpenGL package you need to create a PixelData value and pass that on. You can find example code here:
https://github.com/dagit/nehe-tuts/blob/447f5471f3e7fe07b44dc5d2d87c4a95be35...
https://github.com/dagit/nehe-tuts/blob/447f5471f3e7fe07b44dc5d2d87c4a95be35...
In the red book[1], I see their code using glGenTextures and glBindTexture, but I can't find these in the documentation. Are there different functions I should be calling?
Yes. As you've noticed the API of the OpenGL package sometimes (often?) differs from that of the C OpenGL api. If that's what you're more familiar with then take a look at OpenGLRaw. Here is how to do the same thing as the previous two links but using OpenGLRaw: https://github.com/dagit/nehe-tuts/blob/master/lesson06.hs https://github.com/dagit/nehe-tuts/blob/master/Util.hs
Instead of using Arrays as defined by Haskell98, I would recommend using something else like Data.Vector. The standard arrays must be converted to something else to work with OpenGL. Data.Vector on the other hand allows direct access to the pinned pointer and is thus suitable for use with OpenGL as is.
Have you seen JuicyPixels? The version on hackage uses arrays, but the version in github uses vector. I'd recommend using the version from github. It's faster and it will be easier to pass the data to OpenGL: https://github.com/Twinside/Juicy.Pixels
Good luck! Jason

On 07/02/2012, at 7:00 AM, Clark Gaebel wrote:
Using the OpenGL package on Hackage, how do I load a texture from an array?
In the red book[1], I see their code using glGenTextures and glBindTexture, but I can't find these in the documentation. Are there different functions I should be calling?
The Gloss graphics library has texture support, and the code for drawing them is confined to this module: http://code.ouroborus.net/gloss/gloss-head/gloss/Graphics/Gloss/Internals/Re... Feel free to steal the code from there. Ben.

Awesome. Thanks!
As a follow up question, how do I add a finalizer to a normal variable?
OpenGL returns an integer handle to your texture in graphics memory, and
you have to call deleteObjectNames on it. Is there any way to have this
automatically run once we lose all references to this variable (and all
copies)?
On Mon, Feb 6, 2012 at 10:14 PM, Ben Lippmeier
On 07/02/2012, at 7:00 AM, Clark Gaebel wrote:
Using the OpenGL package on Hackage, how do I load a texture from an array?
In the red book[1], I see their code using glGenTextures and glBindTexture, but I can't find these in the documentation. Are there different functions I should be calling?
The Gloss graphics library has texture support, and the code for drawing them is confined to this module:
http://code.ouroborus.net/gloss/gloss-head/gloss/Graphics/Gloss/Internals/Re...
Feel free to steal the code from there.
Ben.

On 07/02/2012, at 2:40 PM, Clark Gaebel wrote:
Awesome. Thanks!
As a follow up question, how do I add a finalizer to a normal variable? OpenGL returns an integer handle to your texture in graphics memory, and you have to call deleteObjectNames on it. Is there any way to have this automatically run once we lose all references to this variable (and all copies)?
I don't know. I've only used ForeignPtrs with finalisers before [1]. One problem with these finalisers is that GHC provides no guarantees on when they will be run. It might be just before the program exits, instead of when the pointer actually becomes unreachable. Because texture memory is a scarce resource, I wouldn't want to rely on a finaliser to free it -- though I suppose this depends on what you're doing. Ben. [1] http://www.haskell.org/ghc/docs/latest/html/libraries/haskell2010-1.1.0.1/Fo...

I would be running the GC manually at key points to make sure it gets
cleaned up. Mainly, before any scene changes when basically everything gets
thrown out anyways.
On Mon, Feb 6, 2012 at 10:49 PM, Ben Lippmeier
On 07/02/2012, at 2:40 PM, Clark Gaebel wrote:
Awesome. Thanks!
As a follow up question, how do I add a finalizer to a normal variable? OpenGL returns an integer handle to your texture in graphics memory, and you have to call deleteObjectNames on it. Is there any way to have this automatically run once we lose all references to this variable (and all copies)?
I don't know. I've only used ForeignPtrs with finalisers before [1].
One problem with these finalisers is that GHC provides no guarantees on when they will be run. It might be just before the program exits, instead of when the pointer actually becomes unreachable. Because texture memory is a scarce resource, I wouldn't want to rely on a finaliser to free it -- though I suppose this depends on what you're doing.
Ben.
[1] http://www.haskell.org/ghc/docs/latest/html/libraries/haskell2010-1.1.0.1/Fo...

On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs: newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits. "No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before. Ben.

Is the Haskell garbage collector conservative, or precise?
If it's conservative, then this will only usually work. If it's precise, it
should always work.
On Mon, Feb 6, 2012 at 10:56 PM, Ben Lippmeier
On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.

It's a precise GC of course (conservative collection would be madness
considering how much memory Haskell programs chew through.) That still
doesn't ensure your finalizer will run during the next GC even if all the
references are gone by then.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:09 PM, Clark Gaebel
On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Even the next major, manually triggered GC? I'm just dealing with GHC here,
if that simplifies the discussion.
Although important and good to know, I don't really care what the spec says
here. I just want to know if, with the current implementation of GHC,
finalizeres will be run if a GC is manually triggered and there are no
references to the objects they point to.
Also, afaik, the performGC function is a GHC extension anyways.
On Mon, Feb 6, 2012 at 11:16 PM, Austin Seipp
It's a precise GC of course (conservative collection would be madness considering how much memory Haskell programs chew through.) That still doesn't ensure your finalizer will run during the next GC even if all the references are gone by then.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:09 PM, Clark Gaebel
wrote: Is the Haskell garbage collector conservative, or precise?
If it's conservative, then this will only usually work. If it's precise, it should always work.
On Mon, Feb 6, 2012 at 10:56 PM, Ben Lippmeier
wrote: On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Just to clarify, this guarantee possibly could be made, ghc just doesn't do
it now. In the past ghc never guaranteed a finalizer would ever be run.
Regardless I would be wary of trusting finalizers to clean up very scarce
resources. A malloc'd buffer is probably fine to have a finalizer for,
texture objects or file descriptors are a different matter. Predictability
matters in those cases.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:16 PM, Austin Seipp
On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, Feb 7, 2012 at 5:23 AM, Austin Seipp
Just to clarify, this guarantee possibly could be made, ghc just doesn't do it now. In the past ghc never guaranteed a finalizer would ever be run.
Regardless I would be wary of trusting finalizers to clean up very scarce resources. A malloc'd buffer is probably fine to have a finalizer for, texture objects or file descriptors are a different matter. Predictability matters in those cases.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:16 PM, Austin Seipp
wrote: It's a precise GC of course (conservative collection would be madness considering how much memory Haskell programs chew through.) That still doesn't ensure your finalizer will run during the next GC even if all the references are gone by then.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:09 PM, Clark Gaebel
wrote: Is the Haskell garbage collector conservative, or precise?
If it's conservative, then this will only usually work. If it's precise, it should always work.
On Mon, Feb 6, 2012 at 10:56 PM, Ben Lippmeier
wrote: On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically everything gets thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
You have to be really careful with automatic cleanup using finalizers. Not only to the mentioned not cleaning up of resources but also to deleting it too early. What could happen is that you code doesn't explicitly use (= call a GL function with it) an object after binding it. Then it could be seen as a dead pointer and be deleted by it's finalizer. But thereby it might unbind the object from the binding point. Maybe a (more) realistic example is using only one shader program, you create it once, call usePorgram with it and never change it after that. As there is no other program to use you don't have to reactivate the program with useProgram or have to change anything about it. So in effect it's not used by Haskell anymore and the finalizer is run for it deleting the program. For a program this is not a big problem as the OpenGL spec tells you that it isn't deleted immediately so you can use it afterwards. With textures it's different, the are deleted immediately, so you may think you have a texture bound but in reality the finalizer might have run and deleted the texture for you. So watch doing the OpenGL memory management using the references in Haskell, as you might accidentally delete objects ahead of time. Lars, P.S. To make it worse, the bound objects (programs, textures, etc.) can also be queried and thereby there are non dead objects automatically, but there is no Haskell reference to them so the GC cannot now this.

Sounds hairy. Is there any way to get reference counting garbage collection
in Haskell?
On Tue, Feb 7, 2012 at 9:26 AM, L Corbijn
On Tue, Feb 7, 2012 at 5:23 AM, Austin Seipp
wrote: Just to clarify, this guarantee possibly could be made, ghc just doesn't do it now. In the past ghc never guaranteed a finalizer would ever be run.
Regardless I would be wary of trusting finalizers to clean up very scarce resources. A malloc'd buffer is probably fine to have a finalizer for, texture objects or file descriptors are a different matter. Predictability matters in those cases.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:16 PM, Austin Seipp
wrote: It's a precise GC of course (conservative collection would be madness considering how much memory Haskell programs chew through.) That still doesn't ensure your finalizer will run during the next GC even if all the references are gone by then.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:09 PM, Clark Gaebel
wrote: Is the Haskell garbage collector conservative, or precise?
If it's conservative, then this will only usually work. If it's precise, it should always work.
On Mon, Feb 6, 2012 at 10:56 PM, Ben Lippmeier
wrote: On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically
everything gets
thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
You have to be really careful with automatic cleanup using finalizers. Not only to the mentioned not cleaning up of resources but also to deleting it too early. What could happen is that you code doesn't explicitly use (= call a GL function with it) an object after binding it. Then it could be seen as a dead pointer and be deleted by it's finalizer. But thereby it might unbind the object from the binding point. Maybe a (more) realistic example is using only one shader program, you create it once, call usePorgram with it and never change it after that. As there is no other program to use you don't have to reactivate the program with useProgram or have to change anything about it. So in effect it's not used by Haskell anymore and the finalizer is run for it deleting the program. For a program this is not a big problem as the OpenGL spec tells you that it isn't deleted immediately so you can use it afterwards.
With textures it's different, the are deleted immediately, so you may think you have a texture bound but in reality the finalizer might have run and deleted the texture for you. So watch doing the OpenGL memory management using the references in Haskell, as you might accidentally delete objects ahead of time.
Lars,
P.S. To make it worse, the bound objects (programs, textures, etc.) can also be queried and thereby there are non dead objects automatically, but there is no Haskell reference to them so the GC cannot now this.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

It's possible ResourceT from the yesod guys could be quite useful. It
allows you to manually release things, but also ensures that things are
released in case of exceptions. It also supports, from what I can tell,
some kind of reference counting for use with multiple threads (the
deallocator isn't called unless all threads have released it, I think).
Cheers,
Alex
On 8 February 2012 15:02, Clark Gaebel
Sounds hairy. Is there any way to get reference counting garbage collection in Haskell?
On Tue, Feb 7, 2012 at 9:26 AM, L Corbijn
wrote: Just to clarify, this guarantee possibly could be made, ghc just doesn't do it now. In the past ghc never guaranteed a finalizer would ever be run.
Regardless I would be wary of trusting finalizers to clean up very scarce resources. A malloc'd buffer is probably fine to have a finalizer for, texture objects or file descriptors are a different matter. Predictability matters in those cases.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:16 PM, Austin Seipp
wrote: It's a precise GC of course (conservative collection would be madness considering how much memory Haskell programs chew through.) That still doesn't ensure your finalizer will run during the next GC even if all
references are gone by then.
Sent from my iPhone^H^H^H^H^HPortable Turing machine
On Feb 6, 2012, at 10:09 PM, Clark Gaebel
wrote: Is the Haskell garbage collector conservative, or precise?
If it's conservative, then this will only usually work. If it's
On Tue, Feb 7, 2012 at 5:23 AM, Austin Seipp
wrote: the precise, it should always work.
On Mon, Feb 6, 2012 at 10:56 PM, Ben Lippmeier
wrote: On 07/02/2012, at 2:50 PM, Clark Gaebel wrote:
I would be running the GC manually at key points to make sure it gets cleaned up. Mainly, before any scene changes when basically
everything gets
thrown out anyways.
From the docs:
newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)Source Turns a plain memory reference into a foreign pointer, and associates a finalizer with the reference. The finalizer will be executed after the last reference to the foreign object is dropped. There is no guarantee of promptness, however the finalizer will be executed before the program exits.
"No guarantee of promptness". Even if the GC knows your pointer is unreachable, it might choose not to call the finaliser. I think people have been bitten by this before.
Ben.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
You have to be really careful with automatic cleanup using finalizers. Not only to the mentioned not cleaning up of resources but also to deleting it too early. What could happen is that you code doesn't explicitly use (= call a GL function with it) an object after binding it. Then it could be seen as a dead pointer and be deleted by it's finalizer. But thereby it might unbind the object from the binding point. Maybe a (more) realistic example is using only one shader program, you create it once, call usePorgram with it and never change it after that. As there is no other program to use you don't have to reactivate the program with useProgram or have to change anything about it. So in effect it's not used by Haskell anymore and the finalizer is run for it deleting the program. For a program this is not a big problem as the OpenGL spec tells you that it isn't deleted immediately so you can use it afterwards.
With textures it's different, the are deleted immediately, so you may think you have a texture bound but in reality the finalizer might have run and deleted the texture for you. So watch doing the OpenGL memory management using the references in Haskell, as you might accidentally delete objects ahead of time.
Lars,
P.S. To make it worse, the bound objects (programs, textures, etc.) can also be queried and thereby there are non dead objects automatically, but there is no Haskell reference to them so the GC cannot now this.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Alex Mason
participants (6)
-
Alex Mason
-
Austin Seipp
-
Ben Lippmeier
-
Clark Gaebel
-
Jason Dagit
-
L Corbijn