Skip to content

Commit 1d3ef25

Browse files
committed
Use PBO for OpenGL
1 parent 44abc05 commit 1d3ef25

File tree

4 files changed

+78
-15
lines changed

4 files changed

+78
-15
lines changed

pathfinder/gpu/gl/command_encoder.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

pathfinder/gpu/gl/texture.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "texture.h"
22

3+
#include <assert.h>
4+
35
#include "../../common/global_macros.h"
46
#include "debug_marker.h"
57

@@ -46,16 +48,39 @@ TextureGl::~TextureGl() {
4648
return;
4749
}
4850
glDeleteTextures(1, &gl_id_);
51+
52+
if (pbo_id_ > 0) {
53+
glDeleteBuffers(1, &pbo_id_);
54+
}
4955
}
5056

5157
uint32_t TextureGl::get_texture_id() const {
5258
return gl_id_;
5359
}
5460

61+
uint32_t TextureGl::get_pbo_id() const {
62+
return pbo_id_;
63+
}
64+
5565
void TextureGl::set_label(const std::string& label) {
5666
Texture::set_label(label);
5767

5868
DebugMarker::label_texture(gl_id_, label);
5969
}
6070

71+
void TextureGl::prepare_pbo() {
72+
if (pbo_id_ > 0) {
73+
return;
74+
}
75+
76+
glGenBuffers(1, &pbo_id_);
77+
assert(pbo_id_ != 0);
78+
79+
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo_id_);
80+
81+
glBufferData(GL_PIXEL_UNPACK_BUFFER, static_cast<GLsizeiptr>(desc_.byte_size()), nullptr, GL_STREAM_DRAW);
82+
83+
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
84+
}
85+
6186
} // namespace Pathfinder

pathfinder/gpu/gl/texture.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ class TextureGl : public Texture {
1515

1616
uint32_t get_texture_id() const;
1717

18+
uint32_t get_pbo_id() const;
19+
1820
void set_label(const std::string& label) override;
1921

22+
void prepare_pbo();
23+
2024
private:
2125
explicit TextureGl(const TextureDescriptor& desc);
2226

@@ -25,6 +29,8 @@ class TextureGl : public Texture {
2529
bool wrapped = false;
2630

2731
uint32_t gl_id_ = 0;
32+
33+
uint32_t pbo_id_ = 0;
2834
};
2935

3036
} // namespace Pathfinder

pathfinder/gpu/texture.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class Texture {
5959
return desc_.format;
6060
}
6161

62+
TextureDescriptor get_descriptor() const {
63+
return desc_;
64+
}
65+
6266
// Sometimes, we need to update label for a texture as we reuse it for another purpose.
6367
virtual void set_label(const std::string& label) {
6468
label_ = label;

0 commit comments

Comments
 (0)