From: Steinar H. Gunderson Date: Wed, 12 Sep 2018 22:48:01 +0000 (+0200) Subject: Release flow textures when we are done with them. X-Git-Tag: 1.8.0~76^2~109 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=00a917a3feec0fdd99db1a58a7d1edf973a0eb57 Release flow textures when we are done with them. --- diff --git a/flow.cpp b/flow.cpp index 873bdf2..ece0d51 100644 --- a/flow.cpp +++ b/flow.cpp @@ -1019,11 +1019,14 @@ GLuint Interpolate::exec(GLuint image_tex, GLuint bidirectional_flow_tex, GLuint GLuint TexturePool::get_texture(GLenum format, GLuint width, GLuint height, GLuint num_layers) { - for (Texture &tex : textures) { - if (!tex.in_use && !tex.is_renderbuffer && tex.format == format && - tex.width == width && tex.height == height && tex.num_layers == num_layers) { - tex.in_use = true; - return tex.tex_num; + { + lock_guard lock(mu); + for (Texture &tex : textures) { + if (!tex.in_use && !tex.is_renderbuffer && tex.format == format && + tex.width == width && tex.height == height && tex.num_layers == num_layers) { + tex.in_use = true; + return tex.tex_num; + } } } @@ -1041,17 +1044,23 @@ GLuint TexturePool::get_texture(GLenum format, GLuint width, GLuint height, GLui tex.num_layers = num_layers; tex.in_use = true; tex.is_renderbuffer = false; - textures.push_back(tex); + { + lock_guard lock(mu); + textures.push_back(tex); + } return tex.tex_num; } GLuint TexturePool::get_renderbuffer(GLenum format, GLuint width, GLuint height) { - for (Texture &tex : textures) { - if (!tex.in_use && tex.is_renderbuffer && tex.format == format && - tex.width == width && tex.height == height) { - tex.in_use = true; - return tex.tex_num; + { + lock_guard lock(mu); + for (Texture &tex : textures) { + if (!tex.in_use && tex.is_renderbuffer && tex.format == format && + tex.width == width && tex.height == height) { + tex.in_use = true; + return tex.tex_num; + } } } @@ -1064,12 +1073,16 @@ GLuint TexturePool::get_renderbuffer(GLenum format, GLuint width, GLuint height) tex.height = height; tex.in_use = true; tex.is_renderbuffer = true; - textures.push_back(tex); + { + lock_guard lock(mu); + textures.push_back(tex); + } return tex.tex_num; } void TexturePool::release_texture(GLuint tex_num) { + lock_guard lock(mu); for (Texture &tex : textures) { if (!tex.is_renderbuffer && tex.tex_num == tex_num) { assert(tex.in_use); @@ -1082,6 +1095,7 @@ void TexturePool::release_texture(GLuint tex_num) void TexturePool::release_renderbuffer(GLuint tex_num) { + lock_guard lock(mu); for (Texture &tex : textures) { if (tex.is_renderbuffer && tex.tex_num == tex_num) { assert(tex.in_use); diff --git a/flow.h b/flow.h index 6475d9b..f268316 100644 --- a/flow.h +++ b/flow.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -383,6 +384,7 @@ private: GLuint uniform_scale_factor; }; +// All operations, except construction and destruction, are thread-safe. class TexturePool { public: GLuint get_texture(GLenum format, GLuint width, GLuint height, GLuint num_layers = 0); @@ -398,7 +400,8 @@ private: bool in_use = false; bool is_renderbuffer = false; }; - std::vector textures; + std::mutex mu; + std::vector textures; // Under mu. }; class DISComputeFlow { diff --git a/video_stream.cpp b/video_stream.cpp index 441e36a..820a933 100644 --- a/video_stream.cpp +++ b/video_stream.cpp @@ -318,12 +318,16 @@ void VideoStream::schedule_interpolated_frame(int64_t output_pts, unsigned strea check_error(); glGenerateTextureMipmap(resources.gray_tex); check_error(); - GLuint flow_tex = compute_flow->exec(resources.gray_tex, DISComputeFlow::FORWARD_AND_BACKWARD, DISComputeFlow::DO_NOT_RESIZE_FLOW); + qf.flow_tex = compute_flow->exec(resources.gray_tex, DISComputeFlow::FORWARD_AND_BACKWARD, DISComputeFlow::DO_NOT_RESIZE_FLOW); check_error(); - qf.output_tex = interpolate->exec(resources.input_tex, flow_tex, 1280, 720, alpha); + qf.output_tex = interpolate->exec(resources.input_tex, qf.flow_tex, 1280, 720, alpha); check_error(); + // We could have released qf.flow_tex here, but to make sure we don't cause a stall + // when trying to reuse it for the next frame, we can just as well hold on to it + // and release it only when the readback is done. + // Read it down (asynchronously) to the CPU. glPixelStorei(GL_PACK_ROW_LENGTH, 0); glBindBuffer(GL_PIXEL_PACK_BUFFER, resources.pbo); @@ -377,6 +381,8 @@ void VideoStream::encode_thread_func() glClientWaitSync(qf.fence.get(), /*flags=*/0, GL_TIMEOUT_IGNORED); vector jpeg = encode_jpeg((const uint8_t *)qf.resources.pbo_contents, 1280, 720); + compute_flow->release_texture(qf.flow_tex); + interpolate->release_texture(qf.output_tex); AVPacket pkt; av_init_packet(&pkt); diff --git a/video_stream.h b/video_stream.h index 953e28e..3645123 100644 --- a/video_stream.h +++ b/video_stream.h @@ -66,8 +66,8 @@ private: int64_t input_second_pts; float alpha; InterpolatedFrameResources resources; - GLuint output_tex; RefCountedGLsync fence; // Set when the interpolated image is read back to the CPU. + GLuint flow_tex, output_tex; // Released in the receiving thread; not really used for anything else. }; std::deque frame_queue; // Under . std::mutex queue_lock;