Files
igl/external/embree/tests/retrace.cpp
T

828 lines
27 KiB
C++
Executable File

// ======================================================================== //
// Copyright 2009-2014 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "sys/platform.h"
#include "sys/ref.h"
#include "embree2/rtcore.h"
#include "embree2/rtcore_ray.h"
#include "../kernels/common/default.h"
#include "../kernels/common/raystream_log.h"
#include "sys/intrinsics.h"
#include "sys/thread.h"
#include "sys/sysinfo.h"
#include "sys/sync/barrier.h"
#include "sys/sync/mutex.h"
#include "sys/sync/condition.h"
#include <vector>
#include <iostream>
#include <fstream>
#define DBG(x)
#define SSC_MARK(mark_value) \
{__asm mov ebx, mark_value} \
{__asm _emit 0x64} \
{__asm _emit 0x67} \
{__asm _emit 0x90}
namespace embree
{
struct RayStreamStats
{
size_t numTotalRays;
size_t numRayPackets;
size_t numIntersectRayPackets;
size_t numOccludedRayPackets;
size_t numIntersectRays;
size_t numOccludedRays;
size_t num4widePackets;
size_t num8widePackets;
RayStreamStats() {
memset(this,0,sizeof(RayStreamStats));
}
void add(RayStreamLogger::LogRay16 &r)
{
size_t numRays = r.numRays;
numRayPackets++;
numTotalRays += numRays;
if (r.type == RayStreamLogger::RAY_INTERSECT)
{
numIntersectRayPackets++;
numIntersectRays += numRays;
}
else if (r.type == RayStreamLogger::RAY_OCCLUDED)
{
numOccludedRayPackets++;
numOccludedRays += numRays;
}
else
FATAL("unknown log ray type");
num4widePackets += (numRays+3)/4;
num8widePackets += (numRays+7)/8;
}
void add(RayStreamLogger::LogRay4 &r)
{
size_t numRays = r.numRays;
numRayPackets++;
numTotalRays += numRays;
if (r.type == RayStreamLogger::RAY_INTERSECT)
{
numIntersectRayPackets++;
numIntersectRays += numRays;
}
else if (r.type == RayStreamLogger::RAY_OCCLUDED)
{
numOccludedRayPackets++;
numOccludedRays += numRays;
}
else
FATAL("unknown log ray type");
}
void add(RayStreamLogger::LogRay8 &r)
{
size_t numRays = r.numRays;
numRayPackets++;
numTotalRays += numRays;
if (r.type == RayStreamLogger::RAY_INTERSECT)
{
numIntersectRayPackets++;
numIntersectRays += numRays;
}
else if (r.type == RayStreamLogger::RAY_OCCLUDED)
{
numOccludedRayPackets++;
numOccludedRays += numRays;
}
else
FATAL("unknown log ray type");
num4widePackets += (numRays+3)/4;
}
void add(RayStreamLogger::LogRay1 &r)
{
numRayPackets++;
numTotalRays ++;
if (r.type == RayStreamLogger::RAY_INTERSECT)
{
numIntersectRayPackets++;
numIntersectRays++;
}
else if (r.type == RayStreamLogger::RAY_OCCLUDED)
{
numOccludedRayPackets++;
numOccludedRays++;
}
else
FATAL("unknown log ray type");
num4widePackets += 1;
num8widePackets += 1;
}
void print(size_t simd_width)
{
std::cout << "numTotalRays = " << numTotalRays << std::endl;
std::cout << "numRayPackets = " << numRayPackets << std::endl;
std::cout << "numIntersectionRays = " << numIntersectRays << " [" << 100. * (double)numIntersectRays / numTotalRays << "%]" << std::endl;
std::cout << "numOcclusionRays = " << numOccludedRays << " [" << 100. * (double)numOccludedRays / numTotalRays << "%]" << std::endl;
if (simd_width > 1)
{
std::cout << "avg. intersect " << simd_width << "-wide packet utilization = " << 100. * (double)numIntersectRays / (numIntersectRayPackets * (double)simd_width) << "%" << std::endl;
std::cout << "avg. occluded " << simd_width << "-wide packet utilization = " << 100. * (double)numOccludedRays / (numOccludedRayPackets * (double)simd_width) << "%" << std::endl;
std::cout << "avg. total " << simd_width << "-wide packet utilization = " << 100. * (double)numTotalRays / (numRayPackets * (double)simd_width) << "%" << std::endl;
}
if (simd_width == 16)
{
std::cout << "avg. 4-wide packet utilization = " << 100. * (double)numTotalRays / (num4widePackets * 4.) << "%" << std::endl;
std::cout << "avg. 8-wide packet utilization = " << 100. * (double)numTotalRays / (num8widePackets * 8.) << "%" << std::endl;
}
}
};
struct RetraceTask
{
RTCScene scene;
void *raydata;
void *raydata_verify;
size_t numLogRayStreamElements;
bool check;
};
/* configuration */
#if !defined(__MIC__)
RTCAlgorithmFlags aflags = (RTCAlgorithmFlags) (RTC_INTERSECT1 | RTC_INTERSECT4 | RTC_INTERSECT8);
static std::string g_rtcore = "verbose=2";
#else
RTCAlgorithmFlags aflags = (RTCAlgorithmFlags) (RTC_INTERSECT1 | RTC_INTERSECT16);
static std::string g_rtcore = "verbose=2,threads=1";
#endif
/* vertex and triangle layout */
struct Vertex { float x,y,z,a; };
struct Triangle { int v0, v1, v2; };
__forceinline std::ostream &operator<<(std::ostream &o, const Vertex &v)
{
o << "vtx " << v.x << " " << v.y << " " << v.z << " " << v.a << std::endl;
return o;
}
__forceinline std::ostream &operator<<(std::ostream &o, const Triangle &t)
{
o << "tri " << t.v0 << " " << t.v1 << " " << t.v2 << std::endl;
return o;
}
static AlignedAtomicCounter32 g_counter = 0;
static bool g_check = false;
static bool g_sde = false;
static size_t g_threadCount = 1;
static size_t g_frames = 1;
static size_t g_simd_width = 0;
static AlignedAtomicCounter32 g_rays_traced = 0;
static AlignedAtomicCounter32 g_rays_traced_diff = 0;
static std::vector<thread_t> g_threads;
#if !defined(__MIC__)
static BarrierSys g_barrier;
#else
static LinearBarrierActive g_barrier;
#endif
static bool g_exitThreads = false;
static RetraceTask g_retraceTask;
static MutexSys g_mutex;
#if defined(__MIC__)
static std::string g_binaries_path = "/home/micuser/";
#else
static std::string g_binaries_path = "./";
#endif
#define AssertNoError() \
if (rtcGetError() != RTC_NO_ERROR) return false;
#define AssertAnyError() \
if (rtcGetError() == RTC_NO_ERROR) return false;
#define AssertError(code) \
if (rtcGetError() != code) return false;
static void parseCommandLine(int argc, char** argv)
{
for (int i=1; i<argc; i++)
{
std::string tag = argv[i];
if (tag == "") return;
else if (tag == "-rtcore" && i+1<argc) {
g_rtcore += std::stringOf(',') + argv[++i];
}
/* rtcore configuration */
else if (tag == "-check") {
g_check = true;
}
else if (tag == "-threads" && i+1<argc) {
g_threadCount = atoi(argv[++i]);
}
else if (tag == "-frames" && i+1<argc) {
g_frames = atoi(argv[++i]);
}
else if (tag == "-simd_width" && i+1<argc) {
g_simd_width = atoi(argv[++i]);
if (g_simd_width != 1 && g_simd_width != 4 && g_simd_width != 8 && g_simd_width != 16)
std::cout << "only simd widths of 1,4,8, and 16 are supported" << std::endl;
}
else if (tag == "-sde") {
g_sde = true;
}
else if (tag == "-h" || tag == "-help") {
std::cout << "Usage: retrace [OPTIONS] [PATH_TO_BINARY_FILES] " << std::endl;
std::cout << "Options:" << std::endl;
std::cout << "-threads N : sets number of render/worker threads for the retracing phase to N" << std::endl;
std::cout << "-frames N : retraces all rays N times " << std::endl;
std::cout << "-check : loads second ray stream file and validates result of rtcIntersectN/rtcOccludedN for each ray/packet" << std::endl;
std::cout << "-simd_width N: loads ray stream for simd width N (if existing)" << std:: endl;
std::cout << "-sde : inserts markers for generating instruction traces with SDE" << std:: endl;
exit(0);
}
/* skip unknown command line parameter */
else {
g_binaries_path = tag;
}
}
}
bool existsFile(std::string &filename)
{
std::ifstream file;
file.open(filename.c_str(),std::ios::in | std::ios::binary);
if (!file) return false;
file.close();
return true;
}
void *loadGeometryData(std::string &geometryFile)
{
std::ifstream geometryData;
geometryData.open(geometryFile.c_str(),std::ios::in | std::ios::binary);
if (!geometryData) { FATAL("could not open geometry data file"); }
geometryData.seekg(0, std::ios::beg);
std::streampos begin = geometryData.tellg();
geometryData.seekg(0, std::ios::end);
std::streampos end = geometryData.tellg();
size_t fileSize = end - begin;
char *ptr = (char*)os_malloc(fileSize);
geometryData.seekg(0, std::ios::beg);
geometryData.read(ptr,fileSize);
geometryData.close();
return ptr;
}
template<class T>
void *loadRayStreamData(std::string &rayStreamFile, size_t &numLogRayStreamElements)
{
std::ifstream rayStreamData;
rayStreamData.open(rayStreamFile.c_str(),std::ios::in | std::ios::binary);
if (!rayStreamData) { FATAL("could not open raystream data file"); }
rayStreamData.seekg(0, std::ios::beg);
std::streampos begin = rayStreamData.tellg();
rayStreamData.seekg(0, std::ios::end);
std::streampos end = rayStreamData.tellg();
size_t fileSize = end - begin;
char *ptr = (char*)os_malloc(fileSize);
rayStreamData.seekg(0, std::ios::beg);
rayStreamData.read(ptr,fileSize);
numLogRayStreamElements = fileSize / sizeof(T);
rayStreamData.close();
return ptr;
}
template<class T>
RayStreamStats analyseRayStreamData(void *r, size_t numLogRayStreamElements)
{
RayStreamStats stats;
std::cout << "numLogRayStreamElements " << numLogRayStreamElements << std::endl;
for (size_t i=0;i<numLogRayStreamElements;i++)
stats.add(((T*)r)[i]);
return stats;
}
RTCScene transferGeometryData(char *g)
{
RTCScene scene = rtcNewScene(RTC_SCENE_STATIC,aflags);
int magick = *(size_t*)g; g += sizeof(int);
if (magick != 0x35238765LL) {
FATAL("invalid binary file");
}
int numGroups = *(int*)g; g += sizeof(int);
for (size_t i=0; i<numGroups; i++)
{
int type = *(int*)g; g += sizeof(int);
if (type == 1)
{
int numTimeSteps = *(int*)g; g += sizeof(int);
int numVertices = *(int*)g; g += sizeof(int);
int numTriangles = *(int*)g; g += sizeof(int);
unsigned int geometry = rtcNewTriangleMesh (scene, RTC_GEOMETRY_STATIC, numTriangles, numVertices, numTimeSteps);
for (size_t i=0; i<numTimeSteps; i++) {
if (((size_t)g % 16) != 0) g += 16 - ((size_t)g % 16);
rtcSetBuffer(scene, geometry, (RTCBufferType)(RTC_VERTEX_BUFFER0+i), g, 0, sizeof(Vec3fa));
g += numVertices*sizeof(Vec3fa);
}
if (((size_t)g % 16) != 0) g += 16 - ((size_t)g % 16);
rtcSetBuffer(scene, geometry, RTC_INDEX_BUFFER, g, 0, sizeof(Triangle));
g += numTriangles*sizeof(Triangle);
}
else if (type == 2)
{
int numTimeSteps = *(int*)g; g += sizeof(int);
int numVertices = *(int*)g; g += sizeof(int);
int numCurves = *(int*)g; g += sizeof(int);
unsigned int geometry = rtcNewHairGeometry (scene, RTC_GEOMETRY_STATIC, numCurves, numVertices, numTimeSteps);
for (size_t i=0; i<numTimeSteps; i++) {
if (((size_t)g % 16) != 0) g += 16 - ((size_t)g % 16);
rtcSetBuffer(scene, geometry, (RTCBufferType)(RTC_VERTEX_BUFFER0+i), g, 0, sizeof(Vec3fa));
g += numVertices*sizeof(Vec3fa);
}
if (((size_t)g % 16) != 0) g += 16 - ((size_t)g % 16);
rtcSetBuffer(scene, geometry, RTC_INDEX_BUFFER, g, 0, sizeof(int));
g += numCurves*sizeof(int);
}
else if (type == -1) {
}
else {
FATAL("unknown geometry type");
}
}
rtcCommit(scene);
return scene;
}
size_t check_ray1_packets(RTCRay &start, RTCRay &end)
{
if (start.primID != end.primID) return 1;
if (start.geomID != end.geomID) return 1;
if (start.u != end.u) return 1;
if (start.v != end.v) return 1;
if (start.tfar != end.tfar) return 1;
return 0;
}
template<class T>
void print(const char *name, T *ptr, const size_t N)
{
std::cout << name << " "; for (size_t i=0;i<N;i++) std::cout << ptr[i] << " "; std::cout << std::endl;
}
template<class T>
void print_packet(T &t)
{
const size_t elements = sizeof(T) / (18 * 4); // 18 elements, and 4 bytes per element
print("orgx" ,t.orgx,elements);
print("orgy" ,t.orgy,elements);
print("orgz" ,t.orgz,elements);
print("dirx" ,t.dirx,elements);
print("diry" ,t.diry,elements);
print("dirz" ,t.dirz,elements);
print("tnear" ,t.tnear,elements);
print("tfar" ,t.tfar,elements);
print("primID",t.primID,elements);
print("geomID",t.geomID,elements);
print("u" ,t.u,elements);
print("v" ,t.v,elements);
print("Ngx" ,t.Ngx,elements);
print("Ngy" ,t.Ngy,elements);
print("Ngz" ,t.Ngz,elements);
}
template<class T>
size_t check_ray_packets(const unsigned int m_valid, T &start, T &end)
{
size_t diff = 0;
const size_t elements = sizeof(T) / (18 * 4); // 18 elements, and 4 bytes per element
for (size_t i=0;i<elements;i++)
{
if ( (((unsigned int)1 << i) & m_valid) == 0) continue;
if (start.primID[i] != end.primID[i]) { diff++; continue; }
if (start.geomID[i] != end.geomID[i]) { diff++; continue; }
if (start.u[i] != end.u[i]) { diff++; continue; }
if (start.v[i] != end.v[i]) { diff++; continue; }
if (start.tnear[i] != end.tnear[i]) { diff++; continue; }
if (start.tfar[i] != end.tfar[i]) { diff++; continue; }
if (start.Ngx[i] != end.Ngx[i]) { diff++; continue; }
if (start.Ngy[i] != end.Ngy[i]) { diff++; continue; }
if (start.Ngz[i] != end.Ngz[i]) { diff++; continue; }
}
return diff;
}
#define RAY_BLOCK_SIZE 16
template<size_t SIMD_WIDTH>
void retrace_loop()
{
size_t rays = 0;
size_t diff = 0;
while(1)
{
size_t global_index = g_counter.add(RAY_BLOCK_SIZE);
if (global_index >= g_retraceTask.numLogRayStreamElements) break;
size_t startID = global_index;
size_t endID = min(g_retraceTask.numLogRayStreamElements,startID+RAY_BLOCK_SIZE);
for (size_t index=startID;index<endID;index++)
{
if (SIMD_WIDTH == 1)
{
RayStreamLogger::LogRay1 *raydata = (RayStreamLogger::LogRay1 *)g_retraceTask.raydata;
RayStreamLogger::LogRay1 *raydata_verify = (RayStreamLogger::LogRay1 *)g_retraceTask.raydata_verify;
RTCRay &ray = raydata[index].ray;
rays ++;
if (raydata[index].type == RayStreamLogger::RAY_INTERSECT)
rtcIntersect(g_retraceTask.scene,ray);
else
rtcOccluded(g_retraceTask.scene,ray);
if (unlikely(g_check))
diff += check_ray1_packets(ray, raydata_verify[index].ray);
}
#if !defined(__MIC__)
else if (SIMD_WIDTH == 4)
{
RayStreamLogger::LogRay4 *raydata = (RayStreamLogger::LogRay4 *)g_retraceTask.raydata;
RayStreamLogger::LogRay4 *raydata_verify = (RayStreamLogger::LogRay4 *)g_retraceTask.raydata_verify;
RTCRay4 &ray4 = raydata[index].ray4;
sseb valid((int)raydata[index].m_valid);
rays += raydata[index].numRays;
if (raydata[index].type == RayStreamLogger::RAY_INTERSECT)
rtcIntersect4(&valid,g_retraceTask.scene,ray4);
else
rtcOccluded4(&valid,g_retraceTask.scene,ray4);
if (unlikely(g_check))
diff += check_ray_packets<RTCRay4>(raydata[index].m_valid, raydata[index].ray4, raydata_verify[index].ray4);
}
else if (SIMD_WIDTH == 8)
{
RayStreamLogger::LogRay8 *raydata = (RayStreamLogger::LogRay8 *)g_retraceTask.raydata;
RayStreamLogger::LogRay8 *raydata_verify = (RayStreamLogger::LogRay8 *)g_retraceTask.raydata_verify;
RTCRay8 &ray8 = raydata[index].ray8;
__aligned(64) sseb valid[2];
valid[0] = sseb((int)(raydata[index].m_valid & 0xf));
valid[1] = sseb((int)(raydata[index].m_valid>>4));
rays += raydata[index].numRays;
if (raydata[index].type == RayStreamLogger::RAY_INTERSECT)
rtcIntersect8(valid,g_retraceTask.scene,ray8);
else
rtcOccluded8(valid,g_retraceTask.scene,ray8);
if (unlikely(g_check))
diff += check_ray_packets<RTCRay8>(raydata[index].m_valid, raydata[index].ray8, raydata_verify[index].ray8);
}
#endif
else if (SIMD_WIDTH == 16)
{
RayStreamLogger::LogRay16 *raydata = (RayStreamLogger::LogRay16 *)g_retraceTask.raydata;
RayStreamLogger::LogRay16 *raydata_verify = (RayStreamLogger::LogRay16 *)g_retraceTask.raydata_verify;
#if defined(__MIC__)
RTCRay16 &ray16 = raydata[index].ray16;
mic_i valid = select((mic_m)raydata[index].m_valid,mic_i(-1),mic_i(0));
rays += raydata[index].numRays;
//raydata[index+1].prefetchL2();
if (raydata[index].type == RayStreamLogger::RAY_INTERSECT)
rtcIntersect16(&valid,g_retraceTask.scene,ray16);
else
rtcOccluded16(&valid,g_retraceTask.scene,ray16);
#endif
if (unlikely(g_check))
diff += check_ray_packets<RTCRay16>(raydata[index].m_valid, raydata[index].ray16, raydata_verify[index].ray16);
}
}
}
if (unlikely(g_check && diff))
g_rays_traced_diff.add(diff);
g_rays_traced.add(rays);
}
void renderMainLoop(size_t id)
{
switch(g_simd_width)
{
case 1:
retrace_loop<1>();
break;
case 4:
retrace_loop<4>();
break;
case 8:
retrace_loop<8>();
break;
case 16:
retrace_loop<16>();
break;
};
}
void threadMainLoop(void *ptr)
{
size_t id = (size_t)ptr;
setAffinity(id);
DBG(
g_mutex.lock();
DBG_PRINT(id);
g_mutex.unlock();
);
while(1)
{
g_barrier.wait(id,g_threadCount);
if (g_exitThreads) break;
renderMainLoop(id);
g_barrier.wait(id,g_threadCount);
}
}
void createThreads(size_t numThreads)
{
for (size_t i=1; i<numThreads; i++)
g_threads.push_back(createThread(threadMainLoop,(void*)i,1000000,i));
}
/* main function in embree namespace */
int main(int argc, char** argv)
{
g_threadCount = getNumberOfLogicalThreads();
#if defined (__MIC__)
g_threadCount -= 4;
#endif
setAffinity(0);
/* parse command line */
parseCommandLine(argc,argv);
/* perform tests */
DBG_PRINT(g_rtcore.c_str());
rtcInit(g_rtcore.c_str());
DBG_PRINT(g_threadCount);
/* binary file path */
g_binaries_path += "/";
std::cout << "binary file path = " << g_binaries_path << std::endl;
/* load geometry file */
std::string geometryFileName = g_binaries_path + "geometry.bin";
std::cout << "loading geometry data from file '" << geometryFileName << "'..." << std::flush;
void *g = loadGeometryData(geometryFileName);
std::cout << "done" << std::endl << std::flush;
/* transfer geometry data */
std::cout << "transfering geometry data:" << std::endl << std::flush;
RTCScene scene = transferGeometryData((char*)g);
/* looking for ray stream file */
std::string rayStreamFileName;
std::string rayStreamVerifyFileName;
if (g_simd_width != 0)
{
rayStreamFileName = g_binaries_path + "ray" + std::stringOf(g_simd_width) + ".bin";
rayStreamVerifyFileName = g_binaries_path + "ray" + std::stringOf(g_simd_width) + "_verify.bin";
}
else
{
/* looking for stream files in the following order: ray1.bin, ray4.bin, ray8.bin, ray16.bin */
for (size_t shift=0;shift<=4;shift++)
{
g_simd_width = (size_t)1 << shift;
rayStreamFileName = g_binaries_path + "ray" + std::stringOf(g_simd_width) + ".bin";
rayStreamVerifyFileName = g_binaries_path + "ray" + std::stringOf(g_simd_width) + "_verify.bin";
if (existsFile( rayStreamFileName )) break;
}
}
if (g_simd_width == 0)
FATAL("no valid ray stream data files found");
DBG_PRINT( rayStreamFileName );
DBG_PRINT( rayStreamVerifyFileName );
if (!existsFile( rayStreamFileName )) FATAL("ray stream file does not exists!");
if (!existsFile( rayStreamVerifyFileName )) FATAL("ray stream verify file does not exists!");
/* load ray stream data */
std::cout << "loading ray stream data from files '" << rayStreamFileName << "/" << rayStreamVerifyFileName << "'..." << std::flush;
size_t numLogRayStreamElements = 0;
size_t numLogRayStreamElementsVerify = 0;
void *raydata = NULL;
void *raydata_verify = NULL;
switch(g_simd_width)
{
case 1:
raydata = loadRayStreamData<RayStreamLogger::LogRay1>(rayStreamFileName, numLogRayStreamElements);
if (g_check)
raydata_verify = loadRayStreamData<RayStreamLogger::LogRay1>(rayStreamVerifyFileName, numLogRayStreamElementsVerify);
break;
case 4:
raydata = loadRayStreamData<RayStreamLogger::LogRay4>(rayStreamFileName, numLogRayStreamElements);
if (g_check)
raydata_verify = loadRayStreamData<RayStreamLogger::LogRay4>(rayStreamVerifyFileName, numLogRayStreamElementsVerify);
break;
case 8:
raydata = loadRayStreamData<RayStreamLogger::LogRay8>(rayStreamFileName, numLogRayStreamElements);
if (g_check)
raydata_verify = loadRayStreamData<RayStreamLogger::LogRay8>(rayStreamVerifyFileName, numLogRayStreamElementsVerify);
break;
case 16:
raydata = loadRayStreamData<RayStreamLogger::LogRay16>(rayStreamFileName, numLogRayStreamElements);
if (g_check)
raydata_verify = loadRayStreamData<RayStreamLogger::LogRay16>(rayStreamVerifyFileName, numLogRayStreamElementsVerify);
break;
default:
FATAL("unknown SIMD width");
}
std::cout << "done" << std::endl << std::flush;
if (g_check)
if (numLogRayStreamElements != numLogRayStreamElementsVerify)
FATAL("numLogRayStreamElements != numLogRayStreamElementsVerify");
/* analyse ray stream data */
std::cout << "analyse ray stream:" << std::endl << std::flush;
RayStreamStats stats;
switch(g_simd_width)
{
case 1:
stats = analyseRayStreamData<RayStreamLogger::LogRay1>(raydata,numLogRayStreamElements);
break;
case 4:
stats = analyseRayStreamData<RayStreamLogger::LogRay4>(raydata,numLogRayStreamElements);
break;
case 8:
stats = analyseRayStreamData<RayStreamLogger::LogRay8>(raydata,numLogRayStreamElements);
break;
case 16:
stats = analyseRayStreamData<RayStreamLogger::LogRay16>(raydata,numLogRayStreamElements);
break;
}
stats.print(g_simd_width);
#if defined(RTCORE_ENABLE_RAYSTREAM_LOGGER)
FATAL("ray stream logger still active, must be disabled to run 'retrace'");
#endif
/* init global tasking barrier */
g_barrier.init( g_threadCount );
g_retraceTask.scene = scene;
g_retraceTask.raydata = raydata;
g_retraceTask.raydata_verify = raydata_verify;
g_retraceTask.numLogRayStreamElements = numLogRayStreamElements;
g_retraceTask.check = g_check;
std::cout << "using " << g_threadCount << " threads for retracing rays" << std::endl << std::flush;
createThreads(g_threadCount);
/* retrace ray packets */
DBG_PRINT( g_threadCount );
std::cout << "Retracing logged rays:" << std::endl << std::flush;
double avg_time = 0;
double mrays_sec = 0;
for (size_t i=0;i<g_frames;i++)
{
double dt = getSeconds();
/* retrace rays using all threads */
g_rays_traced = 0;
g_rays_traced_diff = 0;
g_counter = 0;
if (g_sde)
{
#if defined(__INTEL_COMPILER)
__asm { int 3 };
SSC_MARK(111);
#endif
}
g_barrier.wait(0,g_threadCount);
renderMainLoop(0);
dt = getSeconds()-dt;
mrays_sec += (double)g_rays_traced / dt / 1000000.;
#if 0
std::cout << "frame " << i << " => time " << 1000. * dt << " " << 1. / dt << " fps " << "ms " << g_rays_traced / dt / 1000000. << " mrays/sec" << std::endl;
#endif
g_barrier.wait(0,g_threadCount);
if (g_sde)
{
#if defined(__INTEL_COMPILER)
__asm { int 3 };
SSC_MARK(222);
#endif
}
if (unlikely(g_check))
std::cout << g_rays_traced_diff << " rays differ in result (" << 100. * g_rays_traced_diff / g_rays_traced << "%)" << std::endl;
}
std::cout << "rays " << g_rays_traced << " avg. mrays/sec = " << mrays_sec / (double)g_frames << std::endl;
std::cout << "freeing threads..." << std::flush;
g_exitThreads = true;
g_barrier.wait(0,g_threadCount);
std::cout << "done" << std::endl << std::flush;
/* done */
rtcExit();
return 0;
}
}
int main(int argc, char** argv)
{
try {
return embree::main(argc, argv);
}
catch (const std::exception& e) {
std::cout << "Error: " << e.what() << std::endl;
return 1;
}
catch (...) {
std::cout << "Error: unknown exception caught." << std::endl;
return 1;
}
}