[C Binding] Turning the mutable to immutable?

Hello, I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) --> http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid. I particularly like the way HGL works, with the Draw monad which (IMO) enables powerful composability of the drawings. But HGL is simpler in the way that, for instance, it doesn't deal with images/sprites. So that's why I would like to pick up advice concerning the design of such a binding. First, this is how SFML (in C/C++) works: The main types are RenderWindow, Drawable, Image, Sprite, Shape, Font and Text. An Image basically represents an array of pixels. It is just a resource, and is not directly drawable. An image is loaded from a file, and provides methods for accessing/altering its pixels. Its main purpose is to be bound as an OpenGL texture. A RenderWindow is the window on which the Drawables are... well... drawn. A Sprite, now, is a Drawable. One Sprite is linked to one Image. A Sprite NEVER alters its Image, it just provides positionning/rotation/resizing/colorizing methods that will be translated, when drawing on the RenderWindow, to glTranslate/glRotate/glScale/glColor, etc. So we can see a Sprite as an instance of an Image, since if a same Image is to be drawn 3 times on the same frame, we are advised to create three Sprites of it, which will differ by their position. A Font is loaded from a file, it is a simple resource, just like Image. Text and Shape are Drawables. So, now, questions: 1) For those who know HGL, can the monad Draw principle be adapted to my case? Or am I heading for disaster? 2) How would I handle images? SFML API enables the user to alter the pixels of the image, and I obviously don't wanna copy the entire Image each time a pixel is changed. 3) Is there another library on hackage that handles images in a functional way? (I mean not *all in IO*)

On 5 jul 2010, at 23:48, Yves Parès wrote:
Hello,
I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) --> http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid.
Have you considered writing a low-level binding and building a high-level library on top of that? -chris

That's indeed an advice I've read [1].
But wouldn't it damage the performances, since code will have to go through
an extra layer?
[1] http://blog.ezyang.com/2010/06/principles-of-ffi-api-design
2010/7/7 Chris Eidhof
On 5 jul 2010, at 23:48, Yves Parès wrote:
Hello,
I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) --> http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid.
Have you considered writing a low-level binding and building a high-level library on top of that?
-chris

Making an immutable API from a mutable one generally damages
performance (on von neumann architectures) somewhat, the goal is to
minimize that impact.
Cheers.
~Liam
On 7 July 2010 19:40, Yves Parès
That's indeed an advice I've read [1]. But wouldn't it damage the performances, since code will have to go through an extra layer?
[1] http://blog.ezyang.com/2010/06/principles-of-ffi-api-design
2010/7/7 Chris Eidhof
On 5 jul 2010, at 23:48, Yves Parès wrote:
Hello,
I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) --> http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid.
Have you considered writing a low-level binding and building a high-level library on top of that?
-chris
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

2010/7/7 Liam O'Connor
Making an immutable API from a mutable one generally damages performance (on von neumann architectures) somewhat, the goal is to minimize that impact.
In fact, I would like to determine if an EFFICIENT way to make images and such immutable exists, or if it is impossible. I looked at graphics-drawingcombinators. It is nice, but it doesn't fully answer to my problem since it just loads images and draws them. It provides no ways to alter them, no problem of mutability, then.
2010/7/7 Chris Eidhof
Premature optimization is the root of all evil ;)
Yes, you are right, this is wise.

On Wed, Jul 7, 2010 at 2:24 PM, Yves Parès
2010/7/7 Liam O'Connor
Making an immutable API from a mutable one generally damages performance (on von neumann architectures) somewhat, the goal is to minimize that impact.
In fact, I would like to determine if an EFFICIENT way to make images and such immutable exists, or if it is impossible.
Both OpenGL and DirectX, while supporting updates to images, make it slow enough that any image data is effectively immutable. Each animation step a completely fresh frame buffer is created, without overwriting any of the inputs, by combining these immutable images in interesting ways. You're expected to combine multiple immutable data sources in the shader to produce the final output (which will be a different image from the inputs). Examples of data sources would be images, transformation matrices, colours etc. It's extremely rare to see people poke values individually into a mutable buffer (in fact, the capability of doing this on the GPU is very recent, and even then it's highly limited). You do a big purely functional transform from inputs to outputs instead. HLSL and GLSL may not look like functional languages, but they essentially are, in that each kernel runs independently with no shared mutable state, producing outputs from immutable inputs. So, if you want to do it on the CPU, I would mimic the way GPUs have been doing it for ages. Define what operations you want to perform in terms of the inputs, and then do them all "in bulk" to produce the output image. You don't want people to go in and arbitrarily set pixels to anything they want at any time they want. -- Sebastian Sylvan

Okay,
so I think that the better idea is to carry on with my low-level, imperative
binding, and then build a more functional on top of this.
Concerning the mutability of images, I notice that the problem with SFML is
that it handles Sprites in a way that is even more imperative than OpenGL
texture handling.
2010/7/7 Sebastian Sylvan
On Wed, Jul 7, 2010 at 2:24 PM, Yves Parès
wrote: 2010/7/7 Liam O'Connor
Making an immutable API from a mutable one generally damages performance (on von neumann architectures) somewhat, the goal is to minimize that impact.
In fact, I would like to determine if an EFFICIENT way to make images and such immutable exists, or if it is impossible.
Both OpenGL and DirectX, while supporting updates to images, make it slow enough that any image data is effectively immutable. Each animation step a completely fresh frame buffer is created, without overwriting any of the inputs, by combining these immutable images in interesting ways.
You're expected to combine multiple immutable data sources in the shader to produce the final output (which will be a different image from the inputs). Examples of data sources would be images, transformation matrices, colours etc.
It's extremely rare to see people poke values individually into a mutable buffer (in fact, the capability of doing this on the GPU is very recent, and even then it's highly limited). You do a big purely functional transform from inputs to outputs instead. HLSL and GLSL may not look like functional languages, but they essentially are, in that each kernel runs independently with no shared mutable state, producing outputs from immutable inputs.
So, if you want to do it on the CPU, I would mimic the way GPUs have been doing it for ages. Define what operations you want to perform in terms of the inputs, and then do them all "in bulk" to produce the output image. You don't want people to go in and arbitrarily set pixels to anything they want at any time they want.
-- Sebastian Sylvan

I think it might influence performance, but it doesn't have to be that much. There are some optimization tricks you can apply to deal with this. Premature optimization is the root of all evil ;) -chris On 7 jul 2010, at 11:40, Yves Parès wrote:
That's indeed an advice I've read [1]. But wouldn't it damage the performances, since code will have to go through an extra layer?
[1] http://blog.ezyang.com/2010/06/principles-of-ffi-api-design
2010/7/7 Chris Eidhof
On 5 jul 2010, at 23:48, Yves Parès wrote: Hello,
I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) --> http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid.
Have you considered writing a low-level binding and building a high-level library on top of that?
-chris

To answer the question in your subject, “Very Carefully.” While I don’t know much about your particular problem domain (and it seems others have given useful advice), I can say some general things about making mutable things immutable. There is a very simple way to make something mutable immutable: say that you won’t ever mutate it again! Doing this correctly is two-fold: you first have to know when you can do this and when it is useful (which requires in-depth understanding of the side-effects that the low-level API invokes), and second is knowing how to encapsulate your interface so that there is no type-checking use-case of your code (without unsafePerformIO) that accidentally mutates a pure structure. You can use this to do a standard pattern seen in ST and others: mutate during creation inside a monad, but when the monad is done running, return a pure version of the output with unsafePerformIO. If you can guarantee that another caching the pointer so that if someone else calls your function with the same arguments, you return the same pointer, is safe, then this is ok. Memcopying a datastructure when you need to modify it, while a cringe-worthy offense in your theoretical CS class, is a surprisingly practical and not-to-bad performing technique for making your data persistent. It works better the smaller the data structure is, and you'd be surprised how many C libraries implement some feature with a memory copy (moving GC, anyone?) Cheers, Edward
participants (6)
-
Chris Eidhof
-
Edward Z. Yang
-
Jake McArthur
-
Liam O'Connor
-
Sebastian Sylvan
-
Yves Parès