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