8
8
#include " nbl/asset/IGeometry.h"
9
9
#include " nbl/asset/IAccelerationStructure.h"
10
10
11
+ #include < span>
11
12
12
13
namespace nbl ::asset
13
14
{
@@ -26,87 +27,91 @@ class NBL_API2 IPolygonGeometryBase : public virtual core::IReferenceCounted
26
27
assert (retval>0 );
27
28
return retval;
28
29
}
29
- //
30
- inline uint8_t reuseCount () const
30
+ // at which we consume indices for each new polygon
31
+ inline uint8_t rate () const
31
32
{
32
- const auto retval = reuseCount_impl ();
33
- assert (retval< degree ());
33
+ const auto retval = rate_impl ();
34
+ assert (retval> 0 && retval<= degree ());
34
35
return retval;
35
36
}
36
37
37
- struct SContext
38
+ template <typename OutT> requires (sizeof (OutT)<8 && hlsl::concepts::UnsignedIntegralScalar<OutT>)
39
+ struct SContext final
38
40
{
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
41
+ // `indexOfIndex` is somewhat of a baseIndex
42
+ inline void streamOut (const uint32_t indexOfIndex, const std::span<const int32_t > permutation)
44
43
{
45
- switch (indexSizeLog2)
44
+ auto & typedOut = reinterpret_cast <OutT*&>(out);
45
+ if (indexBuffer)
46
+ switch (indexSize)
46
47
{
47
- case 0 :
48
- *reinterpret_cast <uint8_t *>(out) = value;
49
- break ;
50
48
case 1 :
51
- *reinterpret_cast <uint16_t *>(out) = value;
49
+ for (const auto relIx : permutation)
50
+ *(typedOut++) = reinterpret_cast <const uint8_t *>(indexBuffer)[indexOfIndex+relIx];
52
51
break ;
53
52
case 2 :
54
- *reinterpret_cast <uint32_t *>(out) = value;
53
+ for (const auto relIx : permutation)
54
+ *(typedOut++) = reinterpret_cast <const uint16_t *>(indexBuffer)[indexOfIndex+relIx];
55
55
break ;
56
- case 3 :
57
- *reinterpret_cast <uint64_t *>(out) = value;
56
+ case 4 :
57
+ for (const auto relIx : permutation)
58
+ *(typedOut++) = reinterpret_cast <const uint32_t *>(indexBuffer)[indexOfIndex+relIx];
58
59
break ;
59
60
default :
60
61
assert (false );
61
62
break ;
62
63
}
64
+ else
65
+ for (const auto relIx : permutation)
66
+ *(typedOut++) = indexOfIndex+relIx;
63
67
}
64
68
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 ;
69
+ // always the base pointer, doesn't get advanced
70
+ const void * const indexBuffer;
71
+ const uint64_t indexSize : 3 ;
72
+ const uint64_t beginPrimitive : 30 ;
73
+ const uint64_t endPrimitive : 31 ;
74
+ void * out;
73
75
};
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
- }
76
+ // could have been a static if not virtual
77
+ virtual void operator ()(SContext<uint8_t >& ctx) const = 0;
78
+ virtual void operator ()(SContext<uint16_t >& ctx) const = 0;
79
+ virtual void operator ()(SContext<uint32_t >& ctx) const = 0;
85
80
86
81
// default is unknown
87
82
virtual inline E_PRIMITIVE_TOPOLOGY knownTopology () const {return static_cast <E_PRIMITIVE_TOPOLOGY>(~0 );}
88
83
89
84
protected:
90
85
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;
86
+ virtual uint8_t rate_impl () const = 0;
94
87
};
95
88
//
96
89
static IIndexingCallback* PointList ();
97
90
static IIndexingCallback* LineList ();
98
91
static IIndexingCallback* TriangleList ();
99
92
static IIndexingCallback* QuadList ();
100
- //
93
+ // TODO: Adjacency, Patch, etc.
101
94
static IIndexingCallback* TriangleStrip ();
102
95
static IIndexingCallback* TriangleFan ();
103
96
104
- //
97
+ // This should be a pointer to a stateless singleton (think of it more like a dynamic enum/template than anything else)
105
98
inline const IIndexingCallback* getIndexingCallback () const {return m_indexing;}
106
99
107
100
protected:
108
101
virtual ~IPolygonGeometryBase () = default ;
109
102
103
+ // indexing callback cannot be cleared
104
+ bool setIndexingCallback (IIndexingCallback* indexing)
105
+ {
106
+ if (!indexing)
107
+ return false ;
108
+ const auto deg = m_indexing->degree ();
109
+ if (deg==0 || m_indexing->rate ()==0 || m_indexing->rate ()>deg)
110
+ return false ;
111
+ m_indexing = indexing;
112
+ return true ;
113
+ }
114
+
110
115
//
111
116
const IIndexingCallback* m_indexing = nullptr ;
112
117
};
@@ -131,9 +136,6 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>, public
131
136
return false ;
132
137
if (!m_indexing)
133
138
return false ;
134
- // things that make no sense
135
- if (m_verticesPerSupplementary==0 || m_verticesPerSupplementary>m_verticesForFirst)
136
- return false ;
137
139
// there needs to be at least one vertex to reference (it also needs to be formatted)
138
140
const auto & positionBase = base_t ::m_positionView.composed ;
139
141
const auto vertexCount = positionBase.getElementCount ();
@@ -170,7 +172,7 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>, public
170
172
const auto verticesForFirst = m_indexing->degree ();
171
173
if (vertexReferenceCount<verticesForFirst)
172
174
return 0 ;
173
- return (vertexReferenceCount-verticesForFirst)/(verticesForFirst- m_indexing->reuseCount ()) ;
175
+ return (vertexReferenceCount-verticesForFirst)/m_indexing->rate ()+ 1 ;
174
176
}
175
177
176
178
// For when the geometric normal of the patch isn't enough and you want interpolated custom normals
@@ -205,8 +207,8 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>, public
205
207
inline BLASTriangles exportForBLAS () const
206
208
{
207
209
BLASTriangles retval = {};
208
- // must be a triangle list
209
- if (m_verticesForFirst== 3 && m_verticesPerSupplementary== 3 )
210
+ // must be a triangle list, but don't want to compare pointers
211
+ if (m_indexing && m_indexing-> knownTopology ()==EPT_TRIANGLE_LIST) // && m_indexing->degree() == TriangleList()->degree() && m_indexing->rate() == TriangleList->rate() )
210
212
{
211
213
auto indexType = EIT_UNKNOWN;
212
214
// disallowed index format
@@ -239,15 +241,20 @@ class NBL_API2 IPolygonGeometry : public IIndexableGeometry<BufferType>, public
239
241
protected:
240
242
virtual ~IPolygonGeometry () = default ;
241
243
242
- //
244
+ // 64bit indices are just too much to deal with in all the other code
245
+ // Also if you have more than 2G vertex references in a single geometry there's something wrong with your architecture
246
+ // Note that this still allows 6GB vertex attribute streams (assuming at least 3 bytes for a postion)
243
247
inline bool setIndexView (SDataView&& view)
244
248
{
245
- if (! view || view. isFormattedScalarInteger () )
249
+ if (view)
246
250
{
247
- m_indexView = std::move (view);
248
- return true ;
251
+ if (!view.isFormattedScalarInteger () || view.format == EF_R64_UINT || view.format == EF_R64_SINT)
252
+ return false ;
253
+ if (view.getElementCount ()>(1u <<31 ))
254
+ return false ;
249
255
}
250
- return false ;
256
+ m_indexView = std::move (view);
257
+ return true ;
251
258
}
252
259
253
260
//
0 commit comments