mercredi 11 janvier 2017

How can I get rid of the duplication in this code?

As part of a Proof of Concept, I'm trying to trying to build code that I can use to build GLSL scripts. One of the first things I've done is create references to the GLSL types, and created a system where I can query, based on an enum (which is the type of the GLSL data type) the string-literal that represents it in GLSL code. Here's what it looks like:

#define VEC_EXPAND(name) g ## name ## 2, g ## name ## 3, g ## name ## 4
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)

enum class gtype : uint32_t {
    gvoid,
    gbool, gint, guint, gfloat, gdouble,
    VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
    MAT_EXPAND(mat), MAT_EXPAND(dmat),
    gsampler2d
};

#undef VEC_EXPAND
#undef MAT_EXPAND

#define GLSL_EXPAND(name) #name
#define VEC_EXPAND(name) GLSL_EXPAND(name ## 2), GLSL_EXPAND(name ## 3), GLSL_EXPAND(name ## 4)
#define MAT_EXPAND(name) VEC_EXPAND(name), VEC_EXPAND(name ## 2x), VEC_EXPAND(name ## 3x), VEC_EXPAND(name ## 4x)

template<class T, class... Tail, class Elem = typename std::decay<T>::type>
constexpr std::array<Elem, 1 + sizeof...(Tail)> make_array(T&& head, Tail&&... values)
{
    return { std::forward<T>(head), std::forward<Tail>(values)... };
}


constexpr auto glsl_string_array = make_array(
    "void", "bool", "int", "uint", "float", "double",
    VEC_EXPAND(bvec), VEC_EXPAND(ivec), VEC_EXPAND(uvec), VEC_EXPAND(vec), VEC_EXPAND(dvec),
    MAT_EXPAND(mat), MAT_EXPAND(dmat),
    "sampler2d"
);
constexpr const char * to_string_literal(gtype type) {
    return glsl_string_array[uint32_t(type)];
}

std::string to_string(gtype type) {
    return to_string_literal(type);
}

#undef GLSL_EXPAND
#undef VEC_EXPAND
#undef MAT_EXPAND

So far, I've had no problems with the functionality of the code, but that duplication of the code where I define the types as an enum, and then write them again as a string literal is definitely troubling to me. I'm going to have to add more types as well (these are hardly the only GLSL types!) and I would like to write similar code for writing OpenCL Kernel code (which will depend on similar semantics), so how can I reduce this code down so that I only need one declaration of each type?

Also, any advice which would reduce or even eliminate my use of Macros would be appreciated.





Aucun commentaire:

Enregistrer un commentaire