Skip to content

Commit

Permalink
Implement Frame Chunking logic
Browse files Browse the repository at this point in the history
This happens via a FrameStart, FrameEnd, ChunkSize and 2 internal
parameters that are just calculations based on the previous ones.

We've also reorganized some of the code to hopefully isolate it against
future changes.

Signed-off-by: Alex Hughes <[email protected]>
  • Loading branch information
Ahuge committed Dec 11, 2024
1 parent 9c41d77 commit aa7b65f
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 88 deletions.
17 changes: 17 additions & 0 deletions src/deadline/ae_submitter/UI/AESubmitterUI.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,12 @@ function __generateSubmitterUI() {
frameListGroup.useCompFrameList.value = initUseCompFrameRange;
frameListGroup.useCompFrameList.helpTip = 'If enabled, the Comp\'s frame list will be used instead of the frame list in this submitter.';

frameListGroup.framesPerTask = frameListGroup.add('edittext', undefined, 10);
frameListGroup.framesPerTask.size = SHORT_TEXT_SIZE;
frameListGroup.framesPerTaskLabel = frameListGroup.add('statictext', undefined, 'Frames Per Task');
frameListGroup.framesPerTaskLabel.size = LABEL_SIZE;
frameListGroup.framesPerTaskLabel.helpTip = 'This is the number of frames to be rendered per Job Task.';

// Create Comp submission group and widgets (Select One, Use Selected in RQ, All as separate)
compSubmissionGroup = deadlineCloud.aeOptionsPanel.add('group', undefined);
compSubmissionGroup.alignment = [ScriptUI.Alignment.FILL, ScriptUI.Alignment.TOP];
Expand Down Expand Up @@ -1222,6 +1228,17 @@ function __generateSubmitterUI() {
}
}

frameListGroup.framesPerTask.onChange = function() {
currentValue = frameListGroup.framesPerTask.text.replace(/[^\d]/g, '');

if (parseInt(currentValue) > 9999) {
frameListGroup.framesPerTask.text = "9999"
}
if (parseInt(currentValue) < 1) {
frameListGroup.framesPerTask.text = "1"
}
}

