@@ -225,8 +225,13 @@ bool CommandEncoderGl::finish() {
225225 case DescriptorType::Image: {
226226 auto texture_gl = static_cast <TextureGl *>(descriptor.texture .get ());
227227
228- glBindImageTexture (
229- binding_point, texture_gl->get_texture_id (), 0 , GL_FALSE, 0 , GL_READ_WRITE, GL_RGBA8);
228+ glBindImageTexture (binding_point,
229+ texture_gl->get_texture_id (),
230+ 0 ,
231+ GL_FALSE,
232+ 0 ,
233+ GL_READ_WRITE,
234+ GL_RGBA8);
230235 } break ;
231236#endif
232237 default :
@@ -295,9 +300,24 @@ bool CommandEncoderGl::finish() {
295300 args.buffer ->download_via_mapping (args.data_size , args.offset , args.data );
296301 } break ;
297302 case CommandType::WriteTexture: {
298- auto &args = cmd.args .write_texture ;
303+ const auto &args = cmd.args .write_texture ;
299304
300305 auto texture_gl = static_cast <TextureGl *>(args.texture );
306+ texture_gl->prepare_pbo ();
307+
308+ const GLsizeiptr region_data_size = (args.width - args.offset_x ) * (args.height - args.offset_y ) *
309+ get_pixel_size (texture_gl->get_format ());
310+
311+ glBindBuffer (GL_PIXEL_UNPACK_BUFFER, texture_gl->get_pbo_id ());
312+
313+ void *ptr = glMapBufferRange (GL_PIXEL_UNPACK_BUFFER,
314+ 0 ,
315+ region_data_size,
316+ GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
317+ if (ptr) {
318+ memcpy (ptr, args.data , region_data_size);
319+ glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
320+ }
301321
302322 glBindTexture (GL_TEXTURE_2D, texture_gl->get_texture_id ());
303323 glTexSubImage2D (GL_TEXTURE_2D,
@@ -308,33 +328,41 @@ bool CommandEncoderGl::finish() {
308328 (GLint)args.height ,
309329 to_gl_pixel_data_format (args.texture ->get_format ()),
310330 to_gl_data_type (texture_format_to_data_type (args.texture ->get_format ())),
311- args.data );
312- glBindTexture (GL_TEXTURE_2D, 0 ); // Unbind.
331+ 0 );
332+
333+ // Unbind.
334+ glBindTexture (GL_TEXTURE_2D, 0 );
335+ glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0 );
313336
314337 gl_check_error (" WriteTexture" );
315338 } break ;
316339 case CommandType::ReadTexture: {
317- auto &args = cmd.args .read_texture ;
340+ const auto &args = cmd.args .read_texture ;
318341
319342 auto texture_gl = static_cast <TextureGl *>(args.texture );
343+ texture_gl->prepare_pbo ();
320344
321- GLenum temp_fbo;
322- glGenFramebuffers (1 , &temp_fbo);
323- glBindFramebuffer (GL_FRAMEBUFFER, temp_fbo);
345+ const GLsizeiptr region_data_size = (args.width - args.offset_x ) * (args.height - args.offset_y ) *
346+ get_pixel_size (texture_gl->get_format ());
324347
325- glFramebufferTexture2D (
326- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_gl->get_texture_id (), 0 );
348+ glBindBuffer (GL_PIXEL_PACK_BUFFER, texture_gl->get_pbo_id ());
327349
328350 glReadPixels (args.offset_x ,
329351 args.offset_y ,
330352 args.width ,
331353 args.height ,
332- GL_RGBA ,
354+ to_gl_pixel_data_format (args. texture -> get_format ()) ,
333355 to_gl_data_type (texture_format_to_data_type (args.texture ->get_format ())),
334- args.data );
356+ 0 );
357+
358+ void *ptr = glMapBufferRange (GL_PIXEL_PACK_BUFFER, 0 , region_data_size, GL_MAP_READ_BIT);
359+ if (ptr) {
360+ memcpy (args.data , ptr, region_data_size);
361+ glUnmapBuffer (GL_PIXEL_PACK_BUFFER);
362+ }
335363
336- glBindTexture (GL_FRAMEBUFFER, 0 ); // Unbind.
337- glDeleteFramebuffers ( 1 , &temp_fbo );
364+ // Unbind.
365+ glBindBuffer (GL_PIXEL_PACK_BUFFER, 0 );
338366
339367 gl_check_error (" ReadTexture" );
340368 } break ;
0 commit comments