Files
UnrealEngine/Engine/Source/ThirdParty/Alembic/alembic-1.8.7/bin/AbcWalk/Main.cpp
2025-05-18 13:04:45 +08:00

329 lines
9.6 KiB
C++

//-*****************************************************************************
//
// Copyright (c) 2013,
// Sony Pictures Imageworks Inc. and
// Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Sony Pictures Imageworks, nor
// Industrial Light & Magic, nor the names of their contributors may be used
// to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//-*****************************************************************************
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <Alembic/Abc/All.h>
#include <Alembic/AbcCoreFactory/All.h>
double getTimeSec()
{
timeval t;
gettimeofday(&t, 0);
return (double) t.tv_sec + (double) t.tv_usec / 1000000.0;
}
using namespace Alembic;
struct ArchiveAndData
{
Abc::IArchive archive;
std::vector< Abc::IArrayProperty > arrays;
std::vector< Abc::IScalarProperty > scalars;
std::size_t maxNumSamples;
};
class ArchiveWalker;
// used two different ways, one when traverse the archives
// (int archive is ignored), and one where we read samples
struct WorkUnit
{
int start;
int end;
int archive;
ArchiveWalker * walker;
};
class ArchiveWalker
{
public:
std::vector< ArchiveAndData > mArchives;
void addArchive(Abc::IArchive iArchive)
{
ArchiveAndData data;
data.archive = iArchive;
data.maxNumSamples = 0;
mArchives.push_back(data);
}
void readProps(WorkUnit & data)
{
size_t numArchives = mArchives.size();
printf("readProps Work Unit Start %d %d\n", data.start, data.end);
double startTime = getTimeSec();
for (size_t a = 0; a < numArchives; ++a)
{
std::size_t numScalars = mArchives[a].scalars.size();
std::size_t numArrays = mArchives[a].arrays.size();
for (std::size_t i = 0; i < numScalars; ++i)
{
Abc::IScalarProperty & prop = mArchives[a].scalars[i];
int propEnd = std::min(data.end, (int) prop.getNumSamples());
if (prop.isConstant())
{
propEnd = 1;
}
for (int j = data.start; j < propEnd; ++j)
{
if (prop.getDataType().getPod() != Alembic::Util::kStringPOD)
{
char buffer[4096];
prop.get(buffer, j);
}
else
{
std::vector< std::string > buffer(
prop.getDataType().getExtent());
prop.get(&buffer.front(), j);
}
}
}
for (std::size_t i = 0; i < numArrays; ++i)
{
Abc::IArrayProperty & prop = mArchives[a].arrays[i];
int propEnd = std::min(data.end, (int) prop.getNumSamples());
if (prop.isConstant())
{
propEnd = 1;
}
for (int j = data.start; j < propEnd; ++j)
{
Alembic::AbcCoreAbstract::ArraySamplePtr samp;
prop.get(samp, j);
}
}
}
printf("readProps Work Unit End %d %d %f\n",
data.start, data.end, getTimeSec() - startTime);
pthread_exit(0);
}
void findProps(int iArchiveNum, Abc::ICompoundProperty & iParent)
{
size_t numProps = iParent.getNumProperties();
for (size_t i = 0; i < numProps; ++i)
{
const Alembic::AbcCoreAbstract::PropertyHeader & childHeader =
iParent.getPropertyHeader(i);
if (childHeader.isScalar())
{
Alembic::Abc::IScalarProperty prop(iParent, childHeader.getName());
if (prop.getNumSamples() > 0)
{
mArchives[iArchiveNum].scalars.push_back(prop);
mArchives[iArchiveNum].maxNumSamples = std::max(
mArchives[iArchiveNum].maxNumSamples, prop.getNumSamples());
}
}
else if (childHeader.isArray())
{
Alembic::Abc::IArrayProperty prop(iParent, childHeader.getName());
if (prop.getNumSamples() > 0)
{
mArchives[iArchiveNum].arrays.push_back(prop);
mArchives[iArchiveNum].maxNumSamples = std::max(
mArchives[iArchiveNum].maxNumSamples, prop.getNumSamples());
}
}
else
{
Alembic::Abc::ICompoundProperty prop(iParent,
childHeader.getName());
findProps(iArchiveNum, prop);
}
}
}
void walkObjects(int iArchiveNum, Abc::IObject & iParent)
{
size_t numChildren = iParent.getNumChildren();
for (size_t i = 0; i < numChildren; i++)
{
const Abc::ObjectHeader & header = iParent.getChildHeader(i);
Abc::IObject child(iParent, header.getName());
Abc::ICompoundProperty prop = child.getProperties();
findProps(iArchiveNum, prop);
walkObjects(iArchiveNum, child);
}
}
void walkArchives(WorkUnit & data)
{
printf("walkArchives Work Unit Start %d %d\n", data.start, data.end);
for (int i = data.start; i < data.end; ++i)
{
Abc::IObject top = mArchives[i].archive.getTop();
walkObjects(i, top);
}
printf("walkArchives Work Unit End %d %d\n", data.start, data.end);
}
};
void * readPropsWrap(void * ptr)
{
WorkUnit * data = (WorkUnit *) ptr;
data->walker->readProps(*data);
pthread_exit(0);
}
void * walkArchivesWrap(void * ptr)
{
WorkUnit * data = (WorkUnit *) ptr;
data->walker->walkArchives(*data);
pthread_exit(0);
}
int main(int argc, char ** argv)
{
if (argc < 4)
{
printf ("sceneWalk maxNumThreads ogawaStreams fileName [fileName ...]\n");
return 0;
}
int maxThreads = atoi(argv[1]);
int ogawaStreams = atoi(argv[2]);
{
ArchiveWalker walker;
Alembic::AbcCoreFactory::IFactory factory;
Alembic::AbcCoreFactory::IFactory::CoreType coreType;
factory.setOgawaNumStreams(ogawaStreams);
double time_start = getTimeSec();
for (int i = 3; i < argc; ++i)
{
Abc::IArchive archive = factory.getArchive(argv[i], coreType);
if (archive.valid())
{
walker.addArchive(archive);
}
}
int numTraverse = std::min(maxThreads, (int) walker.mArchives.size());
std::vector<WorkUnit> traverseArchives(numTraverse);
int lastEnd = 0;
int workSize = walker.mArchives.size() / numTraverse;
int workRem = 0;
if ((int) walker.mArchives.size() > numTraverse)
workRem = walker.mArchives.size() % numTraverse;
pthread_t * walkThreads = new pthread_t[numTraverse];
for (int i = 0; i < numTraverse; ++i)
{
traverseArchives[i].archive = i;
traverseArchives[i].start = lastEnd;
traverseArchives[i].walker = &walker;
lastEnd += workSize;
if (i < workRem)
lastEnd ++;
traverseArchives[i].end = lastEnd;
pthread_create(&(walkThreads[i]), NULL, walkArchivesWrap,
(void *) &(traverseArchives[i]));
}
for (int i = 0; i < numTraverse; ++i)
{
pthread_join(walkThreads[i], NULL);
}
delete [] walkThreads;
double totalTime = getTimeSec() - time_start;
printf ("Property Collection Wall Time: %f\n\n", totalTime);
time_start = getTimeSec();
size_t maxSamples = 0;
for (size_t i = 0; i < walker.mArchives.size(); ++i)
{
maxSamples = std::max(walker.mArchives[i].maxNumSamples, maxSamples);
}
int numSamples = std::min(maxThreads, (int) maxSamples);
std::vector<WorkUnit> readSamples(numSamples);
lastEnd = 0;
workSize = maxSamples / numSamples;
workRem = 0;
if ((int) maxSamples > numSamples)
workRem = maxSamples % numSamples;
pthread_t * readThreads = new pthread_t[numSamples];
for (int i = 0; i < numSamples; ++i)
{
readSamples[i].archive = i; // ignored
readSamples[i].start = lastEnd;
readSamples[i].walker = &walker;
lastEnd += workSize;
if (i < workRem)
lastEnd ++;
readSamples[i].end = lastEnd;
pthread_create(&(readThreads[i]), NULL, readPropsWrap,
(void *) &(readSamples[i]));
}
for (int i = 0; i < numSamples; ++i)
{
pthread_join(readThreads[i], NULL);
}
delete [] readThreads;
totalTime = getTimeSec()-time_start;
printf ("Property Read Wall Time: %f\n\n", totalTime);
}
return 0;
}