Type extraction and offset from the structure field in the template

Please note: even if my example is from OpenGL, this is not an OpenGL question, but a general question D.

Background: In my game project, I have a shader class that helps interact with GLSL code. Setting up the uniform works great:

uniform(string name, float value) --> glUniform1f(...) uniform(string name, mat4 m) --> glUniformMatrix4fv( ...) etc. etc. 

That is, it selects the correct function depending on the type of parameter, so when I change my code, it automatically changes the use of the correct function (assuming that I have no type conflicts between D and GLSL).

My problems implement a somewhat similar attribute binding mechanism. I have a VERTEX structure:

 struct VERTEX { ...; vec3 pos; ... } 

For the binding attribute, in addition to knowing the type of field, I need an offset, but I don't need values. I managed to write a clumpsy implementation where the call looks like this:

 vbo.attrib!(typeof(mesh.VERTEX.pos))("vert_pos", mesh.VERTEX.pos.offsetof); 

And VBO.attrib is implemented as follows:

 void attrib(T: vec2)(string name, ulong offset) { /* 2 floats from offset */ } void attrib(T: vec3)(string name, ulong offset) { /* 3 floats from offset */ } 

Question: Is there a way to make this simpler and more elegant? As a rule, I do not like to duplicate a field when called, that is, first retrieve the type to select the correct attribute binding function, and then separately send the offset. I would like the function call to look something like this:

 vbo.attrib("vert_pos", mesh.VERTEX.pos); 

... And a template to extract both types and offsets from the argument. I read the manuals and tutorials on D templates, but I still haven't figured out how to implement the templates. Is it possible and how?

Clarification: I have a feeling that I'm already close, I just do not have enough imagination (and knowledge from D-templates and mixes) to implement the first phase:

 XXX(name, field) --> some unknown magic --> vbo.attrib!(typeof(field))(name,field.offsetof) --> void attrib(T: vec2)(string name, ulong offset) { /* arguments for GL call */ } 

EDIT: With mixins, I managed to do this:

  template attrib(string name, string field) { const char[] attrib = "vbo.attrib!" ~ "(typeof(" ~ field ~ "))" ~ "(\"" ~ name ~ "\", " ~ field ~ ".offsetof);"; } mixin(attrib!("vert_pos", "mesh.VERTEX.pos")); mixin(attrib!("vert_uv", "mesh.VERTEX.uv")); 

Honestly, this (call) looks even more difficult to use than my current one, so I keep my opinion and are looking for a more pleasant solution.

+5
source share
1 answer

you are really very close to a solution. this works with DMD git head:

 import std.stdio; struct vec2 { float a, b; } struct vec3 { float a, b, c; } struct VERTEX { vec3 pos; vec2 uv; } void attrib(T: vec2) (string name, ulong offset) { writefln("vec2: name=%s; ofs=%s", name, offset); } void attrib(T: vec3) (string name, ulong offset) { writefln("vec3: name=%s; ofs=%s", name, offset); } static void attrib(string name, alias field) () { attrib!(typeof(field))(name, field.offsetof); } void main () { attrib!("vert_pos", VERTEX.pos); // outputs "vec3: name=vert_pos; ofs=0" attrib!("vert_uv", VERTEX.uv); // outputs: "vec2: name=vert_uv; ofs=12" } 

Unfortunately, I do not have official release 2.066 to check if it works with it. this will not work with 2.065, so you're out of luck with the GDC (since it still uses 2.065).

the trick is in static , which means that "this template does not need any context."

ps just checked it out and yes it works with 2.066 release.

+5
source

Source: https://habr.com/ru/post/1209853/


All Articles