Skip to content

DiskBlur #6529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 16, 2025
Merged

DiskBlur #6529

merged 1 commit into from
Aug 16, 2025

Conversation

danieldresser-ie
Copy link
Contributor

It's been a bit of a scramble to turn this from research code to something properly tested and reasonably cleanly layed out.

I'm now feeling fairly good about the reliability and overall organization of this code. There are definitely still some of the lower level parts that could use more comments ( like applyScanlinesHalfKernel and the compute() for scanlinesLUTPlug() ), but I know I've already spent too long cleaning this up. Hopefully the overall state is somewhere where it can be reviewed somewhat productively.

Copy link
Member

@johnhaddon johnhaddon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Daniel! Seems to be working nicely in my limited testing, and at a pleasing speed.

I've taken a top-down approach to review, mostly commenting on the user-visible stuff and the overall code structure. I see you have a bunch of TODO items for documenting specific functions/sections, but I think what would be more valuable would be some higher-level introductory description about the overall strategy.

Like I say though, seems to be working well, so I don't think we should spend too much time reorganising. If my suggestions about object-orienting things like the scanline LUT don't chime with you, then let's just add some high-level commenting and move on.

Cheers...
John

@murraystevenson
Copy link
Contributor

I've run into a crash in DiskBlur::computeChannelData() if you have set the planeDividers plug and then try to blur an image with no alpha channel. Disabling the Shuffle in the script below should trigger it.

import Gaffer
import GafferImage
import IECore
import imath

Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 1, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 6, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 0, persistent=False )
Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 0, persistent=False )

__children = {}

__children["DiskBlur"] = GafferImage.DiskBlur( "DiskBlur" )
parent.addChild( __children["DiskBlur"] )
__children["DiskBlur"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Macaw"] = GafferImage.ImageReader( "Macaw" )
parent.addChild( __children["Macaw"] )
__children["Macaw"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Shuffle"] = GafferImage.Shuffle( "Shuffle" )
parent.addChild( __children["Shuffle"] )
__children["Shuffle"]["shuffles"].addChild( Gaffer.ShufflePlug( "shuffle0", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["Shuffle"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) )
__children["DiskBlur"]["in"].setInput( __children["Shuffle"]["out"] )
__children["DiskBlur"]["radius"].setValue( 25.0 )
__children["DiskBlur"]["planeDividers"].setValue( IECore.FloatVectorData( [ -32, -16, -8, -4, -2, -1, 1, 2, 4, 8, 16, 32 ] ) )
__children["DiskBlur"]["__uiPosition"].setValue( imath.V2f( 2.35000038, -5.0500021 ) )
__children["Macaw"]["fileName"].setValue( '${GAFFER_ROOT}/resources/images/macaw.exr' )
__children["Macaw"]["__uiPosition"].setValue( imath.V2f( 2.35000038, 10.4500017 ) )
__children["Shuffle"]["in"].setInput( __children["Macaw"]["out"] )
__children["Shuffle"]["shuffles"]["shuffle0"]["source"].setValue( '__white' )
__children["Shuffle"]["shuffles"]["shuffle0"]["destination"].setValue( 'A' )
__children["Shuffle"]["__uiPosition"].setValue( imath.V2f( 2.35000038, 3.11406064 ) )


del __children

@danieldresser-ie
Copy link
Contributor Author

I've run into a crash in DiskBlur::computeChannelDat

Addressed in 7b997ae

@danieldresser-ie
Copy link
Contributor Author

Finished the documentation / cleanup pass on the low level details.

@johnhaddon
Copy link
Member

Thanks for the update Daniel - I've gone through it all and closed the relevant conversations, and added comments to a few others.

@danieldresser-ie
Copy link
Contributor Author

Addressed all remaining comments, plus two commits optimizing computeScanlinesLUT: 4bb69b0, 1600519, and a final commit adding a Changelog entry.

To the best of my knowledge, this should be good to merge, aside from not having been squashed yet - it will be a trivial squash, everything just goes into one commit.

@johnhaddon
Copy link
Member

johnhaddon commented Aug 15, 2025

Thanks Daniel - I've replied to a couple of things inline, but I think we're close enough to merge if needs be. Seems worth getting into today's alpha release either way...

Comment on lines 1892 to 1895
// It shouldn't be necessary to hash the maxRadiusPlug here, since we include it's actual value in
// the hash below ... but for some reason, removing this line shows a 10% degradation in one
// performance. Hashing the maxRadius in twice isn't hurting anything.
maxRadiusPlug()->hash( h );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's vexing - any theory as to why? hashChannelData() isn't even called that often, so I'm struggling to see why this would be so at all.

Comment on lines 1733 to 2097
void DiskBlur::hashDeep( const GafferImage::ImagePlug *parent, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
ImageProcessor::hashDeep( parent, context, h );
h.append( false );
}

bool DiskBlur::computeDeep( const Gaffer::Context *context, const ImagePlug *parent ) const
{
return false;
}

void DiskBlur::hashSampleOffsets( const GafferImage::ImagePlug *parent, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
h = ImagePlug::flatTileSampleOffsets()->Object::hash();
}

IECore::ConstIntVectorDataPtr DiskBlur::computeSampleOffsets( const Imath::V2i &tileOrigin, const Gaffer::Context *context, const ImagePlug *parent ) const
{
return ImagePlug::flatTileSampleOffsets();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it makes sense to just have these be pass-through connections from the input

I perhaps wasn't clear enough, but by "these" I was referring to hash/computeSampleOffsets() too.

@danieldresser-ie danieldresser-ie force-pushed the diskBlur branch 2 times, most recently from 7012521 to ea91464 Compare August 15, 2025 17:41
@danieldresser-ie
Copy link
Contributor Author

Addressed final round of minor feedback, and squashed so it's ready to merge.

@murraystevenson murraystevenson merged commit c074484 into GafferHQ:main Aug 16, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants