Skip to content

Commit

Permalink
Merge pull request #50 from JenusL/feat/optix_display
Browse files Browse the repository at this point in the history
Full OptiX Denoiser support
  • Loading branch information
sjannuz authored Dec 27, 2018
2 parents 2c4ae83 + 1d7b957 commit fa93108
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 32 deletions.
27 changes: 27 additions & 0 deletions plugins/sitoa/common/Tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,33 @@ CString CStringUtilities::GetMasterBaseNodeName(CString &in_name)
return splits[count-1];
}


// Return true or false if string starts with substring
//
// @param in_string The input string
// @param in_subString The start string
//
// @return true or false
//
bool CStringUtilities::StartsWith(CString in_string, CString in_subString)
{
return (in_string.FindString(in_subString) == 0);
}


// Return true or false if string ends with substring
//
// @param in_string The input string
// @param in_subString The end string
//
// @return true or false
//
bool CStringUtilities::EndsWith(CString in_string, CString in_subString)
{
return (in_string.ReverseFindString(in_subString) == (in_string.Length() - in_subString.Length()));
}


////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions plugins/sitoa/common/Tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ class CStringUtilities
CString GetSoftimageNameFromSItoAName(CString &in_nane);
// Return the name of the master node of a ginstance or a cloned light
CString GetMasterBaseNodeName(CString &in_name);
// Checks if string starts with substring
bool StartsWith(CString in_string, CString in_subString);
// Checks if string ends with substring
bool EndsWith(CString in_string, CString in_subString);

private:
// Build the name for an Arnold node (overload for a CString input type)
Expand Down
10 changes: 7 additions & 3 deletions plugins/sitoa/loader/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,14 +490,18 @@ bool LoadDrivers(AtNode *in_optionsNode, Pass &in_pass, double in_frame, bool in
}

// if layerName ends with "_denoise", we add a denoise filter named after the layer and then add the output
if (thisFb.m_layerName.ReverseFindString(L"_denoise") == (thisFb.m_layerName.Length() - CString(L"_denoise").Length()))
if (CStringUtilities().EndsWith(thisFb.m_layerName, L"_denoise"))
{
// OptiX denoise needs a separete filter for each AOV, so we create them here instad of in LoadFilters()
CString optixFilterName = L"sitoa_" + thisFb.m_layerName + L"_optix_filter";
AtNode* optixFilterNode = AiNode("denoise_optix_filter");
if (!optixFilterNode)
{
GetMessageQueue()->LogMsg(L"[sitoa] Couldn't create denoise_optix_filter for layer " + thisFb.m_layerName, siErrorMsg);
continue;
CNodeUtilities().SetName(optixFilterNode, CString(L"sitoa_" + thisFb.m_layerName + L"_optix_filter").GetAsciiString());
AiArraySetStr(outputs, activeBuffer, CString(thisFb.m_layerName + L" " + thisFb.m_layerDataType + L" sitoa_" + thisFb.m_layerName + L"_optix_filter " + masterFb.m_fullName).GetAsciiString());
}
CNodeUtilities().SetName(optixFilterNode, optixFilterName.GetAsciiString());
AiArraySetStr(outputs, activeBuffer, CString(thisFb.m_layerName + L" " + thisFb.m_layerDataType + L" " + optixFilterName + L" " + masterFb.m_fullName).GetAsciiString());
}
// Adding to outputs. masterFb differs from thisFb if they are both exr and share the same filename
else if (thisFb.m_layerDataType.IsEqualNoCase(L"RGB") || thisFb.m_layerDataType.IsEqualNoCase(L"RGBA"))
Expand Down
98 changes: 74 additions & 24 deletions plugins/sitoa/renderer/DisplayDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ void CDisplayDriverData::Init(const AtBBox2 &in_display_window, const AtBBox2 &i
m_data_window = in_data_window;
m_overscan = m_display_window.minx != m_data_window.minx || m_display_window.miny != m_data_window.miny ||
m_display_window.maxx != m_data_window.maxx || m_display_window.maxy != m_data_window.maxy;

// get parameters necessary for progressive progress bar
AtNode* options = AiUniverseGetOptions();
bool progressive = AiNodeGetBool(options, "enable_progressive_render");
int aaSamples = AiNodeGetInt(options, "AA_samples");
bool adaptiveSampling = AiNodeGetBool(options, "enable_adaptive_sampling");
int aaSamplesMax = AiNodeGetInt(options, "AA_samples_max");

if (progressive)
{
if (adaptiveSampling && (aaSamplesMax > aaSamples))
m_progressivePasses = aaSamplesMax * aaSamplesMax;
else
m_progressivePasses = aaSamples * aaSamples;
}

}


Expand Down Expand Up @@ -143,7 +159,7 @@ node_initialize
{
CDisplayDriverData *ddData = new CDisplayDriverData;
AiNodeSetLocalData(node, ddData);
AiDriverInitialize(node, false);
AiDriverInitialize(node, true);
}

node_update {}
Expand Down Expand Up @@ -171,35 +187,34 @@ driver_process_bucket
int i, j, pixel_type;
AtRGB rgb;
AtRGBA rgba;
const char* aov_name;

CDisplayDriverData *ddData = (CDisplayDriverData*)AiNodeGetLocalData(node);

CRenderInstance* renderInstance = GetRenderInstance();
DisplayDriver* displayDriver = renderInstance->GetDisplayDriver();

// get parameters necessary for progressive progress bar
AtNode* options = AiUniverseGetOptions();
bool progressive = AiNodeGetBool(options, "enable_progressive_render");
int aaSamples = AiNodeGetInt(options, "AA_samples");
bool adaptiveSampling = AiNodeGetBool(options, "enable_adaptive_sampling");
int aaSamplesMax = AiNodeGetInt(options, "AA_samples_max");
int progressivePasses = aaSamples * aaSamples;
if (adaptiveSampling && (aaSamplesMax > aaSamples))
progressivePasses = aaSamplesMax * aaSamplesMax;

if (renderInstance->InterruptRenderSignal())
return;

// Progress bar
displayDriver->m_paintedDisplayArea += (bucket_size_x * bucket_size_y);
int percent = (int)((displayDriver->m_paintedDisplayArea / (float)displayDriver->m_displayArea) * 100.0f);
// if in progressive render mode we need to divide percent by number of progressive passes
if (progressive && (progressivePasses > 1))
percent = percent / progressivePasses;
displayDriver->m_renderContext.ProgressUpdate(CValue(percent).GetAsText() + L"% Rendered", L"Rendering", percent);

if (!AiOutputIteratorGetNext(iterator, NULL, &pixel_type, &bucket_data))
if (!AiOutputIteratorGetNext(iterator, &aov_name, &pixel_type, &bucket_data))
return;

// don't update progressbar if Main (RGBA) is being denoised
if (!displayDriver->m_useOptixOnMain ||
(displayDriver->m_useOptixOnMain &&
!strcmp(aov_name, "RGBA_denoise") == 0))
{
// Progress bar
displayDriver->m_paintedDisplayArea += (bucket_size_x * bucket_size_y);
int percent = (int)((displayDriver->m_paintedDisplayArea / (float)displayDriver->m_displayArea) * 100.0f);
// if in progressive render mode we need to divide percent by number of progressive passes
if (ddData->m_progressivePasses > 1)
percent = percent / ddData->m_progressivePasses;
displayDriver->m_renderContext.ProgressUpdate(CValue(percent).GetAsText() + L"% Rendered", L"Rendering", percent);
}

// if the Arnold bucket is completely in the overscan frame, don't
// send it to the Softimage render view
if (ddData->IsBucketOutsideView(bucket_xo, bucket_yo, bucket_size_x, bucket_size_y))
Expand Down Expand Up @@ -291,6 +306,17 @@ driver_process_bucket

