mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 07:23:00 +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() {
|
void Blender::run() {
|
||||||
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||||
int numBlendshapeOffsets = 0; // number of offsets required for all meshes.
|
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.
|
int numMeshes = 0; // number of meshes in this model.
|
||||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||||
numMeshes++;
|
numMeshes++;
|
||||||
|
@ -1743,16 +1744,19 @@ void Blender::run() {
|
||||||
}
|
}
|
||||||
int numVertsInMesh = meshIter->vertices.size();
|
int numVertsInMesh = meshIter->vertices.size();
|
||||||
numBlendshapeOffsets += numVertsInMesh;
|
numBlendshapeOffsets += numVertsInMesh;
|
||||||
|
maxBlendshapeOffsets = std::max(maxBlendshapeOffsets, numVertsInMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
// all elements are default constructed to zero offsets.
|
// allocate the required sizes
|
||||||
QVector<BlendshapeOffset> packedBlendshapeOffsets(numBlendshapeOffsets);
|
|
||||||
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(numBlendshapeOffsets);
|
|
||||||
|
|
||||||
// allocate the required size
|
|
||||||
QVector<int> blendedMeshSizes;
|
QVector<int> blendedMeshSizes;
|
||||||
blendedMeshSizes.reserve(numMeshes);
|
blendedMeshSizes.reserve(numMeshes);
|
||||||
|
|
||||||
|
QVector<BlendshapeOffset> packedBlendshapeOffsets;
|
||||||
|
packedBlendshapeOffsets.reserve(numBlendshapeOffsets);
|
||||||
|
|
||||||
|
QVector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets;
|
||||||
|
unpackedBlendshapeOffsets.reserve(maxBlendshapeOffsets); // reuse for all meshes
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
for (auto meshIter = _hfmModel->meshes.cbegin(); meshIter != _hfmModel->meshes.cend(); ++meshIter) {
|
||||||
if (meshIter->blendshapes.isEmpty()) {
|
if (meshIter->blendshapes.isEmpty()) {
|
||||||
|
@ -1762,6 +1766,9 @@ void Blender::run() {
|
||||||
int numVertsInMesh = meshIter->vertices.size();
|
int numVertsInMesh = meshIter->vertices.size();
|
||||||
blendedMeshSizes.push_back(numVertsInMesh);
|
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.
|
// for each blendshape in this mesh, accumulate the offsets into unpackedBlendshapeOffsets.
|
||||||
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
|
||||||
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), meshIter->blendshapes.size()); i < n; i++) {
|
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) {
|
for (int j = 0; j < blendshape.indices.size(); ++j) {
|
||||||
int index = blendshape.indices.at(j);
|
int index = blendshape.indices.at(j);
|
||||||
|
|
||||||
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[offset + index];
|
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
|
||||||
currentBlendshapeOffset.positionOffset += blendshape.vertices.at(j) * vertexCoefficient;
|
currentBlendshapeOffset.positionOffset += blendshape.vertices.at(j) * vertexCoefficient;
|
||||||
currentBlendshapeOffset.normalOffset += blendshape.normals.at(j) * normalCoefficient;
|
currentBlendshapeOffset.normalOffset += blendshape.normals.at(j) * normalCoefficient;
|
||||||
if (j < blendshape.tangents.size()) {
|
if (j < blendshape.tangents.size()) {
|
||||||
|
@ -1784,20 +1791,19 @@ void Blender::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset += numVertsInMesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
// convert unpackedBlendshapeOffsets into packedBlendshapeOffsets for the gpu.
|
||||||
// FIXME it feels like we could be more effectively using SIMD here
|
|
||||||
{
|
|
||||||
auto unpacked = unpackedBlendshapeOffsets.data();
|
auto unpacked = unpackedBlendshapeOffsets.data();
|
||||||
auto packed = packedBlendshapeOffsets.data();
|
auto packed = packedBlendshapeOffsets.data() + offset;
|
||||||
for (int i = 0; i < unpackedBlendshapeOffsets.size(); ++i) {
|
for (int i = 0; i < numVertsInMesh; ++i) {
|
||||||
packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked));
|
packBlendshapeOffsetTo_Pos_F32_3xSN10_Nor_3xSN10_Tan_3xSN10((*packed).packedPosNorTan, (*unpacked));
|
||||||
++unpacked;
|
++unpacked;
|
||||||
++packed;
|
++packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offset += numVertsInMesh;
|
||||||
}
|
}
|
||||||
|
Q_ASSERT(offset == numBlendshapeOffsets);
|
||||||
|
|
||||||
// post the result to the ModelBlender, which will dispatch to the model if still alive
|
// post the result to the ModelBlender, which will dispatch to the model if still alive
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
|
QMetaObject::invokeMethod(DependencyManager::get<ModelBlender>().data(), "setBlendedVertices",
|
||||||
|
|
Loading…
Reference in a new issue