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/idMap.h"
17#include "hdPrman/renderParam.h"
18#include "hdPrman/instancer.h"
19#include "hdPrman/material.h"
20#include "hdPrman/rixStrings.h"
21#include "hdPrman/utils.h"
25PXR_NAMESPACE_OPEN_SCOPE
29template <
typename BASE>
33 using BaseType = BASE;
45 HdPrman_RenderParam *param =
46 static_cast<HdPrman_RenderParam*
>(renderParam);
47 const SdfPath&
id = BASE::GetId();
48 riley::Riley *riley = param->AcquireRiley();
54 param->ReleaseCoordSysBindings(
id);
57 for (
const auto &instId: _instanceIds) {
58 if (instId != riley::GeometryInstanceId::InvalidId()) {
59 riley->DeleteGeometryInstance(
60 riley::GeometryPrototypeId::InvalidId(), instId);
66 if (HdPrmanInstancer* instancer = param->GetInstancer(
67 BASE::GetInstancerId())) {
68 instancer->Depopulate(renderParam,
id);
71 for (
const auto &protoId: _prototypeIds) {
72 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
73 riley->DeleteGeometryPrototype(protoId);
76 _prototypeIds.clear();
81 HdDirtyBits* dirtyBits,
82 TfToken const &reprToken)
override;
85 HdDirtyBits GetInitialDirtyBitsMask()
const override = 0;
88 _PropagateDirtyBits(HdDirtyBits bits)
const override
95 _InitRepr(
TfToken const &reprToken,
96 HdDirtyBits *dirtyBits)
override
113 virtual riley::MaterialId
114 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
116 return renderParam->GetFallbackMaterialId();
123 HdPrman_RenderParam *renderParam,
127 RtPrimVarList *primvars,
128 std::vector<HdGeomSubset> *geomSubsets,
129 std::vector<RtPrimVarList> *geomSubsetPrimvars) = 0;
133 _AddPrimvars(RtPrimVarList*)
const
139 virtual const std::vector<riley::CoordinateSystemId>&
140 _GetAdditionalCoordSysIds()
const
142 static const std::vector<riley::CoordinateSystemId> empty;
152template <
typename BASE>
156 HdDirtyBits* dirtyBits,
160 HF_MALLOC_TAG_FUNCTION();
166 static const HdDirtyBits internalDirtyBits =
167 HdChangeTracker::InitRepr |
168 HdChangeTracker::Varying |
169 HdChangeTracker::NewRepr |
170 HdChangeTracker::CustomBitsMask;
172 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
175 if (((*dirtyBits & ~internalDirtyBits)
176 & HdChangeTracker::AllSceneDirtyBits) == 0) {
180 HdPrman_RenderParam *param =
181 static_cast<HdPrman_RenderParam*
>(renderParam);
184 riley::Riley *riley = param->AcquireRiley();
187 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
190 SdfPath const&
id = BASE::GetId();
191 SdfPath const& instancerId = BASE::GetInstancerId();
192 const bool isHdInstance = !instancerId.
IsEmpty();
198#
if HD_API_VERSION >= 68
199 param->GetShutterInterval()[0],
200 param->GetShutterInterval()[1],
206 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
210 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
211#if HD_API_VERSION < 37
212 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
218 riley::MaterialId materialId = _GetFallbackMaterial(param);
219 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
220 const SdfPath & hdMaterialId = BASE::GetMaterialId();
221 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
224 riley::CoordinateSystemList coordSysList = {0,
nullptr};
225 std::vector<riley::CoordinateSystemId> allCoordSysIds;
226 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
227 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
228 allCoordSysIds.insert(allCoordSysIds.end(),
229 convertedCoordSys->begin(),
230 convertedCoordSys->end());
233 const auto& additionalCoordSysIds = _GetAdditionalCoordSysIds();
234 allCoordSysIds.insert(allCoordSysIds.end(),
235 additionalCoordSysIds.begin(),
236 additionalCoordSysIds.end());
237 coordSysList.count = allCoordSysIds.size();
238 coordSysList.ids = allCoordSysIds.data();
243 static const HdDirtyBits prmanProtoAttrBits =
244 HdChangeTracker::DirtyPoints |
245 HdChangeTracker::DirtyNormals |
246 HdChangeTracker::DirtyWidths |
247 HdChangeTracker::DirtyVolumeField |
248 HdChangeTracker::DirtyTopology |
249 HdChangeTracker::DirtyPrimvar;
253 static const HdDirtyBits prmanInstAttrBits =
254 HdChangeTracker::DirtyMaterialId |
255 HdChangeTracker::DirtyTransform |
256 HdChangeTracker::DirtyVisibility |
257 HdChangeTracker::DirtyDoubleSided |
258 HdChangeTracker::DirtySubdivTags |
259 HdChangeTracker::DirtyVolumeField |
260 HdChangeTracker::DirtyCategories |
261 HdChangeTracker::DirtyPrimvar |
262 HdChangeTracker::DirtyRenderTag;
266 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
267 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
272 std::vector<riley::MaterialId> subsetMaterialIds;
273 std::vector<SdfPath> subsetPaths;
276 RtPrimVarList primvars;
277 HdGeomSubsets geomSubsets;
278 std::vector<RtPrimVarList> geomSubsetPrimvars;
279 bool ok = _ConvertGeometry(param, sceneDelegate,
id,
280 &primType, &primvars,
281 &geomSubsets, &geomSubsetPrimvars);
288 primvars.SetString(RixStr.k_identifier_object,
289 RtUString(
id.GetName().c_str()));
290 for (
size_t i=0, n=geomSubsets.size(); i<n; ++i) {
291 geomSubsetPrimvars[i]
292 .SetString(RixStr.k_identifier_object,
293 RtUString(geomSubsets[i].
id.GetName().c_str()));
298#if PXR_VERSION < 2311
300 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
305 const size_t oldCount = _prototypeIds.size();
306 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
307 if (newCount != oldCount) {
308 for (
const auto &oldPrototypeId: _prototypeIds) {
309 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
310 riley->DeleteGeometryPrototype(oldPrototypeId);
313 _prototypeIds.resize(newCount,
314 riley::GeometryPrototypeId::InvalidId());
317 _AddPrimvars(&primvars);
320 if (geomSubsets.empty()) {
324 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
325 RtUString(primPath.
GetText()));
326 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
327 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
328 _prototypeIds[0] = riley->CreateGeometryPrototype(
330 stats::AddDataLocation(primPath.
GetText()).GetValue()),
331 primType, dispId, primvars);
332 }
else if (prmanProtoAttrBitsWereSet) {
333 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
334 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
342 subsetMaterialIds.reserve(geomSubsets.size());
346 subsetPaths.reserve(geomSubsets.size());
348 for (
size_t j=0; j < geomSubsets.size(); ++j) {
349 auto& prototypeId = _prototypeIds[j];
351 RtPrimVarList &subsetPrimvars = geomSubsetPrimvars[j];
354 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
356 subsetPrimvars.SetIntegerArray(RixStr.k_shade_faceset,
358 int32Indices.size());
360 riley::MaterialId subsetMaterialId = materialId;
361 riley::DisplacementId subsetDispId = dispId;
365 HdPrman_ResolveMaterial(
367 riley, &subsetMaterialId, &subsetDispId);
368 subsetMaterialIds.push_back(subsetMaterialId);
373 subsetPaths.push_back(subsetPath);
374 subsetPrimvars.SetString(
375 RixStr.k_stats_prototypeIdentifier,
376 RtUString(subsetPath.
GetText()));
378 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
379 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
381 riley->CreateGeometryPrototype(
383 stats::AddDataLocation(
384 subsetPath.
GetText()).GetValue()),
385 primType, subsetDispId, subsetPrimvars);
386 }
else if (prmanProtoAttrBitsWereSet) {
387 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
388 riley->ModifyGeometryPrototype(
389 primType, prototypeId,
390 &subsetDispId, &subsetPrimvars);
394 *dirtyBits &= ~prmanProtoAttrBits;
400 if (_PrototypeOnly()) {
410 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
414 attrs.SetString(RtUString(
"user:__materialid"), RtUString(hdMaterialId.
GetText()));
421 for (
size_t i=0; i < xf.count; ++i) {
422 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
424 const riley::Transform xform = {
430 const size_t oldCount = _instanceIds.size();
431 const size_t newCount = _prototypeIds.size();
432 if (newCount != oldCount) {
433 for (
const auto &oldInstanceId: _instanceIds) {
434 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
435 riley->DeleteGeometryInstance(
436 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
441 riley::GeometryInstanceId::InvalidId());
445 param->AddRenderTagToGroupingMembership(
450 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
451 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
452 auto const& prototypeId = _prototypeIds[j];
453 auto& instanceId = _instanceIds[j];
454 auto instanceMaterialId = materialId;
455 RtParamList finalAttrs = attrs;
460 if (!subsetPaths.empty()) {
461 idPath = &subsetPaths[j];
465 param->GetIdMap()->RegisterId(
466 { idPath->GetString(),
472 if (!subsetMaterialIds.empty()) {
474 instanceMaterialId = subsetMaterialIds[j];
478 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
479 TRACE_SCOPE(
"riley::CreateGeometryInstance");
480 instanceId = riley->CreateGeometryInstance(
482 stats::AddDataLocation(idPath->GetText()).GetValue()),
483 riley::GeometryPrototypeId::InvalidId(), prototypeId,
484 instanceMaterialId, coordSysList, xform, finalAttrs);
485 }
else if (prmanInstAttrBitsWereSet) {
486 TRACE_SCOPE(
"riley::ModifyGeometryInstance");
487 riley->ModifyGeometryInstance(
488 riley::GeometryPrototypeId::InvalidId(),
489 instanceId, &instanceMaterialId, &coordSysList, &xform,
493 *dirtyBits &= ~prmanInstAttrBits;
494 }
else if (prmanInstAttrBitsWereSet
511 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
513 if (subsetMaterialIds.size() == 0) {
514 subsetMaterialIds.push_back(materialId);
516 if (subsetPaths.size() == 0) {
517 subsetPaths.push_back(primPath);
519 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
520 _prototypeIds.size() == subsetPaths.size(),
521 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
522 subsetMaterialIds.size(), subsetPaths.size());
530 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
532 return id == riley::GeometryPrototypeId::InvalidId();
534 TF_WARN(
"Riley geometry prototype creation failed for "
535 "instanced gprim <%s>; the prim will not be instanced.",
539 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
557PXR_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 render index is part of the Hydra 1.0 API and is only used for emulation purposes so that HdScene...
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.