if (!renderInstance->InterruptRenderSignal())
{
// only_show_denoise
// display driver doesn't work properly if we just skip writing to the framebuffer.
// as a workaround we just output 1x1 pixel of RGBA
if (!strcmp(aov_name, "RGBA_denoise") == 0 &&
displayDriver->m_useOptixOnMain &&
displayDriver->m_onlyShowDenoise &&
ddData->m_progressivePasses > 1)
{
view_bucket_size_x = 1U;
view_bucket_size_y = 1U;
}
RenderTile fragment(view_bucket_xo, displayDriver->m_renderHeight - view_bucket_yo - view_bucket_size_y ,
view_bucket_size_x, view_bucket_size_y, buffer, displayDriver->m_dither);

Expand Down Expand Up @@ -332,11 +358,14 @@ void DisplayDriver::CreateDisplayDriver()


void DisplayDriver::UpdateDisplayDriver(RendererContext& in_rendererContext, unsigned int in_displayArea,
const bool in_filterColorAov, const bool in_filterNumericAov)
const bool in_filterColorAov, const bool in_filterNumericAov,
const bool in_useOptixOnMain, const bool in_onlyShowDenoise)
{
m_renderContext = in_rendererContext;
m_displayArea = in_displayArea;
m_renderHeight = (int)m_renderContext.GetAttribute(L"ImageHeight");
m_useOptixOnMain = in_useOptixOnMain;
m_onlyShowDenoise = in_onlyShowDenoise;

AtNode* options = AiUniverseGetOptions();
AtArray *outputs, *new_outputs;
Expand All @@ -350,12 +379,13 @@ void DisplayDriver::UpdateDisplayDriver(RendererContext& in_rendererContext, uns
Framebuffer frameBuffer = m_renderContext.GetDisplayFramebuffer();
RenderChannel renderchannel = frameBuffer.GetRenderChannel();
CString layerName = GetLayerName(renderchannel.GetName());
CString layerdataType;

if (m_renderContext.GetAttribute(L"FileOutput"))
{
// Display Driver format will use the DataType of the MAIN framebuffer Softimage
// returns us from m_renderContext.GetDisplayFramebuffer() to avoid black images in render window (trac #780)
CString layerdataType = ParAcc_GetValue(frameBuffer, L"DataType", DBL_MAX).GetAsText();
layerdataType = ParAcc_GetValue(frameBuffer, L"DataType", DBL_MAX).GetAsText();
if (layerdataType.IsEqualNoCase(L"RGB") || layerdataType.IsEqualNoCase(L"RGBA"))
{
if (in_filterColorAov)
Expand All @@ -381,17 +411,17 @@ void DisplayDriver::UpdateDisplayDriver(RendererContext& in_rendererContext, uns
else
{
// Display Driver format will use the layer data type from the renderchannel
CString layerdataType = GetDriverLayerDataTypeByName(layerName);
layerdataType = GetDriverLayerDataTypeByName(layerName);

// If empty get dataType from RenderChannel.ChannelType.
if (layerdataType.IsEqualNoCase(L""))
layerdataType = GetDriverLayerChannelType((LONG)renderchannel.GetChannelType());

// if layerName ends with "_denoise", we connect the driver to the optix filter for that layer
if (layerName.ReverseFindString(L"_denoise") == (layerName.Length() - CString(L"_denoise").Length()))
if (CStringUtilities().EndsWith(layerName, L"_denoise"))
{
// we need to check if the optix filter exist. If it doesn't exist, we create one.
CString optixFilterName = L"sitoa_" + layerName + L"_optix_filter";
CString optixFilterName = L"sitoa_" + layerName + L"_optix_filter_display";
AtNode* optixFilterNode = AiNodeLookUpByName(optixFilterName.GetAsciiString());
if (!optixFilterNode)
{
Expand Down Expand Up @@ -419,6 +449,26 @@ void DisplayDriver::UpdateDisplayDriver(RendererContext& in_rendererContext, uns
new_outputs = AiArray(1, 1, AI_TYPE_STRING, CStringUtilities().Strdup(displayDriver.GetAsciiString()));
}

// if layerName is RGBA (Main) and use_optix_on_main is ON,
// we will add the denoised main to the new_outputs
if (layerName == "RGBA" && m_useOptixOnMain)
{
// we need to check if the optix filter exist. If it doesn't exist, we create one.
CString optixFilterName = L"sitoa_RGBA_denoise_optix_filter_display";
AtNode* optixFilterNode = AiNodeLookUpByName(optixFilterName.GetAsciiString());
if (!optixFilterNode)
{
optixFilterNode = AiNode("denoise_optix_filter");
if (optixFilterNode)
CNodeUtilities().SetName(optixFilterNode, optixFilterName.GetAsciiString());
}
displayDriver = L"RGBA_denoise " + layerdataType + L" " + optixFilterName + " xsi_driver";

// resize new_outputs so we can add optix output to display driver outputs
AiArrayResize(new_outputs, AiArrayGetNumElements(new_outputs) + 1, 1);
AiArraySetStr(new_outputs, AiArrayGetNumElements(new_outputs) - 1, CStringUtilities().Strdup(displayDriver.GetAsciiString()));
}

AiNodeSetArray(options, "outputs", new_outputs);
}

Expand Down
11 changes: 9 additions & 2 deletions plugins/sitoa/renderer/DisplayDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class CDisplayDriverData
AtBBox2 m_data_window; // can be negative if overscan enabled

public:
CDisplayDriverData() : m_overscan(false)
CDisplayDriverData() : m_overscan(false),
m_progressivePasses(1)
{}

// Initialize the driver data
Expand All @@ -44,6 +45,8 @@ class CDisplayDriverData
const int in_bucket_size_x, const int in_bucket_size_y,
unsigned int &out_bucket_xo, unsigned int &out_bucket_yo,
unsigned int &out_bucket_size_x, unsigned int &out_bucket_size_y);

int m_progressivePasses;
};


Expand All @@ -56,7 +59,9 @@ class DisplayDriver
void ResetAreaRendered();
// Update the render context in order to reuse the same Arnold driver
// with another render session
void UpdateDisplayDriver(RendererContext& in_rendererContext, unsigned int in_displayArea, const bool in_filterColorAov, const bool in_filterNumericAov);
void UpdateDisplayDriver(RendererContext& in_rendererContext, unsigned int in_displayArea,
const bool in_filterColorAov, const bool in_filterNumericAov,
const bool in_useOptixOnMain, const bool in_onlyShowDenoise);
// Sets the dithering
void SetDisplayDithering(bool in_dither);

Expand All @@ -65,6 +70,8 @@ class DisplayDriver
int m_renderHeight;
int m_displayArea;
int m_paintedDisplayArea;
bool m_useOptixOnMain;
bool m_onlyShowDenoise;
};


7 changes: 5 additions & 2 deletions plugins/sitoa/renderer/RenderInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ int CRenderInstance::RenderProgressiveScene()
aa_steps.insert(-2);
if ((aa_max > -1) && GetRenderOptions()->m_progressive_minus1)
aa_steps.insert(-1);
// if progressive rendering, ignore the 1 aa step because that is already the first step in progressive
if (!GetRenderOptions()->m_enable_progressive_render)
{
if ((aa_max > 1) && GetRenderOptions()->m_progressive_plus1)
Expand Down Expand Up @@ -1263,7 +1264,8 @@ CStatus CRenderInstance::ProcessPass()

if (enableDisplayDriver)
m_displayDriver.UpdateDisplayDriver(m_renderContext, m_renderWidth*m_renderHeight,
GetRenderOptions()->m_filter_color_AOVs, GetRenderOptions()->m_filter_numeric_AOVs);
GetRenderOptions()->m_filter_color_AOVs, GetRenderOptions()->m_filter_numeric_AOVs,
GetRenderOptions()->m_use_optix_on_main, GetRenderOptions()->m_only_show_denoise);

// Check if the render has not been aborted just before render
if (InterruptRenderSignal())
Expand Down Expand Up @@ -1514,7 +1516,8 @@ CStatus CRenderInstance::ProcessRegion()
// for these new render options (1.12), let's check their existance. Else, filterColorAov defaults to false,
// and all the previously saved scenes render aliased
m_displayDriver.UpdateDisplayDriver(m_renderContext, displayArea,
GetRenderOptions()->m_filter_color_AOVs, GetRenderOptions()->m_filter_numeric_AOVs);
GetRenderOptions()->m_filter_color_AOVs, GetRenderOptions()->m_filter_numeric_AOVs,
GetRenderOptions()->m_use_optix_on_main, GetRenderOptions()->m_only_show_denoise);

SetLogSettings(L"Region", m_frame);
}
Expand Down
30 changes: 30 additions & 0 deletions plugins/sitoa/renderer/RendererOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ void CRenderOptions::Read(const Property &in_cp)
m_output_cameras = (bool)ParAcc_GetValue(in_cp, L"output_cameras", DBL_MAX);
m_output_lights = (bool)ParAcc_GetValue(in_cp, L"output_lights", DBL_MAX);
m_output_shaders = (bool)ParAcc_GetValue(in_cp, L"output_shaders", DBL_MAX);

// denoiser
m_use_optix_on_main = (bool)ParAcc_GetValue(in_cp, L"use_optix_on_main", DBL_MAX);
m_only_show_denoise = (bool)ParAcc_GetValue(in_cp, L"only_show_denoise", DBL_MAX);
}


Expand Down Expand Up @@ -501,6 +505,10 @@ SITOA_CALLBACK CommonRenderOptions_Define(CRef& in_ctxt)
cpset.AddParameter(L"output_lights", CValue::siBool, siPersistable, L"", L"", true, CValue(), CValue(), CValue(), CValue(), p);
cpset.AddParameter(L"output_shaders", CValue::siBool, siPersistable, L"", L"", true, CValue(), CValue(), CValue(), CValue(), p);

// denoiser
cpset.AddParameter(L"use_optix_on_main", CValue::siBool, siPersistable, L"", L"", false, CValue(), CValue(), CValue(), CValue(), p);
cpset.AddParameter(L"only_show_denoise", CValue::siBool, siPersistable, L"", L"", true, CValue(), CValue(), CValue(), CValue(), p);

// the hidden version string saved with the scene
cpset.AddParameter(L"sitoa_version", CValue::siString, siPersistable, L"", L"", L"", CValue(), CValue(), CValue(), CValue(), p);
p.PutCapabilityFlag(siNotInspectable, true);
Expand Down Expand Up @@ -1074,6 +1082,12 @@ SITOA_CALLBACK CommonRenderOptions_DefineLayout(CRef& in_ctxt)
item.PutAttribute(siUICX, 140);
layout.EndRow();

layout.AddTab(L"Denoiser");
layout.AddGroup(L"OptiX Denoiser");
layout.AddItem(L"use_optix_on_main", L"Apply on Main");
layout.AddItem(L"only_show_denoise", L"Only show denoise (in progressive)");
layout.EndGroup();

layout.AddItem(L"sitoa_version", L"SItoA Version");

return CStatus::OK;
Expand Down Expand Up @@ -1118,6 +1132,7 @@ SITOA_CALLBACK CommonRenderOptions_PPGEvent(const CRef& in_ctxt)
SubdivisionTabLogic(cpset);
DiagnosticsTabLogic(cpset);
AssOutputTabLogic(cpset);
DenoiserTabLogic(cpset);

Pass pass(Application().GetActiveProject().GetActiveScene().GetActivePass());

Expand Down Expand Up @@ -1306,6 +1321,9 @@ SITOA_CALLBACK CommonRenderOptions_PPGEvent(const CRef& in_ctxt)
paramName == L"compress_output_ass")
AssOutputTabLogic(cpset);

