Pure, garbage-collected graphics resources

I'd like to use some OpenGL resources (VBOs, textures, shaders, and shader programs) in a functional way, with immutability, garbage collection, and IO-free creation interfaces. Has anyone played with doing such a thing? I guess the GC part would involve foreign pointers with foreign finalizers (which now run promptly in GHC iiuc). I don't know of any reliable way to add finalizers to Ptr values, because of the unboxing problem [1]. One tricky issue is that graphics context initialization must take place before any of these "pure" resources get evaluated. If the APIs allowed access to to multiple graphics contexts, things would get stickier. Comments? - Conal [1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-Mem-Weak.h...

2009/7/21 Conal Elliott
I'd like to use some OpenGL resources (VBOs, textures, shaders, and shader programs) in a functional way, with immutability, garbage collection, and IO-free creation interfaces. Has anyone played with doing such a thing? I guess the GC part would involve foreign pointers with foreign finalizers (which now run promptly in GHC iiuc). I don't know of any reliable way to add finalizers to Ptr values, because of the unboxing problem [1].
One tricky issue is that graphics context initialization must take place before any of these "pure" resources get evaluated. If the APIs allowed access to to multiple graphics contexts, things would get stickier.
Comments?
Hi, I wanted to point you to a paper (Stretching the storage manager: weak pointers and stable names in Haskell) but see you're one of the authors. As you say, there is the notion of context. I guess you can create the context with something explicitely in IO, like createContext :: IO Context then implementing the "pure" resources as data structure referencing the context. Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ? Although the OpenGL C API is imperative, it maps fairly well to a data-centric approach.

Thanks for these comments
Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ?
This "data-centric" style (I like that term) is exactly what I like to do in
all of my libraries, and it's what I'm doing again now. OpenGL types are
hidden in the library implementation, and the exposed semantics is
unaffected by the imperativeness of OpenGL (just as the semantics of Integer
is unaffected by the imperativeness of 'print').
And then I find myself in an implementation puzzle. My 'run' function (for
the purely functional type) involves creating VBOs and textures, which
greatly accelerate rendering. I want to *reuse* these resources without
mutation (i.e. reuse the content, not the memory), which is easy if they're
wrapped up as functional values that go into my higher-level functional
values, but tricky if they get created only during 'run'. Another example
is shader programs, which I synthesize and then never mutate.
Since I'm using this graphics data in a purely functional way, I want both
creation and destruction to be handled in a functional way, i.e., lazy
evaluation and garbage collection, with no visible IO. I think we can
finally get there, now that we have dependable prompt execution of C-based
finalizers.
However, I do not think robust finalization can be added on top of the Ptr
type, which is used in HOpenGL, because GHC optimizations often drop
constructors (like Ptr) keeping only the contents, which allows finalizers
to get called much too soon. Some examples of this general problem are
mentioned in the addFinalizer documentation [1]. I think a solution would
be to replace Ptr with ForeignPtr in HOpenGL.
- Conal
[1]
http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-Mem-Weak.h...
On Tue, Jul 21, 2009 at 4:30 AM, minh thu
2009/7/21 Conal Elliott
: I'd like to use some OpenGL resources (VBOs, textures, shaders, and shader programs) in a functional way, with immutability, garbage collection, and IO-free creation interfaces. Has anyone played with doing such a thing? I guess the GC part would involve foreign pointers with foreign finalizers (which now run promptly in GHC iiuc). I don't know of any reliable way to add finalizers to Ptr values, because of the unboxing problem [1].
One tricky issue is that graphics context initialization must take place before any of these "pure" resources get evaluated. If the APIs allowed access to to multiple graphics contexts, things would get stickier.
Comments?
Hi,
I wanted to point you to a paper (Stretching the storage manager: weak pointers and stable names in Haskell) but see you're one of the authors.
As you say, there is the notion of context. I guess you can create the context with something explicitely in IO, like
createContext :: IO Context
then implementing the "pure" resources as data structure referencing the context.
Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ?
Although the OpenGL C API is imperative, it maps fairly well to a data-centric approach.

Conal, if you figure this out, could you let me know how you did it?
I'm currently pre-allocating all my textures and VBOs, caching them in
an LRU cache, and cycling through them in Hieroglyph. I'd love to see
them allocated and destroyed lazily and functionally by the garbage
collector and runtime...
-- Jeff
On Tue, Jul 21, 2009 at 12:15 PM, Conal Elliott
Thanks for these comments
Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ?
This "data-centric" style (I like that term) is exactly what I like to do in all of my libraries, and it's what I'm doing again now. OpenGL types are hidden in the library implementation, and the exposed semantics is unaffected by the imperativeness of OpenGL (just as the semantics of Integer is unaffected by the imperativeness of 'print').
And then I find myself in an implementation puzzle. My 'run' function (for the purely functional type) involves creating VBOs and textures, which greatly accelerate rendering. I want to *reuse* these resources without mutation (i.e. reuse the content, not the memory), which is easy if they're wrapped up as functional values that go into my higher-level functional values, but tricky if they get created only during 'run'. Another example is shader programs, which I synthesize and then never mutate.
Since I'm using this graphics data in a purely functional way, I want both creation and destruction to be handled in a functional way, i.e., lazy evaluation and garbage collection, with no visible IO. I think we can finally get there, now that we have dependable prompt execution of C-based finalizers.
However, I do not think robust finalization can be added on top of the Ptr type, which is used in HOpenGL, because GHC optimizations often drop constructors (like Ptr) keeping only the contents, which allows finalizers to get called much too soon. Some examples of this general problem are mentioned in the addFinalizer documentation [1]. I think a solution would be to replace Ptr with ForeignPtr in HOpenGL.
- Conal
[1] http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-Mem-Weak.h...
On Tue, Jul 21, 2009 at 4:30 AM, minh thu
wrote: 2009/7/21 Conal Elliott
: I'd like to use some OpenGL resources (VBOs, textures, shaders, and shader programs) in a functional way, with immutability, garbage collection, and IO-free creation interfaces. Has anyone played with doing such a thing? I guess the GC part would involve foreign pointers with foreign finalizers (which now run promptly in GHC iiuc). I don't know of any reliable way to add finalizers to Ptr values, because of the unboxing problem [1].
One tricky issue is that graphics context initialization must take place before any of these "pure" resources get evaluated. If the APIs allowed access to to multiple graphics contexts, things would get stickier.
Comments?
Hi,
I wanted to point you to a paper (Stretching the storage manager: weak pointers and stable names in Haskell) but see you're one of the authors.
As you say, there is the notion of context. I guess you can create the context with something explicitely in IO, like
createContext :: IO Context
then implementing the "pure" resources as data structure referencing the context.
Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ?
Although the OpenGL C API is imperative, it maps fairly well to a data-centric approach.
_______________________________________________ HOpenGL mailing list HOpenGL@haskell.org http://www.haskell.org/mailman/listinfo/hopengl

I'd like to use some OpenGL resources (VBOs, textures, shaders, and shader programs) in a functional way, with immutability, garbage collection, and IO-free creation interfaces. Has anyone played with doing such a
guess the GC part would involve foreign pointers with foreign finalizers (which now run promptly in GHC iiuc). I don't know of any reliable way to add finalizers to Ptr values, because of the unboxing problem [1].
One tricky issue is that graphics context initialization must take
I've been thinking about something similar for a while, and am toying
with the idea of building the rendering pipeline as a typed expression.
It's all very hand-wavey thoughts at the moment, but I reckon it's
possible to define a function that describes the pipeline you want to
establish and then 'compile' that expression into an executable object.
It's equivalent to defining the graph of the pipeline and compiling that
into an executable sequence.
They key thing is it separates the definition of what you want to do
(the expression) from the stateful execution. A major bonus is all
resource allocation/deallocations can be extracted late on in the
process, which offers the potential for clever resource usage
strategies. Increased efficiency is actually why I'm interested in
pursuing it.
Not a small amount of work though. Any thoughts?
Ta,
Sam
From: hopengl-bounces@haskell.org [mailto:hopengl-bounces@haskell.org]
On Behalf Of Conal Elliott
Sent: 21 July 2009 17:15
To: hopengl@haskell.org; minh thu
Subject: Re: [HOpenGL] Pure, garbage-collected graphics resources
Thanks for these comments
Anyway, I've not a clear picture of what you have in mind
(especially,
at which point in time a, say, VBO should be considered to be
part of
things to be rendered). Often, a data structure (say Blah) is
created
in a pure way then given to some kind of run :: Blah -> IO ()
function
for "interpretation". Why not mirror the OpenGL API in a purely
data-centric way then give the data to the run function ?
This "data-centric" style (I like that term) is exactly what I like to
do in all of my libraries, and it's what I'm doing again now. OpenGL
types are hidden in the library implementation, and the exposed
semantics is unaffected by the imperativeness of OpenGL (just as the
semantics of Integer is unaffected by the imperativeness of 'print').
And then I find myself in an implementation puzzle. My 'run' function
(for the purely functional type) involves creating VBOs and textures,
which greatly accelerate rendering. I want to *reuse* these resources
without mutation (i.e. reuse the content, not the memory), which is easy
if they're wrapped up as functional values that go into my higher-level
functional values, but tricky if they get created only during 'run'.
Another example is shader programs, which I synthesize and then never
mutate.
Since I'm using this graphics data in a purely functional way, I want
both creation and destruction to be handled in a functional way, i.e.,
lazy evaluation and garbage collection, with no visible IO. I think we
can finally get there, now that we have dependable prompt execution of
C-based finalizers.
However, I do not think robust finalization can be added on top of the
Ptr type, which is used in HOpenGL, because GHC optimizations often drop
constructors (like Ptr) keeping only the contents, which allows
finalizers to get called much too soon. Some examples of this general
problem are mentioned in the addFinalizer documentation [1]. I think a
solution would be to replace Ptr with ForeignPtr in HOpenGL.
- Conal
[1]
http://www.haskell.org/ghc/docs/latest/html/libraries/base/System-Mem-We
ak.html#v%3AaddFinalizer
On Tue, Jul 21, 2009 at 4:30 AM, minh thu
before any of these "pure" resources get evaluated. If the APIs allowed access to to multiple graphics contexts, things would get stickier.
Comments?
Hi, I wanted to point you to a paper (Stretching the storage manager: weak pointers and stable names in Haskell) but see you're one of the authors. As you say, there is the notion of context. I guess you can create the context with something explicitely in IO, like createContext :: IO Context then implementing the "pure" resources as data structure referencing the context. Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ? Although the OpenGL C API is imperative, it maps fairly well to a data-centric approach.

Sam Martin wrote:
I’ve been thinking about something similar for a while, and am toying with the idea of building the rendering pipeline as a typed expression. It’s all very hand-wavey thoughts at the moment, but I reckon it’s possible to define a function that describes the pipeline you want to establish and then ‘compile’ that expression into an executable object.
We've been working on this approach at Leeds. Last year we submitted an entry to the IEEE Visualization contest using a rendering framework where you create something akin to a scene graph as a data structure. Interfacing with OpenGL is done behind the scenes, including traversing the tree to render, and to respond to events. See our paper in PADL'09 - source code at www.comp.leeds.ac.uk/funvis/. We're currently extending this in two directions. One is better support for writing embedded interactors, which transform a tree in response to an event. We now have a nice parallel coordinates example with interactive brushing of the axes embedded directly into the scene, hope to put up on the web at some point. The other ...
It’s equivalent to defining the graph of the pipeline and compiling that into an executable sequence.
... is essentially that, though for vis pipelines rather than just graphics. Not yet at a point where we could answer Conal's questions, but also working towards it. David -- Dr. David Duke E: djd@comp.leeds.ac.uk School of Computing W: www.comp.leeds.ac.uk/djd/ University of Leeds T: +44 113 3436800 Leeds, LS2 9JT, U.K.

Thanks, I've dug out the paper. It's very interesting. You are trying to solve a slightly different problem to the one I had in mind (the focus on handling extremely large data sets), but it's definitely along similar lines. I haven't absorbed it all yet and will read on. Ta, Sam -----Original Message----- From: David Duke [mailto:djd@comp.leeds.ac.uk] Sent: 21 July 2009 21:22 To: Sam Martin Cc: Conal Elliott; hopengl@haskell.org Subject: Re: [HOpenGL] Pure, garbage-collected graphics resources Sam Martin wrote:
I've been thinking about something similar for a while, and am toying with the idea of building the rendering pipeline as a typed expression. It's all very hand-wavey thoughts at the moment, but I reckon it's possible to define a function that describes the pipeline you want to establish and then 'compile' that expression into an executable object.
We've been working on this approach at Leeds. Last year we submitted an entry to the IEEE Visualization contest using a rendering framework where you create something akin to a scene graph as a data structure. Interfacing with OpenGL is done behind the scenes, including traversing the tree to render, and to respond to events. See our paper in PADL'09 - source code at www.comp.leeds.ac.uk/funvis/. We're currently extending this in two directions. One is better support for writing embedded interactors, which transform a tree in response to an event. We now have a nice parallel coordinates example with interactive brushing of the axes embedded directly into the scene, hope to put up on the web at some point. The other ...
It's equivalent to defining the graph of the pipeline and compiling that into an executable sequence.
... is essentially that, though for vis pipelines rather than just graphics. Not yet at a point where we could answer Conal's questions, but also working towards it. David -- Dr. David Duke E: djd@comp.leeds.ac.uk School of Computing W: www.comp.leeds.ac.uk/djd/ University of Leeds T: +44 113 3436800 Leeds, LS2 9JT, U.K.

2009/7/21 Conal Elliott
Thanks for these comments
Anyway, I've not a clear picture of what you have in mind (especially, at which point in time a, say, VBO should be considered to be part of things to be rendered). Often, a data structure (say Blah) is created in a pure way then given to some kind of run :: Blah -> IO () function for "interpretation". Why not mirror the OpenGL API in a purely data-centric way then give the data to the run function ?
This "data-centric" style (I like that term) is exactly what I like to do in all of my libraries, and it's what I'm doing again now. OpenGL types are hidden in the library implementation, and the exposed semantics is unaffected by the imperativeness of OpenGL (just as the semantics of Integer is unaffected by the imperativeness of 'print').
And then I find myself in an implementation puzzle. My 'run' function (for the purely functional type) involves creating VBOs and textures, which greatly accelerate rendering. I want to *reuse* these resources without mutation (i.e. reuse the content, not the memory), which is easy if they're wrapped up as functional values that go into my higher-level functional values, but tricky if they get created only during 'run'. Another example is shader programs, which I synthesize and then never mutate.
Since I'm using this graphics data in a purely functional way, I want both creation and destruction to be handled in a functional way, i.e., lazy evaluation and garbage collection, with no visible IO. I think we can finally get there, now that we have dependable prompt execution of C-based finalizers.
However, I do not think robust finalization can be added on top of the Ptr type, which is used in HOpenGL, because GHC optimizations often drop constructors (like Ptr) keeping only the contents, which allows finalizers to get called much too soon. Some examples of this general problem are mentioned in the addFinalizer documentation [1]. I think a solution would be to replace Ptr with ForeignPtr in HOpenGL.
I have no clue about the low-level working of finalizers, but... All you explain here makes me think about the examples of the papers, namely, memoizing functions. The functional value you want to manipulate acts a bit like the nice given-to-the-user-to-see memoized version of the original function. That is, instead of wrapping the mechanics used to do the book-keeping for the memoization, here we need to do the book-keeping of the actual OpenGL ids (I assume it is possible to 'name' things in haskell in a functional-friendly manner and those names are 'translated' by the run function into GLuint and GLint returned by functions like glGenBuffers). But maybe all this boils down again to the problem you mention about Ptr. Can you explain how you want things to work ? Say you have your textures, shader programs and vbos created (with already the actual OpenGL calls made or not, that is the values are either placeholders or really the OpenGL data). Now you want to reorganize those with possibly new shaders, textures or vbos. Can this reorganization be explicitely in the IO monad or not (in your view)? Cheers, Thu
participants (5)
-
Conal Elliott
-
David Duke
-
Jeff Heard
-
minh thu
-
Sam Martin