frameListGroup.frameListLabel.enabled = !initSubmitEntireQueue && !initMultiMachine;
frameListGroup.frameList.enabled = !initUseCompFrameRange && !initSubmitEntireQueue && !initMultiMachine;
frameListGroup.useCompFrameList.enabled = !initSubmitEntireQueue && !initMultiMachine;
Expand Down
68 changes: 48 additions & 20 deletions src/deadline/ae_submitter/UI/SubmitButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,46 @@ function __generateSubmitButton() {
function generateStep(basicTemplate, itemName, stepsTemplate, stepID, renderQueueItem)
{
var compNameToCheck = dcUtil.removeIllegalCharacters(renderQueueItem.comp.name);
// logger.debug("[generateStep] itemName: " + itemName + " stepID: " + stepID + " compNameToCheck: " + compNameToCheck, _submitButtonFileName);
stepsTemplate[0].name = itemName;
stepsTemplate[0].parameterSpace.taskParameterDefinitions[0].range = "{{Param." + itemName + "_Frames}}";
stepsTemplate[0].script.embeddedFiles[0].data = "frame: {{Task.Param.Frame}}";
stepsTemplate[0].parameterSpace.taskParameterDefinitions[0].range = "{{Param." + itemName + "_FrameStart}} - {{Param." + itemName + "_FrameEnd}} : {{Param." + itemName + "_ChunkSize}}";
stepsTemplate[0].parameterSpace.taskParameterDefinitions[1].range = "{{Param." + itemName + "_FrameStartPlusChunkSizeMinusOne}}-{{Param." + itemName + "_FrameEndMinusOne}}:{{Param." + itemName + "_ChunkSize}},{{Param." + itemName + "_FrameEnd}}";
if(itemName != compNameToCheck)
{
stepsTemplate[0].stepEnvironments[0].script.embeddedFiles[0].data += "comp_name: {{Param." + compNameToCheck + "_CompName}} \n";
stepsTemplate[0].script.embeddedFiles[0].data = "\"%AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE%\" -project \"{{Param.AfterEffectsProjectFile}}\" -comp \"{{Param." + itemName + "_CompName}}\" -s {{Task.Param.FrameChunkStart}} -e {{Task.Param.FrameChunkEnd}} || exit /b 1 \n"
// stepsTemplate[0].taskParameterDefinitions[2].range = ["{{Param." + compNameToCheck + "_CompName}}"];
}
else
{
stepsTemplate[0].stepEnvironments[0].script.embeddedFiles[0].data += "comp_name: {{Param." + itemName + "_CompName}} \n";
else {
stepsTemplate[0].script.embeddedFiles[0].data = "\"%AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE%\" -project \"{{Param.AfterEffectsProjectFile}}\" -comp \"{{Param." + itemName + "_CompName}}\" -s {{Task.Param.FrameChunkStart}} -e {{Task.Param.FrameChunkEnd}} || exit /b 1 \n"
// stepsTemplate[0].taskParameterDefinitions[2].range = ["{{Param." + itemName + "_CompName}}"];
}
stepsTemplate[0].stepEnvironments[0].script.embeddedFiles[0].data += "output_file_path: {{Param." + itemName + "_OutputFilePath}} \n";
stepsTemplate[0].stepEnvironments[0].script.embeddedFiles[0].data += "output_pattern: {{Param." + itemName + "_OutputPattern}} \n";
stepsTemplate[0].stepEnvironments[0].script.embeddedFiles[0].data += "output_format: {{Param." + itemName + "_OutputFormat}} \n";
basicTemplate.steps[stepID-1] = stepsTemplate[0];
// logger.debug("[generateStep] basicTemplate: " + JSON.stringify(basicTemplate), _submitButtonFileName);
return basicTemplate;
}

function applyFrameChunkingDataToTemplate(itemName, frameList)
{
var output = {
"parameterDefinitions": [],
"parameterValues": [],
}

var chunkParametersList = dcUtil.getFrameChunkParameters(frameList, frameListGroup.framesPerTask.text);
// Currently only support a single frame range
output.parameterDefinitions.push(applyDataToTemplate(itemName + "_FrameStart", dcUtil.deepCopy(dcDataTemplate.FrameStart)));
output.parameterDefinitions.push(applyDataToTemplate(itemName + "_FrameEnd", dcUtil.deepCopy(dcDataTemplate.FrameEnd)));
output.parameterDefinitions.push(applyDataToTemplate(itemName + "_ChunkSize", dcUtil.deepCopy(dcDataTemplate.ChunkSize)));
output.parameterDefinitions.push(applyDataToTemplate(itemName + "_FrameStartPlusChunkSizeMinusOne", dcUtil.deepCopy(dcDataTemplate.FrameStartPlusChunkSizeMinusOne)));
output.parameterDefinitions.push(applyDataToTemplate(itemName + "_FrameEndMinusOne", dcUtil.deepCopy(dcDataTemplate.FrameEndMinusOne)));

output.parameterValues.push(applyDataToParameterTemplate(itemName + "_FrameStart", chunkParametersList[0].frameStart));
output.parameterValues.push(applyDataToParameterTemplate(itemName + "_FrameEnd", chunkParametersList[0].frameEnd));
output.parameterValues.push(applyDataToParameterTemplate(itemName + "_ChunkSize", chunkParametersList[0].chunkSize));
output.parameterValues.push(applyDataToParameterTemplate(itemName + "_FrameStartPlusChunkSizeMinusOne", chunkParametersList[0].frameStartPlusChunkSizeMinusOne));
output.parameterValues.push(applyDataToParameterTemplate(itemName + "_FrameEndMinusOne", chunkParametersList[0].frameEndMinusOne));
return output
}

function applyDataToTemplate(dataName, dataTemplate)
{
if(dataName.indexOf("Frames") >= 0 || dataName.indexOf("OutputFilePath") >= 0)
Expand Down Expand Up @@ -315,6 +335,7 @@ function __generateSubmitButton() {

if (submissionText == useQueue)
totalJobs = 1;
queuedCount = 1;

progressBarPanel.progressBar.value = 0;

Expand Down Expand Up @@ -467,26 +488,27 @@ function __generateSubmitButton() {

var __compName = dcUtil.removeIllegalCharacters(app.project.renderQueue.item(j).comp.name);
var frameList = getFrameList(app.project.renderQueue.item(j));

// logger.debug("[createDataAndParameterTemplateOneJob] __compName: " + __compName, _submitButtonFileName);
// logger.debug("[createDataAndParameterTemplateOneJob] frameList: " + frameList, _submitButtonFileName);


var chunking = applyFrameChunkingDataToTemplate(__compName, frameList)

// Add data to the main template
jobTemplate.parameterDefinitions.push(applyDataToTemplate(__compName + "_Frames", dcUtil.deepCopy(dcDataTemplate.Frames)));
for (var pIdx = 0; pIdx < chunking.parameterDefinitions.length; pIdx++) {
jobTemplate.parameterDefinitions.push(chunking.parameterDefinitions[pIdx]);
}
jobTemplate.parameterDefinitions.push(applyDataToTemplate(__compName + "_OutputPattern", dcUtil.deepCopy(dcDataTemplate.OutputPattern)));
jobTemplate.parameterDefinitions.push(applyDataToTemplate(__compName + "_OutputFormat", dcUtil.deepCopy(dcDataTemplate.OutputFormat)));
jobTemplate.parameterDefinitions.push(applyDataToTemplate(__compName + "_CompName", dcUtil.deepCopy(dcDataTemplate.CompName)));
jobTemplate.parameterDefinitions.push(applyDataToTemplate(__compName + "_OutputFilePath", dcUtil.deepCopy(dcDataTemplate.OutputFilePath)));

// Add steps data per task that needs to be run
jobTemplate = generateStep(jobTemplate, __compName, dcUtil.deepCopy(stepsTemplate), stepIndex, app.project.renderQueue.item(j));
// logger.debug("[createDataAndParameterTemplateOneJob] jobTemplate: " + JSON.stringify(jobTemplate), _submitButtonFileName);

jobTemplate = applyHostReqToTemplate(jobTemplate);
// logger.debug("[createDataAndParameterTemplateOneJob] jobTemplate applyHostReqToTemplate: " + JSON.stringify(jobTemplate), _submitButtonFileName);

// Add data to the parameter template
jobParams.parameterValues.push(applyDataToParameterTemplate(__compName + "_Frames", frameList));
for (var pIdx = 0; pIdx < chunking.parameterValues.length; pIdx++) {
jobParams.parameterValues.push(chunking.parameterValues[pIdx]);
}
jobParams.parameterValues.push(applyDataToParameterTemplate(__compName + "_CompName", app.project.renderQueue.item(j).comp.name));
jobParams.parameterValues.push(applyDataToParameterTemplate(__compName + "_OutputPattern", dcUtil.removePercentageFromFileName(getRenderQueueItemData(app.project.renderQueue.item(j))["fileName"])));
jobParams.parameterValues.push(applyDataToParameterTemplate(__compName + "_OutputFormat", getRenderQueueItemData(app.project.renderQueue.item(j))["extension"]));
Expand All @@ -505,9 +527,13 @@ function __generateSubmitButton() {
{
var compNameToCheck = dcUtil.removeIllegalCharacters(renderQueueItem.comp.name);
var frameList = getFrameList(renderQueueItem);

var chunking = applyFrameChunkingDataToTemplate(itemName, frameList)
jobTemplate = generatePartialTemplate();
// Add data to the main template
jobTemplate.parameterDefinitions.push(applyDataToTemplate(itemName + "_Frames", dcDataTemplate.Frames));
for (var pIdx = 0; pIdx < chunking.parameterDefinitions.length; pIdx++) {
jobTemplate.parameterDefinitions.push(chunking.parameterDefinitions[pIdx]);
}
jobTemplate.parameterDefinitions.push(applyDataToTemplate(itemName + "_OutputPattern", dcDataTemplate.OutputPattern));
jobTemplate.parameterDefinitions.push(applyDataToTemplate(itemName + "_OutputFormat", dcDataTemplate.OutputFormat));
// jobTemplate.parameterDefinitions.push(applyDataToTemplate(itemName + "_CompName", dcDataTemplate.CompName));
Expand All @@ -523,7 +549,9 @@ function __generateSubmitButton() {
jobParams.parameterValues.push(applyDataToParameterTemplate("deadline:maxFailedTasksCount", dcProperties.deadlineJobParameters.maxFailedTasksCount.get()));
jobParams.parameterValues.push(applyDataToParameterTemplate("deadline:maxRetriesPerTask", dcProperties.deadlineJobParameters.maxRetriesPerTask.get()));
jobParams.parameterValues.push(applyDataToParameterTemplate("deadline:priority", dcProperties.deadlineJobParameters.priority.get()));
jobParams.parameterValues.push(applyDataToParameterTemplate(itemName + "_Frames", frameList));
for (var pIdx = 0; pIdx < chunking.parameterValues.length; pIdx++) {
jobParams.parameterValues.push(chunking.parameterValues[pIdx]);
}
// jobParams.parameterValues.push(applyDataToParameterTemplate(itemName + "_CompName", comp));
jobParams.parameterValues.push(applyDataToParameterTemplate(itemName + "_OutputPattern", dcUtil.removePercentageFromFileName((getRenderQueueItemData(renderQueueItem)["fileName"]))));
jobParams.parameterValues.push(applyDataToParameterTemplate(itemName + "_OutputFormat", getRenderQueueItemData(renderQueueItem)["extension"]));
Expand Down
19 changes: 19 additions & 0 deletions src/deadline/ae_submitter/data/RenderScript.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function __generateRenderScriptTemplate(compParameterName) {
return (
"@ECHO OFF\n" +
"IF \"%AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE%\" == \"\" (\n" +
" set AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE=aerender.exe\n" +
")\n" +
"echo \"Running: \\\"%AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE%\\\" -project \\\"{{Param.AfterEffectsProjectFile}}\\\" -comp \\\"" + compParameterName + "\\\" -s {{Task.Param.FrameChunkStart}} -e {{Task.Param.FrameChunkEnd}}\"\n" +
"\"%AFTEREFFECTS_ADAPTOR_AERENDER_EXECUTABLE%\" -project \"{{Param.AfterEffectsProjectFile}}\" -comp \"" + compParameterName + "\" -s {{Task.Param.FrameChunkStart}} -e {{Task.Param.FrameChunkEnd}}\n" +
"IF %ERRORLEVEL% NEQ 0 (\n" +
" echo \"Return code: %ERRORLEVEL%\"\n" +
" exit %ERRORLEVEL%\n" +
")\n" +
"exit 0\n"
)
}

dcRenderScript = {
"generateRenderCommand": __generateRenderScriptTemplate,
};
63 changes: 58 additions & 5 deletions src/deadline/ae_submitter/submission/DataTemplate.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,65 @@
function __generateDataTemplate() {
var Frames =
var FrameStart =
{
"name": "Frames",
"name": "FrameStart",
"type": "STRING",
"userInterface": {
"control": "LINE_EDIT",
"label": "Frames",
"label": "Starting Frames",
"groupLabel": "After Effects Settings"
},
"description": "The frames to render. E.g. 1,8,11",
"description": "The starting frame to render.",
"minLength": 1
}
var FrameEnd =
{
"name": "FrameEnd",
"type": "STRING",
"userInterface": {
"control": "LINE_EDIT",
"label": "Ending Frames",
"groupLabel": "After Effects Settings"
},
"description": "The ending frame to render.",
"minLength": 1
}
var ChunkSize =
{
"name": "ChunkSize",
"type": "STRING",
"userInterface": {
"control": "LINE_EDIT",
"label": "Frames Per Task",
"groupLabel": "After Effects Settings"
},
"description": "The chunk size of frames per task to render",
"minLength": 1
}
var FrameStartPlusChunkSizeMinusOne =
{
"name": "FrameStartPlusChunkSizeMinusOne",
"type": "STRING",
"userInterface": {
"control": "LINE_EDIT",
"label": "FrameStart + ChunkSize - 1",
"groupLabel": "After Effects Settings"
},
"description": "[Internal] This value needs to equal FrameStart + ChunkSize - 1",
"minLength": 1
}
var FrameEndMinusOne =
{
"name": "FrameEndMinusOne",
"type": "STRING",
"userInterface": {
"control": "LINE_EDIT",
"label": "FrameEnd - 1",
"groupLabel": "After Effects Settings"
},
"description": "[Internal] This value needs to equal FrameEnd - 1",
"minLength": 1
}

var OutputPattern =
{
"name": "OutputPattern",
Expand Down Expand Up @@ -45,7 +94,11 @@ function __generateDataTemplate() {
"description": "The render output path."
}
return {
"Frames": Frames,
"FrameStart": FrameStart,
"FrameEnd": FrameEnd,
"ChunkSize": ChunkSize,
"FrameStartPlusChunkSizeMinusOne": FrameStartPlusChunkSizeMinusOne,
"FrameEndMinusOne": FrameEndMinusOne,
"OutputPattern" : OutputPattern,
"OutputFormat": OutputFormat,
"CompName": CompName,
Expand Down
Loading

0 comments on commit aa7b65f

Please sign in to comment.