From 22c106e42c9d35b3c6fc55ad48b7c416ee5420eb Mon Sep 17 00:00:00 2001 From: John Haddon Date: Fri, 30 Aug 2024 10:40:44 +0100 Subject: [PATCH] Cycles Viewer Settings : Add `device` option This allows Cycles GPU rendering to be enabled in the Gaffer viewport. --- Changes.md | 5 +++ python/GafferCyclesUI/CyclesOptionsUI.py | 32 +++++++++++++++++++ startup/gui/cyclesViewerSettings.gfr | 40 ++++++++++++++++-------- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/Changes.md b/Changes.md index 855b13dd5ae..8bd57cfd402 100644 --- a/Changes.md +++ b/Changes.md @@ -1,6 +1,11 @@ 1.4.x.x (relative to 1.4.11.0) ======= +Features +-------- + +- Viewer : Added support for Cycles GPU renderering via a new Device option in the Cycles viewer settings. + Improvements ------------ diff --git a/python/GafferCyclesUI/CyclesOptionsUI.py b/python/GafferCyclesUI/CyclesOptionsUI.py index 339cd4fce9e..1dfd883a0ff 100644 --- a/python/GafferCyclesUI/CyclesOptionsUI.py +++ b/python/GafferCyclesUI/CyclesOptionsUI.py @@ -1481,3 +1481,35 @@ def __registerDevicePresets() : for _pass in GafferCycles.passes.keys(): Gaffer.Metadata.registerValue( GafferCycles.CyclesOptions, "options.displayPass.value", "preset:%s" % _pass.replace( "_", " " ).title(), "%s" % _pass ) + +# Used by `startup/gui/cyclesViewerSettings.gfr`. +class ViewerDevicePlugValueWidget( GafferUI.PresetsPlugValueWidget ) : + + def __init__( self, plugs, **kw ) : + + GafferUI.PresetsPlugValueWidget.__init__( self, plugs, **kw ) + + self.getPlug().node().plugSetSignal().connect( Gaffer.WeakMethod( self.__plugSet ), scoped = False ) + + def __plugSet( self, plug ) : + + if plug != self.getPlug() : + return + + if plug.getValue() != "CPU" : + # Switch to SVM shading to prevent CyclesRenderer falling back + # to CPU shading due to OSL not being available. + ## \todo Change CyclesRenderer to fall back to SVM rather than + # fall back to CPU. + plug.parent()["shadingSystem"].setValue( "SVM" ) + + # Cycles can't switch device after render has started, so we need to + # force a restart (somewhat hackily). This does cause the SceneView to + # create and destroy an OpenGL renderer unnecessarily, but it doesn't + # actually get populated with a scene because that doesn't happen until + # the viewport is drawn, and we've switched back to Cycles before that + # happens. + + if plug.node()["renderer"]["name"].getValue() == "Cycles" : + plug.node()["renderer"]["name"].setValue( "OpenGL" ) + plug.node()["renderer"]["name"].setValue( "Cycles" ) diff --git a/startup/gui/cyclesViewerSettings.gfr b/startup/gui/cyclesViewerSettings.gfr index e374e0c5b48..a7add5f0225 100644 --- a/startup/gui/cyclesViewerSettings.gfr +++ b/startup/gui/cyclesViewerSettings.gfr @@ -7,8 +7,8 @@ import IECore import imath Gaffer.Metadata.registerValue( parent, "serialiser:milestoneVersion", 1, persistent=False ) -Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 1, persistent=False ) -Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 0, persistent=False ) +Gaffer.Metadata.registerValue( parent, "serialiser:majorVersion", 4, persistent=False ) +Gaffer.Metadata.registerValue( parent, "serialiser:minorVersion", 11, persistent=False ) Gaffer.Metadata.registerValue( parent, "serialiser:patchVersion", 0, persistent=False ) __children = {} @@ -76,8 +76,8 @@ __children["ViewerSettings"]["Dot2"].addChild( Gaffer.V2fPlug( "__uiPosition", d __children["ViewerSettings"].addChild( Gaffer.Dot( "Dot3" ) ) __children["ViewerSettings"]["Dot3"].setup( GafferScene.ScenePlug( "in", ) ) __children["ViewerSettings"]["Dot3"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) -__children["ViewerSettings"].addChild( GafferCycles.CyclesOptions( "ShadingSystem" ) ) -__children["ViewerSettings"]["ShadingSystem"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) +__children["ViewerSettings"].addChild( GafferCycles.CyclesOptions( "DeviceOptions" ) ) +__children["ViewerSettings"]["DeviceOptions"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["ViewerSettings"].addChild( Gaffer.StringPlug( "shadingSystem", defaultValue = 'OSL', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) __children["ViewerSettings"].addChild( GafferCycles.CyclesOptions( "CyclesOptions" ) ) __children["ViewerSettings"]["CyclesOptions"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) @@ -113,7 +113,10 @@ __children["ViewerSettings"]["convert_float_to_vector"].addChild( Gaffer.V2fPlug __children["ViewerSettings"].addChild( GafferCycles.CyclesShader( "attribute" ) ) __children["ViewerSettings"]["attribute"].loadShader( "attribute" ) __children["ViewerSettings"]["attribute"].addChild( Gaffer.V2fPlug( "__uiPosition", defaultValue = imath.V2f( 0, 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) -parent["variables"]["imageCataloguePort"]["value"].setValue( 46035 ) +__children["ViewerSettings"].addChild( Gaffer.StringPlug( "device", defaultValue = 'CPU', flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) +__children["openColorIO"] = GafferImage.OpenColorIOConfigPlug( "openColorIO", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) +parent.addChild( __children["openColorIO"] ) +parent["variables"]["imageCataloguePort"]["value"].setValue( 45169 ) Gaffer.Metadata.registerValue( parent["variables"]["imageCataloguePort"], 'readOnly', True ) Gaffer.Metadata.registerValue( parent["variables"]["projectName"]["name"], 'readOnly', True ) Gaffer.Metadata.registerValue( parent["variables"]["projectRootDirectory"]["name"], 'readOnly', True ) @@ -212,6 +215,8 @@ __children["ViewerSettings"]["Backdrop3"]["title"].setValue( 'Subdivision' ) __children["ViewerSettings"]["Backdrop3"]["__uiPosition"].setValue( imath.V2f( -4.19273949, -78.3058624 ) ) __children["ViewerSettings"]["Backdrop3"]["__uiBound"].setValue( imath.Box2f( imath.V2f( -35.9162979, -39.3382263 ), imath.V2f( 42.9688263, 18.8090897 ) ) ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["enableDisplacement"], 'nodule:type', '' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["enableDisplacement"], 'layout:section', 'Settings' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["enableDisplacement"], 'layout:index', 4 ) __children["ViewerSettings"]["LightingOptions"]["in"].setInput( __children["ViewerSettings"]["ShadingSwitch"]["out"]["value"] ) __children["ViewerSettings"]["LightingOptions"]["options"]["maxBounce"].setInput( __children["ViewerSettings"]["LightingSpreadsheet"]["out"]["maxBounce"] ) __children["ViewerSettings"]["LightingOptions"]["__uiPosition"].setValue( imath.V2f( -4.19273949, -47.7442284 ) ) @@ -245,18 +250,19 @@ Gaffer.Metadata.registerValue( __children["ViewerSettings"]["Dot2"]["out"], 'nod __children["ViewerSettings"]["Dot2"]["__uiPosition"].setValue( imath.V2f( 44.500988, 26.1189766 ) ) __children["ViewerSettings"]["Dot3"]["in"].setInput( __children["ViewerSettings"]["PreviewAssignment"]["out"] ) __children["ViewerSettings"]["Dot3"]["__uiPosition"].setValue( imath.V2f( 44.500988, -19.2901993 ) ) -Gaffer.Metadata.registerValue( __children["ViewerSettings"]["ShadingSystem"], 'annotation:user:text', 'SVM most likely is more stable' ) -Gaffer.Metadata.registerValue( __children["ViewerSettings"]["ShadingSystem"], 'annotation:user:color', imath.Color3f( 0.150000006, 0.25999999, 0.25999999 ) ) -__children["ViewerSettings"]["ShadingSystem"]["in"].setInput( __children["ViewerSettings"]["SamplingOptions"]["out"] ) -__children["ViewerSettings"]["ShadingSystem"]["options"]["device"]["enabled"].setValue( True ) -__children["ViewerSettings"]["ShadingSystem"]["options"]["shadingSystem"]["enabled"].setValue( True ) -__children["ViewerSettings"]["ShadingSystem"]["options"]["shadingSystem"]["value"].setInput( __children["ViewerSettings"]["shadingSystem"] ) -__children["ViewerSettings"]["ShadingSystem"]["__uiPosition"].setValue( imath.V2f( -4.19273949, -133.140945 ) ) +__children["ViewerSettings"]["DeviceOptions"]["in"].setInput( __children["ViewerSettings"]["SamplingOptions"]["out"] ) +__children["ViewerSettings"]["DeviceOptions"]["options"]["device"]["enabled"].setValue( True ) +__children["ViewerSettings"]["DeviceOptions"]["options"]["shadingSystem"]["enabled"].setValue( True ) +__children["ViewerSettings"]["DeviceOptions"]["options"]["device"]["value"].setInput( __children["ViewerSettings"]["device"] ) +__children["ViewerSettings"]["DeviceOptions"]["options"]["shadingSystem"]["value"].setInput( __children["ViewerSettings"]["shadingSystem"] ) +__children["ViewerSettings"]["DeviceOptions"]["__uiPosition"].setValue( imath.V2f( -4.19273949, -133.140945 ) ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'nodule:type', '' ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'plugValueWidget:type', 'GafferUI.PresetsPlugValueWidget' ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'preset:OSL', 'OSL' ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'preset:SVM', 'SVM' ) -__children["ViewerSettings"]["CyclesOptions"]["in"].setInput( __children["ViewerSettings"]["ShadingSystem"]["out"] ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'layout:section', 'Settings' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["shadingSystem"], 'layout:index', 6 ) +__children["ViewerSettings"]["CyclesOptions"]["in"].setInput( __children["ViewerSettings"]["DeviceOptions"]["out"] ) __children["ViewerSettings"]["CyclesOptions"]["options"]["textureLimit"]["enabled"].setValue( True ) __children["ViewerSettings"]["CyclesOptions"]["options"]["textureLimit"]["value"].setInput( __children["ViewerSettings"]["Expression5"]["__out"]["p0"] ) __children["ViewerSettings"]["CyclesOptions"]["__uiPosition"].setValue( imath.V2f( -4.19273949, -151.521561 ) ) @@ -272,6 +278,9 @@ Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'preset:2048', 5 ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'preset:4096', 6 ) Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'preset:8192', 7 ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'layout:section', 'Settings' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'layout:index', 7 ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["textureSizeLimit"], 'nodule:type', '' ) __children["ViewerSettings"]["object_info"]["__uiPosition"].setValue( imath.V2f( -69.403717, 17.8482647 ) ) __children["ViewerSettings"]["diffuse_bsdf"]["parameters"]["color"].setInput( __children["ViewerSettings"]["object_info"]["out"]["color"] ) __children["ViewerSettings"]["diffuse_bsdf"]["__uiPosition"].setValue( imath.V2f( 17.4492283, 17.8482647 ) ) @@ -296,6 +305,11 @@ __children["ViewerSettings"]["convert_float_to_vector"]["parameters"]["value_flo __children["ViewerSettings"]["convert_float_to_vector"]["__uiPosition"].setValue( imath.V2f( -72.9163971, -6.86891985 ) ) __children["ViewerSettings"]["attribute"]["parameters"]["attribute"].setValue( 'Cs' ) __children["ViewerSettings"]["attribute"]["__uiPosition"].setValue( imath.V2f( -69.4365692, 27.8806839 ) ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["device"], 'plugValueWidget:type', 'GafferCyclesUI.CyclesOptionsUI.ViewerDevicePlugValueWidget' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["device"], 'presetsPlugValueWidget:allowCustom', True ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["device"], 'layout:section', 'Settings' ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["device"], 'layout:index', 5 ) +Gaffer.Metadata.registerValue( __children["ViewerSettings"]["device"], 'nodule:type', '' ) __children["ViewerSettings"]["Expression3"]["__engine"].setValue( 'OSL' ) __children["ViewerSettings"]["Expression3"]["__expression"].setValue( 'parent.__out.p0 = !parent.__in.p0;' ) __children["ViewerSettings"]["Expression5"]["__engine"].setValue( 'OSL' )