
[ Wrong kind of reply... :-P ]
---------- Forwarded message ----------
From: Sven Panne
As there is no function that depends on the shadertype that I could find on the reference card for OpenGL 4.3 (though I could have missed it). So switching to an algebraic data type seems to me as a good idea. The only disadvantage is that it can no longer be a ObjectName, as the shader needs a type to create. [...]
All shaders share the same name space, so there is no problem regarding OpenGL semantics. The last point regarding ObjectName is the real problem, and it needs some thought to resolve it nicely. As a first brainstorming step let's look at all OpenGL objects and their related lifetime API (see section 2.5, "Objects and the Object Model"): ---------------------------------------------------------------------- * Buffer Objects void GenBuffers( sizei n, uint *buffers ); void DeleteBuffers( sizei n, const uint *buffers ); boolean IsBuffer( uint buffer ); * Shader Objects uint CreateShader( enum type ); void DeleteShader( uint shader ); boolean IsShader( uint shader ); * Program Objects uint CreateProgram( void ); void DeleteProgram( uint program ); boolean IsProgram( uint program ); * Program Pipeline Objects void GenProgramPipelines( sizei n, uint *pipelines ); void DeleteProgramPipelines( sizei n, const uint *pipelines ); boolean IsProgramPipeline( uint pipeline ); * Texture Objects void GenTextures( sizei n, uint *textures ); void DeleteTextures( sizei n, const uint *textures ); boolean IsTexture( uint texture ); * Sampler Objects void GenSamplers( sizei count, uint *samplers ); void DeleteSamplers( sizei count, const uint *samplers ); boolean IsSampler( uint sampler ); * Renderbuffer Objects void GenRenderbuffers( sizei n, uint *renderbuffers ); void DeleteRenderbuffers( sizei n, const uint *renderbuffers ); boolean IsRenderbuffer( uint renderbuffer ); * Framebuffer Objects void GenFramebuffers( sizei n, uint *framebuffers ); void DeleteFramebuffers( sizei n, const uint *framebuffers ); boolean IsFramebuffer( uint framebuffer ); * Vertex Array Objects void GenVertexArrays( sizei n, uint *arrays ); void DeleteVertexArrays( sizei n, const uint *arrays ); boolean IsVertexArray( uint array ); * Transform Feedback Objects void GenTransformFeedbacks( sizei n, uint *ids ); void DeleteTransformFeedbacks( sizei n, const uint *ids ); boolean IsTransformFeedback( uint id ); * Query Objects void GenQueries( sizei n, uint *ids ); void DeleteQueries( sizei n, const uint *ids ); boolean IsQuery( uint id ); * Sync Objects sync FenceSync( enum condition, bitfield flags ); void DeleteSync( sync sync ); boolean IsSync( sync sync ); * Display Lists uint GenLists( sizei s ); void DeleteLists( uint list, sizei range ); boolean IsList( uint list ); ---------------------------------------------------------------------- Looking at this, the following kind of objects are a perfect fit for the current ObjectName class: * Buffer Objects * Program Pipeline Objects * Texture Objects * Sampler Objects * Renderbuffer Objects * Framebuffer Objects * Vertex Array Objects * Transform Feedback Objects * Query Objects The following two object kinds fit, although not 100% perfectly, but this can easily be handled e.g. via comments and exporting a constructor: * Program Objects: CreateProgram directly creates a name *and* the object. * Display Lists: List names don't have to be generated via GenLists, and GenLists itself is guaranteed to return a consecutive range of names. The following two object kinds are the tricky ones: * Shader Objects: Just like program objects, their name and the associated object are created simultaneously. Furthermore, creation needs a parameter (the shader type). * Sync Objects: The same problems as for shader objects (direct creation + arguments for creation), in addition the object identifier is an opaque pointer (GLsync) instead of a GLuint, but the latter fact can be hidden. Any suggestions regarding how to reflect this on the Haskell side? It would be nice to keep ObjectName, perhaps with some modifications and/or additions like e.g. another type class. There are probably several ways of doing this, I would really like to get some ideas and feedback before I rush into changing things.

To make my previous thoughts on ObjectNames a little bit more concrete, here one possible solution: We could split the ObjectName class into 2 parts like this: class NameSpace a where -- Do we need a better name? Not sure... deleteObjectNames:: [a] -> IO () isObjectName :: a -> IO Bool class NameSpace a => ObjectName a where genObjectNames :: Int -> IO [a] All object kinds in OpenGL can be instances of NameSpace, and almost all kinds can be instances of ObjectName, too. Shader objects and sync objects would only be instances of NameSpace, not of ObjectName. They would have creation functions taking additional arguments like: createShader :: ShaderType -> IO Shader fenceSync :: Condition -> [Flags] -> IO Sync It is debatable if Program should be an instance of ObjectName or not: glCreateProgram doesn't need parameters, but it immediately creates a program + a name, not only the name. A separate createProgram function would make this clearer, but I don't have a strong opinion regarding that. One could perhaps make some tricks with MPTC and functional dependencies to unify these creation functions a bit, but I would like to avoid type system extensions. Hints/proposals/rants appreciated, as usual. :-)
participants (1)
-
Sven Panne