mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 09:13:28 +02:00
Strip-mining optimization to improve cache utilization.
For each mesh: init, accumulate, and pack using a recycled offset buffer.
This commit is contained in:
parent
9e309b095d
commit
87c680382f
1 changed files with 19 additions and 13 deletions
|
@ -1735,6 +1735,7 @@ Blender::Blender(ModelPointer model, HFMModel::ConstPointer hfmModel, int blendN
|
|||
void Blender::run() {
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
int numBlendshapeOffsets = 0; // number of offsets required for all meshes.
|
||||
int maxBlendshapeOffsets = 0; // number of offsets in the largest mesh.
|
||||
int numMeshes = 0; // number of meshes in this model.
|
||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||
numMeshes++;
|
||||
|
@ -1743,16 +1744,19 @@ void Blender::run() {
|
|||
}
|
||||
int numVertsInMesh = meshIter->vertices.size();
|
||||
numBlendshapeOffsets += numVertsInMesh;
|
||||
maxBlendshapeOffsets = std::max(maxBlendshapeOffsets, numVertsInMesh);
|
||||
}
|
||||
|
||||
// all elements are default constructed to zero offsets.
|
||||
QVector<BlendshapeOffset> packedBlendshapeOffsets(numBlendshapeOffsets);
|
||||
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(numBlendshapeOffsets);
|
||||
|
||||
// allocate the required size
|
||||
// allocate the required sizes
|
||||
QVector<int> blendedMeshSizes;
|
||||
blendedMeshSizes.reserve(numMeshes);
|
||||
|
||||
QVector<BlendshapeOffset> packedBlendshapeOffsets;
|
||||
packedBlendshapeOffsets.reserve(numBlendshapeOffsets);
|
||||
|
||||
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets;
|
||||
unpackedBlendshapeOffsets.reserve(maxBlendshapeOffsets); // reuse for all meshes
|
||||
|
||||
int offset = 0;
|
||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||
if (meshIter->blendshapes.isEmpty()) {
|
||||
|
@ -1762,6 +1766,9 @@ void Blender::run() {
|
|||
int numVertsInMesh = meshIter->vertices.size();
|
||||
blendedMeshSizes.push_back(numVertsInMesh);
|
||||
|
||||
// initialize offsets to zero
|
||||
memset(unpackedBlendshapeOffsets.data(), 0, numVertsInMesh * sizeof(BlendshapeOffsetUnpacked));
|
||||
|
||||
// for each blendshape in this mesh, accumulate the offsets into unpackedBlendshapeOffsets.
|
||||
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), meshIter->blendshapes.size()); i < n; i++) {
|
||||
|
@ -1776,7 +1783,7 @@ void Blender::run() {
|
|||
for (int j = 0; j < blendshape.indices.size(); ++j) {
|
||||
int index = blendshape.indices.at(j);
|
||||
|
||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[offset + index];
|
||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
|
||||
currentBlendshapeOffset.positionOffset += blendshape.vertices.at(j) * vertexCoefficient;
|
||||
currentBlendshapeOffset.normalOffset += blendshape.normals.at(j) * normalCoefficient;
|
||||
if (j < blendshape.tangents.size()) {
|
||||
|
@ -1784,20 +1791,19 @@ void Blender::run() {
|
|||
}
|
||||
}
|
||||
}
|
||||
offset += numVertsInMesh;
|
||||
}
|
||||
|
||||
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
||||
// FIXME it feels like we could be more effectively using SIMD here
|
||||
{
|
||||
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
||||
auto unpacked = unpackedBlendshapeOffsets.data();
|
||||
auto packed = packedBlendshapeOffsets.data();
|
||||
for (int i = 0; i < unpackedBlendshapeOffsets.size(); ++i) {
|
||||
auto packed = packedBlendshapeOffsets.data() + offset;
|
||||
for (int i = 0; i < numVertsInMesh; ++i) {
|
||||
packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked));
|
||||
++unpacked;
|
||||
++packed;
|
||||
}
|
||||
|
||||
offset += numVertsInMesh;
|
||||
}
|
||||
Q_ASSERT(offset == numBlendshapeOffsets);
|
||||
|
||||
// post the result to the ModelBlender, which will dispatch to the model if still alive
|
||||
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
|
||||
|
|
Loading…
Reference in a new issue