7#ifndef EXT_RMANPKG_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
8#define EXT_RMANPKG_PLUGIN_RENDERMAN_PLUGIN_HD_PRMAN_GPRIM_H
11#include "pxr/imaging/hd/version.h"
15#include "hdPrman/gprimbase.h"
16#include "hdPrman/renderParam.h"
17#include "hdPrman/instancer.h"
18#include "hdPrman/material.h"
19#include "hdPrman/rixStrings.h"
20#include "hdPrman/utils.h"
24PXR_NAMESPACE_OPEN_SCOPE
28template <
typename BASE>
32 using BaseType = BASE;
44 HdPrman_RenderParam *param =
45 static_cast<HdPrman_RenderParam*
>(renderParam);
46 const SdfPath&
id = BASE::GetId();
47 riley::Riley *riley = param->AcquireRiley();
53 param->ReleaseCoordSysBindings(
id);
56 for (
const auto &instId: _instanceIds) {
57 if (instId != riley::GeometryInstanceId::InvalidId()) {
58 riley->DeleteGeometryInstance(
59 riley::GeometryPrototypeId::InvalidId(), instId);
65 if (HdPrmanInstancer* instancer = param->GetInstancer(
66 BASE::GetInstancerId())) {
67 instancer->Depopulate(renderParam,
id);
70 for (
const auto &protoId: _prototypeIds) {
71 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
72 riley->DeleteGeometryPrototype(protoId);
75 _prototypeIds.clear();
80 HdDirtyBits* dirtyBits,
81 TfToken const &reprToken)
override;
84 HdDirtyBits GetInitialDirtyBitsMask()
const override = 0;
87 _PropagateDirtyBits(HdDirtyBits bits)
const override
94 _InitRepr(
TfToken const &reprToken,
95 HdDirtyBits *dirtyBits)
override
112 virtual riley::MaterialId
113 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
115 return renderParam->GetFallbackMaterialId();
122 HdPrman_RenderParam *renderParam,
126 RtPrimVarList *primvars,
127 std::vector<HdGeomSubset> *geomSubsets,
128 std::vector<RtPrimVarList> *geomSubsetPrimvars) = 0;
136template <
typename BASE>
140 HdDirtyBits* dirtyBits,
144 HF_MALLOC_TAG_FUNCTION();
150 static const HdDirtyBits internalDirtyBits =
151 HdChangeTracker::InitRepr |
152 HdChangeTracker::Varying |
153 HdChangeTracker::NewRepr |
154 HdChangeTracker::CustomBitsMask;
156 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
159 if (((*dirtyBits & ~internalDirtyBits)
160 & HdChangeTracker::AllSceneDirtyBits) == 0) {
164 HdPrman_RenderParam *param =
165 static_cast<HdPrman_RenderParam*
>(renderParam);
168 riley::Riley *riley = param->AcquireRiley();
171 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
174 SdfPath const&
id = BASE::GetId();
175 SdfPath const& instancerId = BASE::GetInstancerId();
176 const bool isHdInstance = !instancerId.
IsEmpty();
183 const int32_t primId = BASE::GetPrimId() + 1;
188#
if HD_API_VERSION >= 68
189 param->GetShutterInterval()[0],
190 param->GetShutterInterval()[1],
196 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
200 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
201#if HD_API_VERSION < 37
202 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
208 riley::MaterialId materialId = _GetFallbackMaterial(param);
209 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
210 const SdfPath & hdMaterialId = BASE::GetMaterialId();
211 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
214 riley::CoordinateSystemList coordSysList = {0,
nullptr};
215 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
216 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
217 coordSysList.count = convertedCoordSys->size();
218 coordSysList.ids = convertedCoordSys->data();
224 static const HdDirtyBits prmanProtoAttrBits =
225 HdChangeTracker::DirtyPoints |
226 HdChangeTracker::DirtyNormals |
227 HdChangeTracker::DirtyWidths |
228 HdChangeTracker::DirtyVolumeField |
229 HdChangeTracker::DirtyTopology |
230 HdChangeTracker::DirtyPrimvar;
234 static const HdDirtyBits prmanInstAttrBits =
235 HdChangeTracker::DirtyMaterialId |
236 HdChangeTracker::DirtyTransform |
237 HdChangeTracker::DirtyVisibility |
238 HdChangeTracker::DirtyDoubleSided |
239 HdChangeTracker::DirtySubdivTags |
240 HdChangeTracker::DirtyVolumeField |
241 HdChangeTracker::DirtyCategories |
242 HdChangeTracker::DirtyPrimvar;
246 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
247 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
252 std::vector<riley::MaterialId> subsetMaterialIds;
253 std::vector<SdfPath> subsetPaths;
256 RtPrimVarList primvars;
257 HdGeomSubsets geomSubsets;
258 std::vector<RtPrimVarList> geomSubsetPrimvars;
259 bool ok = _ConvertGeometry(param, sceneDelegate,
id,
260 &primType, &primvars,
261 &geomSubsets, &geomSubsetPrimvars);
268 primvars.SetString(RixStr.k_identifier_object,
269 RtUString(
id.GetName().c_str()));
270 for (
size_t i=0, n=geomSubsets.size(); i<n; ++i) {
271 primvars.SetString(RixStr.k_identifier_object,
272 RtUString(geomSubsets[i].
id.GetName().c_str()));
277#if PXR_VERSION < 2311
279 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
284 const size_t oldCount = _prototypeIds.size();
285 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
286 if (newCount != oldCount) {
287 for (
const auto &oldPrototypeId: _prototypeIds) {
288 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
289 riley->DeleteGeometryPrototype(oldPrototypeId);
292 _prototypeIds.resize(newCount,
293 riley::GeometryPrototypeId::InvalidId());
297 if (geomSubsets.empty()) {
301 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
302 RtUString(primPath.
GetText()));
303 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
304 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
305 _prototypeIds[0] = riley->CreateGeometryPrototype(
307 stats::AddDataLocation(primPath.
GetText()).GetValue()),
308 primType, dispId, primvars);
309 }
else if (prmanProtoAttrBitsWereSet) {
310 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
311 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
319 subsetMaterialIds.reserve(geomSubsets.size());
323 subsetPaths.reserve(geomSubsets.size());
325 for (
size_t j=0; j < geomSubsets.size(); ++j) {
326 auto& prototypeId = _prototypeIds[j];
328 RtPrimVarList &subsetPrimvars = geomSubsetPrimvars[j];
331 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
333 subsetPrimvars.SetIntegerArray(RixStr.k_shade_faceset,
335 int32Indices.size());
337 riley::MaterialId subsetMaterialId = materialId;
338 riley::DisplacementId subsetDispId = dispId;
342 HdPrman_ResolveMaterial(
344 riley, &subsetMaterialId, &subsetDispId);
345 subsetMaterialIds.push_back(subsetMaterialId);
350 subsetPaths.push_back(subsetPath);
351 subsetPrimvars.SetString(
352 RixStr.k_stats_prototypeIdentifier,
353 RtUString(subsetPath.
GetText()));
355 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
356 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
358 riley->CreateGeometryPrototype(
360 stats::AddDataLocation(
361 subsetPath.
GetText()).GetValue()),
362 primType, subsetDispId, subsetPrimvars);
363 }
else if (prmanProtoAttrBitsWereSet) {
364 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
365 riley->ModifyGeometryPrototype(
366 primType, prototypeId,
367 &subsetDispId, &subsetPrimvars);
371 *dirtyBits &= ~prmanProtoAttrBits;
377 if (_PrototypeOnly()) {
387 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
390 attrs.SetInteger(RixStr.k_identifier_id, primId);
394 attrs.SetString(RtUString(
"user:__materialid"), RtUString(hdMaterialId.
GetText()));
401 for (
size_t i=0; i < xf.count; ++i) {
402 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
404 const riley::Transform xform = {
411 attrs.SetInteger(RixStr.k_identifier_id2, 0);
414 const size_t oldCount = _instanceIds.size();
415 const size_t newCount = _prototypeIds.size();
416 if (newCount != oldCount) {
417 for (
const auto &oldInstanceId: _instanceIds) {
418 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
419 riley->DeleteGeometryInstance(
420 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
425 riley::GeometryInstanceId::InvalidId());
429 param->AddRenderTagToGroupingMembership(
434 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
435 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
436 auto const& prototypeId = _prototypeIds[j];
437 auto& instanceId = _instanceIds[j];
438 auto instanceMaterialId = materialId;
439 RtParamList finalAttrs = attrs;
442 SdfPath* subsetPath(&primPath);
443 if (!subsetPaths.empty()) {
444 subsetPath = &subsetPaths[j];
447 finalAttrs.SetString(RixStr.k_identifier_name,
448 RtUString(subsetPath->
GetText()));
451 if (!subsetMaterialIds.empty()) {
453 instanceMaterialId = subsetMaterialIds[j];
456 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
457 TRACE_SCOPE(
"riley::CreateGeometryInstance");
458 instanceId = riley->CreateGeometryInstance(
460 stats::AddDataLocation(subsetPath->
GetText()).GetValue()),
461 riley::GeometryPrototypeId::InvalidId(), prototypeId,
462 instanceMaterialId, coordSysList, xform, finalAttrs);
463 }
else if (prmanInstAttrBitsWereSet) {
464 TRACE_SCOPE(
"riley::ModifyGeometryInstance");
465 riley->ModifyGeometryInstance(
466 riley::GeometryPrototypeId::InvalidId(),
467 instanceId, &instanceMaterialId, &coordSysList, &xform,
471 *dirtyBits &= ~prmanInstAttrBits;
472 }
else if (prmanInstAttrBitsWereSet
489 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
491 if (subsetMaterialIds.size() == 0) {
492 subsetMaterialIds.push_back(materialId);
494 if (subsetPaths.size() == 0) {
495 subsetPaths.push_back(primPath);
497 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
498 _prototypeIds.size() == subsetPaths.size(),
499 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
500 subsetMaterialIds.size(), subsetPaths.size());
508 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
510 return id == riley::GeometryPrototypeId::InvalidId();
512 TF_WARN(
"Riley geometry prototype creation failed for "
513 "instanced gprim <%s>; the prim will not be instanced.",
517 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
535PXR_NAMESPACE_CLOSE_SCOPE
Tracks changes from the HdSceneDelegate, providing invalidation cues to the render engine.
static HD_API bool IsInstancerDirty(HdDirtyBits dirtyBits, SdfPath const &id)
Returns true if the dirtyBits has a dirty instancer. id is for perflog.
HD_API bool IsVisibilityDirty(SdfPath const &id)
Returns true if the rprim identified by id has dirty visibility.
A common base class for HdPrman_Gprim types.
A mix-in template that adds shared gprim behavior to support various HdRprim types.
The Hydra render index is a flattened representation of the client scene graph, which may be composed...
HD_API HdInstancer * GetInstancer(SdfPath const &id) const
Returns the instancer of id.
The HdRenderParam is an opaque (to core Hydra) handle, to an object that is obtained from the render ...
Adapter class providing data exchange with the client scene graph.
virtual HD_API TfToken GetRenderTag(SdfPath const &id)
Returns the render tag that will be used to bucket prims during render pass bucketing.
virtual HD_API SdfPath GetMaterialId(SdfPath const &rprimId)
Returns the material ID bound to the rprim rprimId.
virtual HD_API size_t SampleTransform(SdfPath const &id, size_t maxSampleCount, float *sampleTimes, GfMatrix4d *sampleValues)
Store up to maxSampleCount transform samples in *sampleValues.
HdRenderIndex & GetRenderIndex()
Returns the RenderIndex owned by this delegate.
virtual HD_API SdfPath GetScenePrimPath(SdfPath const &rprimId, int instanceIndex, HdInstancerContext *instancerContext=nullptr)
Returns the scene address of the prim corresponding to the given rprim/instance index.
A path value used to locate objects in layers or scenegraphs.
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
This is a small-vector class with local storage optimization, the local storage can be specified via ...
Token for efficient comparison, assignment, and hashing of known strings.
#define TF_WARN(...)
Issue a warning, but continue execution.
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
#define TF_UNUSED(x)
Stops compiler from producing unused argument or variable warnings.
Describes a subset of a piece of geometry as a set of indices.
VtIntArray indices
The list of element indices contained in the subset.
SdfPath id
The path used to identify this subset in the scene.
SdfPath materialId
The path used to identify this material bound to the subset.
An array of a value sampled over time, in struct-of-arrays layout.