Skip to content

Commit fd87ce7

Browse files
author
devsh
committed
outline some ideas about dealing with indexing schemes
1 parent 0a37d24 commit fd87ce7

File tree

3 files changed

+230
-40
lines changed

3 files changed

+230
-40
lines changed

include/nbl/asset/ICPUPolygonGeometry.h

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ class NBL_API2 ICPUPolygonGeometry final : public IAsset, public IPolygonGeometr
4646
retval->m_auxAttributeViews.push_back(view.clone(nextDepth));
4747
retval->m_normalView = m_normalView.clone(nextDepth);
4848
retval->m_jointCount = m_jointCount;
49-
retval->m_verticesForFirst = m_verticesForFirst;
50-
retval->m_verticesPerSupplementary = m_verticesPerSupplementary;
5149
return retval;
5250
}
5351

@@ -92,27 +90,15 @@ class NBL_API2 ICPUPolygonGeometry final : public IAsset, public IPolygonGeometr
9290
}
9391

9492
//
95-
inline bool setVerticesForFirst(const uint16_t count)
93+
inline bool setIndexing(const IIndexingCallback* indexing)
9694
{
9795
if (isMutable())
9896
{
99-
m_verticesForFirst = count;
97+
m_indexing = indexing;
10098
return true;
10199
}
102100
return false;
103101
}
104-
105-
//
106-
inline bool setVerticesPerSupplementary(const uint16_t count)
107-
{
108-
if (isMutable())
109-
{
110-
m_verticesPerSupplementary = count;
111-
return true;
112-
}
113-
return false;
114-
}
115-
116102
//
117103
inline bool setNormalView(SDataView&& view)
118104
{
@@ -155,7 +141,17 @@ class NBL_API2 ICPUPolygonGeometry final : public IAsset, public IPolygonGeometr
155141
template<typename Out, typename Index=uint32_t> requires (hlsl::concepts::UnsignedIntegralScalar<Out> && hlsl::concepts::UnsignedIntegralScalar<Index>)
156142
inline bool getPrimitiveIndices(Out* out, const Index primitiveID) const
157143
{
158-
// TODO: rename `m_verticesForFirst` to `m_verticesPerPrimitive` or `m_degree`
144+
if (!m_indexing)
145+
return false;
146+
if (m_indexView)
147+
{
148+
}
149+
else
150+
{
151+
}
152+
IIndexingCallback::SContext ctx = {
153+
.indexSizeLog2 = m_indexView
154+
};
159155
for (auto i=0; i<m_verticesForFirst; i++)
160156
{
161157
assert(false);

include/nbl/asset/IPolygonGeometry.h

Lines changed: 133 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,134 @@
1111

1212
namespace nbl::asset
1313
{
14+
//
15+
class NBL_API2 IPolygonGeometryBase : public virtual core::IReferenceCounted
16+
{
17+
public:
18+
//
19+
class NBL_API2 IIndexingCallback
20+
{
21+
public:
22+
// how many vertices per polygon
23+
inline uint8_t degree() const
24+
{
25+
const auto retval = degree_impl();
26+
assert(retval>0);
27+
return retval;
28+
}
29+
//
30+
inline uint8_t reuseCount() const
31+
{
32+
const auto retval = reuseCount_impl();
33+
assert(retval<degree());
34+
return retval;
35+
}
36+
37+
struct SContext
38+
{
39+
template<typename Index> requires std::is_integral_v<Index>
40+
inline Index indexSize() const {return Index(1)<<indexSizeLog2;}
41+
42+
template<typename Index> requires std::is_integral_v<Index>
43+
inline void setOutput(const Index value) const
44+
{
45+
switch (indexSizeLog2)
46+
{
47+
case 0:
48+
*reinterpret_cast<uint8_t*>(out) = value;
49+
break;
50+
case 1:
51+
*reinterpret_cast<uint16_t*>(out) = value;
52+
break;
53+
case 2:
54+
*reinterpret_cast<uint32_t*>(out) = value;
55+
break;
56+
case 3:
57+
*reinterpret_cast<uint64_t*>(out) = value;
58+
break;
59+
default:
60+
assert(false);
61+
break;
62+
}
63+
}
64+
65+
const uint8_t* const indexBuffer;
66+
// no point making them smaller cause of padding
67+
const uint32_t inSizeLog2;
68+
const uint32_t outSizeLog2;
69+
uint8_t* out;
70+
uint32_t newIndexID;
71+
// if `reuseCount()==0` then should be ignored
72+
uint32_t restartValue = ~0ull;
73+
};
74+
inline void operator()(SContext& ctx) const
75+
{
76+
const auto deg = degree();
77+
if (ctx.newIndexID<deg || primitiveRestart)
78+
{
79+
// straight up copy
80+
}
81+
operator_impl(ctx);
82+
ctx.newIndexID += reuseCount();
83+
ctx.out += deg<<ctx.outSizeLog2;
84+
}
85+
86+
// default is unknown
87+
virtual inline E_PRIMITIVE_TOPOLOGY knownTopology() const {return static_cast<E_PRIMITIVE_TOPOLOGY>(~0);}
88+
89+
protected:
90+
virtual uint8_t degree_impl() const = 0;
91+
virtual uint8_t reuseCount_impl() const = 0;
92+
// needs to deal with being handed `!ctx.indexBuffer`
93+
virtual void operator_impl(const SContext& ctx) const = 0;
94+
};
95+
//
96+
static IIndexingCallback* PointList();
97+
static IIndexingCallback* LineList();
98+
static IIndexingCallback* TriangleList();
99+
static IIndexingCallback* QuadList();
100+
//
101+
static IIndexingCallback* TriangleStrip();
102+
static IIndexingCallback* TriangleFan();
103+
104+
//
105+
inline const IIndexingCallback* getIndexingCallback() const {return m_indexing;}
106+
107+
protected:
108+
virtual ~IPolygonGeometryBase() = default;
109+
110+
//
111+
const IIndexingCallback* m_indexing = nullptr;
112+
};
113+
14114
// Don't want to overengineer, support for variable vertex count (order) polgyon meshes is not encouraged or planned.
15115
// If you want different polygon types in same model, bucket the polgyons into separate geometries and reunite in a single collection.
16116
template<class BufferType>
17-
class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
117+
class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>, public IPolygonGeometryBase
18118
{
19119
using base_t = IIndexableGeometry<BufferType>;
20120

21121
protected:
22122
using EPrimitiveType = base_t::EPrimitiveType;
23-
using BLASTriangles = IBottomLevelAccelerationStructure::Triangles<std::remove_const<BufferType>>;
123+
using SDataView = base_t::SDataView;
124+
using BLASTriangles = IBottomLevelAccelerationStructure::Triangles<std::remove_const_t<BufferType>>;
24125

25126
public:
26127
//
27128
virtual inline bool valid() const override
28129
{
29130
if (!base_t::valid())
30131
return false;
132+
if (!m_indexing)
133+
return false;
31134
// things that make no sense
32135
if (m_verticesPerSupplementary==0 || m_verticesPerSupplementary>m_verticesForFirst)
33136
return false;
34137
// there needs to be at least one vertex to reference (it also needs to be formatted)
35-
if (m_positionView.getElementCount()==0)
138+
const auto& positionBase = base_t::m_positionView.composed;
139+
const auto vertexCount = positionBase.getElementCount();
140+
if (vertexCount==0 || !positionBase.isFormatted())
36141
return false;
37-
const auto vertexCount = m_positionView.getElementCount();
38142
if (m_normalView && m_normalView.getElementCount()<vertexCount)
39143
return false;
40144
// the variable length vectors must be filled with valid views
@@ -52,18 +156,21 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
52156
inline EPrimitiveType getPrimitiveType() const override final {return PrimitiveType;}
53157

54158
//
55-
inline const auto& getAABB() const override final {return m_positionView.encodedDataRange;}
159+
inline const IGeometryBase::SAABBStorage& getAABB() const override final {return base_t::m_positionView.encodedDataRange;}
56160

57161
//
58-
inline uint64_t getVertexReferenceCount() const {return getIndexView() ? getIndexCount():m_positionView.getElementCount();}
162+
inline uint64_t getVertexReferenceCount() const {return base_t::getIndexView() ? base_t::getIndexCount():base_t::m_positionView.getElementCount();}
59163

60164
//
61165
inline uint64_t getPrimitiveCount() const override final
62166
{
167+
if (!m_indexing)
168+
return 0;
63169
const auto vertexReferenceCount = getVertexReferenceCount();
64-
if (vertexReferenceCount<m_verticesForFirst)
170+
const auto verticesForFirst = m_indexing->degree();
171+
if (vertexReferenceCount<verticesForFirst)
65172
return 0;
66-
return (vertexReferenceCount-m_verticesForFirst)/m_verticesPerSupplementary;
173+
return (vertexReferenceCount-verticesForFirst)/(verticesForFirst-m_indexing->reuseCount());
67174
}
68175

69176
// For when the geometric normal of the patch isn't enough and you want interpolated custom normals
@@ -92,11 +199,6 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
92199
// For User defined semantics
93200
inline const core::vector<SDataView>& getAuxAttributeViews() const {return m_auxAttributeViews;}
94201

95-
// Simple geometries like point, line, triangle and patch have `m_verticesForFirst==m_verticesPerSupplementary`
96-
// Note that this is also true for adjacency lists, but they're the reason `m_verticesForFirst` is not named `m_order` or `m_n`
97-
// While strips and fans have `m_verticesForFirst>m_verticesPerSupplementary`
98-
inline uint16_t getVerticesForFirst() const {return m_verticesForFirst;}
99-
inline uint16_t getVerticesPerSupplementary() const {return m_verticesPerSupplementary;}
100202

101203
// Does not set the `transform` or `geometryFlags` fields, because it doesn't care about it.
102204
// Also won't set second set of vertex data, opacity mipmaps, etc.
@@ -108,9 +210,9 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
108210
{
109211
auto indexType = EIT_UNKNOWN;
110212
// disallowed index format
111-
if (m_indexView)
213+
if (base_t::m_indexView)
112214
{
113-
switch (m_indexView.format)
215+
switch (base_t::m_indexView.format)
114216
{
115217
case EF_R16_UINT:
116218
indexType = EIT_16BIT;
@@ -124,11 +226,11 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
124226
if (indexType==EIT_UNKNOWN)
125227
return retval;
126228
}
127-
retval.vertexData[0] = m_positionView;
128-
retval.indexData = m_indexView;
129-
retval.maxVertex = m_positionView.getElementCount();
130-
retval.vertexStride = m_positionView.getStride();
131-
retval.vertexFormat = m_positionView.format;
229+
retval.vertexData[0] = base_t::m_positionView;
230+
retval.indexData = base_t::m_indexView;
231+
retval.maxVertex = base_t::m_positionView.getElementCount();
232+
retval.vertexStride = base_t::m_positionView.getStride();
233+
retval.vertexFormat = base_t::m_positionView.format;
132234
retval.indexType = indexType;
133235
}
134236
return retval;
@@ -137,6 +239,17 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
137239
protected:
138240
virtual ~IPolygonGeometry() = default;
139241

242+
//
243+
inline bool setIndexView(SDataView&& view)
244+
{
245+
if (!view || view.isFormattedScalarInteger())
246+
{
247+
m_indexView = std::move(view);
248+
return true;
249+
}
250+
return false;
251+
}
252+
140253
//
141254
core::vector<SJointWeight> m_jointWeightViews = {};
142255
//
@@ -145,9 +258,6 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>
145258
SDataView m_normalView = {};
146259
//
147260
uint32_t m_jointCount = 0;
148-
//
149-
uint16_t m_verticesForFirst = 1;
150-
uint16_t m_verticesPerSupplementary = 0;
151261
};
152262

153263
}

src/nbl/asset/ICPUPolygonGeometry.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include "nbl/asset/ICPUPolygonGeometry.h"
2+
3+
using namespace nbl;
4+
using namespace asset;
5+
6+
7+
template<uint8_t Order> requires (Order>0)
8+
class CListIndexingCB final : public IPolygonGeometryBase::IIndexingCallback
9+
{
10+
inline uint8_t degree_impl() const override {return Order;}
11+
inline uint8_t reuseCount_impl() const override {return 0;}
12+
inline void operator_impl(const SContext& ctx) const override
13+
{
14+
if (ctx.indexBuffer)
15+
memcpy(ctx.out,ctx.indexBuffer+(ctx.newIndexID<<ctx.indexSizeLog2),Order<<ctx.indexSizeLog2);
16+
else
17+
for (auto i=0u; i<Order; i++)
18+
{
19+
ctx.setOutput(ctx.newIndexID+i);
20+
ctx.out += ctx.indexSize();
21+
}
22+
}
23+
};
24+
auto IPolygonGeometryBase::PointList() -> IIndexingCallback*
25+
{
26+
static CListIndexingCB<1> singleton;
27+
return &singleton;
28+
}
29+
auto IPolygonGeometryBase::LineList() -> IIndexingCallback*
30+
{
31+
static CListIndexingCB<2> singleton;
32+
return &singleton;
33+
}
34+
auto IPolygonGeometryBase::TriangleList() -> IIndexingCallback*
35+
{
36+
static CListIndexingCB<3> singleton;
37+
return &singleton;
38+
}
39+
auto IPolygonGeometryBase::QuadList() -> IIndexingCallback*
40+
{
41+
static CListIndexingCB<4> singleton;
42+
return &singleton;
43+
}
44+
45+
class CTriangleStripIndexingCB final : public IIndexingCallback
46+
{
47+
inline uint8_t degree_impl() const override {return 3;}
48+
inline uint8_t reuseCount_impl() const override {return 2;}
49+
inline void operator_impl(const SContext& ctx) const override
50+
{
51+
// two immediately previous and current
52+
memcpy(out,indexBuffer+(newIndexID-2)*indexSize,indexSize*3);
53+
}
54+
};
55+
auto IPolygonGeometryBase::TriangleStrip() -> IIndexingCallback*
56+
{
57+
static CTriangleStripIndexingCB singleton;
58+
return &singleton;
59+
}
60+
61+
class CTriangleFanIndexingCB final : public IIndexingCallback
62+
{
63+
inline uint8_t degree_impl() const override {return 3;}
64+
inline uint8_t reuseCount_impl() const override {return 2;}
65+
inline void operator_impl(const SContext& ctx) const override
66+
{
67+
// first index is always 0
68+
memset(ctx.out,0,ctx.indexSize());
69+
ctx.out += ctx.indexSize();
70+
// immediately previous and current
71+
if (ctx.indexBuffer)
72+
memcpy(ctx.out,ctx.indexBuffer+((ctx.newIndexID-1)<<ctx.indexSizeLog2),2u<<ctx.indexSizeLog2);
73+
else
74+
{
75+
ctx.setOutput(ctx.newIndexID-1);
76+
ctx.setOutput(ctx.newIndexID);
77+
}
78+
}
79+
};
80+
auto IPolygonGeometryBase::TriangleFan() -> IIndexingCallback*
81+
{
82+
static CTriangleFanIndexingCB singleton;
83+
return &singleton;
84+
}

0 commit comments

Comments
 (0)