Cycles: add USD as a file format for Cycles standalone rendering

Long term, this should replace the XML format. This reuses the Hydra render
delegate implementation, and so supports the same features. The same command
line options and GUI work for both XML and USD also.

The implementation of this is still disabled, waiting for some refactoring of
USD library linking. However we want the Cycles code to be in sync between
repositories for the 3.2 release.

Ref T96731
This commit is contained in:
Brecht Van Lommel 2022-04-17 07:01:13 +02:00
parent 060a50a5f7
commit 9b92ce9dc0
11 changed files with 181 additions and 12 deletions

View File

@ -23,6 +23,10 @@
#include "util/unique_ptr.h"
#include "util/version.h"
#ifdef WITH_USD
# include "hydra/file_reader.h"
#endif
#include "app/cycles_xml.h"
#include "app/oiio_output_driver.h"
@ -94,8 +98,16 @@ static void scene_init()
{
options.scene = options.session->scene;
/* Read XML */
xml_read_file(options.scene, options.filepath.c_str());
/* Read XML or USD */
#ifdef WITH_USD
if (!string_endswith(string_to_lower(options.filepath), ".xml")) {
HD_CYCLES_NS::HdCyclesFileReader::read(options.session, options.filepath.c_str());
}
else
#endif
{
xml_read_file(options.scene, options.filepath.c_str());
}
/* Camera width/height override? */
if (!(options.width == 0 || options.height == 0)) {

View File

@ -27,6 +27,7 @@ set(INC_HD_CYCLES
config.h
curves.h
field.h
file_reader.h
geometry.h
geometry.inl
instancer.h
@ -48,6 +49,7 @@ set(SRC_HD_CYCLES
curves.cpp
camera.cpp
field.cpp
file_reader.cpp
instancer.cpp
light.cpp
material.cpp

View File

@ -0,0 +1,121 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include "hydra/file_reader.h"
#include "hydra/camera.h"
#include "hydra/render_delegate.h"
#include "util/path.h"
#include "util/unique_ptr.h"
#include "scene/scene.h"
#include <pxr/base/plug/registry.h>
#include <pxr/imaging/hd/dirtyList.h>
#include <pxr/imaging/hd/renderDelegate.h>
#include <pxr/imaging/hd/renderIndex.h>
#include <pxr/imaging/hd/rprimCollection.h>
#include <pxr/imaging/hd/task.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdGeom/camera.h>
#include <pxr/usdImaging/usdImaging/delegate.h>
HDCYCLES_NAMESPACE_OPEN_SCOPE
/* Dummy task whose only purpose is to provide render tag tokens to the render index. */
class DummyHdTask : public HdTask {
public:
DummyHdTask(HdSceneDelegate *delegate, SdfPath const &id)
: HdTask(id), tags({HdRenderTagTokens->geometry, HdRenderTagTokens->render})
{
}
protected:
void Sync(HdSceneDelegate *delegate, HdTaskContext *ctx, HdDirtyBits *dirtyBits) override
{
}
void Prepare(HdTaskContext *ctx, HdRenderIndex *render_index) override
{
}
void Execute(HdTaskContext *ctx) override
{
}
const TfTokenVector &GetRenderTags() const override
{
return tags;
}
TfTokenVector tags;
};
void HdCyclesFileReader::read(Session *session, const char *filepath, const bool use_camera)
{
/* Initialize USD. */
PlugRegistry::GetInstance().RegisterPlugins(path_get("usd"));
/* Open Stage. */
UsdStageRefPtr stage = UsdStage::Open(filepath);
if (!stage) {
fprintf(stderr, "%s read error\n", filepath);
return;
}
/* Init paths. */
SdfPath root_path = SdfPath::AbsoluteRootPath();
SdfPath task_path("/_hdCycles/DummyHdTask");
/* Create render delegate. */
HdRenderSettingsMap settings_map;
HdCyclesDelegate render_delegate(settings_map, session, true);
/* Create render index and scene delegate. */
unique_ptr<HdRenderIndex> render_index(HdRenderIndex::New(&render_delegate, {}));
unique_ptr<UsdImagingDelegate> scene_delegate = make_unique<UsdImagingDelegate>(
render_index.get(), root_path);
/* Add render tags and collection to render index. */
HdRprimCollection collection(HdTokens->geometry, HdReprSelector(HdReprTokens->smoothHull));
collection.SetRootPath(root_path);
render_index->InsertTask<DummyHdTask>(scene_delegate.get(), task_path);
#if PXR_VERSION < 2111
HdDirtyListSharedPtr dirty_list = std::make_shared<HdDirtyList>(collection,
*(render_index.get()));
render_index->EnqueuePrimsToSync(dirty_list, collection);
#else
render_index->EnqueueCollectionToSync(collection);
#endif
/* Create prims. */
const UsdPrim &stage_root = stage->GetPseudoRoot();
scene_delegate->Populate(stage_root.GetStage()->GetPrimAtPath(root_path), {});
/* Sync prims. */
HdTaskContext task_context;
HdTaskSharedPtrVector tasks;
tasks.push_back(render_index->GetTask(task_path));
render_index->SyncAll(&tasks, &task_context);
render_delegate.CommitResources(&render_index->GetChangeTracker());
/* Use first camera in stage.
* TODO: get camera from UsdRender if available. */
if (use_camera) {
for (UsdPrim const &prim : stage->Traverse()) {
if (prim.IsA<UsdGeomCamera>()) {
HdSprim *sprim = render_index->GetSprim(HdPrimTypeTokens->camera, prim.GetPath());
if (sprim) {
HdCyclesCamera *camera = dynamic_cast<HdCyclesCamera *>(sprim);
camera->ApplyCameraSettings(session->scene->camera);
break;
}
}
}
}
}
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include "hydra/config.h"
#include "session/session.h"
HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesFileReader {
public:
static void read(Session *session, const char *filepath, const bool use_camera = true);
};
HDCYCLES_NAMESPACE_CLOSE_SCOPE

View File

@ -192,11 +192,16 @@ void HdCyclesGeometry<Base, CyclesBase>::Finalize(HdRenderParam *renderParam)
}
const SceneLock lock(renderParam);
const bool keep_nodes = static_cast<const HdCyclesSession *>(renderParam)->keep_nodes;
lock.scene->delete_node(_geom);
if (!keep_nodes) {
lock.scene->delete_node(_geom);
}
_geom = nullptr;
lock.scene->delete_nodes(set<Object *>(_instances.begin(), _instances.end()));
if (!keep_nodes) {
lock.scene->delete_nodes(set<Object *>(_instances.begin(), _instances.end()));
}
_instances.clear();
_instances.shrink_to_fit();
}

View File

@ -352,8 +352,12 @@ void HdCyclesLight::Finalize(HdRenderParam *renderParam)
}
const SceneLock lock(renderParam);
const bool keep_nodes = static_cast<const HdCyclesSession *>(renderParam)->keep_nodes;
if (!keep_nodes) {
lock.scene->delete_node(_light);
}
lock.scene->delete_node(_light);
_light = nullptr;
}

