Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions include/Inventor/actions/SoIRRenderAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,46 @@ class COIN_DLL_API SoIRRenderAction : public SoAction {
*/
class PrimitiveCollector {
public:
//! Primitive attributes needed by the retained renderer.
struct VertexData {
SbVec3f point;
SbVec3f normal;
SbVec4f texcoord = SbVec4f(0.0f, 0.0f, 0.0f, 1.0f);
int materialIndex = 0;
};
virtual ~PrimitiveCollector() {}
virtual void onTriangle(const SoPrimitiveVertex * v1,
const SoPrimitiveVertex * v2,
const SoPrimitiveVertex * v3) = 0;
virtual void onLine(const SoPrimitiveVertex * v1,
const SoPrimitiveVertex * v2) = 0;
virtual void onPoint(const SoPrimitiveVertex * v) = 0;
//! Receive an already resolved triangle and its picking identity.
virtual void onTriangleData(const VertexData & v1,
const VertexData & v2,
const VertexData & v3,
int faceIndex) = 0;
//! Receive an already resolved line segment and its picking identity.
virtual void onLineData(const VertexData & v1,
const VertexData & v2,
int lineIndex) = 0;
//! Reuse or register an explicit non-textured triangle source.
virtual SbBool beginRetainedTriangles(uint64_t sourceKey,
uint64_t revision,
int faceCount)
{ return FALSE; }
//! Reuse a previously registered triangle source without rescanning it.
virtual SbBool reuseRetainedTriangles(uint64_t sourceId,
uint64_t revision)
{ return FALSE; }
//! Reuse or register an explicit non-textured line-segment source.
virtual SbBool beginRetainedLines(uint64_t sourceId,
uint64_t revision,
int segmentCount)
{ return FALSE; }
virtual SbBool reuseRetainedLines(uint64_t sourceId,
uint64_t revision)
{ return FALSE; }
};

static void initClass(void);
Expand Down Expand Up @@ -166,6 +199,9 @@ class COIN_DLL_API SoIRRenderAction : public SoAction {
void popPrimitiveCollector(PrimitiveCollector * collector);
//! Return the currently active primitive collector, or NULL.
PrimitiveCollector * getActivePrimitiveCollector(void) const;
//! Find a geometry resource with the same producer identity this frame.
SoGeometryHandle findGeometrySource(uint64_t sourceKey,
uint64_t revision) const;
//! Enable intrusive construction attribution for benchmark diagnostics.
void setConstructionTimingEnabled(SbBool enabled);
SbBool isConstructionTimingEnabled() const;
Expand Down
2 changes: 2 additions & 0 deletions include/Inventor/elements/SoMultiTextureCoordinateElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class COIN_DLL_API SoMultiTextureCoordinateElement : public SoElement {
const int32_t numCoords, const SbVec4f * const coords);

static CoordType getType(SoState * const state, const int unit = 0);
//! Return the source node revision recorded for this coordinate unit.
static SbUniqueId getNodeId(SoState * const state, const int unit = 0);
virtual CoordType getType(const int unit = 0) const;

static const SoMultiTextureCoordinateElement * getInstance(SoState * const state);
Expand Down
2 changes: 2 additions & 0 deletions include/Inventor/elements/SoMultiTextureImageElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class COIN_DLL_API SoMultiTextureImageElement : public SoElement {
static Wrap getWrapS(SoState * const state, const int unit = 0);
static Wrap getWrapT(SoState * const state, const int unit = 0);
static Wrap getWrapR(SoState * const state, const int unit = 0);
//! Return the source node revision recorded for this texture unit.
static SbUniqueId getNodeId(SoState * const state, const int unit = 0);

static SbBool containsTransparency(SoState * const state);

Expand Down
1 change: 1 addition & 0 deletions include/Inventor/nodes/SoFaceSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class COIN_DLL_API SoFaceSet : public SoNonIndexedShape {
protected:
virtual ~SoFaceSet();

SbBool generateRetainedPrimitives(SoIRRenderAction * action) override;
void generatePrimitives(SoAction * action) override;
void computeBBox(SoAction * action, SbBox3f & box, SbVec3f & center) override;
SbBool generateDefaultNormals(SoState *, SoNormalCache *) override;
Expand Down
2 changes: 2 additions & 0 deletions include/Inventor/nodes/SoIndexedFaceSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#endif // !SO_END_FACE_INDEX

class SoIndexedFaceSetP;
class SoIRRenderAction;

class COIN_DLL_API SoIndexedFaceSet : public SoIndexedShape {
typedef SoIndexedShape inherited;
Expand All @@ -64,6 +65,7 @@ class COIN_DLL_API SoIndexedFaceSet : public SoIndexedShape {
protected:
virtual ~SoIndexedFaceSet();

SbBool generateRetainedPrimitives(SoIRRenderAction * action) override;
void generatePrimitives(SoAction * action) override;

private:
Expand Down
2 changes: 2 additions & 0 deletions include/Inventor/nodes/SoIndexedLineSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#endif // !SO_END_LINE_INDEX

class SoIndexedLineSetP;
class SoIRRenderAction;

class COIN_DLL_API SoIndexedLineSet : public SoIndexedShape {
typedef SoIndexedShape inherited;
Expand All @@ -60,6 +61,7 @@ class COIN_DLL_API SoIndexedLineSet : public SoIndexedShape {
protected:
virtual ~SoIndexedLineSet();
void notify(SoNotList * list) override;
SbBool generateRetainedPrimitives(SoIRRenderAction * action) override;

private:
void generatePrimitives(SoAction * action) override;
Expand Down
2 changes: 2 additions & 0 deletions include/Inventor/nodes/SoShape.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class COIN_DLL_API SoShape : public SoNode {

float getComplexityValue(SoAction * action);
virtual void generatePrimitives(SoAction * action) = 0;
//! Emit directly to a retained primitive collector when supported.
virtual SbBool generateRetainedPrimitives(SoIRRenderAction * action);
#if COIN_HAVE_LEGACY_GL_RENDERER
virtual SbBool shouldGLRender(SoGLRenderAction * action);
void beginSolidShape(SoGLRenderAction * action);
Expand Down
72 changes: 52 additions & 20 deletions include/Inventor/rendering/SoRenderIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,41 @@ struct SoGeometryDesc {

};

//! Stable, draw-list-local reference to a geometry resource.
using SoGeometryHandle = uint32_t;
static constexpr SoGeometryHandle SO_INVALID_GEOMETRY_HANDLE = 0;

//! Backend-neutral identity kinds retained for picking.
enum SoPickElementType : uint8_t {
SO_PICK_OBJECT = 0,
SO_PICK_FACE,
SO_PICK_EDGE,
SO_PICK_VERTEX
};

//! Maps one logical subelement to a geometry draw range.
struct SoRenderElementRange {
SoPickElementType type = SO_PICK_OBJECT;
int elementIndex = -1;
uint32_t drawStart = 0;
uint32_t drawCount = 0;
};

/*!
\struct SoGeometryResource
\brief Draw-list-owned geometry descriptor with producer identity.

Handles are one-based and remain stable until SoDrawList::clear(). The
descriptor keeps the existing frame-lifetime pointer contract; the resource
table separates shared geometry identity from individual draw commands.
*/
struct SoGeometryResource {
SoGeometryDesc geometry;
uint64_t sourceKey = 0;
uint64_t revision = 0;
std::vector<SoRenderElementRange> elementRanges;
};

/*!
\enum SoShadingModel
\brief Effective shading contract carried by a render command.
Expand Down Expand Up @@ -517,31 +552,12 @@ struct COIN_DLL_API SoIRRenderContext {
\enum SoPickElementType
\brief Backend-neutral identity kinds retained for picking.
*/
enum SoPickElementType : uint8_t {
SO_PICK_OBJECT = 0,
SO_PICK_FACE,
SO_PICK_EDGE,
SO_PICK_VERTEX
};

/*! \struct SoRenderElementRange
\brief Maps one logical subelement to a geometry draw range.

For indexed geometry, drawStart/drawCount refer to indices. For
non-indexed geometry, they refer to vertices.
*/
struct SoRenderElementRange {
SoPickElementType type = SO_PICK_OBJECT;
int elementIndex = -1;
uint32_t drawStart = 0;
uint32_t drawCount = 0;
};

/*! \struct SoPickData
\brief Backend-neutral pickability and optional subelement ranges.
*/
struct SoPickData {
bool pickable = true;
bool useResourceElementRanges = false;
std::vector<SoRenderElementRange> elementRanges;
};

Expand Down Expand Up @@ -637,6 +653,7 @@ struct SoRenderCommand {
// Geometry, texture pixels, and other pointer-valued fields are borrowed;
// see the lifetime contract on SoGeometryDesc and SoTextureData.
SoGeometryDesc geometry;
SoGeometryHandle geometryHandle = SO_INVALID_GEOMETRY_HANDLE;
SoMaterialData material;
SoRenderState state;

Expand Down Expand Up @@ -685,6 +702,20 @@ class COIN_DLL_API SoDrawList {
void addCommand(const SoRenderCommand & cmd);
SoRenderCommand & emplaceCommand();

//! Append a geometry resource and return its stable one-based handle.
SoGeometryHandle addGeometryResource(const SoGeometryResource & resource);
//! Return NULL for an invalid handle or a handle outside this draw list.
SoGeometryResource * getGeometryResource(SoGeometryHandle handle);
const SoGeometryResource * getGeometryResource(
SoGeometryHandle handle) const;
int getNumGeometryResources() const;
//! Resolve a command resource, falling back to its embedded descriptor.
const SoGeometryDesc & getCommandGeometry(
const SoRenderCommand & command) const;
//! Resolve command-local or shared geometry subelement ranges.
const std::vector<SoRenderElementRange> & getCommandElementRanges(
const SoRenderCommand & command) const;

int getNumCommands() const;
//! Remove commands beyond index count without reordering remaining commands.
void truncate(int count);
Expand Down Expand Up @@ -730,6 +761,7 @@ class COIN_DLL_API SoDrawList {

private:
std::vector<SoRenderCommand> commands;
std::vector<SoGeometryResource> geometryResources;
std::vector<SoLightingData> lightingSetups;
std::vector<SoDepthClearEvent> depthClearEvents;
SoSelectionState selection;
Expand Down
51 changes: 51 additions & 0 deletions src/actions/SoIRRenderAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include <algorithm>
#include <cstring>
#include <limits>
#include <unordered_map>
#include <vector>

SO_ACTION_SOURCE(SoIRRenderAction);
Expand All @@ -89,6 +90,7 @@ class SoIRRenderActionP {
SoIRBuffer geometryPool;
std::vector<TextureStorage> textureStorage;
SbList<SoIRRenderAction::PrimitiveCollector *> collectorStack;
std::unordered_multimap<uint64_t, SoGeometryHandle> geometrySources;
bool constructionTimingEnabled = false;
SoIRRenderAction::ConstructionStatistics constructionStatistics;
};
Expand Down Expand Up @@ -239,6 +241,40 @@ SoIRRenderAction::addCommand(const SoRenderCommand & command)
state, this->drawlist);
}

if (retained.geometry.cacheKey != 0) {
retained.geometryHandle = this->findGeometrySource(
retained.geometry.cacheKey, retained.geometry.revision);
if (retained.geometryHandle == SO_INVALID_GEOMETRY_HANDLE) {
SoGeometryResource resource;
resource.geometry = retained.geometry;
resource.sourceKey = retained.geometry.cacheKey;
resource.revision = retained.geometry.revision;
resource.elementRanges = retained.pick.elementRanges;
retained.geometryHandle = this->drawlist.addGeometryResource(resource);
retained.pick.elementRanges.clear();
retained.pick.useResourceElementRanges = true;
PRIVATE(this)->geometrySources.emplace(
retained.geometry.cacheKey, retained.geometryHandle);
}
else {
const SoGeometryResource * resource =
this->drawlist.getGeometryResource(retained.geometryHandle);
const auto rangesEqual = [](const SoRenderElementRange & lhs,
const SoRenderElementRange & rhs) {
return lhs.type == rhs.type && lhs.elementIndex == rhs.elementIndex &&
lhs.drawStart == rhs.drawStart && lhs.drawCount == rhs.drawCount;
};
if (resource && resource->elementRanges.size() ==
retained.pick.elementRanges.size() &&
std::equal(resource->elementRanges.begin(),
resource->elementRanges.end(),
retained.pick.elementRanges.begin(), rangesEqual)) {
retained.pick.elementRanges.clear();
retained.pick.useResourceElementRanges = true;
}
}
}

const int commandIndex = this->drawlist.getNumCommands();
this->drawlist.addCommand(retained);

Expand Down Expand Up @@ -418,6 +454,20 @@ SoIRRenderAction::getActivePrimitiveCollector(void) const
return PRIVATE(this)->collectorStack[count - 1];
}

SoGeometryHandle
SoIRRenderAction::findGeometrySource(const uint64_t sourceKey,
const uint64_t revision) const
{
const auto candidates = PRIVATE(this)->geometrySources.equal_range(sourceKey);
for (auto candidate = candidates.first; candidate != candidates.second;
++candidate) {
const SoGeometryResource * resource =
this->drawlist.getGeometryResource(candidate->second);
if (resource && resource->revision == revision) return candidate->second;
}
return SO_INVALID_GEOMETRY_HANDLE;
}

void
SoIRRenderAction::setConstructionTimingEnabled(const SbBool enabled)
{
Expand Down Expand Up @@ -572,6 +622,7 @@ SoIRRenderAction::resetFrameResources()
PRIVATE(this)->geometryPool.clear();
PRIVATE(this)->textureStorage.clear();
PRIVATE(this)->collectorStack.truncate(0);
PRIVATE(this)->geometrySources.clear();
PRIVATE(this)->constructionStatistics = ConstructionStatistics();
}

Expand Down
9 changes: 9 additions & 0 deletions src/elements/SoMultiTextureCoordinateElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,15 @@ SoMultiTextureCoordinateElement::getType(SoState * const state, const int unit)
return element->getType(unit);
}

SbUniqueId
SoMultiTextureCoordinateElement::getNodeId(SoState * const state,
const int unit)
{
const SoMultiTextureCoordinateElement * elem = getInstance(state);
PRIVATE(elem)->ensureCapacity(unit);
return PRIVATE(elem)->unitdata[unit].nodeid;
}

//! FIXME: write doc.

// side effect, will increase array size
Expand Down
10 changes: 10 additions & 0 deletions src/elements/SoMultiTextureImageElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ SoMultiTextureImageElement::get(SoState * const state,
return getImage(state, unit, size, numComponents);
}

SbUniqueId
SoMultiTextureImageElement::getNodeId(SoState * const state, const int unit)
{
const SoMultiTextureImageElement * elem =
coin_assert_cast<const SoMultiTextureImageElement *>(
getConstElement(state, classStackIndex));
PRIVATE(elem)->ensureCapacity(unit);
return PRIVATE(elem)->unitdata[unit].nodeid;
}

/*!
FIXME: write doc.

Expand Down
Loading