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);
73 if (_PrototypeOnly()) {
74 param->FinalizeMeshLightSprim(
id);
77 for (
const auto &protoId: _prototypeIds) {
78 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
79 riley->DeleteGeometryPrototype(protoId);
82 _prototypeIds.clear();
87 HdDirtyBits* dirtyBits,
88 TfToken const &reprToken)
override;
91 HdDirtyBits GetInitialDirtyBitsMask()
const override = 0;
94 _PropagateDirtyBits(HdDirtyBits bits)
const override
101 _InitRepr(
TfToken const &reprToken,
102 HdDirtyBits *dirtyBits)
override
119 virtual riley::MaterialId
120 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
122 return renderParam->GetFallbackMaterialId();
129 HdPrman_RenderParam *renderParam,
133 RtPrimVarList *primvars,
134 std::vector<HdGeomSubset> *geomSubsets,
135 std::vector<RtPrimVarList> *geomSubsetPrimvars) = 0;
139 _AddPrimvars(RtPrimVarList*)
const
145 virtual const std::vector<riley::CoordinateSystemId>&
146 _GetAdditionalCoordSysIds()
const
148 static const std::vector<riley::CoordinateSystemId> empty;
158template <
typename BASE>
162 HdDirtyBits* dirtyBits,
166 HF_MALLOC_TAG_FUNCTION();
172 static const HdDirtyBits internalDirtyBits =
173 HdChangeTracker::InitRepr |
174 HdChangeTracker::Varying |
175 HdChangeTracker::NewRepr |
176 HdChangeTracker::CustomBitsMask;
178 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
181 if (((*dirtyBits & ~internalDirtyBits)
182 & HdChangeTracker::AllSceneDirtyBits) == 0) {
186 HdPrman_RenderParam *param =
187 static_cast<HdPrman_RenderParam*
>(renderParam);
190 riley::Riley *riley = param->AcquireRiley();
193 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
196 SdfPath const&
id = BASE::GetId();
197 SdfPath const& instancerId = BASE::GetInstancerId();
198 const bool isHdInstance = !instancerId.
IsEmpty();
204#
if HD_API_VERSION >= 68
205 param->GetShutterInterval()[0],
206 param->GetShutterInterval()[1],
212 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
216 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
217#if HD_API_VERSION < 37
218 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
224 riley::MaterialId materialId = _GetFallbackMaterial(param);
225 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
226 const SdfPath & hdMaterialId = BASE::GetMaterialId();
227 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
230 riley::CoordinateSystemList coordSysList = {0,
nullptr};
231 std::vector<riley::CoordinateSystemId> allCoordSysIds;
232 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
233 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
234 allCoordSysIds.insert(allCoordSysIds.end(),
235 convertedCoordSys->begin(),
236 convertedCoordSys->end());
239 const auto& additionalCoordSysIds = _GetAdditionalCoordSysIds();
240 allCoordSysIds.insert(allCoordSysIds.end(),
241 additionalCoordSysIds.begin(),
242 additionalCoordSysIds.end());
243 coordSysList.count = allCoordSysIds.size();
244 coordSysList.ids = allCoordSysIds.data();
249 static const HdDirtyBits prmanProtoAttrBits =
250 HdChangeTracker::DirtyPoints |
251 HdChangeTracker::DirtyNormals |
252 HdChangeTracker::DirtyWidths |
253 HdChangeTracker::DirtyVolumeField |
254 HdChangeTracker::DirtyTopology |
255 HdChangeTracker::DirtyPrimvar;
259 static const HdDirtyBits prmanInstAttrBits =
260 HdChangeTracker::DirtyMaterialId |
261 HdChangeTracker::DirtyTransform |
262 HdChangeTracker::DirtyVisibility |
263 HdChangeTracker::DirtyDoubleSided |
264 HdChangeTracker::DirtySubdivTags |
265 HdChangeTracker::DirtyVolumeField |
266 HdChangeTracker::DirtyCategories |
267 HdChangeTracker::DirtyPrimvar |
268 HdChangeTracker::DirtyRenderTag;
272 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
273 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
278 std::vector<riley::MaterialId> subsetMaterialIds;
279 std::vector<SdfPath> subsetPaths;
282 RtPrimVarList primvars;
283 HdGeomSubsets geomSubsets;
284 std::vector<RtPrimVarList> geomSubsetPrimvars;
285 bool ok = _ConvertGeometry(param, sceneDelegate,
id,
286 &primType, &primvars,
287 &geomSubsets, &geomSubsetPrimvars);
294 primvars.SetString(RixStr.k_identifier_object,
295 RtUString(
id.GetText()));
296 for (
size_t i=0, n=geomSubsets.size(); i<n; ++i) {
297 geomSubsetPrimvars[i]
298 .SetString(RixStr.k_identifier_object,
299 RtUString(geomSubsets[i].
id.GetText()));
304#if PXR_VERSION < 2311
306 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
311 const size_t oldCount = _prototypeIds.size();
312 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
313 if (newCount != oldCount) {
314 for (
const auto &oldPrototypeId: _prototypeIds) {
315 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
316 riley->DeleteGeometryPrototype(oldPrototypeId);
319 _prototypeIds.resize(newCount,
320 riley::GeometryPrototypeId::InvalidId());
323 _AddPrimvars(&primvars);
326 if (geomSubsets.empty()) {
330 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
331 RtUString(primPath.
GetText()));
332 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
333 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
334 _prototypeIds[0] = riley->CreateGeometryPrototype(
336 stats::AddDataLocation(primPath.
GetText()).GetValue()),
337 primType, dispId, primvars);
338 }
else if (prmanProtoAttrBitsWereSet) {
339 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
340 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
348 subsetMaterialIds.reserve(geomSubsets.size());
352 subsetPaths.reserve(geomSubsets.size());
354 for (
size_t j=0; j < geomSubsets.size(); ++j) {
355 auto& prototypeId = _prototypeIds[j];
357 RtPrimVarList &subsetPrimvars = geomSubsetPrimvars[j];
360 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
362 subsetPrimvars.SetIntegerArray(RixStr.k_shade_faceset,
364 int32Indices.size());
366 riley::MaterialId subsetMaterialId = materialId;
367 riley::DisplacementId subsetDispId = dispId;
371 HdPrman_ResolveMaterial(
373 riley, &subsetMaterialId, &subsetDispId);
374 subsetMaterialIds.push_back(subsetMaterialId);
379 subsetPaths.push_back(subsetPath);
380 subsetPrimvars.SetString(
381 RixStr.k_stats_prototypeIdentifier,
382 RtUString(subsetPath.
GetText()));
384 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
385 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
387 riley->CreateGeometryPrototype(
389 stats::AddDataLocation(
390 subsetPath.
GetText()).GetValue()),
391 primType, subsetDispId, subsetPrimvars);
392 }
else if (prmanProtoAttrBitsWereSet) {
393 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
394 riley->ModifyGeometryPrototype(
395 primType, prototypeId,
396 &subsetDispId, &subsetPrimvars);
400 *dirtyBits &= ~prmanProtoAttrBits;
406 if (_PrototypeOnly()) {
416 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
420 attrs.SetString(RtUString(
"user:__materialid"), RtUString(hdMaterialId.
GetText()));
427 for (
size_t i=0; i < xf.count; ++i) {
428 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
430 const riley::Transform xform = {
436 const size_t oldCount = _instanceIds.size();
437 const size_t newCount = _prototypeIds.size();
438 if (newCount != oldCount) {
439 for (
const auto &oldInstanceId: _instanceIds) {
440 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
441 riley->DeleteGeometryInstance(
442 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
447 riley::GeometryInstanceId::InvalidId());
451 param->AddRenderTagToGroupingMembership(
456 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
457 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
458 auto const& prototypeId = _prototypeIds[j];
459 auto& instanceId = _instanceIds[j];
460 auto instanceMaterialId = materialId;
461 RtParamList finalAttrs = attrs;
466 if (!subsetPaths.empty()) {
467 idPath = &subsetPaths[j];
471 param->GetIdMap()->RegisterId(
472 { idPath->GetString(),
478 if (!subsetMaterialIds.empty()) {
480 instanceMaterialId = subsetMaterialIds[j];
484 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
485 TRACE_SCOPE(
"riley::CreateGeometryInstance");
486 instanceId = riley->CreateGeometryInstance(
488 stats::AddDataLocation(idPath->GetText()).GetValue()),
489 riley::GeometryPrototypeId::InvalidId(), prototypeId,
490 instanceMaterialId, coordSysList, xform, finalAttrs);
491 }
else if (prmanInstAttrBitsWereSet) {
492 TRACE_SCOPE(
"riley::ModifyGeometryInstance");
493 riley->ModifyGeometryInstance(
494 riley::GeometryPrototypeId::InvalidId(),
495 instanceId, &instanceMaterialId, &coordSysList, &xform,
499 *dirtyBits &= ~prmanInstAttrBits;
500 }
else if (prmanInstAttrBitsWereSet
517 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
519 if (subsetMaterialIds.size() == 0) {
520 subsetMaterialIds.push_back(materialId);
522 if (subsetPaths.size() == 0) {
523 subsetPaths.push_back(primPath);
525 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
526 _prototypeIds.size() == subsetPaths.size(),
527 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
528 subsetMaterialIds.size(), subsetPaths.size());
536 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
538 return id == riley::GeometryPrototypeId::InvalidId();
540 TF_WARN(
"Riley geometry prototype creation failed for "
541 "instanced gprim <%s>; the prim will not be instanced.",
545 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
563PXR_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.