Skip to content

Commit

Permalink
Capsule, RenderController : Preserve ABI compatibility
Browse files Browse the repository at this point in the history
Although the members in question are private, we still need to preserve `sizeof( Capsule )` and `sizeof( RenderController )` if we are to include the RenderOptions changes in `1.3.x`. We'll revert this commit as soon as it is merged to main, so `1.4` will get a cleaner version of the code.
  • Loading branch information
johnhaddon committed Sep 28, 2023
1 parent 3c84f70 commit 2daface
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 31 deletions.
1 change: 0 additions & 1 deletion include/GafferScene/Capsule.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ class GAFFERSCENE_API Capsule : public IECoreScenePreview::Procedural
const ScenePlug *m_scene;
ScenePlug::ScenePath m_root;
Gaffer::ConstContextPtr m_context;
std::optional<GafferScene::Private::RendererAlgo::RenderOptions> m_renderOptions;

};

Expand Down
10 changes: 9 additions & 1 deletion include/GafferScene/RenderController.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ class GAFFERSCENE_API RenderController : public Gaffer::Signals::Trackable
AllGlobalComponents = GlobalsGlobalComponent | SetsGlobalComponent | RenderSetsGlobalComponent | CameraOptionsGlobalComponent | TransformBlurGlobalComponent | DeformationBlurGlobalComponent | IncludedPurposesGlobalComponent
};

struct Unused
{
bool unused1;
bool unused2;
Imath::V2f unused3;
};

void plugDirtied( const Gaffer::Plug *plug );
void contextChanged( const IECore::InternedString &name );
void requestUpdate();
Expand Down Expand Up @@ -159,7 +166,8 @@ class GAFFERSCENE_API RenderController : public Gaffer::Signals::Trackable
std::vector<std::unique_ptr<SceneGraph> > m_sceneGraphs;
unsigned m_dirtyGlobalComponents;
unsigned m_changedGlobalComponents;
Private::RendererAlgo::RenderOptions m_renderOptions;
std::unique_ptr<Private::RendererAlgo::RenderOptions> m_renderOptions;
Unused m_unused;
Private::RendererAlgo::RenderSets m_renderSets;
std::unique_ptr<Private::RendererAlgo::LightLinks> m_lightLinks;
IECoreScenePreview::Renderer::ObjectInterfacePtr m_defaultCamera;
Expand Down
32 changes: 24 additions & 8 deletions src/GafferScene/Capsule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

#include "boost/bind/bind.hpp"

#include <mutex>

using namespace boost::placeholders;
using namespace IECore;
using namespace IECoreScene;
Expand All @@ -53,6 +55,7 @@ using namespace GafferScene;

namespace
{

Gaffer::Context *capsuleContext( const Context &context )
{
Gaffer::Context *result = new Gaffer::Context( context );
Expand All @@ -62,6 +65,10 @@ namespace
result->remove( ScenePlug::scenePathContextName );
return result;
}

std::mutex g_renderOptionsMutex;
std::unordered_map<const Capsule *, Private::RendererAlgo::RenderOptions> g_renderOptions;

}

IE_CORE_DEFINEOBJECTTYPEDESCRIPTION( Capsule );
Expand All @@ -84,6 +91,8 @@ Capsule::Capsule(

Capsule::~Capsule()
{
std::unique_lock renderOptionsLock( g_renderOptionsMutex );
g_renderOptions.erase( this );
}

bool Capsule::isEqualTo( const IECore::Object *other ) const
Expand All @@ -104,14 +113,14 @@ void Capsule::hash( IECore::MurmurHash &h ) const
Procedural::hash( h );
h.append( m_hash );

if( m_renderOptions )
if( auto renderOptions = getRenderOptions() )
{
// Hash only what affects our rendering, not everything in
// `RenderOptions::globals`.
h.append( m_renderOptions->transformBlur );
h.append( m_renderOptions->deformationBlur );
h.append( m_renderOptions->shutter );
m_renderOptions->includedPurposes->hash( h );
h.append( renderOptions->transformBlur );
h.append( renderOptions->deformationBlur );
h.append( renderOptions->shutter );
renderOptions->includedPurposes->hash( h );
}
}

