Skip to content

Commit

Permalink
GafferCycles : Remove and refactor the problematic reset code as we n…
Browse files Browse the repository at this point in the history
…ow only allow scene/session parameters to be set before rendering starts. This will also avoid a mutex lock issue with Windows.
  • Loading branch information
boberfly committed Jan 21, 2023
1 parent a1b6888 commit b71defb
Showing 1 changed file with 84 additions and 113 deletions.
197 changes: 84 additions & 113 deletions src/GafferCycles/IECoreCyclesPreview/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ inline const T *dataCast( const char *name, const IECore::Data *data )
CATEGORY.OPTION = data->readable().c_str(); } \
return; }

void copySocketValues( const ccl::Node &from, ccl::Node &to, bool skipNodeSockets = false )
{
for( const ccl::SocketType &socketType : to.type->inputs )
{
if( skipNodeSockets && socketType.type == ccl::SocketType::NODE )
{
continue;
}
to.copy_value(socketType, from, *from.type->find_input( socketType.name ) );
}
}

} // namespace

//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -760,32 +772,6 @@ class ShaderCache : public IECore::RefCounted
return m_numDefaultShaders;
}

void flushTextures()
{
for( ccl::Shader *shader : m_scene->shaders )
{
for( ccl::ShaderNode *node : shader->graph->nodes )
{
if( node->special_type == ccl::SHADER_SPECIAL_TYPE_IMAGE_SLOT )
{
static_cast<ccl::ImageSlotTextureNode*>( node )->handle.clear();
}
else if( node->type == ccl::SkyTextureNode::get_node_type() )
{
static_cast<ccl::SkyTextureNode*>( node )->handle.clear();
}
else if( node->type == ccl::PointDensityTextureNode::get_node_type() )
{
static_cast<ccl::PointDensityTextureNode*>( node )->handle.clear();
}
//else if( node->type == ccl::VolumeTextureNode::get_node_type() )
//{
// static_cast<ccl::VolumeTextureNode*>( node )->handle.clear();
//}
}
}
}

