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:
Diffstat (limited to 'intern/cycles/hydra/render_delegate.cpp')
-rw-r--r--intern/cycles/hydra/render_delegate.cpp514
1 files changed, 514 insertions, 0 deletions
diff --git a/intern/cycles/hydra/render_delegate.cpp b/intern/cycles/hydra/render_delegate.cpp
new file mode 100644
index 00000000000..748b6a66e1e
--- /dev/null
+++ b/intern/cycles/hydra/render_delegate.cpp
@@ -0,0 +1,514 @@
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2022 NVIDIA Corporation
+ * Copyright 2022 Blender Foundation */
+
+#include "hydra/render_delegate.h"
+#include "hydra/camera.h"
+#include "hydra/curves.h"
+#include "hydra/field.h"
+#include "hydra/instancer.h"
+#include "hydra/light.h"
+#include "hydra/material.h"
+#include "hydra/mesh.h"
+#include "hydra/node_util.h"
+#include "hydra/pointcloud.h"
+#include "hydra/render_buffer.h"
+#include "hydra/render_pass.h"
+#include "hydra/session.h"
+#include "hydra/volume.h"
+#include "scene/integrator.h"
+#include "scene/scene.h"
+#include "session/session.h"
+
+#include <pxr/base/tf/getenv.h>
+#include <pxr/imaging/hd/extComputation.h>
+#include <pxr/imaging/hgi/tokens.h>
+
+HDCYCLES_NAMESPACE_OPEN_SCOPE
+
+// clang-format off
+TF_DEFINE_PRIVATE_TOKENS(_tokens,
+ (cycles)
+ (openvdbAsset)
+);
+
+TF_DEFINE_PRIVATE_TOKENS(HdCyclesRenderSettingsTokens,
+ ((device, "cycles:device"))
+ ((threads, "cycles:threads"))
+ ((time_limit, "cycles:time_limit"))
+ ((samples, "cycles:samples"))
+ ((sample_offset, "cycles:sample_offset"))
+);
+// clang-format on
+
+namespace {
+
+const TfTokenVector kSupportedRPrimTypes = {
+ HdPrimTypeTokens->basisCurves,
+ HdPrimTypeTokens->mesh,
+ HdPrimTypeTokens->points,
+#ifdef WITH_OPENVDB
+ HdPrimTypeTokens->volume,
+#endif
+};
+
+const TfTokenVector kSupportedSPrimTypes = {
+ HdPrimTypeTokens->camera,
+ HdPrimTypeTokens->material,
+ HdPrimTypeTokens->diskLight,
+ HdPrimTypeTokens->distantLight,
+ HdPrimTypeTokens->domeLight,
+ HdPrimTypeTokens->rectLight,
+ HdPrimTypeTokens->sphereLight,
+ HdPrimTypeTokens->extComputation,
+};
+
+const TfTokenVector kSupportedBPrimTypes = {
+ HdPrimTypeTokens->renderBuffer,
+#ifdef WITH_OPENVDB
+ _tokens->openvdbAsset,
+#endif
+};
+
+SessionParams GetSessionParams(const HdRenderSettingsMap &settings)
+{
+ SessionParams params;
+ params.threads = 0;
+ params.background = false;
+ params.use_resolution_divider = false;
+
+ HdRenderSettingsMap::const_iterator it;
+
+ // Pull all setting that contribute to device creation first
+ it = settings.find(HdCyclesRenderSettingsTokens->threads);
+ if (it != settings.end()) {
+ params.threads = VtValue::Cast<int>(it->second).GetWithDefault(params.threads);
+ }
+
+ // Get the Cycles device from settings or environment, falling back to CPU
+ std::string deviceType = Device::string_from_type(DEVICE_CPU);
+ it = settings.find(HdCyclesRenderSettingsTokens->device);
+ if (it != settings.end()) {
+ deviceType = VtValue::Cast<std::string>(it->second).GetWithDefault(deviceType);
+ }
+ else {
+ const std::string deviceTypeEnv = TfGetenv("CYCLES_DEVICE");
+ if (!deviceTypeEnv.empty()) {
+ deviceType = deviceTypeEnv;
+ }
+ }
+
+ // Move to all uppercase for Device::type_from_string
+ std::transform(deviceType.begin(), deviceType.end(), deviceType.begin(), ::toupper);
+
+ vector<DeviceInfo> devices = Device::available_devices(
+ DEVICE_MASK(Device::type_from_string(deviceType.c_str())));
+ if (devices.empty()) {
+ devices = Device::available_devices(DEVICE_MASK_CPU);
+ if (!devices.empty()) {
+ params.device = devices.front();
+ }
+ }
+ else {
+ params.device = Device::get_multi_device(devices, params.threads, params.background);
+ }
+
+ return params;
+}
+
+} // namespace
+
+HdCyclesDelegate::HdCyclesDelegate(const HdRenderSettingsMap &settingsMap, Session *session_)
+ : HdRenderDelegate()
+{
+ _renderParam = session_ ? std::make_unique<HdCyclesSession>(session_) :
+ std::make_unique<HdCyclesSession>(GetSessionParams(settingsMap));
+
+ // If the delegate owns the session, pull any remaining settings
+ if (!session_) {
+ for (const auto &setting : settingsMap) {
+ // Skip over the settings known to be used for initialization only
+ if (setting.first == HdCyclesRenderSettingsTokens->device ||
+ setting.first == HdCyclesRenderSettingsTokens->threads) {
+ continue;
+ }
+
+ SetRenderSetting(setting.first, setting.second);
+ }
+ }
+}
+
+HdCyclesDelegate::~HdCyclesDelegate()
+{
+}
+
+void HdCyclesDelegate::SetDrivers(const HdDriverVector &drivers)
+{
+ for (HdDriver *hdDriver : drivers) {
+ if (hdDriver->name == HgiTokens->renderDriver && hdDriver->driver.IsHolding<Hgi *>()) {
+ _hgi = hdDriver->driver.UncheckedGet<Hgi *>();
+ break;
+ }
+ }
+}
+
+bool HdCyclesDelegate::IsDisplaySupported() const
+{
+#ifdef _WIN32
+ return _hgi && _hgi->GetAPIName() == HgiTokens->OpenGL;
+#else
+ return false;
+#endif
+}
+
+const TfTokenVector &HdCyclesDelegate::GetSupportedRprimTypes() const
+{
+ return kSupportedRPrimTypes;
+}
+
+const TfTokenVector &HdCyclesDelegate::GetSupportedSprimTypes() const
+{
+ return kSupportedSPrimTypes;
+}
+
+const TfTokenVector &HdCyclesDelegate::GetSupportedBprimTypes() const
+{
+ return kSupportedBPrimTypes;
+}
+
+HdRenderParam *HdCyclesDelegate::GetRenderParam() const
+{
+ return _renderParam.get();
+}
+
+HdResourceRegistrySharedPtr HdCyclesDelegate::GetResourceRegistry() const
+{
+ return HdResourceRegistrySharedPtr();
+}
+
+bool HdCyclesDelegate::IsPauseSupported() const
+{
+ return true;
+}
+
+bool HdCyclesDelegate::Pause()
+{
+ _renderParam->session->set_pause(true);
+ return true;
+}
+
+bool HdCyclesDelegate::Resume()
+{
+ _renderParam->session->set_pause(false);
+ return true;
+}
+
+HdRenderPassSharedPtr HdCyclesDelegate::CreateRenderPass(HdRenderIndex *index,
+ const HdRprimCollection &collection)
+{
+ return HdRenderPassSharedPtr(new HdCyclesRenderPass(index, collection, _renderParam.get()));
+}
+
+HdInstancer *HdCyclesDelegate::CreateInstancer(HdSceneDelegate *delegate,
+ const SdfPath &instancerId
+#if PXR_VERSION < 2102
+ ,
+ const SdfPath &parentId
+#endif
+)
+{
+ return new HdCyclesInstancer(delegate,
+ instancerId
+#if PXR_VERSION < 2102
+ ,
+ parentId
+#endif
+ );
+}
+
+void HdCyclesDelegate::DestroyInstancer(HdInstancer *instancer)
+{
+ delete instancer;
+}
+
+HdRprim *HdCyclesDelegate::CreateRprim(const TfToken &typeId,
+ const SdfPath &rprimId
+#if PXR_VERSION < 2102
+ ,
+ const SdfPath &instancerId
+#endif
+)
+{
+ if (typeId == HdPrimTypeTokens->mesh) {
+ return new HdCyclesMesh(rprimId
+#if PXR_VERSION < 2102
+ ,
+ instancerId
+#endif
+ );
+ }
+ if (typeId == HdPrimTypeTokens->basisCurves) {
+ return new HdCyclesCurves(rprimId
+#if PXR_VERSION < 2102
+ ,
+ instancerId
+#endif
+ );
+ }
+ if (typeId == HdPrimTypeTokens->points) {
+ return new HdCyclesPoints(rprimId
+#if PXR_VERSION < 2102
+ ,
+ instancerId
+#endif
+ );
+ }
+#ifdef WITH_OPENVDB
+ if (typeId == HdPrimTypeTokens->volume) {
+ return new HdCyclesVolume(rprimId
+# if PXR_VERSION < 2102
+ ,
+ instancerId
+# endif
+ );
+ }
+#endif
+
+ TF_CODING_ERROR("Unknown Rprim type %s", typeId.GetText());
+ return nullptr;
+}
+
+void HdCyclesDelegate::DestroyRprim(HdRprim *rPrim)
+{
+ delete rPrim;
+}
+
+HdSprim *HdCyclesDelegate::CreateSprim(const TfToken &typeId, const SdfPath &sprimId)
+{
+ if (typeId == HdPrimTypeTokens->camera) {
+ return new HdCyclesCamera(sprimId);
+ }
+ if (typeId == HdPrimTypeTokens->material) {
+ return new HdCyclesMaterial(sprimId);
+ }
+ if (typeId == HdPrimTypeTokens->diskLight || typeId == HdPrimTypeTokens->distantLight ||
+ typeId == HdPrimTypeTokens->domeLight || typeId == HdPrimTypeTokens->rectLight ||
+ typeId == HdPrimTypeTokens->sphereLight) {
+ return new HdCyclesLight(sprimId, typeId);
+ }
+ if (typeId == HdPrimTypeTokens->extComputation) {
+ return new HdExtComputation(sprimId);
+ }
+
+ TF_CODING_ERROR("Unknown Sprim type %s", typeId.GetText());
+ return nullptr;
+}
+
+HdSprim *HdCyclesDelegate::CreateFallbackSprim(const TfToken &typeId)
+{
+ return CreateSprim(typeId, SdfPath::EmptyPath());
+}
+
+void HdCyclesDelegate::DestroySprim(HdSprim *sPrim)
+{
+ delete sPrim;
+}
+
+HdBprim *HdCyclesDelegate::CreateBprim(const TfToken &typeId, const SdfPath &bprimId)
+{
+ if (typeId == HdPrimTypeTokens->renderBuffer) {
+ return new HdCyclesRenderBuffer(bprimId);
+ }
+#ifdef WITH_OPENVDB
+ if (typeId == _tokens->openvdbAsset) {
+ return new HdCyclesField(bprimId, typeId);
+ }
+#endif
+
+ TF_RUNTIME_ERROR("Unknown Bprim type %s", typeId.GetText());
+ return nullptr;
+}
+
+HdBprim *HdCyclesDelegate::CreateFallbackBprim(const TfToken &typeId)
+{
+ return CreateBprim(typeId, SdfPath::EmptyPath());
+}
+
+void HdCyclesDelegate::DestroyBprim(HdBprim *bPrim)
+{
+ delete bPrim;
+}
+
+void HdCyclesDelegate::CommitResources(HdChangeTracker *tracker)
+{
+ TF_UNUSED(tracker);
+
+ const SceneLock lock(_renderParam.get());
+
+ _renderParam->UpdateScene();
+}
+
+TfToken HdCyclesDelegate::GetMaterialBindingPurpose() const
+{
+ return HdTokens->full;
+}
+
+#if HD_API_VERSION < 41
+TfToken HdCyclesDelegate::GetMaterialNetworkSelector() const
+{
+ return _tokens->cycles;
+}
+#else
+TfTokenVector HdCyclesDelegate::GetMaterialRenderContexts() const
+{
+ return {_tokens->cycles};
+}
+#endif
+
+VtDictionary HdCyclesDelegate::GetRenderStats() const
+{
+ const Stats &stats = _renderParam->session->stats;
+ const Progress &progress = _renderParam->session->progress;
+
+ double totalTime, renderTime;
+ progress.get_time(totalTime, renderTime);
+ double fractionDone = progress.get_progress();
+
+ std::string status, substatus;
+ progress.get_status(status, substatus);
+ if (!substatus.empty()) {
+ status += " | " + substatus;
+ }
+
+ return {{"rendererName", VtValue("Cycles")},
+ {"rendererVersion", VtValue(GfVec3i(0, 0, 0))},
+ {"percentDone", VtValue(floor_to_int(fractionDone * 100))},
+ {"fractionDone", VtValue(fractionDone)},
+ {"loadClockTime", VtValue(totalTime - renderTime)},
+ {"peakMemory", VtValue(stats.mem_peak)},
+ {"totalClockTime", VtValue(totalTime)},
+ {"totalMemory", VtValue(stats.mem_used)},
+ {"renderProgressAnnotation", VtValue(status)}};
+}
+
+HdAovDescriptor HdCyclesDelegate::GetDefaultAovDescriptor(const TfToken &name) const
+{
+ if (name == HdAovTokens->color) {
+ HdFormat colorFormat = HdFormatFloat32Vec4;
+ if (IsDisplaySupported()) {
+ // Can use Cycles 'DisplayDriver' in OpenGL, but it only supports 'half4' format
+ colorFormat = HdFormatFloat16Vec4;
+ }
+
+ return HdAovDescriptor(colorFormat, false, VtValue(GfVec4f(0.0f)));
+ }
+ if (name == HdAovTokens->depth) {
+ return HdAovDescriptor(HdFormatFloat32, false, VtValue(1.0f));
+ }
+ if (name == HdAovTokens->normal) {
+ return HdAovDescriptor(HdFormatFloat32Vec3, false, VtValue(GfVec3f(0.0f)));
+ }
+ if (name == HdAovTokens->primId || name == HdAovTokens->instanceId ||
+ name == HdAovTokens->elementId) {
+ return HdAovDescriptor(HdFormatInt32, false, VtValue(-1));
+ }
+
+ return HdAovDescriptor();
+}
+
+HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() const
+{
+ Scene *const scene = _renderParam->session->scene;
+
+ HdRenderSettingDescriptorList descriptors;
+
+ descriptors.push_back({
+ "Time Limit",
+ HdCyclesRenderSettingsTokens->time_limit,
+ VtValue(0.0),
+ });
+ descriptors.push_back({
+ "Sample Count",
+ HdCyclesRenderSettingsTokens->samples,
+ VtValue(1024),
+ });
+ descriptors.push_back({
+ "Sample Offset",
+ HdCyclesRenderSettingsTokens->sample_offset,
+ VtValue(0),
+ });
+
+ for (const SocketType &socket : scene->integrator->type->inputs) {
+ descriptors.push_back({socket.ui_name.string(),
+ TfToken("cycles:integrator:" + socket.name.string()),
+ GetNodeValue(scene->integrator, socket)});
+ }
+
+ return descriptors;
+}
+
+void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS::VtValue &value)
+{
+ Scene *const scene = _renderParam->session->scene;
+ Session *const session = _renderParam->session;
+
+ if (key == HdCyclesRenderSettingsTokens->time_limit) {
+ session->set_time_limit(
+ VtValue::Cast<double>(value).GetWithDefault(session->params.time_limit));
+ }
+ else if (key == HdCyclesRenderSettingsTokens->samples) {
+ int samples = VtValue::Cast<int>(value).GetWithDefault(session->params.samples);
+ samples = std::min(std::max(1, samples), Integrator::MAX_SAMPLES);
+ session->set_samples(samples);
+ }
+ else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
+ session->params.sample_offset = VtValue::Cast<int>(value).GetWithDefault(
+ session->params.sample_offset);
+ ++_settingsVersion;
+ }
+ else {
+ const std::string &keyString = key.GetString();
+ if (keyString.rfind("cycles:integrator:", 0) == 0) {
+ ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
+ if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
+ SetNodeValue(scene->integrator, *socket, value);
+ ++_settingsVersion;
+ }
+ }
+ }
+}
+
+VtValue HdCyclesDelegate::GetRenderSetting(const TfToken &key) const
+{
+ Scene *const scene = _renderParam->session->scene;
+ Session *const session = _renderParam->session;
+
+ if (key == HdCyclesRenderSettingsTokens->device) {
+ return VtValue(TfToken(Device::string_from_type(session->params.device.type)));
+ }
+ else if (key == HdCyclesRenderSettingsTokens->threads) {
+ return VtValue(session->params.threads);
+ }
+ else if (key == HdCyclesRenderSettingsTokens->time_limit) {
+ return VtValue(session->params.time_limit);
+ }
+ else if (key == HdCyclesRenderSettingsTokens->samples) {
+ return VtValue(session->params.samples);
+ }
+ else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
+ return VtValue(session->params.sample_offset);
+ }
+ else {
+ const std::string &keyString = key.GetString();
+ if (keyString.rfind("cycles:integrator:", 0) == 0) {
+ ustring socketName(keyString, sizeof("cycles:integrator:") - 1);
+ if (const SocketType *socket = scene->integrator->type->find_input(socketName)) {
+ return GetNodeValue(scene->integrator, *socket);
+ }
+ }
+ }
+
+ return VtValue();
+}
+
+HDCYCLES_NAMESPACE_CLOSE_SCOPE