Expand Down Expand Up @@ -157,7 +166,7 @@ void Capsule::render( IECoreScenePreview::Renderer *renderer ) const
{
throwIfNoScene();
ScenePlug::GlobalScope scope( m_context.get() );
std::optional<GafferScene::Private::RendererAlgo::RenderOptions> renderOptions = m_renderOptions;
std::optional<GafferScene::Private::RendererAlgo::RenderOptions> renderOptions = getRenderOptions();
if( !renderOptions )
{
renderOptions = GafferScene::Private::RendererAlgo::RenderOptions( m_scene );
Expand Down Expand Up @@ -189,12 +198,19 @@ void Capsule::setRenderOptions( const GafferScene::Private::RendererAlgo::Render
// This is not pretty, but it allows the capsule to render with the correct
// motion blur and `includedPurposes`, taken from the downstream node being
// rendered rather than from the capsule's own globals.
m_renderOptions = renderOptions;
std::unique_lock renderOptionsLock( g_renderOptionsMutex );
g_renderOptions[this] = renderOptions;
}

std::optional<GafferScene::Private::RendererAlgo::RenderOptions> Capsule::getRenderOptions() const
{
return m_renderOptions;
std::unique_lock renderOptionsLock( g_renderOptionsMutex );
auto it = g_renderOptions.find( this );
if( it != g_renderOptions.end() )
{
return it->second;
}
return std::nullopt;
}

void Capsule::throwIfNoScene() const
Expand Down
43 changes: 22 additions & 21 deletions src/GafferScene/RenderController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ class RenderController::SceneGraph
// Root - get attributes from globals.
if( changedGlobals & GlobalsGlobalComponent )
{
if( updateAttributes( controller->m_renderOptions.globals.get() ) )
if( updateAttributes( controller->m_renderOptions->globals.get() ) )
{
m_changedComponents |= AttributesComponent;
}
Expand All @@ -401,15 +401,15 @@ class RenderController::SceneGraph
// If attributes have changed, need to check if this has affected our motion sample times
if( ( m_changedComponents & AttributesComponent ) || ( changedGlobals & TransformBlurGlobalComponent ) )
{
if( Private::RendererAlgo::transformMotionTimes( controller->m_renderOptions, m_fullAttributes.get(), m_transformTimes ) )
if( Private::RendererAlgo::transformMotionTimes( *controller->m_renderOptions, m_fullAttributes.get(), m_transformTimes ) )
{
m_dirtyComponents |= TransformComponent;
}
}

if( ( m_changedComponents & AttributesComponent ) || ( changedGlobals & DeformationBlurGlobalComponent ) )
{
if( Private::RendererAlgo::deformationMotionTimes( controller->m_renderOptions, m_fullAttributes.get(), m_deformationTimes ) )
if( Private::RendererAlgo::deformationMotionTimes( *controller->m_renderOptions, m_fullAttributes.get(), m_deformationTimes ) )
{
m_dirtyComponents |= ObjectComponent;
}
Expand Down Expand Up @@ -442,7 +442,7 @@ class RenderController::SceneGraph
if( ( m_changedComponents & AttributesComponent ) || ( changedGlobals & IncludedPurposesGlobalComponent ) )
{
const bool purposeIncludedPreviously = m_purposeIncluded;
m_purposeIncluded = controller->m_renderOptions.purposeIncluded( m_fullAttributes.get() );
m_purposeIncluded = controller->m_renderOptions->purposeIncluded( m_fullAttributes.get() );
if( m_purposeIncluded != purposeIncludedPreviously )
{
// We'll need to hide or show the object by considering `m_purposeIncluded` in
Expand Down Expand Up @@ -487,7 +487,7 @@ class RenderController::SceneGraph
m_objectHash = MurmurHash();
}

if( ( m_dirtyComponents & ObjectComponent ) && updateObject( controller->m_scene->objectPlug(), type, controller->m_renderer.get(), controller->m_renderOptions, controller->m_scene.get(), controller->m_lightLinks.get() ) )
if( ( m_dirtyComponents & ObjectComponent ) && updateObject( controller->m_scene->objectPlug(), type, controller->m_renderer.get(), *controller->m_renderOptions, controller->m_scene.get(), controller->m_lightLinks.get() ) )
{
m_changedComponents |= ObjectComponent;
}
Expand All @@ -511,7 +511,7 @@ class RenderController::SceneGraph
{
// Failed to apply attributes - must replace entire object.
m_objectHash = MurmurHash();
if( updateObject( controller->m_scene->objectPlug(), type, controller->m_renderer.get(), controller->m_renderOptions, controller->m_scene.get(), controller->m_lightLinks.get() ) )
if( updateObject( controller->m_scene->objectPlug(), type, controller->m_renderer.get(), *controller->m_renderOptions, controller->m_scene.get(), controller->m_lightLinks.get() ) )
{
m_changedComponents |= ObjectComponent;
controller->m_failedAttributeEdits++;
Expand Down Expand Up @@ -1347,7 +1347,8 @@ RenderController::RenderController( const ConstScenePlugPtr &scene, const Gaffer
m_updateRequested( false ),
m_failedAttributeEdits( 0 ),
m_dirtyGlobalComponents( NoGlobalComponent ),
m_changedGlobalComponents( NoGlobalComponent )
m_changedGlobalComponents( NoGlobalComponent ),
m_renderOptions( make_unique<Private::RendererAlgo::RenderOptions>() )
{
for( int i = SceneGraph::FirstType; i <= SceneGraph::LastType; ++i )
{
Expand Down Expand Up @@ -1627,43 +1628,43 @@ void RenderController::updateInternal( const ProgressCallback &callback, const I
if( m_dirtyGlobalComponents & GlobalsGlobalComponent )
{
RenderOptions renderOptions( m_scene.get() );
Private::RendererAlgo::outputOptions( renderOptions.globals.get(), m_renderOptions.globals.get(), m_renderer.get() );
Private::RendererAlgo::outputOutputs( m_scene.get(), renderOptions.globals.get(), m_renderOptions.globals.get(), m_renderer.get() );
if( *renderOptions.globals != *m_renderOptions.globals )
Private::RendererAlgo::outputOptions( renderOptions.globals.get(), m_renderOptions->globals.get(), m_renderer.get() );
Private::RendererAlgo::outputOutputs( m_scene.get(), renderOptions.globals.get(), m_renderOptions->globals.get(), m_renderer.get() );
if( *renderOptions.globals != *m_renderOptions->globals )
{
m_changedGlobalComponents |= GlobalsGlobalComponent;
}
if( cameraGlobalsChanged( renderOptions.globals.get(), m_renderOptions.globals.get(), m_scene.get() ) )
if( cameraGlobalsChanged( renderOptions.globals.get(), m_renderOptions->globals.get(), m_scene.get() ) )
{
m_changedGlobalComponents |= CameraOptionsGlobalComponent;
}
if( *renderOptions.includedPurposes != *m_renderOptions.includedPurposes )
if( *renderOptions.includedPurposes != *m_renderOptions->includedPurposes )
{
m_changedGlobalComponents |= IncludedPurposesGlobalComponent;
}
if( renderOptions.shutter != m_renderOptions.shutter || renderOptions.transformBlur != m_renderOptions.transformBlur )
if( renderOptions.shutter != m_renderOptions->shutter || renderOptions.transformBlur != m_renderOptions->transformBlur )
{
m_changedGlobalComponents |= TransformBlurGlobalComponent;
}
if( renderOptions.shutter != m_renderOptions.shutter || renderOptions.deformationBlur != m_renderOptions.deformationBlur )
if( renderOptions.shutter != m_renderOptions->shutter || renderOptions.deformationBlur != m_renderOptions->deformationBlur )
{
m_changedGlobalComponents |= DeformationBlurGlobalComponent;
}
if( renderOptions.shutter != m_renderOptions.shutter )
if( renderOptions.shutter != m_renderOptions->shutter )
{
m_changedGlobalComponents |= CameraOptionsGlobalComponent;
}
m_renderOptions = renderOptions;
*m_renderOptions = renderOptions;
}

if( ( m_dirtyGlobalComponents & CameraShutterGlobalComponent ) && !( m_dirtyGlobalComponents & GlobalsGlobalComponent ) )
{
// Shutter override from a camera may have changed, and won't have been covered by
// the block above (because the globals weren't dirty).
const V2f shutter = SceneAlgo::shutter( m_renderOptions.globals.get(), m_scene.get() );
if( shutter != m_renderOptions.shutter )
const V2f shutter = SceneAlgo::shutter( m_renderOptions->globals.get(), m_scene.get() );
if( shutter != m_renderOptions->shutter )
{
m_renderOptions.shutter = shutter;
m_renderOptions->shutter = shutter;
m_changedGlobalComponents |= ( DeformationBlurGlobalComponent | TransformBlurGlobalComponent );
}
}
Expand Down Expand Up @@ -1774,15 +1775,15 @@ void RenderController::updateDefaultCamera()
return;
}

const StringData *cameraOption = m_renderOptions.globals->member<StringData>( g_cameraGlobalName );
const StringData *cameraOption = m_renderOptions->globals->member<StringData>( g_cameraGlobalName );
m_defaultCamera = nullptr;
if( cameraOption && !cameraOption->readable().empty() )
{
return;
}

CameraPtr defaultCamera = new IECoreScene::Camera;
SceneAlgo::applyCameraGlobals( defaultCamera.get(), m_renderOptions.globals.get(), m_scene.get() );
SceneAlgo::applyCameraGlobals( defaultCamera.get(), m_renderOptions->globals.get(), m_scene.get() );
IECoreScenePreview::Renderer::AttributesInterfacePtr defaultAttributes = m_renderer->attributes( m_scene->attributesPlug()->defaultValue() );
ConstStringDataPtr name = new StringData( "gaffer:defaultCamera" );
m_defaultCamera = m_renderer->camera( name->readable(), defaultCamera.get(), defaultAttributes.get() );
Expand Down

0 comments on commit 2daface

Please sign in to comment.