Packing the offsets and catching up performances

This commit is contained in:
Sam Gateau 2018-09-28 02:13:08 -07:00
parent 97de12fcbc
commit faf489855c
4 changed files with 75 additions and 5 deletions

View file

@ -274,8 +274,9 @@ void GLBackend::renderPassDraw(const Batch& batch) {
case Batch::COMMAND_drawIndexedInstanced:
case Batch::COMMAND_multiDrawIndirect:
case Batch::COMMAND_multiDrawIndexedIndirect: {
#ifdef GPU_BATCH_DETAILED_TRACING
PROFILE_RANGE(render_gpu_gl_detail, "drawcall");
#endif
// updates for draw calls
++_currentDraw;
updateInput();

View file

@ -10,6 +10,10 @@
<@func declareBlendshape(USE_NORMAL, USE_TANGENT)@>
struct PackedBlendshapeOffset {
ivec4 packedPosNorTan;
};
struct BlendshapeOffset {
vec4 position;
vec4 normal;
@ -32,10 +36,21 @@ BlendshapeOffset getBlendshapeOffset(int i) {
}
#else
layout(std140, binding=0) buffer blendshapeOffsetsBuffer {
BlendshapeOffset _blendshapeOffsets[];
ivec4 _blendshapeOffsets[];
// BlendshapeOffset _blendshapeOffsets[];
};
BlendshapeOffset getBlendshapeOffset(int i) {
return _blendshapeOffsets[i];
// return _blendshapeOffsets[i];
ivec4 elem_packed = _blendshapeOffsets[i];
BlendshapeOffset unpacked;
unpacked.position = vec4(unpackHalf2x16(uint(elem_packed.x)), unpackHalf2x16(uint(elem_packed.y)));
unpacked.normal = vec4(0.0);
unpacked.tangent = vec4(0.0);
return unpacked;
}
#endif

View file

@ -1632,6 +1632,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe
_blendshapeCoefficients(blendshapeCoefficients) {
}
void Blender::run() {
QVector<BlendshapeOffset> blendshapeOffsets;
if (_model && _model->isLoaded()) {
@ -1648,6 +1649,8 @@ void Blender::run() {
blendshapeOffsets += modelMeshBlendshapeOffsets->second;
BlendshapeOffset* meshBlendshapeOffsets = blendshapeOffsets.data() + offset;
offset += modelMeshBlendshapeOffsets->second.size();
std::vector<BlendshapeOffsetUnpacked> unpackedBlendshapeOffsets(modelMeshBlendshapeOffsets->second.size());
const float NORMAL_COEFFICIENT_SCALE = 0.01f;
for (int i = 0, n = qMin(_blendshapeCoefficients.size(), mesh.blendshapes.size()); i < n; i++) {
float vertexCoefficient = _blendshapeCoefficients.at(i);
@ -1655,12 +1658,25 @@ void Blender::run() {
if (vertexCoefficient < EPSILON) {
continue;
}
float normalCoefficient = vertexCoefficient * NORMAL_COEFFICIENT_SCALE;
const FBXBlendshape& blendshape = mesh.blendshapes.at(i);
bool doTangent = (mesh.tangents.size()) && (blendshape.tangents.size());
tbb::parallel_for(tbb::blocked_range<int>(0, blendshape.indices.size()), [&](const tbb::blocked_range<int>& range) {
for (auto j = range.begin(); j < range.end(); j++) {
int index = blendshape.indices.at(j);
auto& currentBlendshapeOffset = meshBlendshapeOffsets[index];
#ifdef PACKED_BLENDSHAPE_OFFSET
auto& currentBlendshapeOffset = unpackedBlendshapeOffsets[index];
currentBlendshapeOffset.positionOffsetAndSpare += blendshape.vertices.at(j) * vertexCoefficient;
currentBlendshapeOffset.normalOffsetAndSpare += blendshape.normals.at(j) * normalCoefficient;
if (doTangent) {
currentBlendshapeOffset.tangentOffsetAndSpare += blendshape.tangents.at(j) * normalCoefficient;
}
#else
auto& currentBlendshapeOffset = blendshapeOffsets[index];
currentBlendshapeOffset.positionOffsetAndSpare += glm::vec4(blendshape.vertices.at(j) * vertexCoefficient, 0.0f);
currentBlendshapeOffset.normalOffsetAndSpare += glm::vec4(blendshape.normals.at(j) * normalCoefficient, 0.0f);
@ -1669,9 +1685,28 @@ void Blender::run() {
currentBlendshapeOffset.tangentOffsetAndSpare += glm::vec4(blendshape.tangents.at(j) * normalCoefficient, 0.0f);
}
}
#endif
}
});
}
#ifdef PACKED_BLENDSHAPE_OFFSET
auto unpacked = unpackedBlendshapeOffsets.data();
auto packed = meshBlendshapeOffsets;
for (int i = 0; i < unpackedBlendshapeOffsets.size(); i++) {
auto pposXY = glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare));
auto pposZ = glm::packHalf2x16(glm::vec2(unpacked->positionOffsetAndSpare.z, 0.0f));
auto pnor = glm::packSnorm3x10_1x2(glm::vec4(unpacked->normalOffsetAndSpare, 0.0f));
auto ptan = glm::packSnorm3x10_1x2(glm::vec4(unpacked->tangentOffsetAndSpare, 0.0f));
(*packed).packedPosNorTan = glm::uvec4(pposXY, pposZ, pnor, ptan);
unpacked++;
packed++;
}
#endif
}
}
// post the result to the ModelBlender, which will dispatch to the model if still alive

View file

@ -75,11 +75,30 @@ struct SortedTriangleSet {
int subMeshIndex;
};
struct BlendshapeOffset {
#define PACKED_BLENDSHAPE_OFFSET 1
#ifdef PACKED_BLENDSHAPE_OFFSET
struct BlendshapeOffsetPacked {
glm::ivec4 packedPosNorTan;
};
struct BlendshapeOffsetUnpacked {
glm::vec3 positionOffsetAndSpare;
glm::vec3 normalOffsetAndSpare;
glm::vec3 tangentOffsetAndSpare;
};
using BlendshapeOffset = BlendshapeOffsetPacked;
#else
struct BlendshapeOffsetUnpacked {
glm::vec4 positionOffsetAndSpare;
glm::vec4 normalOffsetAndSpare;
glm::vec4 tangentOffsetAndSpare;
};
using BlendshapeOffset = BlendshapeOffsetUnpacked;
#endif
/// A generic 3D model displaying geometry loaded from a URL.
class Model : public QObject, public std::enable_shared_from_this<Model>, public scriptable::ModelProvider {