// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #include "pxr/imaging/hdx/renderTask.h" #include "pxr/imaging/hdx/renderSetupTask.h" #include "pxr/imaging/hdx/tokens.h" #include "pxr/imaging/hdx/debugCodes.h" #include "pxr/imaging/hd/perfLog.h" #include "pxr/imaging/hd/renderDelegate.h" #include "pxr/imaging/hd/renderIndex.h" #include "pxr/imaging/hd/renderPass.h" #include "pxr/imaging/hd/renderPassState.h" #include "pxr/imaging/hd/rprimCollection.h" #include "pxr/imaging/hd/sceneDelegate.h" #include "pxr/imaging/hdSt/renderPass.h" #include "pxr/imaging/hdSt/renderPassShader.h" PXR_NAMESPACE_OPEN_SCOPE // -------------------------------------------------------------------------- // HdxRenderTask::HdxRenderTask(HdSceneDelegate* delegate, SdfPath const& id) : HdxTask(id) , _pass() , _renderTags() , _setupTask() { } HdxRenderTask::~HdxRenderTask() { } bool HdxRenderTask::IsConverged() const { if (_pass) { return _pass->IsConverged(); } return true; } void HdxRenderTask::_Sync(HdSceneDelegate* delegate, HdTaskContext* ctx, HdDirtyBits* dirtyBits) { HD_TRACE_FUNCTION(); HdDirtyBits bits = *dirtyBits; if (bits & HdChangeTracker::DirtyCollection) { VtValue val = delegate->Get(GetId(), HdTokens->collection); HdRprimCollection collection = val.Get(); // Check for cases where the collection is empty (i.e. default // constructed). To do this, the code looks at the root paths, // if it is empty, the collection doesn't refer to any prims at // all. if (collection.GetName().IsEmpty()) { _pass.reset(); } else { if (!_pass) { HdRenderIndex &index = delegate->GetRenderIndex(); HdRenderDelegate *renderDelegate = index.GetRenderDelegate(); _pass = renderDelegate->CreateRenderPass(&index, collection); } else { _pass->SetRprimCollection(collection); } } } if (bits & HdChangeTracker::DirtyParams) { HdxRenderTaskParams params; // if HdxRenderTaskParams is set on this task, create an // HdxRenderSetupTask to unpack them internally. // // As params is optional, the base class helpper can't be used. VtValue valueVt = delegate->Get(GetId(), HdTokens->params); if (valueVt.IsHolding()) { params = valueVt.UncheckedGet(); if (!_setupTask) { // note that _setupTask should have the same id, since it will // use that id to look up params in the scene delegate. // this setup task isn't indexed, so there's no concern // about name conflicts. _setupTask.reset( new HdxRenderSetupTask(delegate, GetId())); } _setupTask->SyncParams(delegate, params); } else { // If params are not set, expect the renderpass state to be passed // in the task context. } } if (bits & HdChangeTracker::DirtyRenderTags) { _renderTags = _GetTaskRenderTags(delegate); } // sync render pass if (_pass) { _pass->Sync(); } *dirtyBits = HdChangeTracker::Clean; } void HdxRenderTask::Prepare(HdTaskContext* ctx, HdRenderIndex* renderIndex) { if (_setupTask) { _setupTask->Prepare(ctx, renderIndex); } if (_pass) { _pass->Prepare(GetRenderTags()); } } void HdxRenderTask::Execute(HdTaskContext* ctx) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); HdRenderPassStateSharedPtr renderPassState = _GetRenderPassState(ctx); if (!TF_VERIFY(renderPassState)) return; if (HdStRenderPassState* extendedState = dynamic_cast(renderPassState.get())) { _SetHdStRenderPassState(ctx, extendedState); } // Bind the render state and render geometry with the rendertags (if any) if (_pass) { renderPassState->Bind(); _pass->Execute(renderPassState, GetRenderTags()); renderPassState->Unbind(); } } const TfTokenVector & HdxRenderTask::GetRenderTags() const { return _renderTags; } HdRenderPassStateSharedPtr HdxRenderTask::_GetRenderPassState(HdTaskContext *ctx) const { if (_setupTask) { // If HdxRenderTaskParams is set on this task, we will have created an // internal HdxRenderSetupTask in _Sync, to sync and unpack the params, // and we should use the resulting resources. return _setupTask->GetRenderPassState(); } else { // Otherwise, we expect an application-created HdxRenderSetupTask to // have run and put the renderpass resources in the task context. // See HdxRenderSetupTask::_Execute. HdRenderPassStateSharedPtr renderPassState; _GetTaskContextData(ctx, HdxTokens->renderPassState, &renderPassState); return renderPassState; } } size_t HdxRenderTask::_GetDrawItemCount() const { if (HdSt_RenderPass* hdStRenderPass = dynamic_cast(_pass.get())) { return hdStRenderPass->GetDrawItemCount(); } else { return 0; } } void HdxRenderTask::_SetHdStRenderPassState(HdTaskContext *ctx, HdStRenderPassState *renderPassState) { // Can't use GetTaskContextData because the lightingShader // is optional. VtValue lightingShader = (*ctx)[HdxTokens->lightingShader]; // it's possible to not set lighting shader to HdRenderPassState. // Hd_DefaultLightingShader will be used in that case. if (lightingShader.IsHolding()) { renderPassState->SetLightingShader( lightingShader.Get()); } // Selection Setup // Note that selectionTask comes after renderTask, so that // it can access rprimIDs populated in RenderTask::_Sync. VtValue vo = (*ctx)[HdxTokens->selectionOffsets]; VtValue vu = (*ctx)[HdxTokens->selectionUniforms]; VtValue vc = (*ctx)[HdxTokens->selectionPointColors]; HdStRenderPassShaderSharedPtr renderPassShader = renderPassState->GetRenderPassShader(); if (!vo.IsEmpty() && !vu.IsEmpty() && !vc.IsEmpty()) { HdBufferArrayRangeSharedPtr obar = vo.Get(); HdBufferArrayRangeSharedPtr ubar = vu.Get(); HdBufferArrayRangeSharedPtr cbar = vc.Get(); renderPassShader->AddBufferBinding( HdBindingRequest(HdBinding::SSBO, HdxTokens->selectionOffsets, obar, /*interleave*/false)); renderPassShader->AddBufferBinding( HdBindingRequest(HdBinding::UBO, HdxTokens->selectionUniforms, ubar, /*interleave*/true)); renderPassShader->AddBufferBinding( HdBindingRequest(HdBinding::SSBO, HdxTokens->selectionPointColors, cbar, /*interleave*/false)); } else { renderPassShader->RemoveBufferBinding(HdxTokens->selectionOffsets); renderPassShader->RemoveBufferBinding(HdxTokens->selectionUniforms); renderPassShader->RemoveBufferBinding(HdxTokens->selectionPointColors); } } PXR_NAMESPACE_CLOSE_SCOPE