View File

@ -562,10 +562,13 @@ void HdCyclesMaterial::Finalize(HdRenderParam *renderParam)
}
const SceneLock lock(renderParam);
const bool keep_nodes = static_cast<const HdCyclesSession *>(renderParam)->keep_nodes;
_nodes.clear();
lock.scene->delete_node(_shader);
if (!keep_nodes) {
lock.scene->delete_node(_shader);
}
_shader = nullptr;
}

View File

@ -119,10 +119,12 @@ SessionParams GetSessionParams(const HdRenderSettingsMap &settings)
} // namespace
HdCyclesDelegate::HdCyclesDelegate(const HdRenderSettingsMap &settingsMap, Session *session_)
HdCyclesDelegate::HdCyclesDelegate(const HdRenderSettingsMap &settingsMap,
Session *session_,
const bool keep_nodes)
: HdRenderDelegate()
{
_renderParam = session_ ? std::make_unique<HdCyclesSession>(session_) :
_renderParam = session_ ? std::make_unique<HdCyclesSession>(session_, keep_nodes) :
std::make_unique<HdCyclesSession>(GetSessionParams(settingsMap));
// If the delegate owns the session, pull any remaining settings

View File

@ -14,7 +14,8 @@ HDCYCLES_NAMESPACE_OPEN_SCOPE
class HdCyclesDelegate final : public PXR_NS::HdRenderDelegate {
public:
HdCyclesDelegate(const PXR_NS::HdRenderSettingsMap &settingsMap,
CCL_NS::Session *session_ = nullptr);
CCL_NS::Session *session_ = nullptr,
const bool keep_nodes = false);
~HdCyclesDelegate() override;
void SetDrivers(const PXR_NS::HdDriverVector &drivers) override;

View File

@ -36,12 +36,13 @@ SceneLock::~SceneLock()
{
}
HdCyclesSession::HdCyclesSession(Session *session_) : session(session_), _ownCyclesSession(false)
HdCyclesSession::HdCyclesSession(Session *session_, const bool keep_nodes)
: session(session_), keep_nodes(true), _ownCyclesSession(false)
{
}
HdCyclesSession::HdCyclesSession(const SessionParams &params)
: session(new Session(params, SceneParams())), _ownCyclesSession(true)
: session(new Session(params, SceneParams())), keep_nodes(false), _ownCyclesSession(true)
{
Scene *const scene = session->scene;

View File

@ -23,7 +23,7 @@ struct SceneLock {
class HdCyclesSession final : public PXR_NS::HdRenderParam {
public:
HdCyclesSession(CCL_NS::Session *session_);
HdCyclesSession(CCL_NS::Session *session_, const bool keep_nodes);
HdCyclesSession(const CCL_NS::SessionParams &params);
~HdCyclesSession() override;
@ -59,6 +59,7 @@ class HdCyclesSession final : public PXR_NS::HdRenderParam {
void RemoveAovBinding(PXR_NS::HdRenderBuffer *renderBuffer);
CCL_NS::Session *session;
bool keep_nodes;
private:
const bool _ownCyclesSession;