2013-10-08 8 views
6

sto andando un po 'matto su questo dato che davvero non capisco ciò che è sbagliato e cosa no. Ci deve essere qualcosa che ho frainteso molto o c'è qualche tipo di errore nel codice o nel driver. Sto eseguendo questo su AMD Radeon 5850 con gli ultimi driver di catalyst beta della scorsa settimana.lettura e l'aggiornamento consistenza di buffer in OpenGL/GLSL 4.3

OK, ho cominciato a fare un'implementazione OIT-rendering e voleva usare una struttura-array salvato in un oggetto di buffer di archiviazione shader. Ebbene, gli indici in quella riflettevano/andare avanti in modo memoria sbagliato e ho praticamente scontato che si trattava di un bug conducente - dal momento che solo di recente iniziato a sostenere tale cosa + sì, è un driver beta. Perciò spostato indietro una tacca e GLSL-immagini utilizzate dalla trama oggetti invece tampone, che immagino era stato supportato poiché almeno un po 'indietro.

Ancora non si stava comportando in modo corretto. Così ho creato un semplice progetto di prova e ho vagabondato un po 'e ora penso di aver appena pizzicato dove si trova la cosa.

OK! Prima I inizializza il il buffer e la trama.

//Clearcolor and Cleardepth setup, disabling of depth test, compile and link shaderprogram etc. 
... 
// 
GLint tbo, tex; 
datasize = resolution.x * resolution.y * 4 * sizeof(GLfloat); 
glGenBuffers(1, &tbo); 
glBindBuffer(GL_TEXTURE_BUFFER, tbo); 
glBufferData(GL_TEXTURE_BUFFER, datasize, NULL, GL_DYNAMIC_COPY); 
glBindBuffer(GL_TEXTURE_BUFFER, 0); 

glGenTextures(1, &tex); 
glBindTexture(GL_TEXTURE_BUFFER, tex); 
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); 
glBindTexture(GL_TEXTURE_BUFFER, 0); 
glBindImageTexture(2, tex, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F); 

Poi il ciclo di rendering è - aggiornamento e disegnare, l'aggiornamento e disegnare ... Con un ritardo in mezzo in modo da avere il tempo di vedere ciò che l'aggiornamento fa.

Il aggiornamento è come questo ...

ivec2 resolution; //Using GLM 
resolution.x = (GLuint)(iResolution.x + .5f); 
resolution.y = (GLuint)(iResolution.y + .5f); 

glBindBuffer(GL_TEXTURE_BUFFER, tbo); 
void *ptr = glMapBuffer(GL_TEXTURE_BUFFER, GL_WRITE_ONLY); 
color *c = (color*)ptr; //color is a simple struct containing 4 GLfloats. 
for (int i = 0; i < resolution.x*resolution.y; ++i) 
{ 
    c[i].r = c[i].g = c[i].b = c[i].a = 1.0f; 
} 
glUnmapBuffer(GL_TEXTURE_BUFFER); c = (color*)(ptr = NULL); 
glBindBuffer(GL_TEXTURE_BUFFER, 0); 

E il disegnare è come questo ...

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glMemoryBarrier(GL_ALL_BARRIER_BITS); 
ShaderProgram->Use(); //Simple shader program class 
quad->Draw(GL_TRIANGLES); //Simple mesh class containing triangles (vertices) and colors 
glFinish(); 
glMemoryBarrier(GL_ALL_BARRIER_BITS); 

ho appena messo alcune barriere di memoria in giro per essere più sicuri , non dovrebbe nuocere più delle prestazioni giusto? Bene, il risultato è stato lo stesso con o senza le barriere comunque, quindi ... :)

Il programma Shader è un semplice shader di vertici passante e lo shader di frammenti che sta eseguendo il test.

Vertex Shader

#version 430 

in vec3 in_vertex; 

void main(void) 
{ 
    gl_Position = vec4(in_vertex, 1.0); 
} 

