Strip-mining optimization to improve cache utilization.

For each mesh: init, accumulate, and pack using a recycled offset buffer.
This commit is contained in:
Ken Cooke 2019-06-23 08:42:38 -07:00
parent 9e309b095d
commit 87c680382f

View file

@ -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",