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();
119 virtual RtPrimVarList
120 _ConvertGeometry(HdPrman_RenderParam *renderParam,
124 std::vector<HdGeomSubset> *geomSubsets) = 0;
132template <
typename BASE>
136 HdDirtyBits* dirtyBits,
140 HF_MALLOC_TAG_FUNCTION();
146 static const HdDirtyBits internalDirtyBits =
147 HdChangeTracker::InitRepr |
148 HdChangeTracker::Varying |
149 HdChangeTracker::NewRepr |
150 HdChangeTracker::CustomBitsMask;
152 *dirtyBits &= ~(HdChangeTracker::NewRepr | HdChangeTracker::CustomBitsMask);
155 if (((*dirtyBits & ~internalDirtyBits)
156 & HdChangeTracker::AllSceneDirtyBits) == 0) {
160 HdPrman_RenderParam *param =
161 static_cast<HdPrman_RenderParam*
>(renderParam);
164 riley::Riley *riley = param->AcquireRiley();
167 BASE::_UpdateInstancer(sceneDelegate, dirtyBits);
170 SdfPath const&
id = BASE::GetId();
171 SdfPath const& instancerId = BASE::GetInstancerId();
172 const bool isHdInstance = !instancerId.
IsEmpty();
179 const int32_t primId = BASE::GetPrimId() + 1;
184#
if HD_API_VERSION >= 68
185 param->GetShutterInterval()[0],
186 param->GetShutterInterval()[1],
192 BASE::_UpdateVisibility(sceneDelegate, dirtyBits);
196 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
197#if HD_API_VERSION < 37
198 BASE::_SetMaterialId(sceneDelegate->
GetRenderIndex().GetChangeTracker(),
204 riley::MaterialId materialId = _GetFallbackMaterial(param);
205 riley::DisplacementId dispId = riley::DisplacementId::InvalidId();
206 const SdfPath & hdMaterialId = BASE::GetMaterialId();
207 HdPrman_ResolveMaterial(sceneDelegate, hdMaterialId, riley, &materialId, &dispId);
210 riley::CoordinateSystemList coordSysList = {0,
nullptr};
211 if (HdPrman_RenderParam::RileyCoordSysIdVecRefPtr convertedCoordSys =
212 param->ConvertAndRetainCoordSysBindings(sceneDelegate,
id)) {
213 coordSysList.count = convertedCoordSys->size();
214 coordSysList.ids = convertedCoordSys->data();
220 static const HdDirtyBits prmanProtoAttrBits =
221 HdChangeTracker::DirtyPoints |
222 HdChangeTracker::DirtyNormals |
223 HdChangeTracker::DirtyWidths |
224 HdChangeTracker::DirtyVolumeField |
225 HdChangeTracker::DirtyTopology |
226 HdChangeTracker::DirtyPrimvar;
230 static const HdDirtyBits prmanInstAttrBits =
231 HdChangeTracker::DirtyMaterialId |
232 HdChangeTracker::DirtyTransform |
233 HdChangeTracker::DirtyVisibility |
234 HdChangeTracker::DirtyDoubleSided |
235 HdChangeTracker::DirtySubdivTags |
236 HdChangeTracker::DirtyVolumeField |
237 HdChangeTracker::DirtyCategories |
238 HdChangeTracker::DirtyPrimvar;
242 const bool prmanProtoAttrBitsWereSet(*dirtyBits & prmanProtoAttrBits);
243 const bool prmanInstAttrBitsWereSet(*dirtyBits & prmanInstAttrBits);
248 std::vector<riley::MaterialId> subsetMaterialIds;
249 std::vector<SdfPath> subsetPaths;
252 HdGeomSubsets geomSubsets;
253 RtPrimVarList primvars = _ConvertGeometry(param, sceneDelegate,
id,
254 &primType, &geomSubsets);
257 primvars.SetString(RixStr.k_identifier_object,
258 RtUString(
id.GetName().c_str()));
262#if PXR_VERSION < 2311
264 HdPrman_TransferMaterialPrimvarOpinions(sceneDelegate, hdMaterialId,
269 const size_t oldCount = _prototypeIds.size();
270 const size_t newCount = std::max((
size_t) 1, geomSubsets.size());
271 if (newCount != oldCount) {
272 for (
const auto &oldPrototypeId: _prototypeIds) {
273 if (oldPrototypeId != riley::GeometryPrototypeId::InvalidId()) {
274 riley->DeleteGeometryPrototype(oldPrototypeId);
277 _prototypeIds.resize(newCount,
278 riley::GeometryPrototypeId::InvalidId());
282 if (geomSubsets.empty()) {
286 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
287 RtUString(primPath.
GetText()));
288 if (_prototypeIds[0] == riley::GeometryPrototypeId::InvalidId()) {
290 _prototypeIds[0] = riley->CreateGeometryPrototype(
292 stats::AddDataLocation(primPath.
GetText()).GetValue()),
293 primType, dispId, primvars);
294 }
else if (prmanProtoAttrBitsWereSet) {
296 riley->ModifyGeometryPrototype(primType, _prototypeIds[0],
304 subsetMaterialIds.reserve(geomSubsets.size());
307 subsetPaths.reserve(geomSubsets.size());
309 for (
size_t j=0; j < geomSubsets.size(); ++j) {
310 auto& prototypeId = _prototypeIds[j];
314 std::vector<int32_t> int32Indices(subset.
indices.cbegin(),
316 primvars.SetIntegerArray(RixStr.k_shade_faceset,
318 int32Indices.size());
320 riley::MaterialId subsetMaterialId = materialId;
321 riley::DisplacementId subsetDispId = dispId;
325 HdPrman_ResolveMaterial(sceneDelegate, subset.
materialId,
326 riley, &subsetMaterialId, &subsetDispId);
327 subsetMaterialIds.push_back(subsetMaterialId);
331 subsetPaths.push_back(subsetPath);
332 primvars.SetString(RixStr.k_stats_prototypeIdentifier,
333 RtUString(subsetPath.
GetText()));
335 if (prototypeId == riley::GeometryPrototypeId::InvalidId()) {
338 riley->CreateGeometryPrototype(
340 stats::AddDataLocation(subsetPath.
GetText()).GetValue()),
341 primType, dispId, primvars);
342 }
else if (prmanProtoAttrBitsWereSet) {
344 riley->ModifyGeometryPrototype(primType, prototypeId,
345 &subsetDispId, &primvars);
349 *dirtyBits &= ~prmanProtoAttrBits;
355 if (_PrototypeOnly()) {
365 RtParamList attrs = param->ConvertAttributes(sceneDelegate,
id,
true);
368 attrs.SetInteger(RixStr.k_identifier_id, primId);
372 attrs.SetString(RtUString(
"user:__materialid"), RtUString(hdMaterialId.
GetText()));
379 for (
size_t i=0; i < xf.count; ++i) {
380 xf_rt[i] = HdPrman_Utils::GfMatrixToRtMatrix(xf.values[i]);
382 const riley::Transform xform = {
389 attrs.SetInteger(RixStr.k_identifier_id2, 0);
392 const size_t oldCount = _instanceIds.size();
393 const size_t newCount = _prototypeIds.size();
394 if (newCount != oldCount) {
395 for (
const auto &oldInstanceId: _instanceIds) {
396 if (oldInstanceId != riley::GeometryInstanceId::InvalidId()) {
397 riley->DeleteGeometryInstance(
398 riley::GeometryPrototypeId::InvalidId(), oldInstanceId);
403 riley::GeometryInstanceId::InvalidId());
407 param->AddRenderTagToGroupingMembership(
412 TF_VERIFY(_instanceIds.size() == _prototypeIds.size());
413 for (
size_t j=0; j < _prototypeIds.size(); ++j) {
414 auto const& prototypeId = _prototypeIds[j];
415 auto& instanceId = _instanceIds[j];
416 auto instanceMaterialId = materialId;
417 RtParamList finalAttrs = attrs;
420 SdfPath* subsetPath(&primPath);
421 if (!subsetPaths.empty()) {
422 subsetPath = &subsetPaths[j];
425 finalAttrs.SetString(RixStr.k_identifier_name,
426 RtUString(subsetPath->
GetText()));
429 if (!subsetMaterialIds.empty()) {
431 instanceMaterialId = subsetMaterialIds[j];
434 if (instanceId == riley::GeometryInstanceId::InvalidId()) {
436 instanceId = riley->CreateGeometryInstance(
438 stats::AddDataLocation(subsetPath->
GetText()).GetValue()),
439 riley::GeometryPrototypeId::InvalidId(), prototypeId,
440 instanceMaterialId, coordSysList, xform, finalAttrs);
441 }
else if (prmanInstAttrBitsWereSet) {
443 riley->ModifyGeometryInstance(
444 riley::GeometryPrototypeId::InvalidId(),
445 instanceId, &instanceMaterialId, &coordSysList, &xform,
449 *dirtyBits &= ~prmanInstAttrBits;
450 }
else if (prmanInstAttrBitsWereSet
467 HdInstancer::_SyncInstancerAndParents(renderIndex, instancerId);
469 if (subsetMaterialIds.size() == 0) {
470 subsetMaterialIds.push_back(materialId);
472 if (subsetPaths.size() == 0) {
473 subsetPaths.push_back(primPath);
475 TF_VERIFY(_prototypeIds.size() == subsetMaterialIds.size() &&
476 _prototypeIds.size() == subsetPaths.size(),
477 "size mismatch (%lu, %lu, %lu)\n", _prototypeIds.size(),
478 subsetMaterialIds.size(), subsetPaths.size());
486 if (std::any_of(_prototypeIds.begin(), _prototypeIds.end(),
488 return id == riley::GeometryPrototypeId::InvalidId();
490 TF_WARN(
"Riley geometry prototype creation failed for "
491 "instanced gprim <%s>; the prim will not be instanced.",
495 HdPrmanInstancer *instancer =
static_cast<HdPrmanInstancer*
>(
513PXR_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.
#define TRACE_SCOPE(name)
Records a timestamp when constructed and a timespan event when destructed, using name as the key.