2017-01-11 3 views
0

Als Teil eines Proof of Concept versuche ich Code zu erstellen, mit dem ich GLSL-Skripte erstellen kann. Eines der ersten Dinge, die ich getan habe, ist die Erstellung von Verweisen auf die GLSL-Typen und das Erstellen eines Systems, in dem ich basierend auf einer Enumeration (dem Typ des GLSL-Datentyps) das String-Literal abfragen kann, das es in GLSL darstellt Code. Hier ist, wie es aussieht:Wie kann ich die Duplizierung in diesem Code loswerden?

#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 

Bisher habe ich mit der Funktionalität des Codes keine Probleme hatte, aber das Duplizierung des Codes, wo ich die Typen als Enum definieren und sie dann schreiben wieder als String-Literal beunruhigt mich definitiv. Ich werde auch mehr Typen hinzufügen müssen (das sind kaum die einzigen GLSL-Typen!) Und ich würde gerne ähnlichen Code zum Schreiben von OpenCL-Kernel-Code schreiben (was von ähnlicher Semantik abhängt), wie kann ich das reduzieren? code down, so dass ich nur eine Deklaration für jeden Typ brauche?

Auch jeder Hinweis, der meine Verwendung von Macros reduzieren oder sogar eliminieren würde, wäre willkommen.

Antwort

1

Ich weiß nicht, ob dies der Fall passt, aber ich kann so etwas vorschlagen:

// things.inc 
#ifndef GTYPE_VOID 
#define GTYPE_VOID GTYPE_DECL(gvoid) 
#endif 
GTYPE_VOID 

#undef GTYPE_VOID 
#ifndef GTYPE_INT 
#define GTYPE_INT GTYPE_DECL(gint) 
#endif 
GTYPE_INT 
#undef GTYPE_INT 

#ifndef GTYPE_FLOAT 
#define GTYPE_FLOAT GTYPE_DECL(gfloat) 
#endif 
GTYPE_FLOAT 
#undef GTYPE_FLOAT 

Anschließend können Sie das Makro in der Art und Weise definieren Sie mögen, und schließen es an Orten, wo Sie brauchen:

// things.cpp 
enum class gtypes { 
#define GTYPE_DECL(Thing) Thing, 
#include "things.inc" 
#undef GTYPE_DECL 
}; 
const char *as_string(gtype t) { 
    switch (t) { 
    #define GTYPE_DECL(Thing) case gtype::Thing: return #Thing; 
    #include "things.inc" 
    #undef GTYPE_DECL 
    } 
    // or unreachable 
    return "(unknown)"; 
} 

Sie können auch versuchen, eine constexpr-Karte zu verwenden.

+0

Ich werde dies an meine Bedürfnisse anpassen müssen, aber ich werde es testen und sehen, ob es funktioniert. – Xirema

Verwandte Themen