Skip to content

Commit

Permalink
Refactoring to add support for cacheID in the hydra delegate Autodesk…
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastienblor committed Sep 11, 2023
1 parent 39bc4de commit 5ec7109
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 154 deletions.
1 change: 1 addition & 0 deletions libs/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set(COMMON_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/constant_strings.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/parameters_utils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/rendersettings_utils.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/procedural_reader.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/shape_utils.cpp")

set(COMMON_HDR
Expand Down
1 change: 1 addition & 0 deletions libs/common/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ source_files = [
'parameters_utils.cpp',
'rendersettings_utils.cpp',
'shape_utils.cpp',
'procedural_reader.cpp',
]

if not system.IS_WINDOWS:
Expand Down
103 changes: 103 additions & 0 deletions libs/common/procedural_reader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// SPDX-License-Identifier: Apache-2.0
//

#include "procedural_reader.h"
#include <ai.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdUtils/stageCache.h>
#include <pxr/usd/sdf/layer.h>
#include <pxr/usd/sdf/path.h>

int s_anonymousOverrideCounter = 0;
static AtMutex s_overrideReaderMutex;

PXR_NAMESPACE_USING_DIRECTIVE

void ProceduralReader::Read(const std::string &filename,
AtArray *overrides, const std::string &path)
{
// Nodes were already exported, should we skip here,
// or should we just append the new nodes ?
if (!GetNodes().empty()) {
return;
}

SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(filename);
_filename = filename; // Store the filename that is currently being read
_overrides = nullptr;

if (overrides == nullptr || AiArrayGetNumElements(overrides) == 0) {
// Only open the usd file as a root layer
if (rootLayer == nullptr) {
AiMsgError("[usd] Failed to open file (%s)", filename.c_str());
_overrides = nullptr;
return;
}
UsdStageRefPtr stage = UsdStage::Open(rootLayer, UsdStage::LoadAll);
ReadStage(stage, path);
} else {
_overrides = overrides; // Store the overrides that are currently being applied
auto getLayerName = []() -> std::string {
int counter;
{
std::lock_guard<AtMutex> guard(s_overrideReaderMutex);
counter = s_anonymousOverrideCounter++;
}
std::stringstream ss;
ss << "anonymous__override__" << counter << ".usda";
return ss.str();
};

auto overrideLayer = SdfLayer::CreateAnonymous(getLayerName());
const auto overrideCount = AiArrayGetNumElements(overrides);

std::vector<std::string> layerNames;
layerNames.reserve(overrideCount);
// Make sure they kep around after the loop scope ends.
std::vector<SdfLayerRefPtr> layers;
layers.reserve(overrideCount);

for (auto i = decltype(overrideCount){0}; i < overrideCount; ++i) {
auto layer = SdfLayer::CreateAnonymous(getLayerName());
if (layer->ImportFromString(AiArrayGetStr(overrides, i).c_str())) {
layerNames.emplace_back(layer->GetIdentifier());
layers.push_back(layer);
}
}

overrideLayer->SetSubLayerPaths(layerNames);
// If there is no rootLayer for a usd file, we only pass the overrideLayer to prevent
// USD from crashing #235
auto stage = rootLayer ? UsdStage::Open(rootLayer, overrideLayer, UsdStage::LoadAll)
: UsdStage::Open(overrideLayer, UsdStage::LoadAll);

ReadStage(stage, path);
}

_filename = ""; // finished reading, let's clear the filename
_overrides = nullptr; // clear the overrides pointer. Note that we don't own this array
}

bool ProceduralReader::Read(int cacheId, const std::string &path)
{
if (!GetNodes().empty()) {
return true;
}
_cacheId = cacheId;
// Load the USD stage in memory using a cache ID
UsdStageCache &stageCache = UsdUtilsStageCache::Get();
UsdStageCache::Id id = UsdStageCache::Id::FromLongInt(cacheId);

UsdStageRefPtr stage = (id.IsValid()) ? stageCache.Find(id) : nullptr;
if (!stage) {
AiMsgWarning("[usd] Cache ID not valid %d", cacheId);
_cacheId = 0;
return false;
}
ReadStage(stage, path);
return true;

}


22 changes: 19 additions & 3 deletions libs/common/procedural_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
//

#pragma once
#include <ai.h>
#include <pxr/usd/usd/stage.h>

PXR_NAMESPACE_USING_DIRECTIVE
/// @brief This is the base class for any arnold procedural reader
class ProceduralReader {
public:
Expand All @@ -20,8 +23,21 @@ class ProceduralReader {
virtual void SetUniverse(AtUniverse *universe) = 0;
virtual void SetRenderSettings(const std::string &renderSettings) = 0;
virtual void CreateViewportRegistry(AtProcViewportMode mode, const AtParamValueMap* params) = 0;
virtual void Read(
const std::string &filename, AtArray *overrides, const std::string &path = "") = 0; // read a USD file
virtual bool Read(int cacheId, const std::string &path = "") = 0; // read a USdStage from memory
virtual void ReadStage(UsdStageRefPtr stage,
const std::string &path) = 0;

virtual const std::vector<AtNode *> &GetNodes() const = 0;

const std::string &GetFilename() const { return _filename; }
const AtArray *GetOverrides() const { return _overrides; }
int GetCacheId() const {return _cacheId;}

void Read(const std::string &filename,
AtArray *overrides, const std::string &path = "");

bool Read(int cacheId, const std::string &path = "");
protected:
std::string _filename;
AtArray *_overrides = nullptr;
int _cacheId = 0; // usdStage cacheID used with a StageCache
};
57 changes: 7 additions & 50 deletions libs/render_delegate/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,63 +127,20 @@ HydraArnoldReader::HydraArnoldReader(AtUniverse *universe) : _universe(universe)
}

const std::vector<AtNode *> &HydraArnoldReader::GetNodes() const { return static_cast<HdArnoldRenderDelegate*>(_renderDelegate)->_nodes; }

void HydraArnoldReader::Read(const std::string &filename, AtArray *overrides,
const std::string &path )
void HydraArnoldReader::ReadStage(UsdStageRefPtr stage,
const std::string &path)
{
HdArnoldRenderDelegate *arnoldRenderDelegate = static_cast<HdArnoldRenderDelegate*>(_renderDelegate);
if (arnoldRenderDelegate == 0)
return;

UsdStageRefPtr stage = nullptr;
SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(filename);

HydraArnoldAPI context(arnoldRenderDelegate);
if (overrides == nullptr || AiArrayGetNumElements(overrides) == 0) {
if (rootLayer == nullptr) {
AiMsgError("[usd] Failed to open file (%s)", filename.c_str());
return;
}
stage = UsdStage::Open(rootLayer, UsdStage::LoadAll);
} else {
auto getLayerName = []() -> std::string {
int counter;
{
std::lock_guard<AtMutex> guard(s_globalReaderMutex);
counter = s_anonymousOverrideCounter++;
}
std::stringstream ss;
ss << "anonymous__override__" << counter << ".usda";
return ss.str();
};

auto overrideLayer = SdfLayer::CreateAnonymous(getLayerName());
const auto overrideCount = AiArrayGetNumElements(overrides);

std::vector<std::string> layerNames;
layerNames.reserve(overrideCount);
// Make sure they kep around after the loop scope ends.
std::vector<SdfLayerRefPtr> layers;
layers.reserve(overrideCount);

for (auto i = decltype(overrideCount){0}; i < overrideCount; ++i) {
auto layer = SdfLayer::CreateAnonymous(getLayerName());
if (layer->ImportFromString(AiArrayGetStr(overrides, i).c_str())) {
layerNames.emplace_back(layer->GetIdentifier());
layers.push_back(layer);
}
}

overrideLayer->SetSubLayerPaths(layerNames);
// If there is no rootLayer for a usd file, we only pass the overrideLayer to prevent
// USD from crashing #235
stage = rootLayer ? UsdStage::Open(rootLayer, overrideLayer, UsdStage::LoadAll)
: UsdStage::Open(overrideLayer, UsdStage::LoadAll);
if (stage == nullptr) {
AiMsgError("[usd] Unable to create USD stage from %s", _filename.c_str());
return;
}
HydraArnoldAPI context(arnoldRenderDelegate);

if (!stage)
return;

// if we have a procedural parent, we want to skip certain kind of prims
int procMask = (arnoldRenderDelegate->GetProceduralParent()) ?
(AI_NODE_CAMERA | AI_NODE_LIGHT | AI_NODE_SHAPE | AI_NODE_SHADER | AI_NODE_OPERATOR)
Expand Down
9 changes: 3 additions & 6 deletions libs/render_delegate/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ class HydraArnoldReader : public ProceduralReader {
~HydraArnoldReader();
const std::vector<AtNode *> &GetNodes() const override;

void Read(const std::string &filename, AtArray *overrides,
const std::string &path = "") override; // read a USD file

// TODO: what should the behavior in case we have a cacheId ?
bool Read(int cacheId, const std::string &path = "") override {return false;};

void ReadStage(UsdStageRefPtr stage,
const std::string &path) override; // read a specific UsdStage

void SetProceduralParent(AtNode *node) override;
void SetUniverse(AtUniverse *universe) override;

Expand Down
83 changes: 0 additions & 83 deletions libs/translator/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ namespace {
};
// global reader registry, will be used in the default case
static UsdArnoldReaderRegistry *s_readerRegistry = nullptr;
static int s_anonymousOverrideCounter = 0;
static int s_mustDeleteRegistry = 0;

static AtMutex s_globalReaderMutex;
Expand All @@ -101,88 +100,6 @@ UsdArnoldReader::~UsdArnoldReader()
// Should we delete the created nodes in case there was no procParent ?
}

void UsdArnoldReader::Read(const std::string &filename, AtArray *overrides, const std::string &path)
{
// Nodes were already exported, should we skip here,
// or should we just append the new nodes ?
if (!_nodes.empty()) {
return;
}

SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(filename);
_filename = filename; // Store the filename that is currently being read
_overrides = overrides; // Store the overrides that are currently being applied

if (overrides == nullptr || AiArrayGetNumElements(overrides) == 0) {
// Only open the usd file as a root layer
if (rootLayer == nullptr) {
AiMsgError("[usd] Failed to open file (%s)", filename.c_str());
return;
}
UsdStageRefPtr stage = UsdStage::Open(rootLayer, UsdStage::LoadAll);
ReadStage(stage, path);
} else {
auto getLayerName = []() -> std::string {
int counter;
{
std::lock_guard<AtMutex> guard(s_globalReaderMutex);
counter = s_anonymousOverrideCounter++;
}
std::stringstream ss;
ss << "anonymous__override__" << counter << ".usda";
return ss.str();
};

auto overrideLayer = SdfLayer::CreateAnonymous(getLayerName());
const auto overrideCount = AiArrayGetNumElements(overrides);

std::vector<std::string> layerNames;
layerNames.reserve(overrideCount);
// Make sure they kep around after the loop scope ends.
std::vector<SdfLayerRefPtr> layers;
layers.reserve(overrideCount);

for (auto i = decltype(overrideCount){0}; i < overrideCount; ++i) {
auto layer = SdfLayer::CreateAnonymous(getLayerName());
if (layer->ImportFromString(AiArrayGetStr(overrides, i).c_str())) {
layerNames.emplace_back(layer->GetIdentifier());
layers.push_back(layer);
}
}

overrideLayer->SetSubLayerPaths(layerNames);
// If there is no rootLayer for a usd file, we only pass the overrideLayer to prevent
// USD from crashing #235
auto stage = rootLayer ? UsdStage::Open(rootLayer, overrideLayer, UsdStage::LoadAll)
: UsdStage::Open(overrideLayer, UsdStage::LoadAll);

ReadStage(stage, path);
}

_filename = ""; // finished reading, let's clear the filename
_overrides = nullptr; // clear the overrides pointer. Note that we don't own this array
}

bool UsdArnoldReader::Read(int cacheId, const std::string &path)
{
if (!_nodes.empty()) {
return true;
}
_cacheId = cacheId;
// Load the USD stage in memory using a cache ID
UsdStageCache &stageCache = UsdUtilsStageCache::Get();
UsdStageCache::Id id = UsdStageCache::Id::FromLongInt(cacheId);

UsdStageRefPtr stage = (id.IsValid()) ? stageCache.Find(id) : nullptr;
if (!stage) {
AiMsgWarning("[usd] Cache ID not valid %d", cacheId);
_cacheId = 0;
return false;
}
ReadStage(stage, path);
return true;
}

void UsdArnoldReader::TraverseStage(UsdPrim *rootPrim, UsdArnoldReaderContext &context,
int threadId, int threadCount,
bool doPointInstancer, bool doSkelData, AtArray *matrix)
Expand Down
15 changes: 3 additions & 12 deletions libs/translator/reader/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ class UsdArnoldReader : public ProceduralReader {
_threadCount(1),
_mask(AI_NODE_ALL),
_defaultShader(nullptr),
_overrides(nullptr),
_cacheId(0),
_hasRootPrim(false),
_readStep(READ_NOT_STARTED),
_purpose(UsdGeomTokens->render),
Expand All @@ -66,11 +64,8 @@ class UsdArnoldReader : public ProceduralReader {
}
~UsdArnoldReader();

void Read(const std::string &filename, AtArray *overrides,
const std::string &path = "") override; // read a USD file
bool Read(int cacheId, const std::string &path = "") override; // read a USdStage from memory
void ReadStage(UsdStageRefPtr stage,
const std::string &path = ""); // read a specific UsdStage
const std::string &path) override; // read a specific UsdStage
void ReadPrimitive(const UsdPrim &prim, UsdArnoldReaderContext &context, bool isInstance = false, AtArray *parentMatrix = nullptr);

void ClearNodes();
Expand Down Expand Up @@ -100,13 +95,11 @@ class UsdArnoldReader : public ProceduralReader {
bool GetDebug() const { return _debug; }
bool GetConvertPrimitives() const { return _convert; }
const TimeSettings &GetTimeSettings() const { return _time; }
const std::string &GetFilename() const { return _filename; }
const AtArray *GetOverrides() const { return _overrides; }

unsigned int GetThreadCount() const { return _threadCount; }
int GetMask() const { return _mask; }
unsigned int GetId() const { return _id;}
const TfToken &GetPurpose() const {return _purpose;}
int GetCacheId() const {return _cacheId;}
const std::string &GetRenderSettings() const {return _renderSettings;}

static unsigned int ReaderThread(void *data);
Expand Down Expand Up @@ -231,9 +224,7 @@ class UsdArnoldReader : public ProceduralReader {
std::unordered_map<std::string, UsdCollectionAPI> _shadowLinksMap;

AtNode *_defaultShader;
std::string _filename; // usd filename that is currently being read
AtArray *_overrides; // usd overrides that are currently being applied on top of the usd file
int _cacheId; // usdStage cacheID used with a StageCache

bool _hasRootPrim; // are we reading this stage based on a root primitive
UsdPrim _rootPrim; // eventual root primitive used to traverse the stage
AtMutex _readerLock; // arnold mutex for multi-threaded translator
Expand Down

0 comments on commit 5ec7109

Please sign in to comment.