Skip to content

Commit b27c41b

Browse files
Fix bugs and remove createMeshBufferDuplicate because of its semantics that don't fit any one single function that uses it
1 parent b27afca commit b27c41b

File tree

8 files changed

+199
-230
lines changed

8 files changed

+199
-230
lines changed

include/nbl/asset/utils/IMeshManipulator.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,6 @@ class IMeshManipulator : public virtual core::IReferenceCounted
202202
@param _outIndexType Type of output index buffer data (32bit or 16bit).
203203
*/
204204
static core::smart_refctd_ptr<ICPUBuffer> idxBufferFromTrianglesFanToTriangles(const void* _input, uint32_t& _idxCount, E_INDEX_TYPE _inIndexType, E_INDEX_TYPE _outIndexType);
205-
206-
207-
//! Created duplicate of meshbuffer
208-
static core::smart_refctd_ptr<ICPUMeshBuffer> createMeshBufferDuplicate(const ICPUMeshBuffer* _src);
209205

210206
//! Get amount of polygons in mesh buffer.
211207
/** \param meshbuffer Input mesh buffer
@@ -613,21 +609,6 @@ class IMeshManipulator : public virtual core::IReferenceCounted
613609
}
614610
}
615611

616-
617-
//! Creates Mesh Duplicate
618-
static inline core::smart_refctd_ptr<ICPUMesh> createMeshDuplicate(const ICPUMesh* _src)
619-
{
620-
if (!_src)
621-
return nullptr;
622-
623-
core::smart_refctd_ptr<ICPUMesh> dst = core::make_smart_refctd_ptr<ICPUMesh>();
624-
auto& dstMeshBuffers = dst->getMeshBufferVector();
625-
for (auto meshbuffer : _src->getMeshBuffers())
626-
dstMeshBuffers.emplace_back(createMeshBufferDuplicate(meshbuffer));
627-
628-
return dst;
629-
}
630-
631612
//! Get amount of polygons in mesh.
632613
/** \param meshbuffer Input mesh
633614
\param Outputted Number of polygons in mesh, if successful.

src/nbl/asset/bawformat/CBAWMeshFileLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ SAssetBundle CBAWMeshFileLoader::loadAsset(io::IReadFile* _file, const asset::IA
253253
auto normalBuffer = core::smart_refctd_ptr<ICPUBuffer>(const_cast<ICPUBuffer*>(originalMeshFormat->getMappedBuffer(normalAttribute)));
254254
const bool hasNormal = normalBuffer && normalBuffer->getPointer();
255255

256-
auto copy = m_manager->getMeshManipulator()->createMeshBufferDuplicate(mb);
256+
auto copy = m_manager->getMeshManipulator()->createMeshBufferDuplicate(mb); // TODO: createMeshBufferDuplicate is now non-public
257257
auto meshFormat = copy->getMeshDataAndFormat();
258258

259259
meshFormat->setIndexBuffer(core::smart_refctd_ptr<ICPUBuffer>(const_cast<ICPUBuffer*>(originalMeshFormat->getIndexBuffer())));

src/nbl/asset/utils/CMeshManipulator.cpp

Lines changed: 91 additions & 110 deletions
Large diffs are not rendered by default.

src/nbl/asset/utils/CMeshManipulator.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class CMeshManipulator : public IMeshManipulator
4949
static void _filterInvalidTriangles(ICPUMeshBuffer* _input);
5050

5151
//! Meant to create 32bit index buffer from subrange of index buffer containing 16bit indices. Remember to set to index buffer offset to 0 after mapping buffer resulting from this function.
52-
static inline core::smart_refctd_ptr<ICPUBuffer> create32BitFrom16BitIdxBufferSubrange(const uint16_t* _in, size_t _idxCount)
52+
static inline core::smart_refctd_ptr<ICPUBuffer> create32BitFrom16BitIdxBufferSubrange(const uint16_t* _in, uint32_t _idxCount)
5353
{
5454
if (!_in)
5555
return nullptr;
@@ -58,7 +58,7 @@ class CMeshManipulator : public IMeshManipulator
5858

5959
auto* outPtr = reinterpret_cast<uint32_t*>(out->getPointer());
6060

61-
for (size_t i = 0; i < _idxCount; ++i)
61+
for (uint32_t i=0u; i<_idxCount; ++i)
6262
outPtr[i] = _in[i];
6363

6464
return out;
@@ -135,8 +135,8 @@ class CMeshManipulator : public IMeshManipulator
135135
return output;
136136
}
137137

138-
private:
139-
CQuantNormalCache quantNormalCache;
138+
private:
139+
CQuantNormalCache quantNormalCache;
140140
};
141141

142142
} // end namespace scene

src/nbl/asset/utils/COverdrawMeshOptimizer.cpp

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,96 +12,103 @@
1212
#include "CMeshManipulator.h"
1313
#include "os.h"
1414

15-
namespace nbl { namespace asset
15+
namespace nbl
16+
{
17+
namespace asset
1618
{
1719

18-
core::smart_refctd_ptr<asset::ICPUMeshBuffer> COverdrawMeshOptimizer::createOptimized(asset::ICPUMeshBuffer* _inbuffer, bool _createNew, float _threshold)
20+
void COverdrawMeshOptimizer::createOptimized(asset::ICPUMeshBuffer* _outbuffer, const asset::ICPUMeshBuffer* _inbuffer, float _threshold)
1921
{
20-
if (!_inbuffer)
21-
return nullptr;
22+
if (!_outbuffer || !_inbuffer)
23+
return;
2224

2325
const asset::E_INDEX_TYPE indexType = _inbuffer->getIndexType();
24-
if (indexType == asset::EIT_UNKNOWN)
25-
return nullptr;
26-
27-
const size_t indexSize = indexType == asset::EIT_16BIT ? 2u : 4u;
28-
29-
auto outbuffer = _createNew ? IMeshManipulator::createMeshBufferDuplicate(_inbuffer) : core::smart_refctd_ptr<asset::ICPUMeshBuffer>(_inbuffer);
26+
const size_t indexSize = indexType == asset::EIT_16BIT ? sizeof(uint16_t):sizeof(uint32_t);
3027

31-
void* const indices = outbuffer->getIndices();
32-
if (!indices)
28+
const uint32_t idxCount = _inbuffer->getIndexCount();
29+
const void* const inIndices = _inbuffer->getIndices();
30+
if (idxCount==0u || indexType==asset::EIT_UNKNOWN || !inIndices)
3331
{
3432
#ifdef _NBL_DEBUG
3533
os::Printer::log("Overdraw optimization: no index buffer -- mesh buffer left unchanged.");
3634
#endif
37-
return outbuffer;
35+
return;
3836
}
3937

40-
const size_t idxCount = outbuffer->getIndexCount();
41-
void* indicesCopy = _NBL_ALIGNED_MALLOC(indexSize*idxCount,_NBL_SIMD_ALIGNMENT);
42-
memcpy(indicesCopy, indices, indexSize*idxCount);
43-
const size_t vertexCount = IMeshManipulator::upperBoundVertexID(outbuffer.get());
44-
core::vector<core::vectorSIMDf> vertexPositions;
38+
void* const outIndices = _outbuffer->getIndices();
39+
if (_outbuffer->getIndexCount()!=idxCount || _outbuffer->getIndexType()!=indexType || !outIndices)
4540
{
46-
core::vectorSIMDf pos;
47-
for (size_t i = 0; i < vertexCount; ++i)
48-
{
49-
outbuffer->getAttribute(pos, outbuffer->getPositionAttributeIx(), i);
50-
vertexPositions.push_back(pos);
51-
}
41+
#ifdef _NBL_DEBUG
42+
os::Printer::log("Overdraw optimization: output meshbuffer's index buffer does not match input -- mesh buffer left unchanged.");
43+
#endif
44+
return;
5245
}
5346

54-
uint32_t* const hardClusters = (uint32_t*)_NBL_ALIGNED_MALLOC((idxCount/3) * 4,_NBL_SIMD_ALIGNMENT);
47+
void* indexCopy = nullptr;
48+
const uint16_t* inIndices16 = reinterpret_cast<const uint16_t*>(inIndices);
49+
const uint32_t* inIndices32 = reinterpret_cast<const uint32_t*>(inIndices);
50+
// TODO: more accure check for overlap
51+
if (_outbuffer->getIndexBufferBinding().buffer==_inbuffer->getIndexBufferBinding().buffer)
52+
{
53+
const size_t dataSize = indexSize*idxCount;
54+
indexCopy = _NBL_ALIGNED_MALLOC(dataSize,indexSize);
55+
memcpy(outIndices,inIndices,dataSize);
56+
inIndices16 = reinterpret_cast<const uint16_t*>(dataSize);
57+
inIndices32 = reinterpret_cast<const uint32_t*>(dataSize);
58+
}
59+
uint16_t* outIndices16 = reinterpret_cast<uint16_t*>(outIndices);
60+
uint32_t* outIndices32 = reinterpret_cast<uint32_t*>(outIndices);
61+
62+
const uint32_t vertexCount = IMeshManipulator::upperBoundVertexID(_inbuffer);
63+
core::vector<core::vectorSIMDf> vertexPositions(vertexCount);
64+
for (uint32_t i=0u; i<vertexCount; ++i)
65+
_inbuffer->getAttribute(vertexPositions[i],_inbuffer->getPositionAttributeIx(),i);
66+
67+
uint32_t* const hardClusters = reinterpret_cast<uint32_t*>(_NBL_ALIGNED_MALLOC((idxCount/3)*sizeof(uint32_t),_NBL_SIMD_ALIGNMENT));
5568
const size_t hardClusterCount = indexType == asset::EIT_16BIT ?
56-
genHardBoundaries(hardClusters, (uint16_t*)indices, idxCount, vertexCount) :
57-
genHardBoundaries(hardClusters, (uint32_t*)indices, idxCount, vertexCount);
69+
genHardBoundaries(hardClusters, inIndices16, idxCount, vertexCount) :
70+
genHardBoundaries(hardClusters, inIndices32, idxCount, vertexCount);
5871

59-
uint32_t* const softClusters = (uint32_t*)_NBL_ALIGNED_MALLOC((idxCount/3 + 1) * 4,_NBL_SIMD_ALIGNMENT);
72+
uint32_t* const softClusters = reinterpret_cast<uint32_t*>(_NBL_ALIGNED_MALLOC((idxCount/3+1)*sizeof(uint32_t),_NBL_SIMD_ALIGNMENT));
6073
const size_t softClusterCount = indexType == asset::EIT_16BIT ?
61-
genSoftBoundaries(softClusters, (uint16_t*)indices, idxCount, vertexCount, hardClusters, hardClusterCount, _threshold) :
62-
genSoftBoundaries(softClusters, (uint32_t*)indices, idxCount, vertexCount, hardClusters, hardClusterCount, _threshold);
74+
genSoftBoundaries(softClusters, inIndices16, idxCount, vertexCount, hardClusters, hardClusterCount, _threshold) :
75+
genSoftBoundaries(softClusters, inIndices32, idxCount, vertexCount, hardClusters, hardClusterCount, _threshold);
6376

6477
ClusterSortData* sortedData = (ClusterSortData*)_NBL_ALIGNED_MALLOC(softClusterCount*sizeof(ClusterSortData),_NBL_SIMD_ALIGNMENT);
6578
if (indexType == asset::EIT_16BIT)
66-
calcSortData(sortedData, (uint16_t*)indices, idxCount, vertexPositions, softClusters, softClusterCount);
79+
calcSortData(sortedData, inIndices16, idxCount, vertexPositions, softClusters, softClusterCount);
6780
else
68-
calcSortData(sortedData, (uint32_t*)indices, idxCount, vertexPositions, softClusters, softClusterCount);
81+
calcSortData(sortedData, inIndices32, idxCount, vertexPositions, softClusters, softClusterCount);
6982

70-
std::stable_sort(sortedData, sortedData + softClusterCount, std::greater<ClusterSortData>());
83+
std::stable_sort(sortedData, sortedData+softClusterCount, std::greater<ClusterSortData>());
7184

72-
for (size_t it = 0, jt = 0; it < softClusterCount; ++it)
85+
auto reorderIndices = [&](auto* out, const auto* in)
7386
{
74-
const uint32_t cluster = sortedData[it].cluster;
87+
for (size_t it = 0, jt = 0; it < softClusterCount; ++it)
88+
{
89+
const uint32_t cluster = sortedData[it].cluster;
7590

76-
size_t start = softClusters[cluster];
77-
size_t end = (cluster+1 < softClusterCount) ? softClusters[cluster+1] : idxCount/3;
91+
size_t start = softClusters[cluster];
92+
size_t end = (cluster+1<softClusterCount) ? softClusters[cluster+1]:idxCount/3;
7893

79-
if (indexType == asset::EIT_16BIT)
80-
{
81-
for (size_t i = start; i < end; ++i)
82-
{
83-
((uint16_t*)indices)[jt++] = ((uint16_t*)indicesCopy)[3*i + 0];
84-
((uint16_t*)indices)[jt++] = ((uint16_t*)indicesCopy)[3*i + 1];
85-
((uint16_t*)indices)[jt++] = ((uint16_t*)indicesCopy)[3*i + 2];
86-
}
87-
}
88-
else
89-
{
9094
for (size_t i = start; i < end; ++i)
9195
{
92-
((uint32_t*)indices)[jt++] = ((uint32_t*)indicesCopy)[3*i + 0];
93-
((uint32_t*)indices)[jt++] = ((uint32_t*)indicesCopy)[3*i + 1];
94-
((uint32_t*)indices)[jt++] = ((uint32_t*)indicesCopy)[3*i + 2];
96+
out[jt++] = in[3 * i + 0];
97+
out[jt++] = in[3 * i + 1];
98+
out[jt++] = in[3 * i + 2];
9599
}
96100
}
97-
}
101+
};
102+
if (indexType==asset::EIT_16BIT)
103+
reorderIndices(outIndices16,inIndices16);
104+
else
105+
reorderIndices(outIndices32,inIndices32);
98106

99-
_NBL_ALIGNED_FREE(indicesCopy);
107+
if (indexCopy)
108+
_NBL_ALIGNED_FREE(indexCopy);
100109
_NBL_ALIGNED_FREE(hardClusters);
101110
_NBL_ALIGNED_FREE(softClusters);
102111
_NBL_ALIGNED_FREE(sortedData);
103-
104-
return outbuffer;
105112
}
106113

107114
template<typename IdxT>

src/nbl/asset/utils/COverdrawMeshOptimizer.h

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,52 @@
99

1010
// Based on zeux's meshoptimizer (https://github.com/zeux/meshoptimizer) available under MIT license
1111

12-
namespace nbl { namespace asset
12+
namespace nbl
13+
{
14+
namespace asset
1315
{
1416

1517
class COverdrawMeshOptimizer
1618
{
17-
enum
18-
{
19-
CACHE_SIZE = 16
20-
};
21-
22-
struct ClusterSortData
23-
{
24-
uint32_t cluster;
25-
float dot;
19+
_NBL_STATIC_INLINE_CONSTEXPR size_t CACHE_SIZE = 16;
2620

27-
bool operator>(const ClusterSortData& other) const
21+
struct ClusterSortData
2822
{
29-
// high product = possible occluder, render early
30-
return dot > other.dot;
31-
}
32-
};
33-
34-
// private, undefined constructor
35-
COverdrawMeshOptimizer() = delete;
36-
37-
public:
38-
//! Creates new or modifies given mesh reordering indices to reduce pixel overdraw and vertex shader invocations.
39-
/**
40-
@param _inbuffer Input mesh buffer.
41-
@param _createNew Flag deciding whether to create new mesh (not modifying given one) or just optimize given mesh. Defaulted to true (i.e. create new).
42-
@param _threshold Indicates how much the overdraw optimizer can degrade vertex cache efficiency (1.05 = up to 5%) to reduce overdraw more efficiently. Defaulted to 1.05 (i.e. 5%).
43-
*/
44-
static core::smart_refctd_ptr<asset::ICPUMeshBuffer> createOptimized(asset::ICPUMeshBuffer* _inbuffer, bool _createNew = true, float _threshold = 1.05f);
45-
46-
private:
47-
template<typename IdxT>
48-
static size_t genHardBoundaries(uint32_t* _dst, const IdxT* _indices, size_t _idxCount, size_t _vtxCount);
49-
template<typename IdxT>
50-
static size_t genSoftBoundaries(uint32_t* _dst, const IdxT* _indices, size_t _idxCount, size_t _vtxCount, const uint32_t* _clusters, size_t _clusterCount, float _threshold);
51-
52-
template<typename IdxT>
53-
static void calcSortData(ClusterSortData* _dst, const IdxT* _indices, size_t _idxCount, const core::vector<core::vectorSIMDf>& _positions, const uint32_t* _clusters, size_t _clusterCount);
54-
55-
static size_t updateCache(uint32_t _a, uint32_t _b, uint32_t _c, size_t* _cacheTimestamps, size_t& _timestamp);
23+
uint32_t cluster;
24+
float dot;
25+
26+
bool operator>(const ClusterSortData& other) const
27+
{
28+
// high product = possible occluder, render early
29+
return dot > other.dot;
30+
}
31+
};
32+
33+
// private, undefined constructor
34+
COverdrawMeshOptimizer() = delete;
35+
36+
public:
37+
//! Creates new or modifies given mesh reordering indices to reduce pixel overdraw and vertex shader invocations.
38+
/**
39+
@param _inbuffer Input mesh buffer.
40+
@param _createNew Flag deciding whether to create new mesh (not modifying given one) or just optimize given mesh. Defaulted to true (i.e. create new).
41+
@param _threshold Indicates how much the overdraw optimizer can degrade vertex cache efficiency (1.05 = up to 5%) to reduce overdraw more efficiently. Defaulted to 1.05 (i.e. 5%).
42+
*/
43+
static void createOptimized(asset::ICPUMeshBuffer* _outbuffer, const asset::ICPUMeshBuffer* _inbuffer, float _threshold = 1.05f);
44+
45+
private:
46+
template<typename IdxT>
47+
static size_t genHardBoundaries(uint32_t* _dst, const IdxT* _indices, size_t _idxCount, size_t _vtxCount);
48+
template<typename IdxT>
49+
static size_t genSoftBoundaries(uint32_t* _dst, const IdxT* _indices, size_t _idxCount, size_t _vtxCount, const uint32_t* _clusters, size_t _clusterCount, float _threshold);
50+
51+
template<typename IdxT>
52+
static void calcSortData(ClusterSortData* _dst, const IdxT* _indices, size_t _idxCount, const core::vector<core::vectorSIMDf>& _positions, const uint32_t* _clusters, size_t _clusterCount);
53+
54+
static size_t updateCache(uint32_t _a, uint32_t _b, uint32_t _c, size_t* _cacheTimestamps, size_t& _timestamp);
5655
};
5756

58-
}}
57+
}
58+
}
5959

6060
#endif

src/nbl/asset/utils/CSmoothNormalGenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ namespace nbl
138138
}
139139
}
140140

141-
CSmoothNormalGenerator::VertexHashMap CSmoothNormalGenerator::setupData(asset::ICPUMeshBuffer * buffer, float epsilon)
141+
CSmoothNormalGenerator::VertexHashMap CSmoothNormalGenerator::setupData(const asset::ICPUMeshBuffer* buffer, float epsilon)
142142
{
143143
const size_t idxCount = buffer->getIndexCount();
144144
_NBL_DEBUG_BREAK_IF((idxCount % 3));

src/nbl/asset/utils/CSmoothNormalGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class CSmoothNormalGenerator
7171
};
7272

7373
private:
74-
static VertexHashMap setupData(asset::ICPUMeshBuffer* buffer, float epsilon);
74+
static VertexHashMap setupData(const asset::ICPUMeshBuffer* buffer, float epsilon);
7575
static void processConnectedVertices(asset::ICPUMeshBuffer* buffer, VertexHashMap& vertices, float epsilon, uint32_t normalAttrID, IMeshManipulator::VxCmpFunction vxcmp);
7676

7777
};

0 commit comments

Comments
 (0)