void removeOSLShaders()
{
ccl::set<ccl::Shader *> remove;
Expand Down Expand Up @@ -2444,12 +2430,14 @@ IECore::InternedString g_progressLevelOptionName( "cycles:progress_level" );
// Session
IECore::InternedString g_experimentalOptionName( "cycles:session:experimental" );
IECore::InternedString g_samplesOptionName( "cycles:session:samples" );
IECore::InternedString g_sampleOffsetOptionName( "cycles:session:sample_offset");
IECore::InternedString g_pixelSizeOptionName( "cycles:session:pixel_size" );
IECore::InternedString g_threadsOptionName( "cycles:session:threads" );
IECore::InternedString g_timeLimitOptionName( "cycles:session:time_limit" );
IECore::InternedString g_useProfilingOptionName( "cycles:session:use_profiling" );
IECore::InternedString g_useAutoTileOptionName( "cycles:session:use_auto_tile" );
IECore::InternedString g_tileSizeOptionName( "cycles:session:tile_size" );
IECore::InternedString g_useResolutionDividerOptionName( "cycles:session:use_resolution_divider");
// Scene
IECore::InternedString g_bvhTypeOptionName( "cycles:scene:bvh_type" );
IECore::InternedString g_bvhLayoutOptionName( "cycles:scene:bvh_layout" );
Expand Down Expand Up @@ -2500,6 +2488,10 @@ IECore::InternedString g_textureBlurGlossyOptionName( "cycles:texture:blur_gloss
IECore::InternedString g_textureUseCustomCachePathOptionName( "cycles:texture:use_custom_cache_path" );
IECore::InternedString g_textureCustomCachePathOptionName( "cycles:texture:custom_cache_path" );

// Some of the session parameters that can be changed in interactive rendering
std::array<IECore::InternedString, 5> g_optionsInteractivelyChangeable =
{{ g_samplesOptionName, g_sampleOffsetOptionName, g_timeLimitOptionName, g_useResolutionDividerOptionName, g_useProfilingOptionName }};

IE_CORE_FORWARDDECLARE( CyclesRenderer )

class CyclesRenderer final : public IECoreScenePreview::Renderer
Expand Down Expand Up @@ -2567,10 +2559,10 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer

init();

m_scene->background->set_transparent( true );
// CyclesOptions will set some values to these.
m_integrator = *(m_scene->integrator);
m_background = *(m_scene->background);
m_scene->background->set_transparent( true );
m_film = *(m_scene->film);

m_cameraCache = new CameraCache();
Expand Down Expand Up @@ -2600,14 +2592,24 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
auto *background = m_scene->background;
auto *film = m_scene->film;

// Error about options that cannot be set while interactive rendering.
// Error about options that cannot be set while in interactive rendering.
if( m_renderState == RENDERSTATE_RENDERING )
{
if( name == g_deviceOptionName ||
bool changeable = false;
for( auto &optionName : g_optionsInteractivelyChangeable )
{
if( optionName == name )
{
changeable = true;
break;
}
}
if( !changeable && (
name == g_deviceOptionName ||
name == g_shadingsystemOptionName ||
boost::starts_with( name.string(), "cycles:session:" ) ||
boost::starts_with( name.string(), "cycles:scene:" ) ||
boost::starts_with( name.string(), "cycles:texture:" ) )
boost::starts_with( name.string(), "cycles:texture:" ) ) )
{
IECore::msg( IECore::Msg::Error, "CyclesRenderer::option", boost::format( "\"%s\" requires a manual render restart." ) % name );
}
Expand Down Expand Up @@ -2856,13 +2858,15 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
}
else if( boost::starts_with( name.string(), "cycles:session:" ) )
{
OPTION(bool, m_sessionParams, g_experimentalOptionName, experimental);
OPTION(int, m_sessionParams, g_samplesOptionName, samples);
OPTION(int, m_sessionParams, g_pixelSizeOptionName, pixel_size);
OPTION(float, m_sessionParams, g_timeLimitOptionName, time_limit);
OPTION(bool, m_sessionParams, g_useProfilingOptionName, use_profiling);
OPTION(bool, m_sessionParams, g_useAutoTileOptionName, use_auto_tile);
OPTION(int, m_sessionParams, g_tileSizeOptionName, tile_size);
OPTION(bool, m_sessionParams, g_experimentalOptionName, experimental);
OPTION(int, m_sessionParams, g_samplesOptionName, samples);
OPTION(int, m_sessionParams, g_sampleOffsetOptionName, sample_offset);
OPTION(int, m_sessionParams, g_pixelSizeOptionName, pixel_size);
OPTION(float, m_sessionParams, g_timeLimitOptionName, time_limit);
OPTION(bool, m_sessionParams, g_useProfilingOptionName, use_profiling);
OPTION(bool, m_sessionParams, g_useAutoTileOptionName, use_auto_tile);
OPTION(int, m_sessionParams, g_tileSizeOptionName, tile_size);
OPTION(bool, m_sessionParams, g_useResolutionDividerOptionName, use_resolution_divider);

IECore::msg( IECore::Msg::Warning, "CyclesRenderer::option", boost::format( "Unknown option \"%s\"." ) % name.string() );
return;
Expand Down Expand Up @@ -3198,8 +3202,13 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
void render() override
{
const IECore::MessageHandler::Scope s( m_messageHandler.get() );

{
// Make sure to apply any scene/session parameters first so we only hard-reset once
// before any rendering starts as we cannot set these after rendering starts.
if( m_renderState != RENDERSTATE_RENDERING )
{
updateSessionParams();
}
std::scoped_lock sceneLock( m_scene->mutex );
if( m_renderState == RENDERSTATE_RENDERING && m_renderType == Interactive )
{
Expand Down Expand Up @@ -3345,15 +3354,13 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
m_attributesCache->clearUnused();
}

void updateSceneObjects( bool newScene = false )
void updateSceneObjects()
{
if( newScene )
if( m_sessionParams.shadingsystem == ccl::SHADINGSYSTEM_SVM && m_shaderCache->hasOSLShader() )
{
// Get all objects held by Gaffer
m_instanceCache->nodesCreated( m_objectsCreated, m_geometryCreated );
m_lightCache->nodesCreated( m_lightsCreated );
IECore::msg( IECore::Msg::Error, "CyclesRenderer", "OSL Shader detected, this will cause problems in a running interactive render" );
m_shaderCache->removeOSLShaders();
}

// Add every shader each time, less issues
m_shaderCache->nodesCreated( m_shadersCreated );

Expand All @@ -3362,12 +3369,44 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
m_shaderCache->update( m_scene, m_shadersCreated );
}

void updateOptions()
void updateSessionParams()
{
#ifdef WITH_CYCLES_TEXTURE_CACHE
m_sceneParams.texture = m_textureCacheParams;
#endif
// Check if an OSL shader exists & set the shadingsystem
if( m_sessionParams.shadingsystem == ccl::SHADINGSYSTEM_SVM && m_shaderCache->hasOSLShader() )
{
IECore::msg( IECore::Msg::Warning, "CyclesRenderer", "OSL Shader detected, forcing OSL shading-system (CPU-only)" );
m_sessionParams.shadingsystem = ccl::SHADINGSYSTEM_OSL;
m_sceneParams.shadingsystem = ccl::SHADINGSYSTEM_OSL;
}

// If anything changes in scene or session, we reset.
if( m_scene->params.modified( m_sceneParams ) ||
m_session->params.modified( m_sessionParams )
)
{
copySocketValues( *(m_scene->integrator), m_integrator );
copySocketValues( *(m_scene->background), m_background );
copySocketValues( *(m_scene->film), m_film );

init();
// Re-apply the settings for these.
// Skip "node" types as this would be copying a stale pointer eg. the shader
// for background that should be "default_background" at this stage
// which potentially will be set later to something else in `updateOptions()` anyways.
copySocketValues( m_integrator, *(m_scene->integrator), true );
copySocketValues( m_background, *(m_scene->background), true );
copySocketValues( m_film, *(m_scene->film), true );

m_scene->integrator->tag_update( m_scene, ccl::Integrator::UPDATE_ALL );
m_scene->background->tag_update( m_scene );
}
}

void updateOptions()
{
ccl::Integrator *integrator = m_scene->integrator;
ccl::Background *background = m_scene->background;

Expand Down Expand Up @@ -3421,38 +3460,9 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer

if( film->is_modified() )
{
//film->tag_update( m_scene );
integrator->tag_update( m_scene, ccl::Integrator::UPDATE_ALL );
m_film = *film;
}

// Check if an OSL shader exists & set the shadingsystem
if( m_sessionParams.shadingsystem == ccl::SHADINGSYSTEM_SVM && m_shaderCache->hasOSLShader() )
{
if( m_renderState != RENDERSTATE_RENDERING )
{
IECore::msg( IECore::Msg::Warning, "CyclesRenderer", "OSL Shader detected, forcing OSL shading-system (CPU-only)" );
m_sessionParams.shadingsystem = ccl::SHADINGSYSTEM_OSL;
m_sceneParams.shadingsystem = ccl::SHADINGSYSTEM_OSL;
}
else
{
IECore::msg( IECore::Msg::Error, "CyclesRenderer", "OSL Shader detected, this will cause problems in a running interactive render" );
m_shaderCache->removeOSLShaders();
}
}

// If anything changes in scene or session, we reset.
if( m_scene->params.modified( m_sceneParams ) ||
m_session->params.modified( m_sessionParams )
)
{
// Flag it true here so that we never mutex unlock a different scene pointer due to the reset
if( m_renderState != RENDERSTATE_RENDERING )
{
reset();
}
}
}

void updateOutputs()
Expand Down Expand Up @@ -3667,45 +3677,6 @@ class CyclesRenderer final : public IECoreScenePreview::Renderer
m_outputsChanged = false;
}

void reset()
{
m_session->cancel();
m_renderState = RENDERSTATE_READY;
// This is so cycles doesn't delete the objects that Gaffer manages.
m_scene->objects.clear();
m_scene->geometry.clear();
m_shaderCache->flushTextures();
m_scene->shaders.resize( m_shaderCache->numDefaultShaders() );
m_scene->lights.clear();

init();

// Re-apply the settings for these.
for( const ccl::SocketType &socketType : m_scene->integrator->type->inputs )
{
m_scene->integrator->copy_value(socketType, m_integrator, *m_integrator.type->find_input( socketType.name ) );
}
for( const ccl::SocketType &socketType : m_scene->background->type->inputs )
{
m_scene->background->copy_value(socketType, m_background, *m_background.type->find_input( socketType.name ) );
}
for( const ccl::SocketType &socketType : m_scene->film->type->inputs )
{
m_scene->film->copy_value(socketType, m_film, *m_film.type->find_input( socketType.name ) );
}

m_scene->background->set_shader( m_scene->default_background );

m_scene->shader_manager->tag_update( m_scene, ccl::ShaderManager::UPDATE_ALL );
m_scene->integrator->tag_update( m_scene, ccl::Integrator::UPDATE_ALL );
m_scene->background->tag_update( m_scene );

m_session->stats.mem_peak = m_session->stats.mem_used;
// Make sure the instance cache points to the right scene.
updateSceneObjects( true );
m_scene->geometry_manager->tag_update( m_scene, ccl::GeometryManager::UPDATE_ALL );
}

void updateCamera()
{
// Check that the camera we want to use exists,
Expand Down

0 comments on commit b71defb

Please sign in to comment.