From 23e9f4d891f94569b0cd08a55b0e3ee2d4ef29de Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Fri, 26 Jul 2024 22:11:40 +0200 Subject: [PATCH 1/2] fix (mvUtilities): correct UpdateTexture The textures are updated using a PBO. The correct order is: - Fill the PBO - Trigger the texture update from the PBO And not the other. This fixes incorrect data being sent on some frames. --- src/mvUtilities_linux.cpp | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/mvUtilities_linux.cpp b/src/mvUtilities_linux.cpp index b26ef1ff6..3a59b32c1 100644 --- a/src/mvUtilities_linux.cpp +++ b/src/mvUtilities_linux.cpp @@ -219,18 +219,6 @@ UpdateTexture(void* texture, unsigned width, unsigned height, std::vector { auto textureId = (GLuint)(size_t)texture; - // start to copy from PBO to texture object /////// - - // bind the texture and PBO - glBindTexture(GL_TEXTURE_2D, textureId); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO_ids[textureId]); - - // copy pixels from PBO to texture object - // Use offset instead of ponter. - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, 0); - - /////////////////////////////////////////////////// - // start to modify pixel values /////////////////// // bind PBO to update pixel values @@ -256,16 +244,6 @@ UpdateTexture(void* texture, unsigned width, unsigned height, std::vector /////////////////////////////////////////////////// - // it is good idea to release PBOs with ID 0 after use. - // Once bound with 0, all pixel operations behave normal ways. - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); -} - - void -UpdateRawTexture(void* texture, unsigned width, unsigned height, float* data, int components) -{ - auto textureId = (GLuint)(size_t)texture; - // start to copy from PBO to texture object /////// // bind the texture and PBO @@ -274,13 +252,20 @@ UpdateRawTexture(void* texture, unsigned width, unsigned height, float* data, in // copy pixels from PBO to texture object // Use offset instead of ponter. - if(components == 4) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, 0); - else - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, 0); /////////////////////////////////////////////////// + // it is good idea to release PBOs with ID 0 after use. + // Once bound with 0, all pixel operations behave normal ways. + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); +} + + void +UpdateRawTexture(void* texture, unsigned width, unsigned height, float* data, int components) +{ + auto textureId = (GLuint)(size_t)texture; + // start to modify pixel values /////////////////// // bind PBO to update pixel values @@ -306,6 +291,21 @@ UpdateRawTexture(void* texture, unsigned width, unsigned height, float* data, in /////////////////////////////////////////////////// + // start to copy from PBO to texture object /////// + + // bind the texture and PBO + glBindTexture(GL_TEXTURE_2D, textureId); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO_ids[textureId]); + + // copy pixels from PBO to texture object + // Use offset instead of ponter. + if(components == 4) + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_FLOAT, 0); + else + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_FLOAT, 0); + + /////////////////////////////////////////////////// + // it is good idea to release PBOs with ID 0 after use. // Once bound with 0, all pixel operations behave normal ways. glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); From 379eb4961efe0ad6e5b874503587b72631f93e8a Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Fri, 26 Jul 2024 22:12:48 +0200 Subject: [PATCH 2/2] opt: Update textures only when the content has changed Track whether the texture content has changed. This enables to avoid updating the texture every frame if the content hasn't changed. --- src/mvTextureItems.cpp | 14 ++++++++++++-- src/mvTextureItems.h | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/mvTextureItems.cpp b/src/mvTextureItems.cpp index f4036ebc6..342a51fc7 100644 --- a/src/mvTextureItems.cpp +++ b/src/mvTextureItems.cpp @@ -114,6 +114,7 @@ PyObject* mvDynamicTexture::getPyValue() void mvDynamicTexture::setPyValue(PyObject* value) { *_value = ToFloatVect(value); + _updateNeeded = true; } void mvDynamicTexture::setDataSource(mvUUID dataSource) @@ -135,6 +136,7 @@ void mvDynamicTexture::setDataSource(mvUUID dataSource) return; } _value = *static_cast>*>(item->getValue()); + _updateNeeded = true; } void mvDynamicTexture::draw(ImDrawList* drawlist, float x, float y) @@ -151,8 +153,11 @@ void mvDynamicTexture::draw(ImDrawList* drawlist, float x, float y) return; } - UpdateTexture(_texture, _permWidth, _permHeight, *_value); + if (!_updateNeeded) + return; + UpdateTexture(_texture, _permWidth, _permHeight, *_value); + _updateNeeded = false; } void mvDynamicTexture::handleSpecificRequiredArgs(PyObject* dict) @@ -165,6 +170,7 @@ void mvDynamicTexture::handleSpecificRequiredArgs(PyObject* dict) _permHeight = ToInt(PyTuple_GetItem(dict, 1)); config.height = _permHeight; *_value = ToFloatVect(PyTuple_GetItem(dict, 2)); + _updateNeeded = true; } void mvDynamicTexture::handleSpecificKeywordArgs(PyObject* dict) @@ -203,6 +209,7 @@ void mvRawTexture::setPyValue(PyObject* value) { mvThrowPythonError(mvErrorCode::mvTextureNotFound, GetEntityCommand(type), "Texture data not valid", this); } + _updateNeeded = true; } PyBuffer_Release(&buffer_info); if (_buffer) @@ -238,9 +245,12 @@ void mvRawTexture::draw(ImDrawList* drawlist, float x, float y) return; } + if (!_updateNeeded) + return; + if (_componentType == ComponentType::MV_FLOAT_COMPONENT) UpdateRawTexture(_texture, _permWidth, _permHeight, (float*)_value, _components); - + _updateNeeded = false; } void mvRawTexture::handleSpecificRequiredArgs(PyObject* dict) diff --git a/src/mvTextureItems.h b/src/mvTextureItems.h index e3157c04e..0546e3160 100644 --- a/src/mvTextureItems.h +++ b/src/mvTextureItems.h @@ -75,6 +75,7 @@ class mvRawTexture : public mvAppItem void* _value = nullptr; void* _texture = nullptr; bool _dirty = true; + bool _updateNeeded = true; ComponentType _componentType = ComponentType::MV_FLOAT_COMPONENT; int _components = 4; int _permWidth = 0; @@ -106,6 +107,7 @@ class mvDynamicTexture : public mvAppItem std::shared_ptr> _value = std::make_shared>(std::vector{0.0f}); void* _texture = nullptr; bool _dirty = true; + bool _updateNeeded = true; int _permWidth = 0; int _permHeight = 0;