From f15eb9fc0d036378d7e42cb0c32a31c13d20a98e Mon Sep 17 00:00:00 2001 From: John Haddon Date: Tue, 17 Sep 2024 14:22:37 +0100 Subject: [PATCH] ImageGadget : Fix unnecessary texture updates When an image tile doesn't need updating, `Tile::computeUpdate()` still returns an `Update` struct, but with `channelData == null`. When processing that in `Tile::applyUpdates()`, we were zeroing out `Tile::m_channelDataHash`, which would cause the next update to do completely unnecessary work. Now we don't do that. --- Changes.md | 1 + python/GafferImageUITest/ImageGadgetTest.py | 26 +++++++++++++++++++++ src/GafferImageUI/ImageGadget.cpp | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index bd6af8aa179..478183fa984 100644 --- a/Changes.md +++ b/Changes.md @@ -9,6 +9,7 @@ Improvements Fixes ----- +- Viewer, ImageGadget : Fixed unnecessary texture updates when specific image tiles don't change. - Constraint : The `target` browser now shows locations from the `targetScene` if it has an input connection. Before it always showed locations from the main input. - ImageInspector : Fixed broken UI caused by double-clicking in the Image tab. diff --git a/python/GafferImageUITest/ImageGadgetTest.py b/python/GafferImageUITest/ImageGadgetTest.py index 8a947a2ed0e..faadd19264e 100644 --- a/python/GafferImageUITest/ImageGadgetTest.py +++ b/python/GafferImageUITest/ImageGadgetTest.py @@ -34,6 +34,7 @@ # ########################################################################## +import time import unittest import imath @@ -120,5 +121,30 @@ def testStateChangedSignal( self ) : self.assertEqual( len( cs ), 2 ) self.assertNotEqual( gadget.state(), gadget.State.Paused ) + def testNoUnecessaryUpdates( self ) : + + script = Gaffer.ScriptNode() + script["image"] = GafferImage.Checkerboard() + script["image"]["format"].setValue( GafferImage.Format( GafferImage.ImagePlug.tileSize(), GafferImage.ImagePlug.tileSize() ) ) + + gadget = GafferImageUI.ImageGadget() + gadget.setImage( script["image"]["out"] ) + gadget.setContext( script.context() ) + + with GafferUI.Window() as window : + GafferUI.GadgetWidget( gadget ) + + window.setVisible( True ) + while gadget.tileUpdateCount() < 4 : + self.waitForIdle() + + for frame in range( 2, 4 ) : + script.context().setFrame( frame ) + t = time.time() + 0.5 + while time.time() < t : + self.waitForIdle() + + self.assertEqual( gadget.tileUpdateCount(), 4 ) + if __name__ == "__main__": unittest.main() diff --git a/src/GafferImageUI/ImageGadget.cpp b/src/GafferImageUI/ImageGadget.cpp index 378ee47b1f1..00423dec669 100644 --- a/src/GafferImageUI/ImageGadget.cpp +++ b/src/GafferImageUI/ImageGadget.cpp @@ -747,7 +747,7 @@ void ImageGadget::Tile::applyUpdates( const std::vector &updates ) for( const auto &u : updates ) { - if( u.tile ) + if( u.channelData ) { u.tile->m_channelDataToConvert = u.channelData; u.tile->m_channelDataHash = u.channelDataHash;