gKit2 light
tuto_read_buffer.cpp
Go to the documentation of this file.
1 
3 
4 #include <vector>
5 
6 #include "app.h"
7 #include "program.h"
8 
9 /*
10  cree 2 buffers dans la memoire privee du gpu, soit avec glBufferData(GL_STATIC) comme d'habitude,
11  soit avec glBufferStorage() introduit par opengl 4.4
12 
13  pour relire les resultats qui se trouvent dans un buffer prive du gpu, il faut d'abord copier les valeurs dans un buffer accessible par l'application,
14  puis relire enfin les valeurs dans l'application, soit en utilisant glGetBufferSubData() soit en utilisant glMapBuffer()
15 
16  les differentes solutions sont dispo pour tester, il suffit de definir (ou pas) USE_BUFFER_STORAGE et USE_MAP.
17  la configuration choisie est affichee par init().
18 
19  bilan de l'operation : c'est beaucoup plus simple et direct a faire avec glBufferStorage(), les flags de glBufferData() sont bien penibles a choisir correctement
20  remarque : un mauvais choix impactera sans doute les geforce plus que les radeon
21  */
22 
23 
24 //~ #define USE_BUFFER_STORAGE
25 //~ #define USE_MAP
26 
27 
28 struct ReadBuffer : public App
29 {
30  ReadBuffer( ) : App(1280, 768, 4,3) {}
31 
32  int init( )
33  {
34  m_program= read_program("tutos/M2/read_buffer.glsl");
35  program_print_errors(m_program);
36 
37  std::vector<int> data(1024);
38 
39  glGenBuffers(1, &m_gpu_buffer1);
40  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_gpu_buffer1);
41  #ifdef USE_BUFFER_STORAGE
42  glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(int) * data.size(), data.data(), 0);
43  #else
44  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * data.size(), data.data(), GL_STATIC_COPY);
45  #endif
46 
47  glGenBuffers(1, &m_gpu_buffer2);
48  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_gpu_buffer2);
49  #ifdef USE_BUFFER_STORAGE
50  glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(int) * data.size(), nullptr, 0);
51  #else
52  glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * data.size(), nullptr, GL_STATIC_COPY);
53  #endif
54 
55  glGenBuffers(1, &m_read_buffer);
56  glBindBuffer(GL_COPY_READ_BUFFER, m_read_buffer);
57  #ifdef USE_BUFFER_STORAGE
58  #ifdef USE_MAP
59  glBufferStorage(GL_COPY_READ_BUFFER, sizeof(int) * data.size(), nullptr, GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT);
60  #else
61  glBufferStorage(GL_COPY_READ_BUFFER, sizeof(int) * data.size(), nullptr, GL_CLIENT_STORAGE_BIT);
62  #endif
63  #else
64  glBufferData(GL_COPY_READ_BUFFER, sizeof(int) * data.size(), nullptr, GL_DYNAMIC_READ);
65  #endif
66 
67  #ifdef USE_BUFFER_STORAGE
68  printf("!! use buffer storage\n");
69  #else
70  printf("!! use buffer data\n");
71  #endif
72 
73  return 0;
74  }
75 
76  int quit( )
77  {
78  release_program(m_program);
79  glDeleteBuffers(1, &m_gpu_buffer1);
80  glDeleteBuffers(1, &m_gpu_buffer2);
81  glDeleteBuffers(1, &m_read_buffer);
82 
83  return 0;
84  }
85 
86  int render( )
87  {
88  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_gpu_buffer1);
89  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_gpu_buffer2);
90 
91  // execute le shader
92  glUseProgram(m_program);
93  glDispatchCompute(4, 1, 1);
94 
95  // attends les resultats
96  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
97 
98  // et maintenant comment on recupere les donnees qui se trouvent dans un buffer prive du gpu ?
99  // etape 1 : on commence par copier les donnees dans un buffer intermediaire qui est accessible a l'application,
100  // ie pas un buffer prive, cf la creation des 2 types de buffers dans init()...
101  glBindBuffer(GL_COPY_READ_BUFFER, m_read_buffer);
102  glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_COPY_READ_BUFFER, 0, 0, sizeof(int)*1024);
103 
104  // etape 2 : on relit le contenu du buffer qui contient la copie des donnees
105  #ifdef USE_MAP
106  // soit avec map()
107  printf("!! use map\n");
108 
109  int *tmp= (int *) glMapBuffer(GL_COPY_READ_BUFFER, GL_READ_ONLY);
110  {
111  for(unsigned i= 0; i < 1024; i++)
112  printf("%d ", tmp[i]);
113  printf("\n");
114  }
115  glUnmapBuffer(GL_COPY_READ_BUFFER);
116 
117  #else
118  // soit avec getbuffer()
119  printf("!! use get buffer\n");
120 
121  std::vector<int> tmp(1024);
122  glGetBufferSubData(GL_COPY_READ_BUFFER, 0, sizeof(int) * tmp.size(), tmp.data());
123  for(unsigned i= 0; i < tmp.size(); i++)
124  printf("%d ", tmp[i]);
125  printf("\n");
126  #endif
127 
128  return 0;
129  }
130 
131  GLuint m_gpu_buffer1;
132  GLuint m_gpu_buffer2;
133  GLuint m_read_buffer;
134  GLuint m_program;
135 };
136 
137 int main( )
138 {
139  ReadBuffer app;
140  app.run();
141 
142  return 0;
143 }
classe application.
Definition: app.h:20
int run()
execution de l'application.
Definition: app.cpp:36
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:204
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:432
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:211
int quit()
a deriver pour detruire les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.
int render()
a deriver pour afficher les objets. renvoie 1 pour continuer, 0 pour fermer l'application.
int init()
a deriver pour creer les objets openGL. renvoie -1 pour indiquer une erreur, 0 sinon.