else if (paramName == L"use_optix_on_main")
DenoiserTabLogic(cpset);

else if (paramName == L"skip_license_check")
{
bool skipLicenseCheck = (bool)ParAcc_GetValue(cpset, L"skip_license_check", DBL_MAX);
Expand Down Expand Up @@ -1618,6 +1636,17 @@ void AssOutputTabLogic(CustomProperty &in_cp)
}


// Logic for the denoiser tab
//
// @param in_cp The arnold rendering options property
//
void DenoiserTabLogic(CustomProperty &in_cp)
{
bool useOptixOnMain = (bool)ParAcc_GetValue(in_cp, L"use_optix_on_main", DBL_MAX);
ParAcc_GetParameter(in_cp, L"only_show_denoise").PutCapabilityFlag(siReadOnly, !useOptixOnMain);
}


// Reset the default values of all the parameters
//
// @param in_cp The arnold rendering options property
Expand All @@ -1641,4 +1670,5 @@ void ResetToDefault(CustomProperty &in_cp, PPGEventContext &in_ctxt)
SubdivisionTabLogic(in_cp);
DiagnosticsTabLogic(in_cp);
AssOutputTabLogic(in_cp);
DenoiserTabLogic(in_cp);
}
Loading

0 comments on commit fa93108

Please sign in to comment.