Sure. It was just a rather naive idea at a method for creating a c++ interface in Mental Ray. The issue is that, when Mental Ray loads up, it allocates memory for all of your shader’s parameters (based on how they’ve been defined in the .mi definition) in-line, just as if it had been allocated as a struct. A pointer to the beginning of this block of data is then passed on to the shader author.
Traditionally, in order to access individual parameters from this block of data, the shader writer is required to define a struct that matches the shader parameters exactly. When the shader is called up, the pointer is cast as a struct pointer of this type. And if the layout of your struct is identical to that of the memory block that’s been allocated for your parameters, the members of your struct will point to each individual parameter.
That’s fine. However, for the sake of having a nice C+±ified interface - and just for the record, I know that this isn’t totally necessary. Writing shaders in pure C is still easy. I’m attempting it more for the sake of experimentation. I.E., just for the hell of it. - but anyway, for the sake of this interface, I wanted to have a generalized ParameterList object that would point to the parameters instead (and do a whole lot of other nice things). I also wanted to make it so that creating such an object would remove the necessity of creating the struct, too.
So you could have, say…
class MyShaderParameters : public ParameterList
{
Parameter<int> someInt;
Parameter<miColor> param1;
Parameter<miColor> param2;
};
…and be done with it.
But in order to use this class to access the individual parameters, without ever defining the struct that goes right along with it, I’d need to be able to cast a void pointer to my block of data (which is organized like a struct) as a pointer of my class type…which is probably unsafe, since many of the attributes of that pointer might point to unallocated memory space. But as long as you get the pointer to point at the right place, and only ever attempt to access the appropriate memory blocks, I think it’d be safe.
Byte-padding (which I wasn’t previously aware of) not considered, this actually works… until you start adding more data before the parameters are declared. Then, before you cast the void pointer (that points to the block of data holding your parameters) as your class type, you’d just have to offset the address pointed to by your void pointer, so that when you cast it as your class type, the parameters in memory are in line with the parameters declared in your object.
For that, I thought up a little trick to get the appropriate offset. Take something like this:
class BaseParamList
{
char initializer; //always the first attribute
…
};
class ParamList : public BaseParamList
{
//(object related crap)
char structInitializer; //always right before parameter declarations
//(Parameters)
//(other object related crap)
};
Again, byte-padding not considered, you could create a “ParamList” object, and find out the offset of the parameters from the beginning of the object by finding the difference between the address of the “initializer” and “structInitializer” attributes. Then you could cast the void* of your data (which is basically a struct) as your class object, and offset it appropriately so that everything lines up. Say…
ParameterList paramDataPtr = (ParameterList)(((char*)pointerToData) + offsetFromObjectStart);
ParameterList params(paramDataPtr);
miColor inColor = params->param1.asColor();
…which actually does work, in simple cases. But yeah, I guess with byte padding, and the various other things that each compilers do with objects, it won’t work. Cool idea, but impractical.
Oh well. There are other ways of implementing a ‘ParameterList’ object. They’re just not quite as nice as what I was hoping for. Had the memory organization for objects been identical to structs - or even if it was something easily predictable - I could have even said to hell with this ‘ParameterList’ object, and have the parameters be contained as attributes within the shader object itself (again, without ever needing to define the struct), which would’ve been pretty nice…
:shrug: