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"
16#include "hdPrman/cameraContext.h"
17#include "hdPrman/gprimbase.h"
18#include "hdPrman/idMap.h"
19#include "hdPrman/renderParam.h"
20#include "hdPrman/instancer.h"
21#include "hdPrman/material.h"
22#include "hdPrman/rixStrings.h"
23#include "hdPrman/utils.h"
26#include <RiTypesHelper.h>
28PXR_NAMESPACE_OPEN_SCOPE
32template <
typename BASE>
36 using BaseType = BASE;
48 HdPrman_RenderParam *param =
49 static_cast<HdPrman_RenderParam*
>(renderParam);
50 const SdfPath&
id = BASE::GetId();
51 riley::Riley *riley = param->AcquireRiley();
57 param->ReleaseCoordSysBindings(
id);
60 for (
const auto &instId: _instanceIds) {
61 if (instId != riley::GeometryInstanceId::InvalidId()) {
62 riley->DeleteGeometryInstance(
63 riley::GeometryPrototypeId::InvalidId(), instId);
69 if (HdPrmanInstancer* instancer = param->GetInstancer(
70 BASE::GetInstancerId())) {
71 instancer->Depopulate(renderParam,
id);
76 if (_PrototypeOnly()) {
77 param->FinalizeMeshLightSprim(
id);
80 for (
const auto &protoId: _prototypeIds) {
81 if (protoId != riley::GeometryPrototypeId::InvalidId()) {
82 riley->DeleteGeometryPrototype(protoId);
85 _prototypeIds.clear();
90 HdDirtyBits* dirtyBits,
91 TfToken const &reprToken)
override;
94 HdDirtyBits GetInitialDirtyBitsMask()
const override = 0;
97 _PropagateDirtyBits(HdDirtyBits bits)
const override
104 _InitRepr(
TfToken const &reprToken,
105 HdDirtyBits *dirtyBits)
override
122 virtual riley::MaterialId
123 _GetFallbackMaterial(HdPrman_RenderParam *renderParam)
125 return renderParam->GetFallbackMaterialId();
132 HdPrman_RenderParam *renderParam,
136 RtPrimVarList *primvars,
137 std::vector<HdGeomSubset> *geomSubsets,
138 std::vector<RtPrimVarList> *geomSubsetPrimvars) = 0;
142 _AddPrimvars(RtPrimVarList*)
const
148 virtual const std::vector<riley::CoordinateSystemId>&
149 _GetAdditionalCoordSysIds()
const
151 static const std::vector<riley::CoordinateSystemId> empty;
157 _ResolveDicingCamera(
158 const HdPrman_CameraContext& context,
159 RtPrimVarList* primvars)
163 if (primvars->GetString(RixStr.k_dice_referencecamera, authored) &&
165 const RtUString& resolved = context.ResolveCameraName(
167 if (resolved.Empty()) {
169 primvars->Remove(RixStr.k_dice_referencecamera);
171 primvars->SetString(RixStr.k_dice_referencecamera, resolved);
182template <
typename BASE>
186 HdDirtyBits* dirtyBits,
195 static const HdDirtyBits internalDirtyBits =
196 HdChangeTracker::InitRepr |
197 HdChangeTracker::Varying |
198 HdChangeTracker::NewRepr |
199 HdChangeTracker::CustomBitsMask;
201 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
204 if (((*dirtyBits & ~internalDirtyBits)
205 & HdChangeTracker::AllSceneDirtyBits) == 0) {
209 HdPrman_RenderParam *param =
210 static_cast<HdPrman_RenderParam*
>(renderParam);
213 riley::Riley *riley = param->AcquireRiley();
216 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
219 SdfPath const&
id = BASE::GetId();
220 SdfPath const& instancerId = BASE::GetInstancerId();
221 const bool isHdInstance = !instancerId.
IsEmpty();
227#
if HD_API_VERSION >= 68
228 param->GetShutterInterval()[0],
229 param->GetShutterInterval()[1],
235 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
239 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
240#if HD_API_VERSION < 37
241 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
247 riley::MaterialId materialId = _GetFallbackMaterial(param);
248 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
249 const SdfPath & hdMaterialId = BASE::GetMaterialId();
250 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
253 riley::CoordinateSystemList coordSysList = {0,
nullptr};
254 std::vector<riley::CoordinateSystemId> allCoordSysIds;
255 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
256 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
257 allCoordSysIds.insert(allCoordSysIds.end(),
258 convertedCoordSys->begin(),
259 convertedCoordSys->end());
262 const auto& additionalCoordSysIds = _GetAdditionalCoordSysIds();
263 allCoordSysIds.insert(allCoordSysIds.end(),
264 additionalCoordSysIds.begin(),
265 additionalCoordSysIds.end());
266 coordSysList.count = allCoordSysIds.size();
267 coordSysList.ids = allCoordSysIds.data();
272 static const HdDirtyBits prmanProtoAttrBits =
273 HdChangeTracker::DirtyPoints |
274 HdChangeTracker::DirtyNormals |
275 HdChangeTracker::DirtyWidths |
276 HdChangeTracker::DirtyVolumeField |
277 HdChangeTracker::DirtyTopology |
278 HdChangeTracker::DirtyPrimvar;
282 static const HdDirtyBits prmanInstAttrBits =
283 HdChangeTracker::DirtyMaterialId |
284 HdChangeTracker::DirtyTransform |
285 HdChangeTracker::DirtyVisibility |
286 HdChangeTracker::DirtyDoubleSided |
287 HdChangeTracker::DirtySubdivTags |
288 HdChangeTracker::DirtyVolumeField |
289 HdChangeTracker::DirtyCategories |
290 HdChangeTracker::DirtyPrimvar |
291 HdChangeTracker::DirtyRenderTag;
295 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
296 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
301 std::vector<riley::MaterialId> subsetMaterialIds;
302 std::vector<SdfPath> subsetPaths;
307 RtPrimVarList primvars;
308 HdGeomSubsets geomSubsets;
309 std::vector<RtPrimVarList> geomSubsetPrimvars;
310 bool ok = _ConvertGeometry(param, sceneDelegate,
id,
311 &primType, &primvars,
312 &geomSubsets, &geomSubsetPrimvars);
319 primvars.SetString(RixStr.k_identifier_object,
320 RtUString(
id.GetText()));
321 for (
size_t i=0, n=geomSubsets.size(); i<n; ++i) {
322 geomSubsetPrimvars[i]
323 .SetString(RixStr.k_identifier_object,
324 RtUString(geomSubsets[i].
id.GetText()));
329#if PXR_VERSION < 2311
331 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
336 const size_t oldCount = _prototypeIds.size();
337 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
338 if (newCount != oldCount) {
339 for (
const auto &oldPrototypeId: _prototypeIds) {
340 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
341 riley->DeleteGeometryPrototype(oldPrototypeId);
344 _prototypeIds.resize(newCount,
345 riley::GeometryPrototypeId::InvalidId());
348 const HdPrman_CameraContext& cameraContext = param->GetCameraContext();
349 _ResolveDicingCamera(cameraContext, &primvars);
350 for (RtPrimVarList& subsetPrimvars : geomSubsetPrimvars) {
356 _ResolveDicingCamera(cameraContext, &subsetPrimvars);
359 _AddPrimvars(&primvars);
362 if (geomSubsets.empty()) {
366 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
367 RtUString(primPath.
GetText()));
368 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
369 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
370 _prototypeIds[0] = riley->CreateGeometryPrototype(
372 stats::AddDataLocation(primPath.
GetText()).GetValue()),
373 primType, dispId, primvars);
374 }
else if (prmanProtoAttrBitsWereSet) {
375 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
376 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
384 subsetMaterialIds.reserve(geomSubsets.size());
388 subsetPaths.reserve(geomSubsets.size());
390 for (
size_t j=0; j < geomSubsets.size(); ++j) {
391 auto& prototypeId = _prototypeIds[j];
393 RtPrimVarList &subsetPrimvars = geomSubsetPrimvars[j];
396 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
398 subsetPrimvars.SetIntegerArray(RixStr.k_shade_faceset,
400 int32Indices.size());
402 riley::MaterialId subsetMaterialId = materialId;
403 riley::DisplacementId subsetDispId = dispId;
407 HdPrman_ResolveMaterial(
409 riley, &subsetMaterialId, &subsetDispId);
410 subsetMaterialIds.push_back(subsetMaterialId);
415 subsetPaths.push_back(subsetPath);
416 subsetPrimvars.SetString(
417 RixStr.k_stats_prototypeIdentifier,
418 RtUString(subsetPath.
GetText()));
420 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
421 TRACE_SCOPE(
"riley::CreateGeometryPrototype");
423 riley->CreateGeometryPrototype(
425 stats::AddDataLocation(
426 subsetPath.
GetText()).GetValue()),
427 primType, subsetDispId, subsetPrimvars);
428 }
else if (prmanProtoAttrBitsWereSet) {
429 TRACE_SCOPE(
"riley::ModifyGeometryPrototype");
430 riley->ModifyGeometryPrototype(
431 primType, prototypeId,
432 &subsetDispId, &subsetPrimvars);
436 *dirtyBits &= ~prmanProtoAttrBits;
442 if (_PrototypeOnly()) {
453 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
457 attrs.SetString(RtUString(
"user:__materialid"), RtUString(hdMaterialId.
GetText()));
464 for (
size_t i=0; i < xf.count; ++i) {
465 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
467 const riley::Transform xform = {
473 const size_t oldCount = _instanceIds.size();
474 const size_t newCount = _prototypeIds.size();
475 if (newCount != oldCount) {
476 for (
const auto &oldInstanceId: _instanceIds) {
477 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
478 riley->DeleteGeometryInstance(
479 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
484 riley::GeometryInstanceId::InvalidId());
488 param->AddRenderTagToGroupingMembership(
493 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
494 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
495 auto const& prototypeId = _prototypeIds[j];
496 auto& instanceId = _instanceIds[j];
497 auto instanceMaterialId = materialId;
498 RtParamList finalAttrs = attrs;
503 if (!subsetPaths.empty()) {
504 idPath = &subsetPaths[j];
508 param->GetIdMap()->RegisterId(
509 { idPath->GetString(),
515 if (!subsetMaterialIds.empty()) {
517 instanceMaterialId = subsetMaterialIds[j];
521 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
522 TRACE_SCOPE(
"riley::CreateGeometryInstance");
523 instanceId = riley->CreateGeometryInstance(
525 stats::AddDataLocation(idPath->GetText()).GetValue()),
526 riley::GeometryPrototypeId::InvalidId(), prototypeId,
527 instanceMaterialId, coordSysList, xform, finalAttrs);
528 }
else if (prmanInstAttrBitsWereSet) {
529 TRACE_SCOPE(
"riley::ModifyGeometryInstance");
530 riley->ModifyGeometryInstance(
531 riley::GeometryPrototypeId::InvalidId(),
532 instanceId, &instanceMaterialId, &coordSysList, &xform,
536 *dirtyBits &= ~prmanInstAttrBits;
537 }
else if (prmanInstAttrBitsWereSet
554 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
556 if (subsetMaterialIds.size() == 0) {
557 subsetMaterialIds.push_back(materialId);
559 if (subsetPaths.size() == 0) {
560 subsetPaths.push_back(primPath);
562 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
563 _prototypeIds.size() == subsetPaths.size(),
564 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
565 subsetMaterialIds.size(), subsetPaths.size());
573 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
575 return id == riley::GeometryPrototypeId::InvalidId();
577 TF_WARN(
"Riley geometry prototype creation failed for "
578 "instanced gprim <%s>; the prim will not be instanced.",
582 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
600PXR_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.