1 //
2 // Copyright 2017 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 //    names, trademarks, service marks, or product names of the Licensor
11 //    and its affiliates, except as required to comply with Section 4(c) of
12 //    the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 //     http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/imaging/hdx/taskController.h"
25 
26 #include "pxr/imaging/hd/camera.h"
27 #include "pxr/imaging/hd/light.h"
28 #include "pxr/imaging/hd/renderBuffer.h"
29 #include "pxr/imaging/hdx/aovInputTask.h"
30 #include "pxr/imaging/hdx/colorizeSelectionTask.h"
31 #include "pxr/imaging/hdx/colorCorrectionTask.h"
32 #include "pxr/imaging/hdx/freeCameraSceneDelegate.h"
33 #include "pxr/imaging/hdx/oitRenderTask.h"
34 #include "pxr/imaging/hdx/oitResolveTask.h"
35 #include "pxr/imaging/hdx/oitVolumeRenderTask.h"
36 #include "pxr/imaging/hdx/package.h"
37 #include "pxr/imaging/hdx/pickTask.h"
38 #include "pxr/imaging/hdx/pickFromRenderBufferTask.h"
39 #include "pxr/imaging/hdx/presentTask.h"
40 #include "pxr/imaging/hdx/renderTask.h"
41 #include "pxr/imaging/hdx/selectionTask.h"
42 #include "pxr/imaging/hdx/simpleLightTask.h"
43 #include "pxr/imaging/hdx/skydomeTask.h"
44 #include "pxr/imaging/hdx/shadowTask.h"
45 #include "pxr/imaging/hdx/visualizeAovTask.h"
46 
47 #include "pxr/imaging/hdSt/renderDelegate.h"
48 #include "pxr/imaging/hdSt/tokens.h"
49 
50 #include "pxr/imaging/glf/simpleLight.h"
51 #include "pxr/imaging/glf/simpleLightingContext.h"
52 
53 #include "pxr/base/gf/camera.h"
54 
55 PXR_NAMESPACE_OPEN_SCOPE
56 
57 TF_DEFINE_PRIVATE_TOKENS(
58     _tokens,
59 
60     // tasks
61     (simpleLightTask)
62     (shadowTask)
63     (aovInputTask)
64     (selectionTask)
65     (colorizeSelectionTask)
66     (oitResolveTask)
67     (colorCorrectionTask)
68     (pickTask)
69     (pickFromRenderBufferTask)
70     (presentTask)
71     (skydomeTask)
72     (visualizeAovTask)
73 
74     // global camera
75     (camera)
76 
77     // For the internal delegate...
78     (renderBufferDescriptor)
79     (renderTags)
80 
81     // for the stage orientation
82     (StageOrientation)
83 );
84 
85 // XXX: WBN to expose this to the application.
86 static const uint32_t MSAA_SAMPLE_COUNT = 4;
87 
88 // ---------------------------------------------------------------------------
89 // Delegate implementation.
90 
91 /* virtual */
92 VtValue
Get(SdfPath const & id,TfToken const & key)93 HdxTaskController::_Delegate::Get(SdfPath const& id, TfToken const& key)
94 {
95     _ValueCache *vcache = TfMapLookupPtr(_valueCacheMap, id);
96     VtValue ret;
97     if (vcache && TfMapLookup(*vcache, key, &ret)) {
98         return ret;
99     }
100     return VtValue();
101 }
102 
103 /* virtual */
104 GfMatrix4d
GetTransform(SdfPath const & id)105 HdxTaskController::_Delegate::GetTransform(SdfPath const& id)
106 {
107     // Extract from value cache.
108     if (_ValueCache *vcache = TfMapLookupPtr(_valueCacheMap, id)) {
109         if (VtValue * val = TfMapLookupPtr(*vcache, HdTokens->transform)) {
110             if (val->IsHolding<GfMatrix4d>()) {
111                 return val->Get<GfMatrix4d>();
112             }
113         }
114     }
115 
116     TF_CODING_ERROR(
117         "Unexpected call to GetTransform for %s in HdxTaskController's "
118         "internal scene delegate.\n", id.GetText());
119     return GfMatrix4d(1.0);
120 }
121 
122 /* virtual */
123 VtValue
GetLightParamValue(SdfPath const & id,TfToken const & paramName)124 HdxTaskController::_Delegate::GetLightParamValue(SdfPath const& id,
125                                                  TfToken const& paramName)
126 {
127     return Get(id, paramName);
128 }
129 
130 /* virtual */
131 bool
IsEnabled(TfToken const & option) const132 HdxTaskController::_Delegate::IsEnabled(TfToken const& option) const
133 {
134     return HdSceneDelegate::IsEnabled(option);
135 }
136 
137 /* virtual */
138 HdRenderBufferDescriptor
GetRenderBufferDescriptor(SdfPath const & id)139 HdxTaskController::_Delegate::GetRenderBufferDescriptor(SdfPath const& id)
140 {
141     return GetParameter<HdRenderBufferDescriptor>(id,
142                 _tokens->renderBufferDescriptor);
143 }
144 
145 
146 /* virtual */
147 TfTokenVector
GetTaskRenderTags(SdfPath const & taskId)148 HdxTaskController::_Delegate::GetTaskRenderTags(SdfPath const& taskId)
149 {
150     if (HasParameter(taskId, _tokens->renderTags)) {
151         return GetParameter<TfTokenVector>(taskId, _tokens->renderTags);
152     }
153     return TfTokenVector();
154 }
155 
156 
157 // ---------------------------------------------------------------------------
158 // Task controller implementation.
159 
160 static bool
_IsStormRenderingBackend(HdRenderIndex const * index)161 _IsStormRenderingBackend(HdRenderIndex const *index)
162 {
163     if(!dynamic_cast<HdStRenderDelegate*>(index->GetRenderDelegate())) {
164         return false;
165     }
166 
167     return true;
168 }
169 
170 static GfVec2i
_ViewportToAovDimensions(const GfVec4d & viewport)171 _ViewportToAovDimensions(const GfVec4d& viewport)
172 {
173     // Ignore the viewport offset and use its size as the aov size.
174     // XXX: This is fragile and doesn't handle viewport tricks,
175     // such as camera zoom. In the future, we expect to improve the
176     // API to better communicate AOV sizing, fill region and camera
177     // zoom.
178     return GfVec2i(viewport[2], viewport[3]);
179 }
180 
HdxTaskController(HdRenderIndex * renderIndex,SdfPath const & controllerId)181 HdxTaskController::HdxTaskController(HdRenderIndex *renderIndex,
182                                      SdfPath const& controllerId)
183     : _index(renderIndex)
184     , _controllerId(controllerId)
185     , _delegate(renderIndex, controllerId)
186     , _freeCameraSceneDelegate(
187         std::make_unique<HdxFreeCameraSceneDelegate>(
188             renderIndex, controllerId))
189     , _renderBufferSize(0, 0)
190     , _overrideWindowPolicy{false, CameraUtilFit}
191     , _viewport(0, 0, 1, 1)
192 {
193     _CreateRenderGraph();
194 }
195 
~HdxTaskController()196 HdxTaskController::~HdxTaskController()
197 {
198     SdfPath const tasks[] = {
199         _aovInputTaskId,
200         _oitResolveTaskId,
201         _selectionTaskId,
202         _simpleLightTaskId,
203         _shadowTaskId,
204         _colorizeSelectionTaskId,
205         _colorCorrectionTaskId,
206         _pickTaskId,
207         _pickFromRenderBufferTaskId,
208         _presentTaskId
209     };
210 
211     for (size_t i = 0; i < sizeof(tasks)/sizeof(tasks[0]); ++i) {
212         if (!tasks[i].IsEmpty()) {
213             GetRenderIndex()->RemoveTask(tasks[i]);
214         }
215     }
216 
217     for (auto const& id : _renderTaskIds) {
218         GetRenderIndex()->RemoveTask(id);
219     }
220 
221     const TfToken cameraLightType =
222         (GetRenderIndex()->IsSprimTypeSupported(HdPrimTypeTokens->simpleLight))
223             ? HdPrimTypeTokens->simpleLight
224             : HdPrimTypeTokens->sphereLight;
225     for (auto const& id : _lightIds) {
226         GetRenderIndex()->RemoveSprim(cameraLightType, id);
227         GetRenderIndex()->RemoveSprim(HdPrimTypeTokens->domeLight, id);
228     }
229 
230     for (auto const& id : _aovBufferIds) {
231         GetRenderIndex()->RemoveBprim(HdPrimTypeTokens->renderBuffer, id);
232     }
233 }
234 
235 void
_CreateRenderGraph()236 HdxTaskController::_CreateRenderGraph()
237 {
238     // XXX: The general assumption is that we have "Storm" backends which are
239     // rasterization based and have their own rules, like multipass for
240     // transparency; and other backends are more single-pass.  As render
241     // delegate capabilities evolve, we'll need a more complicated switch
242     // than this...
243     if (_IsStormRenderingBackend(GetRenderIndex())) {
244         _CreateLightingTask();
245         _CreateShadowTask();
246         _renderTaskIds.push_back(_CreateSkydomeTask());
247         _renderTaskIds.push_back(_CreateRenderTask(
248             HdStMaterialTagTokens->defaultMaterialTag));
249         _renderTaskIds.push_back(_CreateRenderTask(
250             HdStMaterialTagTokens->masked));
251         _renderTaskIds.push_back(_CreateRenderTask(
252             HdStMaterialTagTokens->additive));
253         _renderTaskIds.push_back(_CreateRenderTask(
254             HdStMaterialTagTokens->translucent));
255         _renderTaskIds.push_back(_CreateRenderTask(
256             HdStMaterialTagTokens->volume));
257 
258         if (_AovsSupported()) {
259             _CreateAovInputTask();
260             _CreateOitResolveTask();
261             _CreateSelectionTask();
262             _CreateColorCorrectionTask();
263             _CreateVisualizeAovTask();
264             _CreatePresentTask();
265         }
266 
267         // Picking rendergraph
268         _CreatePickTask();
269 
270         // XXX AOVs are OFF by default for Storm TaskController because hybrid
271         // rendering in Presto spawns an ImagineGLEngine, which creates a task
272         // controlller. But the Hydrid rendering setups are not yet AOV ready
273         // since it breaks main cam zoom operations expressed via viewport
274         // manipulation.
275         // App (UsdView) for now calls engine->SetRendererAov(color) to enable.
276         // SetRenderOutputs({HdAovTokens->color});
277     } else {
278         _renderTaskIds.push_back(_CreateRenderTask(TfToken()));
279 
280         if (_AovsSupported()) {
281             _CreateAovInputTask();
282             _CreateColorizeSelectionTask();
283             _CreateColorCorrectionTask();
284             _CreateVisualizeAovTask();
285             _CreatePresentTask();
286             _CreatePickFromRenderBufferTask();
287             // Initialize the AOV system to render color. Note:
288             // SetRenderOutputs special-cases color to include support for
289             // depth-compositing and selection highlighting/picking.
290             SetRenderOutputs({HdAovTokens->color});
291         }
292     }
293 }
294 
295 SdfPath
_GetRenderTaskPath(TfToken const & materialTag) const296 HdxTaskController::_GetRenderTaskPath(TfToken const& materialTag) const
297 {
298     std::string str = TfStringPrintf("renderTask_%s",
299         materialTag.GetText());
300     std::replace(str.begin(), str.end(), ':', '_');
301     return GetControllerId().AppendChild(TfToken(str));
302 }
303 
304 SdfPath
_CreateRenderTask(TfToken const & materialTag)305 HdxTaskController::_CreateRenderTask(TfToken const& materialTag)
306 {
307     SdfPath taskId = _GetRenderTaskPath(materialTag);
308 
309     HdxRenderTaskParams renderParams;
310     renderParams.camera = _freeCameraSceneDelegate->GetCameraId();
311     renderParams.viewport = _viewport;
312     renderParams.framing = _framing;
313     renderParams.overrideWindowPolicy = _overrideWindowPolicy;
314 
315     // Set the blend state based on material tag.
316     _SetBlendStateForMaterialTag(materialTag, &renderParams);
317 
318     HdRprimCollection collection(HdTokens->geometry,
319                                  HdReprSelector(HdReprTokens->smoothHull),
320                                  /*forcedRepr*/ false,
321                                  materialTag);
322     collection.SetRootPath(SdfPath::AbsoluteRootPath());
323 
324     if (materialTag == HdStMaterialTagTokens->defaultMaterialTag ||
325         materialTag == HdStMaterialTagTokens->additive ||
326         materialTag == HdStMaterialTagTokens->masked ||
327         materialTag.IsEmpty()) {
328         GetRenderIndex()->InsertTask<HdxRenderTask>(&_delegate, taskId);
329     } else if (materialTag == HdStMaterialTagTokens->translucent) {
330         GetRenderIndex()->InsertTask<HdxOitRenderTask>(&_delegate, taskId);
331         // OIT is using its own buffers which are only per pixel and not per
332         // sample. Thus, we resolve the AOVs before starting to render any
333         // OIT geometry and only use the resolved AOVs from then on.
334         renderParams.useAovMultiSample = false;
335     } else if (materialTag == HdStMaterialTagTokens->volume) {
336         GetRenderIndex()->InsertTask<HdxOitVolumeRenderTask>(&_delegate, taskId);
337         // See above comment about OIT.
338         renderParams.useAovMultiSample = false;
339     }
340 
341     // Create an initial set of render tags in case the user doesn't set any
342     TfTokenVector renderTags = { HdRenderTagTokens->geometry };
343 
344     _delegate.SetParameter(taskId, HdTokens->params, renderParams);
345     _delegate.SetParameter(taskId, HdTokens->collection, collection);
346     _delegate.SetParameter(taskId, HdTokens->renderTags, renderTags);
347 
348     return taskId;
349 }
350 
351 void
_SetBlendStateForMaterialTag(TfToken const & materialTag,HdxRenderTaskParams * renderParams) const352 HdxTaskController::_SetBlendStateForMaterialTag(TfToken const& materialTag,
353                                         HdxRenderTaskParams *renderParams) const
354 {
355     if (!TF_VERIFY(renderParams)) {
356         return;
357     }
358 
359     if (materialTag == HdStMaterialTagTokens->additive) {
360         // Additive blend -- so no sorting of drawItems is needed
361         renderParams->blendEnable = true;
362         // For color, we are setting all factors to ONE.
363         //
364         // This means we are expecting pre-multiplied alpha coming out
365         // of the shader: vec4(rgb*a, a).  Setting ColorSrc to
366         // HdBlendFactorSourceAlpha would give less control on the
367         // shader side, since it means we would force a pre-multiplied
368         // alpha step on the color coming out of the shader.
369         //
370         renderParams->blendColorOp = HdBlendOpAdd;
371         renderParams->blendColorSrcFactor = HdBlendFactorOne;
372         renderParams->blendColorDstFactor = HdBlendFactorOne;
373 
374         // For alpha, we set the factors so that the alpha in the
375         // framebuffer won't change.  Recall that the geometry in the
376         // additive render pass is supposed to be emitting light but
377         // be fully transparent, that is alpha = 0, so that the order
378         // in which it is drawn doesn't matter.
379         renderParams->blendAlphaOp = HdBlendOpAdd;
380         renderParams->blendAlphaSrcFactor = HdBlendFactorZero;
381         renderParams->blendAlphaDstFactor = HdBlendFactorOne;
382 
383         // Translucent objects should not block each other in depth buffer
384         renderParams->depthMaskEnable = false;
385 
386         // Since we are using alpha blending, we disable screen door
387         // transparency for this renderpass.
388         renderParams->enableAlphaToCoverage = false;
389     } else if (materialTag == HdStMaterialTagTokens->defaultMaterialTag ||
390                materialTag == HdStMaterialTagTokens->masked) {
391         // The default and masked material tags share the same blend state, but
392         // we classify them as separate because in the general case, masked
393         // materials use fragment shader discards while the defaultMaterialTag
394         // should not.
395         renderParams->blendEnable = false;
396         renderParams->depthMaskEnable = true;
397         renderParams->enableAlphaToCoverage = true;
398     }
399 }
400 
401 void
_CreateOitResolveTask()402 HdxTaskController::_CreateOitResolveTask()
403 {
404     HdxRenderTaskParams renderParams;
405     // OIT is using its own buffers which are only per pixel and not per
406     // sample. Thus, we resolve the AOVs before starting to render any
407     // OIT geometry and only use the resolved AOVs from then on.
408     renderParams.useAovMultiSample = false;
409 
410     _oitResolveTaskId = GetControllerId().AppendChild(_tokens->oitResolveTask);
411 
412     GetRenderIndex()->InsertTask<HdxOitResolveTask>(&_delegate,
413         _oitResolveTaskId);
414 
415     _delegate.SetParameter(_oitResolveTaskId, HdTokens->params, renderParams);
416 }
417 
418 void
_CreateSelectionTask()419 HdxTaskController::_CreateSelectionTask()
420 {
421     // Create a selection highlighting task.
422     _selectionTaskId = GetControllerId().AppendChild(_tokens->selectionTask);
423 
424     HdxSelectionTaskParams selectionParams;
425     selectionParams.enableSelection = true;
426     selectionParams.selectionColor = GfVec4f(1,1,0,1);
427     selectionParams.locateColor = GfVec4f(0,0,1,1);
428 
429     GetRenderIndex()->InsertTask<HdxSelectionTask>(&_delegate,
430         _selectionTaskId);
431 
432     _delegate.SetParameter(_selectionTaskId, HdTokens->params,
433         selectionParams);
434 }
435 
436 void
_CreateColorizeSelectionTask()437 HdxTaskController::_CreateColorizeSelectionTask()
438 {
439     // Create a post-process selection highlighting task.
440     _colorizeSelectionTaskId = GetControllerId().AppendChild(
441         _tokens->colorizeSelectionTask);
442 
443     HdxColorizeSelectionTaskParams selectionParams;
444     selectionParams.enableSelection = true;
445     selectionParams.selectionColor = GfVec4f(1,1,0,1);
446     selectionParams.locateColor = GfVec4f(0,0,1,1);
447 
448     GetRenderIndex()->InsertTask<HdxColorizeSelectionTask>(&_delegate,
449         _colorizeSelectionTaskId);
450 
451     _delegate.SetParameter(_colorizeSelectionTaskId, HdTokens->params,
452         selectionParams);
453 }
454 
455 void
_CreateLightingTask()456 HdxTaskController::_CreateLightingTask()
457 {
458     // Simple lighting task uses lighting state from Sprims.
459     _simpleLightTaskId = GetControllerId().AppendChild(
460         _tokens->simpleLightTask);
461 
462     HdxSimpleLightTaskParams simpleLightParams;
463     simpleLightParams.cameraPath = _freeCameraSceneDelegate->GetCameraId();
464 
465     GetRenderIndex()->InsertTask<HdxSimpleLightTask>(&_delegate,
466         _simpleLightTaskId);
467 
468     _delegate.SetParameter(_simpleLightTaskId, HdTokens->params,
469         simpleLightParams);
470 }
471 
472 void
_CreateShadowTask()473 HdxTaskController::_CreateShadowTask()
474 {
475     _shadowTaskId = GetControllerId().AppendChild(_tokens->shadowTask);
476 
477     GetRenderIndex()->InsertTask<HdxShadowTask>(&_delegate, _shadowTaskId);
478 
479     TfTokenVector renderTags = { HdRenderTagTokens->geometry };
480 
481     _delegate.SetParameter(_shadowTaskId, HdTokens->params,
482                            HdxShadowTaskParams());
483     _delegate.SetParameter(_shadowTaskId, _tokens->renderTags, renderTags);
484 }
485 
486 SdfPath
_CreateSkydomeTask()487 HdxTaskController::_CreateSkydomeTask()
488 {
489     SdfPath skydomeTaskId = GetControllerId().AppendChild(_tokens->skydomeTask);
490     GetRenderIndex()->InsertTask<HdxSkydomeTask>(&_delegate, skydomeTaskId);
491 
492     // This task wil be added to the _renderTaskIds so that the AOV's are
493     // properly cleared. This means that we need to set the parameter and
494     // collection values. (Following HdxTaskController::_CreateRenderTask())
495     HdxRenderTaskParams renderParams;
496     renderParams.camera = _freeCameraSceneDelegate->GetCameraId();
497     renderParams.viewport = _viewport;
498     renderParams.framing = _framing;
499     renderParams.overrideWindowPolicy = _overrideWindowPolicy;
500     _delegate.SetParameter(skydomeTaskId, HdTokens->params, renderParams);
501 
502     HdRprimCollection collection(HdTokens->geometry,
503                                 HdReprSelector(HdReprTokens->smoothHull),
504                                 /*forcedRepr*/ false,
505                                 HdStMaterialTagTokens->defaultMaterialTag);
506     _delegate.SetParameter(skydomeTaskId, HdTokens->collection, collection);
507 
508     return skydomeTaskId;
509 }
510 
511 void
_CreateColorCorrectionTask()512 HdxTaskController::_CreateColorCorrectionTask()
513 {
514     _colorCorrectionTaskId = GetControllerId().AppendChild(
515         _tokens->colorCorrectionTask);
516 
517     GetRenderIndex()->InsertTask<HdxColorCorrectionTask>(&_delegate,
518         _colorCorrectionTaskId);
519 
520     _delegate.SetParameter(_colorCorrectionTaskId, HdTokens->params,
521         HdxColorCorrectionTaskParams());
522 }
523 
524 void
_CreateVisualizeAovTask()525 HdxTaskController::_CreateVisualizeAovTask()
526 {
527     _visualizeAovTaskId = GetControllerId().AppendChild(
528         _tokens->visualizeAovTask);
529     GetRenderIndex()->InsertTask<HdxVisualizeAovTask>(&_delegate,
530         _visualizeAovTaskId);
531 
532     _delegate.SetParameter(_visualizeAovTaskId, HdTokens->params,
533         HdxVisualizeAovTaskParams());
534 }
535 
536 void
_CreatePickTask()537 HdxTaskController::_CreatePickTask()
538 {
539     _pickTaskId = GetControllerId().AppendChild(
540         _tokens->pickTask);
541 
542     HdxPickTaskParams taskParams;
543 
544     GetRenderIndex()->InsertTask<HdxPickTask>(&_delegate, _pickTaskId);
545 
546     _delegate.SetParameter(_pickTaskId, HdTokens->params, taskParams);
547 }
548 
549 void
_CreatePickFromRenderBufferTask()550 HdxTaskController::_CreatePickFromRenderBufferTask()
551 {
552     _pickFromRenderBufferTaskId = GetControllerId().AppendChild(
553         _tokens->pickFromRenderBufferTask);
554 
555     HdxPickFromRenderBufferTaskParams taskParams;
556     taskParams.cameraId = _freeCameraSceneDelegate->GetCameraId();
557 
558     GetRenderIndex()->InsertTask<HdxPickFromRenderBufferTask>(&_delegate,
559         _pickFromRenderBufferTaskId);
560 
561     _delegate.SetParameter(_pickFromRenderBufferTaskId, HdTokens->params,
562         taskParams);
563 }
564 
565 void
_CreateAovInputTask()566 HdxTaskController::_CreateAovInputTask()
567 {
568     _aovInputTaskId = GetControllerId().AppendChild(_tokens->aovInputTask);
569 
570     HdxAovInputTaskParams taskParams;
571 
572     GetRenderIndex()->InsertTask<HdxAovInputTask>(&_delegate,
573         _aovInputTaskId);
574 
575     _delegate.SetParameter(_aovInputTaskId, HdTokens->params,
576         taskParams);
577 }
578 
579 void
_CreatePresentTask()580 HdxTaskController::_CreatePresentTask()
581 {
582     _presentTaskId = GetControllerId().AppendChild(
583         _tokens->presentTask);
584 
585     HdxPresentTaskParams taskParams;
586 
587     GetRenderIndex()->InsertTask<HdxPresentTask>(&_delegate,
588         _presentTaskId);
589 
590     _delegate.SetParameter(_presentTaskId, HdTokens->params,
591         taskParams);
592 }
593 
594 bool
_ShadowsEnabled() const595 HdxTaskController::_ShadowsEnabled() const
596 {
597     if (_simpleLightTaskId.IsEmpty())
598         return false;
599 
600     const HdxSimpleLightTaskParams& simpleLightParams =
601         _delegate.GetParameter<HdxSimpleLightTaskParams>(
602                 _simpleLightTaskId, HdTokens->params);
603 
604     // Only enable the shadow task (which renders shadow maps) if shadows are
605     // enabled.
606     return simpleLightParams.enableShadows;
607 }
608 
609 bool
_SelectionEnabled() const610 HdxTaskController::_SelectionEnabled() const
611 {
612     if (_renderTaskIds.empty())
613         return false;
614 
615     const HdxRenderTaskParams& renderTaskParams =
616         _delegate.GetParameter<HdxRenderTaskParams>(
617             _renderTaskIds.front(), HdTokens->params);
618 
619     // Disable selection highlighting when we're rendering ID buffers.
620     return !renderTaskParams.enableIdRender;
621 }
622 
623 bool
_ColorizeSelectionEnabled() const624 HdxTaskController::_ColorizeSelectionEnabled() const
625 {
626     if (_viewportAov == HdAovTokens->color) {
627         return true;
628     }
629     return false;
630 }
631 
632 bool
_ColorCorrectionEnabled() const633 HdxTaskController::_ColorCorrectionEnabled() const
634 {
635     if (_colorCorrectionTaskId.IsEmpty())
636         return false;
637 
638     const HdxColorCorrectionTaskParams& colorCorrectionParams =
639         _delegate.GetParameter<HdxColorCorrectionTaskParams>(
640             _colorCorrectionTaskId, HdTokens->params);
641 
642     bool useColorCorrect = colorCorrectionParams.colorCorrectionMode !=
643                            HdxColorCorrectionTokens->disabled &&
644                            !colorCorrectionParams.colorCorrectionMode.IsEmpty();
645     return useColorCorrect;
646 }
647 
648 bool
_VisualizeAovEnabled() const649 HdxTaskController::_VisualizeAovEnabled() const
650 {
651     // Only non-color AOVs need special colorization for viz.
652     if (_viewportAov != HdAovTokens->color) {
653         return true;
654     }
655     return false;
656 }
657 
658 bool
_AovsSupported() const659 HdxTaskController::_AovsSupported() const
660 {
661     return GetRenderIndex()->IsBprimTypeSupported(
662         HdPrimTypeTokens->renderBuffer);
663 }
664 
665 bool
_UsingAovs() const666 HdxTaskController::_UsingAovs() const
667 {
668     return !_aovBufferIds.empty();
669 }
670 
671 HdTaskSharedPtrVector const
GetRenderingTasks() const672 HdxTaskController::GetRenderingTasks() const
673 {
674     HdTaskSharedPtrVector tasks;
675 
676     /* The superset of tasks we can run, in order, is:
677      * - simpleLightTaskId
678      * - shadowTaskId
679      * - renderTaskIds (There may be more than one)
680      * - aovInputTaskId
681      * - selectionTaskId
682      * - colorizeSelectionTaskId
683      * - colorCorrectionTaskId
684      * - visualizeAovTaskId
685      * - PresentTask
686      *
687      * Some of these won't be populated, based on the backend type.
688      * Additionally, shadow, selection, color correction and color channel can
689      * be conditionally disabled.
690      *
691      * See _CreateRenderGraph for more details.
692      */
693 
694     if (!_simpleLightTaskId.IsEmpty()) {
695         tasks.push_back(GetRenderIndex()->GetTask(_simpleLightTaskId));
696     }
697 
698     if (!_shadowTaskId.IsEmpty() && _ShadowsEnabled()) {
699         tasks.push_back(GetRenderIndex()->GetTask(_shadowTaskId));
700     }
701 
702     // Perform draw calls
703     if (!_renderTaskIds.empty()) {
704         SdfPath volumeId = _GetRenderTaskPath(HdStMaterialTagTokens->volume);
705 
706         // Render opaque prims, additive and translucent blended prims.
707         // Skip volume prims, because volume rendering reads from the depth
708         // buffer so we must resolve depth first first.
709         for (SdfPath const& id : _renderTaskIds) {
710             if (id != volumeId) {
711                 tasks.push_back(GetRenderIndex()->GetTask(id));
712             }
713         }
714 
715         // Take the aov results from the render tasks, resolve the multisample
716         // images and put the results into gpu textures onto shared context.
717         if (!_aovInputTaskId.IsEmpty()) {
718             tasks.push_back(GetRenderIndex()->GetTask(_aovInputTaskId));
719         }
720 
721         // Render volume prims
722         if (std::find(_renderTaskIds.begin(), _renderTaskIds.end(), volumeId)
723                 != _renderTaskIds.end()) {
724             tasks.push_back(GetRenderIndex()->GetTask(volumeId));
725         }
726     }
727 
728     // Merge translucent and volume pixels into color target
729     if (!_oitResolveTaskId.IsEmpty()) {
730         tasks.push_back(GetRenderIndex()->GetTask(_oitResolveTaskId));
731     }
732 
733     if (!_selectionTaskId.IsEmpty() && _SelectionEnabled()) {
734         tasks.push_back(GetRenderIndex()->GetTask(_selectionTaskId));
735     }
736 
737     if (!_colorizeSelectionTaskId.IsEmpty() && _ColorizeSelectionEnabled()) {
738         tasks.push_back(GetRenderIndex()->GetTask(_colorizeSelectionTaskId));
739     }
740 
741     // Apply color correction / grading (convert to display colors)
742     if (_ColorCorrectionEnabled()) {
743         tasks.push_back(GetRenderIndex()->GetTask(_colorCorrectionTaskId));
744     }
745 
746     if (!_visualizeAovTaskId.IsEmpty() && _VisualizeAovEnabled()) {
747         tasks.push_back(GetRenderIndex()->GetTask(_visualizeAovTaskId));
748     }
749 
750     // Render pixels to screen
751     if (!_presentTaskId.IsEmpty()) {
752         tasks.push_back(GetRenderIndex()->GetTask(_presentTaskId));
753     }
754 
755     return tasks;
756 }
757 
758 HdTaskSharedPtrVector const
GetPickingTasks() const759 HdxTaskController::GetPickingTasks() const
760 {
761     HdTaskSharedPtrVector tasks;
762     if (!_pickTaskId.IsEmpty())
763         tasks.push_back(GetRenderIndex()->GetTask(_pickTaskId));
764     if (!_pickFromRenderBufferTaskId.IsEmpty())
765         tasks.push_back(GetRenderIndex()->GetTask(_pickFromRenderBufferTaskId));
766 
767     return tasks;
768 }
769 
770 SdfPath
_GetAovPath(TfToken const & aov) const771 HdxTaskController::_GetAovPath(TfToken const& aov) const
772 {
773     std::string identifier = std::string("aov_") +
774         TfMakeValidIdentifier(aov.GetString());
775     return GetControllerId().AppendChild(TfToken(identifier));
776 }
777 
778 void
_SetParameters(SdfPath const & pathName,GlfSimpleLight const & light)779 HdxTaskController::_SetParameters(SdfPath const& pathName,
780                                   GlfSimpleLight const& light)
781 {
782     _delegate.SetParameter(pathName, HdLightTokens->intensity, VtValue(1.0f));
783     _delegate.SetParameter(pathName, HdTokens->transform,
784         VtValue(light.GetTransform()));
785     _delegate.SetParameter(pathName, HdLightTokens->shadowParams,
786         HdxShadowParams());
787     _delegate.SetParameter(pathName, HdLightTokens->shadowCollection,
788         VtValue());
789     _delegate.SetParameter(pathName, HdLightTokens->params, light);
790 
791     // If we are setting the parameters for the dome light we need to add the
792     // default dome light texture resource.
793     if (light.IsDomeLight()) {
794         _delegate.SetParameter(pathName, HdLightTokens->textureFile,
795                                SdfAssetPath(
796                                    HdxPackageDefaultDomeLightTexture(),
797                                    HdxPackageDefaultDomeLightTexture()));
798     }
799     // When not using storm, initialize the camera light transform based on
800     // the SimpleLight position
801     else if (_simpleLightTaskId.IsEmpty()) {
802         GfMatrix4d trans(1.0);
803         const GfVec4d& pos = light.GetPosition();
804         trans.SetTranslateOnly(GfVec3d(pos[0], pos[1], pos[2]));
805         _delegate.SetParameter(pathName, HdTokens->transform, VtValue(trans));
806     }
807 }
808 
809 GlfSimpleLight
_GetLightAtId(size_t const & pathIdx)810 HdxTaskController::_GetLightAtId(size_t const& pathIdx)
811 {
812     GlfSimpleLight light = GlfSimpleLight();
813     if (pathIdx < _lightIds.size()) {
814         light = _delegate.GetParameter<GlfSimpleLight>(
815             _lightIds[pathIdx], HdLightTokens->params);
816     }
817     return light;
818 }
819 
820 void
_RemoveLightSprim(size_t const & pathIdx)821 HdxTaskController::_RemoveLightSprim(size_t const& pathIdx)
822 {
823     if (pathIdx < _lightIds.size()) {
824         const TfToken cameraLightType = (GetRenderIndex()->
825                 IsSprimTypeSupported(HdPrimTypeTokens->simpleLight))
826             ? HdPrimTypeTokens->simpleLight
827             : HdPrimTypeTokens->sphereLight;
828         GetRenderIndex()->RemoveSprim(cameraLightType, _lightIds[pathIdx]);
829         GetRenderIndex()->RemoveSprim(HdPrimTypeTokens->domeLight,
830                         _lightIds[pathIdx]);
831     }
832 }
833 
834 void
_ReplaceLightSprim(size_t const & pathIdx,GlfSimpleLight const & light,SdfPath const & pathName)835 HdxTaskController::_ReplaceLightSprim(size_t const& pathIdx,
836                         GlfSimpleLight const& light, SdfPath const& pathName)
837 {
838     _RemoveLightSprim(pathIdx);
839     if (light.IsDomeLight()) {
840         GetRenderIndex()->InsertSprim(HdPrimTypeTokens->domeLight,
841                         &_delegate, pathName);
842     }
843     else {
844         const TfToken cameraLightType = (GetRenderIndex()->
845                 IsSprimTypeSupported(HdPrimTypeTokens->simpleLight))
846             ? HdPrimTypeTokens->simpleLight
847             : HdPrimTypeTokens->sphereLight;
848         GetRenderIndex()->InsertSprim(cameraLightType, &_delegate, pathName);
849     }
850     // set the parameters for lights[i] and mark as dirty
851     _SetParameters(pathName, light);
852     GetRenderIndex()->GetChangeTracker().MarkSprimDirty(pathName,
853                                                 HdLight::AllDirty);
854 
855 }
856 
857 void
SetRenderOutputs(TfTokenVector const & outputs)858 HdxTaskController::SetRenderOutputs(TfTokenVector const& outputs)
859 {
860     if (!_AovsSupported() || _renderTaskIds.empty()) {
861         return;
862     }
863 
864     if (_aovOutputs == outputs) {
865         return;
866     }
867     _aovOutputs = outputs;
868 
869     TfTokenVector localOutputs = outputs;
870 
871     // When we're asked to render "color", we treat that as final color,
872     // complete with depth-compositing and selection, so we in-line add
873     // some extra buffers if they weren't already requested.
874     if (_IsStormRenderingBackend(GetRenderIndex())) {
875         if (std::find(localOutputs.begin(),
876                       localOutputs.end(),
877                       HdAovTokens->depth) == localOutputs.end()) {
878             localOutputs.push_back(HdAovTokens->depth);
879         }
880     } else {
881         std::set<TfToken> mainRenderTokens;
882         for (auto const& aov : outputs) {
883             if (aov == HdAovTokens->color || aov == HdAovTokens->depth ||
884                 aov == HdAovTokens->primId || aov == HdAovTokens->instanceId ||
885                 aov == HdAovTokens->elementId) {
886                 mainRenderTokens.insert(aov);
887             }
888         }
889         // For a backend like PrMan/Embree we fill not just the color buffer,
890         // but also buffers that are used during picking.
891         if (mainRenderTokens.count(HdAovTokens->color) > 0) {
892             if (mainRenderTokens.count(HdAovTokens->depth) == 0) {
893                 localOutputs.push_back(HdAovTokens->depth);
894             }
895             if (mainRenderTokens.count(HdAovTokens->primId) == 0) {
896                 localOutputs.push_back(HdAovTokens->primId);
897             }
898             if (mainRenderTokens.count(HdAovTokens->elementId) == 0) {
899                 localOutputs.push_back(HdAovTokens->elementId);
900             }
901             if (mainRenderTokens.count(HdAovTokens->instanceId) == 0) {
902                 localOutputs.push_back(HdAovTokens->instanceId);
903             }
904         }
905     }
906 
907     // Delete the old renderbuffers.
908     for (size_t i = 0; i < _aovBufferIds.size(); ++i) {
909         GetRenderIndex()->RemoveBprim(HdPrimTypeTokens->renderBuffer,
910             _aovBufferIds[i]);
911     }
912     _aovBufferIds.clear();
913 
914     // Get the render buffer dimensions.
915     const GfVec2i dimensions =
916         _renderBufferSize != GfVec2i(0)
917             ? _renderBufferSize
918             : _ViewportToAovDimensions(_viewport);
919 
920     const GfVec3i dimensions3(dimensions[0], dimensions[1], 1);
921 
922     // Get default AOV descriptors from the render delegate.
923     HdAovDescriptorList outputDescs;
924     for (auto it = localOutputs.begin(); it != localOutputs.end();) {
925         HdAovDescriptor desc = GetRenderIndex()->GetRenderDelegate()->
926             GetDefaultAovDescriptor(*it);
927         if (desc.format == HdFormatInvalid) {
928             // The backend doesn't support this AOV, so skip it.
929             it = localOutputs.erase(it);
930         } else {
931             // Otherwise, stash the desc and move forward.
932             outputDescs.push_back(desc);
933             ++it;
934         }
935     }
936 
937     // Add the new renderbuffers. _GetAovPath returns ids of the form
938     // {controller_id}/aov_{name}.
939     for (size_t i = 0; i < localOutputs.size(); ++i) {
940         SdfPath aovId = _GetAovPath(localOutputs[i]);
941         GetRenderIndex()->InsertBprim(HdPrimTypeTokens->renderBuffer,
942             &_delegate, aovId);
943         HdRenderBufferDescriptor desc;
944         desc.dimensions = dimensions3;
945         desc.format = outputDescs[i].format;
946         desc.multiSampled = outputDescs[i].multiSampled;
947         _delegate.SetParameter(aovId, _tokens->renderBufferDescriptor,desc);
948         _delegate.SetParameter(aovId,
949                                HdStRenderBufferTokens->stormMsaaSampleCount,
950                                MSAA_SAMPLE_COUNT);
951         GetRenderIndex()->GetChangeTracker().MarkBprimDirty(aovId,
952             HdRenderBuffer::DirtyDescription);
953         _aovBufferIds.push_back(aovId);
954     }
955 
956     // Create the list of AOV bindings.
957     // Only the first render task clears AOVs so we also have a bindings set
958     // that specifies no clear color for the remaining render tasks.
959     HdRenderPassAovBindingVector aovBindingsClear;
960     HdRenderPassAovBindingVector aovBindingsNoClear;
961     HdRenderPassAovBindingVector aovInputBindings;
962     aovBindingsClear.resize(localOutputs.size());
963     aovBindingsNoClear.resize(aovBindingsClear.size());
964 
965     for (size_t i = 0; i < localOutputs.size(); ++i) {
966         aovBindingsClear[i].aovName = localOutputs[i];
967         aovBindingsClear[i].clearValue = outputDescs[i].clearValue;
968         aovBindingsClear[i].renderBufferId = _GetAovPath(localOutputs[i]);
969         aovBindingsClear[i].aovSettings = outputDescs[i].aovSettings;
970 
971         aovBindingsNoClear[i] = aovBindingsClear[i];
972         aovBindingsNoClear[i].clearValue = VtValue();
973 
974         if (localOutputs[i] == HdAovTokens->depth) {
975             aovInputBindings.push_back(aovBindingsNoClear[i]);
976         }
977     }
978 
979     const SdfPath volumeId = _GetRenderTaskPath(HdStMaterialTagTokens->volume);
980 
981     // Set AOV bindings on render tasks
982     for (SdfPath const& renderTaskId : _renderTaskIds) {
983         const bool isFirstRenderTask = renderTaskId == _renderTaskIds.front();
984 
985         const HdRenderPassAovBindingVector& aovBindings =
986             isFirstRenderTask ?
987             aovBindingsClear :
988             aovBindingsNoClear;
989 
990         HdxRenderTaskParams rParams =
991             _delegate.GetParameter<HdxRenderTaskParams>(renderTaskId,
992                 HdTokens->params);
993 
994         rParams.aovBindings = aovBindings;
995         if (renderTaskId == volumeId) {
996             rParams.aovInputBindings = aovInputBindings;
997         }
998 
999         _delegate.SetParameter(renderTaskId, HdTokens->params, rParams);
1000         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1001             renderTaskId, HdChangeTracker::DirtyParams);
1002     }
1003 
1004     // For AOV visualization, if only one output was specified, send it
1005     // to the viewer; otherwise, disable colorization.
1006     if (outputs.size() == 1) {
1007         SetViewportRenderOutput(outputs[0]);
1008     } else {
1009         SetViewportRenderOutput(TfToken());
1010     }
1011 
1012     // XXX: The viewport data plumbed to tasks unfortunately depends on whether
1013     // aovs are being used.
1014     _SetCameraFramingForTasks();
1015 }
1016 
1017 void
SetViewportRenderOutput(TfToken const & name)1018 HdxTaskController::SetViewportRenderOutput(TfToken const& name)
1019 {
1020     if (!_AovsSupported()) {
1021         return;
1022     }
1023 
1024     if (_viewportAov == name) {
1025         return;
1026     }
1027     _viewportAov = name;
1028 
1029     if (!_aovInputTaskId.IsEmpty()) {
1030         HdxAovInputTaskParams params;
1031         if (name.IsEmpty()) {
1032             params.aovBufferPath = SdfPath::EmptyPath();
1033             params.depthBufferPath = SdfPath::EmptyPath();
1034         } else if (name == HdAovTokens->color) {
1035             params.aovBufferPath = _GetAovPath(HdAovTokens->color);
1036             params.depthBufferPath = _GetAovPath(HdAovTokens->depth);
1037         } else {
1038             params.aovBufferPath = _GetAovPath(name);
1039             params.depthBufferPath = SdfPath::EmptyPath();
1040         }
1041 
1042         _delegate.SetParameter(_aovInputTaskId, HdTokens->params, params);
1043         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1044             _aovInputTaskId, HdChangeTracker::DirtyParams);
1045     }
1046 
1047     if (!_colorizeSelectionTaskId.IsEmpty()) {
1048         HdxColorizeSelectionTaskParams selParams =
1049             _delegate.GetParameter<HdxColorizeSelectionTaskParams>(
1050                 _colorizeSelectionTaskId, HdTokens->params);
1051 
1052         if (name == HdAovTokens->color) {
1053             // If we're rendering color, make sure the colorize selection task
1054             // has the proper id buffers...
1055             selParams.primIdBufferPath =
1056                 _GetAovPath(HdAovTokens->primId);
1057             selParams.instanceIdBufferPath =
1058                 _GetAovPath(HdAovTokens->instanceId);
1059             selParams.elementIdBufferPath =
1060                 _GetAovPath(HdAovTokens->elementId);
1061         } else {
1062             // Otherwise, clear the colorize selection task out.
1063             selParams.primIdBufferPath = SdfPath::EmptyPath();
1064             selParams.instanceIdBufferPath = SdfPath::EmptyPath();
1065             selParams.elementIdBufferPath = SdfPath::EmptyPath();
1066         }
1067 
1068         _delegate.SetParameter(_colorizeSelectionTaskId, HdTokens->params,
1069             selParams);
1070         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1071             _colorizeSelectionTaskId, HdChangeTracker::DirtyParams);
1072     }
1073 
1074     if (!_pickFromRenderBufferTaskId.IsEmpty()) {
1075         HdxPickFromRenderBufferTaskParams pickParams =
1076             _delegate.GetParameter<HdxPickFromRenderBufferTaskParams>(
1077                 _pickFromRenderBufferTaskId, HdTokens->params);
1078 
1079         if (name == HdAovTokens->color) {
1080             // If we're rendering color, make sure the pick task has the
1081             // proper id & depth buffers...
1082             pickParams.primIdBufferPath =
1083                 _GetAovPath(HdAovTokens->primId);
1084             pickParams.instanceIdBufferPath =
1085                 _GetAovPath(HdAovTokens->instanceId);
1086             pickParams.elementIdBufferPath =
1087                 _GetAovPath(HdAovTokens->elementId);
1088             pickParams.depthBufferPath =
1089                 _GetAovPath(HdAovTokens->depth);
1090         } else {
1091             pickParams.primIdBufferPath = SdfPath::EmptyPath();
1092             pickParams.instanceIdBufferPath = SdfPath::EmptyPath();
1093             pickParams.elementIdBufferPath = SdfPath::EmptyPath();
1094             pickParams.depthBufferPath = SdfPath::EmptyPath();
1095         }
1096 
1097         _delegate.SetParameter(_pickFromRenderBufferTaskId, HdTokens->params,
1098             pickParams);
1099         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1100             _pickFromRenderBufferTaskId, HdChangeTracker::DirtyParams);
1101     }
1102 
1103     if (!_colorCorrectionTaskId.IsEmpty()) {
1104         HdxColorCorrectionTaskParams colCorParams =
1105             _delegate.GetParameter<HdxColorCorrectionTaskParams>(
1106                 _colorCorrectionTaskId, HdTokens->params);
1107 
1108         colCorParams.aovName = name;
1109 
1110         _delegate.SetParameter(_colorCorrectionTaskId, HdTokens->params,
1111             colCorParams);
1112         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1113             _colorCorrectionTaskId, HdChangeTracker::DirtyParams);
1114     }
1115 
1116     if (!_visualizeAovTaskId.IsEmpty()) {
1117         HdxVisualizeAovTaskParams params =
1118             _delegate.GetParameter<HdxVisualizeAovTaskParams>(
1119                 _visualizeAovTaskId, HdTokens->params);
1120 
1121         params.aovName = name;
1122 
1123         _delegate.SetParameter(_visualizeAovTaskId, HdTokens->params,
1124             params);
1125         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1126             _visualizeAovTaskId, HdChangeTracker::DirtyParams);
1127     }
1128 }
1129 
1130 HdRenderBuffer*
GetRenderOutput(TfToken const & name)1131 HdxTaskController::GetRenderOutput(TfToken const& name)
1132 {
1133     if (!_AovsSupported()) {
1134         return nullptr;
1135     }
1136 
1137     SdfPath renderBufferId = _GetAovPath(name);
1138     return static_cast<HdRenderBuffer*>(
1139         GetRenderIndex()->GetBprim(HdPrimTypeTokens->renderBuffer,
1140             renderBufferId));
1141 }
1142 
1143 void
SetRenderOutputSettings(TfToken const & name,HdAovDescriptor const & desc)1144 HdxTaskController::SetRenderOutputSettings(TfToken const& name,
1145                                            HdAovDescriptor const& desc)
1146 {
1147     if (!_AovsSupported() || _renderTaskIds.empty()) {
1148         return;
1149     }
1150 
1151     // Check if we're setting a value for a nonexistent AOV.
1152     SdfPath renderBufferId = _GetAovPath(name);
1153     if (!_delegate.HasParameter(renderBufferId,
1154                                 _tokens->renderBufferDescriptor)) {
1155         TF_WARN("Render output %s doesn't exist", name.GetText());
1156         return;
1157     }
1158 
1159     // HdAovDescriptor contains data for both the renderbuffer descriptor,
1160     // and the renderpass aov binding.  Update them both.
1161     HdRenderBufferDescriptor rbDesc =
1162         _delegate.GetParameter<HdRenderBufferDescriptor>(renderBufferId,
1163             _tokens->renderBufferDescriptor);
1164 
1165     if (rbDesc.format != desc.format ||
1166         rbDesc.multiSampled != desc.multiSampled) {
1167 
1168         rbDesc.format = desc.format;
1169         rbDesc.multiSampled = desc.multiSampled;
1170         _delegate.SetParameter(renderBufferId,
1171             _tokens->renderBufferDescriptor, rbDesc);
1172         GetRenderIndex()->GetChangeTracker().MarkBprimDirty(renderBufferId,
1173             HdRenderBuffer::DirtyDescription);
1174     }
1175 
1176     for (SdfPath const& renderTaskId : _renderTaskIds) {
1177         HdxRenderTaskParams renderParams =
1178             _delegate.GetParameter<HdxRenderTaskParams>(
1179                 renderTaskId, HdTokens->params);
1180 
1181         const bool isFirstRenderTask = renderTaskId == _renderTaskIds.front();
1182 
1183         for (size_t i = 0; i < renderParams.aovBindings.size(); ++i) {
1184             if (renderParams.aovBindings[i].renderBufferId == renderBufferId) {
1185                 if (renderParams.aovBindings[i].clearValue != desc.clearValue ||
1186                     renderParams.aovBindings[i].aovSettings != desc.aovSettings)
1187                 {
1188                     // Only the first RenderTask should clear the AOV
1189                     renderParams.aovBindings[i].clearValue = isFirstRenderTask ?
1190                         desc.clearValue : VtValue();
1191 
1192                     renderParams.aovBindings[i].aovSettings = desc.aovSettings;
1193                     _delegate.SetParameter(renderTaskId, HdTokens->params,
1194                         renderParams);
1195                     GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1196                         renderTaskId, HdChangeTracker::DirtyParams);
1197                 }
1198                 break;
1199             }
1200         }
1201     }
1202 }
1203 
1204 HdAovDescriptor
GetRenderOutputSettings(TfToken const & name) const1205 HdxTaskController::GetRenderOutputSettings(TfToken const& name) const
1206 {
1207     if (!_AovsSupported() || _renderTaskIds.empty()) {
1208         return HdAovDescriptor();
1209     }
1210 
1211     // Check if we're getting a value for a nonexistent AOV.
1212     SdfPath renderBufferId = _GetAovPath(name);
1213     if (!_delegate.HasParameter(renderBufferId,
1214                                 _tokens->renderBufferDescriptor)) {
1215         return HdAovDescriptor();
1216     }
1217 
1218     HdRenderBufferDescriptor rbDesc =
1219         _delegate.GetParameter<HdRenderBufferDescriptor>(renderBufferId,
1220             _tokens->renderBufferDescriptor);
1221 
1222     HdAovDescriptor desc;
1223     desc.format = rbDesc.format;
1224     desc.multiSampled = rbDesc.multiSampled;
1225 
1226     const SdfPath& renderTaskId = _renderTaskIds.front();
1227 
1228     HdxRenderTaskParams renderParams =
1229         _delegate.GetParameter<HdxRenderTaskParams>(
1230             renderTaskId, HdTokens->params);
1231 
1232     for (size_t i = 0; i < renderParams.aovBindings.size(); ++i) {
1233         if (renderParams.aovBindings[i].renderBufferId == renderBufferId) {
1234             desc.clearValue = renderParams.aovBindings[i].clearValue;
1235             desc.aovSettings = renderParams.aovBindings[i].aovSettings;
1236             break;
1237         }
1238     }
1239 
1240     return desc;
1241 }
1242 
1243 
1244 void
SetCollection(HdRprimCollection const & collection)1245 HdxTaskController::SetCollection(HdRprimCollection const& collection)
1246 {
1247     // XXX For now we assume the application calling to set a new
1248     //     collection does not know or setup the material tags and does not
1249     //     split up the collection according to material tags.
1250     //     In order to ignore materialTags when comparing collections we need
1251     //     to copy the old tag into the new collection. Since the provided
1252     //     collection is const, we need to make a not-ideal copy.
1253     HdRprimCollection newCollection = collection;
1254 
1255     for (SdfPath const& renderTaskId : _renderTaskIds) {
1256         HdRprimCollection oldCollection =
1257             _delegate.GetParameter<HdRprimCollection>(
1258                 renderTaskId, HdTokens->collection);
1259 
1260         TfToken const& oldMaterialTag = oldCollection.GetMaterialTag();
1261         newCollection.SetMaterialTag(oldMaterialTag);
1262 
1263         if (oldCollection == newCollection) {
1264             continue;
1265         }
1266 
1267         _delegate.SetParameter(renderTaskId, HdTokens->collection,
1268                                newCollection);
1269         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1270             renderTaskId, HdChangeTracker::DirtyCollection);
1271     }
1272 }
1273 
1274 void
SetRenderParams(HdxRenderTaskParams const & params)1275 HdxTaskController::SetRenderParams(HdxRenderTaskParams const& params)
1276 {
1277     for (SdfPath const& renderTaskId : _renderTaskIds) {
1278         HdRprimCollection collection =
1279             _delegate.GetParameter<HdRprimCollection>(
1280                 renderTaskId, HdTokens->collection);
1281 
1282         HdxRenderTaskParams oldParams =
1283             _delegate.GetParameter<HdxRenderTaskParams>(
1284                 renderTaskId, HdTokens->params);
1285 
1286         // We explicitly ignore input camera, viewport, and aovBindings because
1287         // these are internally managed.
1288         HdxRenderTaskParams mergedParams = params;
1289         mergedParams.camera = oldParams.camera;
1290         mergedParams.viewport = oldParams.viewport;
1291         mergedParams.framing = oldParams.framing;
1292         mergedParams.overrideWindowPolicy = oldParams.overrideWindowPolicy;
1293         mergedParams.aovBindings = oldParams.aovBindings;
1294         mergedParams.aovInputBindings = oldParams.aovInputBindings;
1295 
1296         // We also explicitly manage blend params, based on the material tag.
1297         // XXX: Note: if params.enableIdRender is set, we want to use default
1298         // blend params so that we don't try to additive blend ID buffers...
1299         _SetBlendStateForMaterialTag(
1300             params.enableIdRender ? TfToken() : collection.GetMaterialTag(),
1301             &mergedParams);
1302 
1303         if (mergedParams != oldParams) {
1304             _delegate.SetParameter(renderTaskId,
1305                 HdTokens->params, mergedParams);
1306             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1307                 renderTaskId, HdChangeTracker::DirtyParams);
1308         }
1309     }
1310 
1311     // Update shadow task in case materials have been enabled/disabled
1312     if (!_shadowTaskId.IsEmpty()) {
1313         HdxShadowTaskParams oldShParams =
1314             _delegate.GetParameter<HdxShadowTaskParams>(
1315                 _shadowTaskId, HdTokens->params);
1316 
1317         if (oldShParams.enableSceneMaterials != params.enableSceneMaterials) {
1318             oldShParams.enableSceneMaterials = params.enableSceneMaterials;
1319             _delegate.SetParameter(_shadowTaskId,
1320                 HdTokens->params, oldShParams);
1321             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1322                 _shadowTaskId, HdChangeTracker::DirtyParams);
1323         }
1324     }
1325 
1326     // Update pick task
1327     if (!_pickTaskId.IsEmpty()) {
1328         HdxPickTaskParams pickParams =
1329             _delegate.GetParameter<HdxPickTaskParams>(
1330                 _pickTaskId, HdTokens->params);
1331 
1332         if (pickParams.cullStyle != params.cullStyle ||
1333             pickParams.enableSceneMaterials != params.enableSceneMaterials) {
1334 
1335             pickParams.cullStyle = params.cullStyle;
1336             pickParams.enableSceneMaterials = params.enableSceneMaterials;
1337 
1338             _delegate.SetParameter(_pickTaskId, HdTokens->params, pickParams);
1339             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1340                 _pickTaskId, HdChangeTracker::DirtyParams);
1341         }
1342     }
1343 }
1344 
1345 
1346 void
SetRenderTags(TfTokenVector const & renderTags)1347 HdxTaskController::SetRenderTags(TfTokenVector const& renderTags)
1348 {
1349     HdChangeTracker &tracker = GetRenderIndex()->GetChangeTracker();
1350 
1351     for (SdfPath const& renderTaskId : _renderTaskIds) {
1352         if (_delegate.GetTaskRenderTags(renderTaskId) != renderTags) {
1353             _delegate.SetParameter(renderTaskId,
1354                                    _tokens->renderTags,
1355                                    renderTags);
1356             tracker.MarkTaskDirty(renderTaskId,
1357                                   HdChangeTracker::DirtyRenderTags);
1358         }
1359     }
1360 
1361     if (!_pickTaskId.IsEmpty()) {
1362         if (_delegate.GetTaskRenderTags(_pickTaskId) != renderTags) {
1363             _delegate.SetParameter(_pickTaskId,
1364                                    _tokens->renderTags,
1365                                    renderTags);
1366 
1367             tracker.MarkTaskDirty(_pickTaskId,
1368                                   HdChangeTracker::DirtyRenderTags);
1369         }
1370     }
1371 }
1372 
1373 
1374 void
SetShadowParams(HdxShadowTaskParams const & params)1375 HdxTaskController::SetShadowParams(HdxShadowTaskParams const& params)
1376 {
1377     if (_shadowTaskId.IsEmpty()) {
1378         return;
1379     }
1380 
1381     HdxShadowTaskParams oldParams =
1382         _delegate.GetParameter<HdxShadowTaskParams>(
1383             _shadowTaskId, HdTokens->params);
1384 
1385     HdxShadowTaskParams mergedParams = params;
1386     mergedParams.enableSceneMaterials = oldParams.enableSceneMaterials;
1387 
1388     if (mergedParams != oldParams) {
1389         _delegate.SetParameter(_shadowTaskId, HdTokens->params, mergedParams);
1390         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1391             _shadowTaskId, HdChangeTracker::DirtyParams);
1392     }
1393 }
1394 
1395 void
SetEnableShadows(bool enable)1396 HdxTaskController::SetEnableShadows(bool enable)
1397 {
1398     if (_simpleLightTaskId.IsEmpty()) {
1399         return;
1400     }
1401 
1402     HdxSimpleLightTaskParams params =
1403         _delegate.GetParameter<HdxSimpleLightTaskParams>(
1404             _simpleLightTaskId, HdTokens->params);
1405 
1406     if (params.enableShadows != enable) {
1407         params.enableShadows = enable;
1408         _delegate.SetParameter(_simpleLightTaskId, HdTokens->params, params);
1409         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1410             _simpleLightTaskId, HdChangeTracker::DirtyParams);
1411     }
1412 }
1413 
1414 void
SetEnableSelection(bool enable)1415 HdxTaskController::SetEnableSelection(bool enable)
1416 {
1417     if (!_selectionTaskId.IsEmpty()) {
1418         HdxSelectionTaskParams params =
1419             _delegate.GetParameter<HdxSelectionTaskParams>(
1420                 _selectionTaskId, HdTokens->params);
1421 
1422         if (params.enableSelection != enable) {
1423             params.enableSelection = enable;
1424             _delegate.SetParameter(_selectionTaskId,
1425                 HdTokens->params, params);
1426             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1427                 _selectionTaskId, HdChangeTracker::DirtyParams);
1428         }
1429     }
1430 
1431     if (!_colorizeSelectionTaskId.IsEmpty()) {
1432         HdxColorizeSelectionTaskParams params =
1433             _delegate.GetParameter<HdxColorizeSelectionTaskParams>(
1434                 _colorizeSelectionTaskId, HdTokens->params);
1435 
1436         if (params.enableSelection != enable) {
1437             params.enableSelection = enable;
1438             _delegate.SetParameter(_colorizeSelectionTaskId,
1439                 HdTokens->params, params);
1440             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1441                 _colorizeSelectionTaskId, HdChangeTracker::DirtyParams);
1442         }
1443     }
1444 }
1445 
1446 void
SetSelectionColor(GfVec4f const & color)1447 HdxTaskController::SetSelectionColor(GfVec4f const& color)
1448 {
1449     if (!_selectionTaskId.IsEmpty()) {
1450         HdxSelectionTaskParams params =
1451             _delegate.GetParameter<HdxSelectionTaskParams>(
1452                 _selectionTaskId, HdTokens->params);
1453 
1454         if (params.selectionColor != color) {
1455             params.selectionColor = color;
1456             _delegate.SetParameter(_selectionTaskId,
1457                 HdTokens->params, params);
1458             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1459                 _selectionTaskId, HdChangeTracker::DirtyParams);
1460         }
1461     }
1462 
1463     if (!_colorizeSelectionTaskId.IsEmpty()) {
1464         HdxColorizeSelectionTaskParams params =
1465             _delegate.GetParameter<HdxColorizeSelectionTaskParams>(
1466                 _colorizeSelectionTaskId, HdTokens->params);
1467 
1468         if (params.selectionColor != color) {
1469             params.selectionColor = color;
1470             _delegate.SetParameter(_colorizeSelectionTaskId,
1471                 HdTokens->params, params);
1472             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1473                 _colorizeSelectionTaskId, HdChangeTracker::DirtyParams);
1474         }
1475     }
1476 }
1477 
1478 void
SetSelectionEnableOutline(bool enableOutline)1479 HdxTaskController::SetSelectionEnableOutline(bool enableOutline)
1480 {
1481     if (!_colorizeSelectionTaskId.IsEmpty()) {
1482         HdxColorizeSelectionTaskParams params =
1483             _delegate.GetParameter<HdxColorizeSelectionTaskParams>(
1484                 _colorizeSelectionTaskId, HdTokens->params);
1485 
1486         if (params.enableOutline != enableOutline) {
1487             params.enableOutline = enableOutline;
1488             _delegate.SetParameter(_colorizeSelectionTaskId,
1489                 HdTokens->params, params);
1490             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1491                 _colorizeSelectionTaskId, HdChangeTracker::DirtyParams);
1492         }
1493     }
1494 }
1495 
1496 void
SetSelectionOutlineRadius(unsigned int radius)1497 HdxTaskController::SetSelectionOutlineRadius(unsigned int radius)
1498 {
1499     if (!_colorizeSelectionTaskId.IsEmpty()) {
1500         HdxColorizeSelectionTaskParams params =
1501             _delegate.GetParameter<HdxColorizeSelectionTaskParams>(
1502                 _colorizeSelectionTaskId, HdTokens->params);
1503 
1504         if (params.outlineRadius != radius) {
1505             params.outlineRadius = radius;
1506             _delegate.SetParameter(_colorizeSelectionTaskId,
1507                 HdTokens->params, params);
1508             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1509                 _colorizeSelectionTaskId, HdChangeTracker::DirtyParams);
1510         }
1511     }
1512 }
1513 
1514 bool
_SupportBuiltInLightTypes()1515 HdxTaskController::_SupportBuiltInLightTypes()
1516 {
1517     // Verify that the renderDelegate supports the light types for the built-in
1518     // dome and camera lights.
1519     const HdRenderIndex* index = GetRenderIndex();
1520     // Dome Light
1521     bool dome = index->IsSprimTypeSupported(HdPrimTypeTokens->domeLight);
1522     // Camera Light
1523     bool camera = index->IsSprimTypeSupported(HdPrimTypeTokens->simpleLight);
1524     camera |= index->IsSprimTypeSupported(HdPrimTypeTokens->sphereLight);
1525     return dome && camera;
1526 }
1527 
1528 void
_SetBuiltInLightingState(GlfSimpleLightingContextPtr const & src)1529 HdxTaskController::_SetBuiltInLightingState(
1530     GlfSimpleLightingContextPtr const& src)
1531 {
1532     if (!src) {
1533         TF_CODING_ERROR("Null lighting context");
1534         return;
1535     }
1536 
1537     if (_simpleLightTaskId.IsEmpty() && !_SupportBuiltInLightTypes()) {
1538         return;
1539     }
1540 
1541     GlfSimpleLightVector const& lights = src->GetLights();
1542 
1543     // HdxTaskController inserts a set of light prims to represent the lights
1544     // passed in through the simple lighting context (lights vector). These are
1545     // managed by the task controller, and not by the scene; they represent the
1546     // application state.
1547 
1548     // If we need to add lights to the _lightIds vector
1549     if (_lightIds.size() < lights.size()) {
1550 
1551         // cycle through the lights, add the new light and make sure the Sprims
1552         // at _lightIds[i] match with what is in lights[i]
1553         for (size_t i = 0; i < lights.size(); ++i) {
1554 
1555             // Get or create the light path for lights[i]
1556             bool needToAddLightPath = false;
1557             SdfPath lightPath = SdfPath();
1558             if (i >= _lightIds.size()) {
1559                 lightPath = GetControllerId().AppendChild(TfToken(
1560                             TfStringPrintf("light%d", (int)_lightIds.size())));
1561                 needToAddLightPath = true;
1562             }
1563             else {
1564                 lightPath = _lightIds[i];
1565             }
1566             // Make sure that light at _lightIds[i] matches with lights[i]
1567             GlfSimpleLight currLight = _GetLightAtId(i);
1568             if (currLight != lights[i]) {
1569                 _ReplaceLightSprim(i, lights[i], lightPath);
1570             }
1571             if (needToAddLightPath) {
1572                 _lightIds.push_back(lightPath);
1573             }
1574         }
1575     }
1576 
1577     // If we need to remove lights from the _lightIds vector
1578     else if (_lightIds.size() > lights.size()) {
1579 
1580         // Cycle through the lights making sure the Sprims at _lightIds[i]
1581         // match with what is in lights[i]
1582         for (size_t i = 0; i < lights.size(); ++i) {
1583 
1584             // Get the light path for lights[i]
1585             SdfPath lightPath = _lightIds[i];
1586 
1587             // Make sure that light at _lightIds[i] matches with lights[i]
1588             GlfSimpleLight currLight = _GetLightAtId(i);
1589             if (currLight != lights[i]) {
1590                 _ReplaceLightSprim(i, lights[i], lightPath);
1591             }
1592         }
1593         // Now that everything matches, remove the last item in _lightIds
1594         _RemoveLightSprim(_lightIds.size()-1);
1595         _lightIds.pop_back();
1596     }
1597 
1598     // If there has been no change in the number of lights we still may need to
1599     // update the light parameters eg. if the free camera has moved
1600     for (size_t i = 0; i < lights.size(); ++i) {
1601 
1602         // Make sure the light parameters match
1603         GlfSimpleLight light = _GetLightAtId(i);
1604         if (light != lights[i]) {
1605             _delegate.SetParameter(_lightIds[i],
1606                                     HdLightTokens->params, lights[i]);
1607 
1608             if (light.IsDomeLight()) {
1609                 _delegate.SetParameter(
1610                     _lightIds[i], HdLightTokens->textureFile,
1611                     SdfAssetPath(
1612                         HdxPackageDefaultDomeLightTexture(),
1613                         HdxPackageDefaultDomeLightTexture()));
1614             }
1615             GetRenderIndex()->GetChangeTracker().MarkSprimDirty(
1616                 _lightIds[i], HdLight::DirtyParams);
1617         }
1618 
1619         // Update the camera light transform if needed
1620         if (_simpleLightTaskId.IsEmpty() && !light.IsDomeLight()) {
1621             GfMatrix4d const& viewInverseMatrix =
1622                 _freeCameraSceneDelegate->GetTransform(
1623                     _freeCameraSceneDelegate->GetCameraId());
1624             VtValue trans = VtValue(viewInverseMatrix * light.GetTransform());
1625             VtValue oldTrans = _delegate.Get(_lightIds[i], HdTokens->transform);
1626             if (viewInverseMatrix != GfMatrix4d(1.0) && trans != oldTrans) {
1627                 _delegate.SetParameter(_lightIds[i], HdTokens->transform, trans);
1628                 GetRenderIndex()->GetChangeTracker().MarkSprimDirty(
1629                     _lightIds[i], HdLight::DirtyTransform);
1630             }
1631         }
1632     }
1633 }
1634 
1635 void
SetLightingState(GlfSimpleLightingContextPtr const & src)1636 HdxTaskController::SetLightingState(GlfSimpleLightingContextPtr const& src)
1637 {
1638     // Process the Built-in lights
1639     _SetBuiltInLightingState(src);
1640 
1641     if (_simpleLightTaskId.IsEmpty()) {
1642         return;
1643     }
1644     // If simpleLightTask exists, process the lighting context's material
1645     // parameters as well. These are passed in through the simple light task's
1646     // "params" field, so we need to update that field if the material
1647     // parameters changed.
1648     //
1649     // It's unfortunate that the lighting context is split this way.
1650     HdxSimpleLightTaskParams lightParams =
1651         _delegate.GetParameter<HdxSimpleLightTaskParams>(_simpleLightTaskId,
1652             HdTokens->params);
1653 
1654     if (lightParams.sceneAmbient != src->GetSceneAmbient() ||
1655         lightParams.material != src->GetMaterial()) {
1656 
1657         lightParams.sceneAmbient = src->GetSceneAmbient();
1658         lightParams.material = src->GetMaterial();
1659 
1660         _delegate.SetParameter(
1661             _simpleLightTaskId, HdTokens->params, lightParams);
1662         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1663             _simpleLightTaskId, HdChangeTracker::DirtyParams);
1664     }
1665 }
1666 
1667 void
SetRenderViewport(GfVec4d const & viewport)1668 HdxTaskController::SetRenderViewport(GfVec4d const& viewport)
1669 {
1670     if (_viewport == viewport) {
1671         return;
1672     }
1673     _viewport = viewport;
1674 
1675     // Update the params for tasks that consume viewport info.
1676     _SetCameraFramingForTasks();
1677 
1678     // Update all of the render buffer sizes as well.
1679     _UpdateAovDimensions(_ViewportToAovDimensions(viewport));
1680 }
1681 
1682 void
SetRenderBufferSize(const GfVec2i & size)1683 HdxTaskController::SetRenderBufferSize(const GfVec2i &size)
1684 {
1685     if (_renderBufferSize == size) {
1686         return;
1687     }
1688 
1689     _renderBufferSize = size;
1690 
1691     _UpdateAovDimensions(size);
1692 }
1693 
1694 void
SetFraming(const CameraUtilFraming & framing)1695 HdxTaskController::SetFraming(const CameraUtilFraming &framing)
1696 {
1697     _framing = framing;
1698     _SetCameraFramingForTasks();
1699 }
1700 
1701 void
SetOverrideWindowPolicy(const std::pair<bool,CameraUtilConformWindowPolicy> & policy)1702 HdxTaskController::SetOverrideWindowPolicy(
1703     const std::pair<bool, CameraUtilConformWindowPolicy> &policy)
1704 {
1705     _overrideWindowPolicy = policy;
1706     _SetCameraFramingForTasks();
1707 }
1708 
1709 void
SetCameraPath(SdfPath const & id)1710 HdxTaskController::SetCameraPath(SdfPath const& id)
1711 {
1712     _SetCameraParamForTasks(id);
1713 }
1714 
1715 void
SetFreeCameraMatrices(GfMatrix4d const & viewMatrix,GfMatrix4d const & projMatrix)1716 HdxTaskController::SetFreeCameraMatrices(GfMatrix4d const& viewMatrix,
1717                                          GfMatrix4d const& projMatrix)
1718 {
1719     _freeCameraSceneDelegate->SetMatrices(viewMatrix, projMatrix);
1720     _SetCameraParamForTasks(_freeCameraSceneDelegate->GetCameraId());
1721 }
1722 
1723 void
1724 HdxTaskController::
SetFreeCameraClipPlanes(std::vector<GfVec4d> const & clipPlanes)1725 SetFreeCameraClipPlanes(std::vector<GfVec4d> const& clipPlanes)
1726 {
1727     const std::vector<GfVec4f> planes(clipPlanes.begin(), clipPlanes.end());
1728 
1729     _freeCameraSceneDelegate->SetClipPlanes(planes);
1730 }
1731 
1732 bool
IsConverged() const1733 HdxTaskController::IsConverged() const
1734 {
1735     bool converged = true;
1736 
1737     HdTaskSharedPtrVector tasks = GetRenderingTasks();
1738     for (auto const& task : tasks) {
1739         std::shared_ptr<HdxTask> progressiveTask =
1740             std::dynamic_pointer_cast<HdxTask>(task);
1741         if (progressiveTask) {
1742             converged = converged && progressiveTask->IsConverged();
1743             if (!converged) {
1744                 break;
1745             }
1746         }
1747     }
1748 
1749     return converged;
1750 }
1751 
1752 void
SetColorCorrectionParams(HdxColorCorrectionTaskParams const & params)1753 HdxTaskController::SetColorCorrectionParams(
1754     HdxColorCorrectionTaskParams const& params)
1755 {
1756     if (_colorCorrectionTaskId.IsEmpty()) {
1757         return;
1758     }
1759 
1760     HdxColorCorrectionTaskParams oldParams =
1761         _delegate.GetParameter<HdxColorCorrectionTaskParams>(
1762             _colorCorrectionTaskId, HdTokens->params);
1763 
1764     // We assume the caller for SetColorCorrectionParams wants to set the
1765     // OCIO settings, but does not want to override the AOV used to do color-
1766     // correction on. (Currently this AOV is controlled via TaskController)
1767     HdxColorCorrectionTaskParams newParams = params;
1768     newParams.aovName = oldParams.aovName;
1769 
1770     if (newParams != oldParams) {
1771         _delegate.SetParameter(
1772             _colorCorrectionTaskId, HdTokens->params, newParams);
1773 
1774         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1775             _colorCorrectionTaskId, HdChangeTracker::DirtyParams);
1776     }
1777 }
1778 
1779 void
SetEnablePresentation(bool enabled)1780 HdxTaskController::SetEnablePresentation(bool enabled)
1781 {
1782     if (_presentTaskId.IsEmpty()) {
1783         return;
1784     }
1785 
1786     HdxPresentTaskParams params =
1787         _delegate.GetParameter<HdxPresentTaskParams>(
1788             _presentTaskId, HdTokens->params);
1789 
1790     if (params.enabled != enabled) {
1791         params.enabled = enabled;
1792         _delegate.SetParameter(_presentTaskId, HdTokens->params, params);
1793         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1794             _presentTaskId, HdChangeTracker::DirtyParams);
1795     }
1796 }
1797 
1798 void
SetPresentationOutput(TfToken const & api,VtValue const & framebuffer)1799 HdxTaskController::SetPresentationOutput(
1800     TfToken const &api,
1801     VtValue const &framebuffer)
1802 {
1803     if (_presentTaskId.IsEmpty()) {
1804         return;
1805     }
1806 
1807     HdxPresentTaskParams params =
1808         _delegate.GetParameter<HdxPresentTaskParams>(
1809             _presentTaskId, HdTokens->params);
1810 
1811     if ( params.dstApi != api ||
1812          params.dstFramebuffer != framebuffer) {
1813         params.dstApi = api;
1814         params.dstFramebuffer = framebuffer;
1815         _delegate.SetParameter(_presentTaskId, HdTokens->params, params);
1816         GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1817             _presentTaskId, HdChangeTracker::DirtyParams);
1818     }
1819 }
1820 
1821 void
_SetCameraParamForTasks(SdfPath const & id)1822 HdxTaskController::_SetCameraParamForTasks(SdfPath const& id)
1823 {
1824     if (_activeCameraId != id) {
1825         _activeCameraId = id;
1826 
1827         // Update tasks that take a camera task param.
1828         for (SdfPath const& renderTaskId : _renderTaskIds) {
1829             HdxRenderTaskParams params =
1830                 _delegate.GetParameter<HdxRenderTaskParams>(
1831                     renderTaskId, HdTokens->params);
1832             params.camera = _activeCameraId;
1833 
1834             _delegate.SetParameter(renderTaskId, HdTokens->params, params);
1835             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1836                 renderTaskId, HdChangeTracker::DirtyParams);
1837         }
1838 
1839         if (!_simpleLightTaskId.IsEmpty()) {
1840             HdxSimpleLightTaskParams params =
1841                 _delegate.GetParameter<HdxSimpleLightTaskParams>(
1842                     _simpleLightTaskId, HdTokens->params);
1843             params.cameraPath = _activeCameraId;
1844             _delegate.SetParameter(_simpleLightTaskId, HdTokens->params,
1845                                    params);
1846             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1847                 _simpleLightTaskId, HdChangeTracker::DirtyParams);
1848         }
1849 
1850         if (!_pickFromRenderBufferTaskId.IsEmpty()) {
1851             HdxPickFromRenderBufferTaskParams params =
1852                 _delegate.GetParameter<HdxPickFromRenderBufferTaskParams>(
1853                     _pickFromRenderBufferTaskId, HdTokens->params);
1854             params.cameraId = _activeCameraId;
1855             _delegate.SetParameter(
1856                 _pickFromRenderBufferTaskId, HdTokens->params, params);
1857             GetRenderIndex()->GetChangeTracker().MarkTaskDirty(
1858                 _pickFromRenderBufferTaskId, HdChangeTracker::DirtyParams);
1859         }
1860     }
1861 }
1862 
1863 static
1864 GfVec4i
_ToVec4i(const GfVec4d & v)1865 _ToVec4i(const GfVec4d &v)
1866 {
1867     return GfVec4i(int(v[0]), int(v[1]), int(v[2]), int(v[3]));
1868 }
1869 
1870 void
_SetCameraFramingForTasks()1871 HdxTaskController::_SetCameraFramingForTasks()
1872 {
1873     // When aovs are in use, the expectation is that each aov is resized to
1874     // the non-masked region and we render only the necessary pixels.
1875     // The composition step (i.e., the present task) uses the viewport
1876     // offset to update the unmasked region of the bound framebuffer.
1877     const GfVec4d adjustedViewport =
1878         _UsingAovs()
1879             ? GfVec4d(0, 0, _viewport[2], _viewport[3])
1880             : _viewport;
1881 
1882     HdChangeTracker &changeTracker = GetRenderIndex()->GetChangeTracker();
1883 
1884     for (SdfPath const& renderTaskId : _renderTaskIds) {
1885         HdxRenderTaskParams params =
1886             _delegate.GetParameter<HdxRenderTaskParams>(
1887                 renderTaskId, HdTokens->params);
1888 
1889         if (params.viewport != adjustedViewport ||
1890             params.framing != _framing ||
1891             params.overrideWindowPolicy != _overrideWindowPolicy) {
1892 
1893             params.framing = _framing;
1894             params.overrideWindowPolicy = _overrideWindowPolicy;
1895             params.viewport = adjustedViewport;
1896             _delegate.SetParameter(renderTaskId, HdTokens->params, params);
1897             changeTracker.MarkTaskDirty(
1898                 renderTaskId, HdChangeTracker::DirtyParams);
1899         }
1900     }
1901 
1902     if (!_pickFromRenderBufferTaskId.IsEmpty()) {
1903         HdxPickFromRenderBufferTaskParams params =
1904             _delegate.GetParameter<HdxPickFromRenderBufferTaskParams>(
1905                 _pickFromRenderBufferTaskId, HdTokens->params);
1906         if (params.viewport != adjustedViewport ||
1907             params.framing != _framing ||
1908             params.overrideWindowPolicy != _overrideWindowPolicy) {
1909 
1910             params.framing = _framing;
1911             params.overrideWindowPolicy = _overrideWindowPolicy;
1912             params.viewport = adjustedViewport;
1913             _delegate.SetParameter(
1914                 _pickFromRenderBufferTaskId, HdTokens->params, params);
1915             changeTracker.MarkTaskDirty(
1916                 _pickFromRenderBufferTaskId, HdChangeTracker::DirtyParams);
1917         }
1918     }
1919 
1920     if (!_presentTaskId.IsEmpty()) {
1921         HdxPresentTaskParams params =
1922             _delegate.GetParameter<HdxPresentTaskParams>(
1923                 _presentTaskId, HdTokens->params);
1924         // The composition step uses the viewport passed in by the application,
1925         // which may have a non-zero offset for things like camera masking.
1926         const GfVec4i dstRegion =
1927             _framing.IsValid()
1928                 ? GfVec4i(0, 0, _renderBufferSize[0], _renderBufferSize[1])
1929                 : _ToVec4i(_viewport);
1930 
1931         if (params.dstRegion != dstRegion) {
1932             params.dstRegion = dstRegion;
1933             _delegate.SetParameter(_presentTaskId, HdTokens->params, params);
1934             changeTracker.MarkTaskDirty(
1935                 _presentTaskId, HdChangeTracker::DirtyParams);
1936         }
1937     }
1938 }
1939 
1940 void
_UpdateAovDimensions(GfVec2i const & dimensions)1941 HdxTaskController::_UpdateAovDimensions(GfVec2i const& dimensions)
1942 {
1943     const GfVec3i dimensions3(dimensions[0], dimensions[1], 1);
1944 
1945     HdChangeTracker &changeTracker = GetRenderIndex()->GetChangeTracker();
1946 
1947     for (auto const& id : _aovBufferIds) {
1948         HdRenderBufferDescriptor desc =
1949             _delegate.GetParameter<HdRenderBufferDescriptor>(id,
1950                 _tokens->renderBufferDescriptor);
1951         if (desc.dimensions != dimensions3) {
1952             desc.dimensions = dimensions3;
1953             _delegate.SetParameter(id, _tokens->renderBufferDescriptor, desc);
1954             changeTracker.MarkBprimDirty(id,
1955                 HdRenderBuffer::DirtyDescription);
1956         }
1957     }
1958 }
1959 
1960 
1961 PXR_NAMESPACE_CLOSE_SCOPE
1962