2015-02-12 14 views
14

che sto cercando di fare funzione per impostare le uniformi degli shader, ma quando provo a compilare l'ottengo questo errore:parametro formale con __declspec (allineare ('16')), non sarà allineato

Error 2 error C2719: 'value': formal parameter with __declspec(align('16')) won't be aligned

Ecco il codice della funzione:

void Shader::setUniform(std::string name, const glm::mat4 value){ 
    GLint uniform = glGetUniformLocation(m_program, name.c_str()); 
    glUniformMatrix4fv(uniform, 1, GL_FALSE, (GLfloat*)&value); 
} 

sto usando Visual Studio 2013.

+4

'const std :: string & name, const glm :: mat4 & value'. –

+2

GLM ha bisogno di un allineamento di 16 byte perché le ottimizzazioni SIMD funzionino, quindi dice al compilatore questo ed è da lì che il problema sta venendo. GL, d'altra parte, non si preoccupa affatto se 'value' è allineato su un limite di 16 byte. Dovresti passare questi per riferimento comunque, non c'è motivo di fare una copia di una matrice da inviare ad OpenGL. –

risposta

20

Da Microsoft's documentation su tale errore:

The align__declspec modifier is not permitted on function parameters.

Non copia il parametro in una posizione non allineata. Passa un riferimento costante ai dati esistenti e allineati.

void Shader::setUniform(const std::string &name, const glm::mat4 & value) 
//            ^^^^^   ^
0

non sono sicuro circa l'attuazione del glm :: Mat4, ma non è impostato in modo che mette i dati al suo interno su una 'parola' completa posizione all'interno di memoria o è stato creato nel una posizione non allineata (?? voi la lettura da un file facendo alcuni trucchi aritmetica dei puntatori da qualche parte)

http://virtrev.blogspot.com/2010/09/memory-alignment-theory-and-c-examples.html

Se si desidera un trucco per 'farlo funzionare' si può provare:

void Shader::setUniform(std::string name, const glm::mat4 value){ 
    // This assumes your copy constructor works correctly 
    glm::mat4 alignedMat = value; 
    GLint uniform = glGetUniformLocation(m_program, name.c_str()); 
    glUniformMatrix4fv(uniform, 1, GL_FALSE, (GLfloat*)&value); 
} 

Ho usato questo trucco per forzare i dati di allineamento prima. Puoi anche fare una memcpy in alignMat per forzare l'allineamento delle cose a volte. NON ASSUMERE che questo è il modo giusto per farlo. Dovresti creare elementi con un corretto allineamento. È solo per vedere ciò che è fuori allineamento, test e debug.

Anche se si sta utilizzando il modificatore __declspec sul parametro nella definizione del metodo. Non farlo.

+2

In realtà è la copia effettuata quando si chiama questa funzione che è il problema. 'glUniformMatrix4fv (...)' non richiede un indirizzo allineato a 16 byte, ma l'istanziazione di un 'glm :: mat4' lo fa. Puoi vedere da dove viene questo problema [qui] (https://github.com/g-truc/glm/blob/3226580a361742115b7f131ecd9e5249029a036b/glm/detail/type_vec4.hpp), gli intrinseci '__m128' sono implicitamente' __declspec (allinea (16)) '. In teoria, questa limitazione si applica solo quando la compilazione per x86 - x64 allinea sempre la parte superiore dello stack su un limite di 16 byte. –

0

Attualmente la programmazione fisica Bullet utilizzando Visual Studio 2013. Prendere l'indirizzo della variabile, qui un vettore 3D di nome di colore, per sbarazzarsi di l'errore di allineamento:

void SetColor(btVector3 color) { m_color = color; } //does give the error but 

void SetColor(btVector3 &color) { m_color = color; } //does not.