Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mours <pmours@nvidia.com>2022-03-23 18:07:43 +0300
committerPatrick Mours <pmours@nvidia.com>2022-03-23 18:39:05 +0300
commitd350976ba06d4ef93aa53fc4cd9da57be46ae924 (patch)
tree808f38e6b0c663c7a50f1d98619c96ca0bd82018 /intern/cycles/hydra/render_pass.cpp
parent827e9ccb29dd50d155972444d608c35cf4698d6a (diff)
Cycles: Add Hydra render delegate
This patch adds a Hydra render delegate to Cycles, allowing Cycles to be used for rendering in applications that provide a Hydra viewport. The implementation was written from scratch against Cycles X, for integration into the Blender repository to make it possible to continue developing it in step with the rest of Cycles. For this purpose it follows the style of the rest of the Cycles code and can be built with a CMake option (`WITH_CYCLES_HYDRA_RENDER_DELEGATE=1`) similar to the existing standalone version of Cycles. Since Hydra render delegates need to be built against the exact USD version and other dependencies as the target application is using, this is intended to be built separate from Blender (`WITH_BLENDER=0` CMake option) and with support for library versions different from what Blender is using. As such the CMake build scripts for Windows had to be modified slightly, so that the Cycles Hydra render delegate can e.g. be built with MSVC 2017 again even though Blender requires MSVC 2019 now, and it's possible to specify custom paths to the USD SDK etc. The codebase supports building against the latest USD release 22.03 and all the way back to USD 20.08 (with some limitations). Reviewed By: brecht, LazyDodo Differential Revision: https://developer.blender.org/D14398
Diffstat (limited to 'intern/cycles/hydra/render_pass.cpp')
-rw-r--r--intern/cycles/hydra/render_pass.cpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/intern/cycles/hydra/render_pass.cpp b/intern/cycles/hydra/render_pass.cpp
new file mode 100644
index 00000000000..9d47dfc5c8d
--- /dev/null
+++ b/intern/cycles/hydra/render_pass.cpp
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2022 NVIDIA Corporation
+ * Copyright 2022 Blender Foundation */
+
+#include "hydra/render_pass.h"
+#include "hydra/camera.h"
+#include "hydra/display_driver.h"
+#include "hydra/output_driver.h"
+#include "hydra/render_buffer.h"
+#include "hydra/render_delegate.h"
+#include "hydra/session.h"
+#include "scene/camera.h"
+#include "scene/integrator.h"
+#include "scene/scene.h"
+#include "session/session.h"
+
+#include <pxr/imaging/hd/renderPassState.h>
+
+HDCYCLES_NAMESPACE_OPEN_SCOPE
+
+HdCyclesRenderPass::HdCyclesRenderPass(HdRenderIndex *index,
+ HdRprimCollection const &collection,
+ HdCyclesSession *renderParam)
+ : HdRenderPass(index, collection), _renderParam(renderParam)
+{
+ Session *const session = _renderParam->session;
+ // Reset cancel state so session thread can continue rendering
+ session->progress.reset();
+
+ session->set_output_driver(make_unique<HdCyclesOutputDriver>(renderParam));
+
+ const auto renderDelegate = static_cast<const HdCyclesDelegate *>(
+ GetRenderIndex()->GetRenderDelegate());
+ if (renderDelegate->IsDisplaySupported()) {
+ session->set_display_driver(
+ make_unique<HdCyclesDisplayDriver>(renderParam, renderDelegate->GetHgi()));
+ }
+}
+
+HdCyclesRenderPass::~HdCyclesRenderPass()
+{
+ Session *const session = _renderParam->session;
+ session->cancel(true);
+}
+
+bool HdCyclesRenderPass::IsConverged() const
+{
+ for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
+ if (aovBinding.renderBuffer && !aovBinding.renderBuffer->IsConverged()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void HdCyclesRenderPass::ResetConverged()
+{
+ for (const HdRenderPassAovBinding &aovBinding : _renderParam->GetAovBindings()) {
+ if (const auto renderBuffer = static_cast<HdCyclesRenderBuffer *>(aovBinding.renderBuffer)) {
+ renderBuffer->SetConverged(false);
+ }
+ }
+}
+
+void HdCyclesRenderPass::_Execute(const HdRenderPassStateSharedPtr &renderPassState,
+ const TfTokenVector &renderTags)
+{
+ Scene *const scene = _renderParam->session->scene;
+ Session *const session = _renderParam->session;
+
+ if (session->progress.get_cancel()) {
+ return; // Something went wrong and cannot continue without recreating the session
+ }
+
+ if (scene->mutex.try_lock()) {
+ const auto renderDelegate = static_cast<HdCyclesDelegate *>(
+ GetRenderIndex()->GetRenderDelegate());
+
+ const unsigned int settingsVersion = renderDelegate->GetRenderSettingsVersion();
+
+ // Update requested AOV bindings
+ const HdRenderPassAovBindingVector &aovBindings = renderPassState->GetAovBindings();
+ if (_renderParam->GetAovBindings() != aovBindings ||
+ // Need to resync passes when denoising is enabled or disabled to update the pass mode
+ (settingsVersion != _lastSettingsVersion &&
+ scene->integrator->use_denoise_is_modified())) {
+ _renderParam->SyncAovBindings(aovBindings);
+
+ if (renderDelegate->IsDisplaySupported()) {
+ // Update display pass to the first requested color AOV
+ HdRenderPassAovBinding displayAovBinding = !aovBindings.empty() ? aovBindings.front() :
+ HdRenderPassAovBinding();
+ if (displayAovBinding.aovName == HdAovTokens->color && displayAovBinding.renderBuffer) {
+ _renderParam->SetDisplayAovBinding(displayAovBinding);
+ }
+ else {
+ _renderParam->SetDisplayAovBinding(HdRenderPassAovBinding());
+ }
+ }
+ }
+
+ // Update camera dimensions to the viewport size
+#if PXR_VERSION >= 2102
+ CameraUtilFraming framing = renderPassState->GetFraming();
+ if (!framing.IsValid()) {
+ const GfVec4f vp = renderPassState->GetViewport();
+ framing = CameraUtilFraming(GfRect2i(GfVec2i(0), int(vp[2]), int(vp[3])));
+ }
+
+ scene->camera->set_full_width(framing.dataWindow.GetWidth());
+ scene->camera->set_full_height(framing.dataWindow.GetHeight());
+#else
+ const GfVec4f vp = renderPassState->GetViewport();
+ scene->camera->set_full_width(int(vp[2]));
+ scene->camera->set_full_height(int(vp[3]));
+#endif
+
+ if (const auto camera = static_cast<const HdCyclesCamera *>(renderPassState->GetCamera())) {
+ camera->ApplyCameraSettings(scene->camera);
+ }
+ else {
+ HdCyclesCamera::ApplyCameraSettings(renderPassState->GetWorldToViewMatrix(),
+ renderPassState->GetProjectionMatrix(),
+ renderPassState->GetClipPlanes(),
+ scene->camera);
+ }
+
+ // Reset session if the session, scene, camera or AOV bindings changed
+ if (scene->need_reset() || settingsVersion != _lastSettingsVersion) {
+ _lastSettingsVersion = settingsVersion;
+
+ // Reset convergence state of all render buffers
+ ResetConverged();
+
+ BufferParams buffer_params;
+#if PXR_VERSION >= 2102
+ buffer_params.full_x = static_cast<int>(framing.displayWindow.GetMin()[0]);
+ buffer_params.full_y = static_cast<int>(framing.displayWindow.GetMin()[1]);
+ buffer_params.full_width = static_cast<int>(framing.displayWindow.GetSize()[0]);
+ buffer_params.full_height = static_cast<int>(framing.displayWindow.GetSize()[1]);
+
+ buffer_params.window_x = framing.dataWindow.GetMinX() - buffer_params.full_x;
+ buffer_params.window_y = framing.dataWindow.GetMinY() - buffer_params.full_y;
+ buffer_params.window_width = framing.dataWindow.GetWidth();
+ buffer_params.window_height = framing.dataWindow.GetHeight();
+
+ buffer_params.width = buffer_params.window_width;
+ buffer_params.height = buffer_params.window_height;
+#else
+ buffer_params.width = static_cast<int>(vp[2]);
+ buffer_params.height = static_cast<int>(vp[3]);
+ buffer_params.full_width = buffer_params.width;
+ buffer_params.full_height = buffer_params.height;
+ buffer_params.window_width = buffer_params.width;
+ buffer_params.window_height = buffer_params.height;
+#endif
+
+ session->reset(session->params, buffer_params);
+ }
+
+ scene->mutex.unlock();
+
+ // Start Cycles render thread if not already running
+ session->start();
+ }
+
+ session->draw();
+}
+
+void HdCyclesRenderPass::_MarkCollectionDirty()
+{
+}
+
+HDCYCLES_NAMESPACE_CLOSE_SCOPE