Fragment Shader (immagino coerente & memoryBarrier() non è realmente necessario qui da quando li faccio su CPU tra l'esecuzione dello shader draw/frammento ... ma non mi danno)

#version 430 

uniform vec2 iResolution; 
layout(binding = 2, rgba32f) coherent uniform imageBuffer colorMap; 

out vec4 FragColor; 

void main(void) 
{ 
    ivec2 res = ivec2(int(iResolution.x + 0.5), int(iResolution.y + 0.5)); 
    ivec2 pos = ivec2(int(gl_FragCoord.x + 0.5), int(gl_FragCoord.y + 0.5)); 
    int pixelpos = pos.y * res.x + pos.x; 

    memoryBarrier(); 
    vec4 prevPixel = imageLoad(colorMap, pixelpos); 

    vec4 green = vec4(0.0, 1.0, 0.0, 0.0); 
    imageStore(colorMap, pixelpos, green); 
    FragColor = prevPixel; 
} 

Aspettative:? Uno schermo bianco! Dato che sto scrivendo "bianco" sull'intero buffer tra ogni pareggio anche se scrivo in verde all'immagine dopo aver caricato lo shader effettivo.

Risultato: il primo fotogramma è verde, il resto è nero. Una parte di me crede che ci sia una cornice bianca che è troppo veloce per essere vista o qualche cosa di vsync che la tarda, ma è un posto per le logiche? : P

Bene, quindi ho provato una nuova cosa e spostato il blocco di aggiornamento (dove sto scrivendo "bianco" per l'intero buffer) per l'init invece.

aspettativa: Un bianco primo fotogramma, seguito da uno schermo verde.

Risultato: Oh sì, è tutto verde! Anche se il primo fotogramma è con alcuni artefatti di bianco/verde, a volte solo verde. Ciò potrebbe probabilmente essere dovuto a (mancanza di) vsync di qualcosa, non averlo verificato. Comunque, penso di aver ottenuto il risultato che stavo cercando.

La conclusione che posso trarre da questo è che c'è qualcosa di sbagliato nel mio aggiornamento. Ha sganciato il buffer dal riferimento di trama o qualcosa del genere? In tal caso, non è strano che il primo fotogramma sia OK? È solo dopo il primo comando imageStore (beh, il primo fotogramma) che la trama diventa tutto nero - il "bind() - map() - unmap() - bind (0)" funziona la prima volta, ma non dopo. La mia immagine di glMapBuffer è che copia i dati del buffer dalla GPU alla memoria della CPU, cambiamo e Unmap lo copia. Bene, ora ho pensato che forse non copia il buffer dalla GPU alla CPU e poi indietro, ma solo in un modo? Potrebbe essere GL_WRITE_ONLY che dovrebbe essere cambiato in GL_READ_WRITE? Bene, ho provato entrambi. Presumibilmente uno di loro era corretto, non sarebbe il mio schermo quando si utilizza quello essere sempre bianco in "test 1"?

ARGH, quello che sto facendo di sbagliato?

EDIT: Beh, io ancora non so ... Ovviamente glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); dovrebbe essere glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);, ma penso che tbo e tex avevano lo stesso valore da quando sono stati generati nello stesso ordine. Pertanto ha funzionato in questa implementazione. L'ho risolto comunque, in un modo che non sono molto contento visto che penso davvero che quanto sopra dovrebbe funzionare. D'altra parte, la nuova soluzione è probabilmente un po 'più performante. Invece di usare glMapBuffer(), sono passato a mantenere una copia del TBO-memoria della CPU utilizzando glBufferSubData() e glgetBufferSubData() per l'invio dei dati tra CPU/GPU. Questo ha funzionato, quindi continuerò con questa soluzione.

Ma, sì, la questione si è fermato - Perché non glMapBuffer() lavoro con i miei oggetti buffer struttura?

risposta

Problemi correlati