From 58c61d29598539000553920c3640333af519d8a8 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 18:02:22 -0500 Subject: [PATCH 01/10] put back some comments --- src/libcore/tls.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/tls.cpp b/src/libcore/tls.cpp index 34328ee9..75f6912b 100644 --- a/src/libcore/tls.cpp +++ b/src/libcore/tls.cpp @@ -133,22 +133,24 @@ struct ThreadLocalBase::ThreadLocalPrivate { /// Look up a TLS entry. The goal is to make this operation very fast! std::pair get() { bool existed = true; + void *data; #if defined(__OSX__) PerThreadData *ptd = (PerThreadData *) pthread_getspecific(ptdLocal); #else PerThreadData *ptd = ptdLocal; #endif - if(EXPECT_NOT_TAKEN(!ptd)) { - throw std::runtime_error("null per-thread data"); - } + if (EXPECT_NOT_TAKEN(!ptd)) + throw std::runtime_error("Internal error: call to ThreadLocalPrivate::get() " + " precedes the construction of thread-specific data structures!"); - void *data; + /* This is an uncontended thread-local lock (i.e. not to worry) */ boost::lock_guard guard(ptd->mutex); PerThreadData::key_iterator it = ptd->map.find(this); if (EXPECT_TAKEN(it != ptd->map.end())) { data = it->second.data; } else { + /* This is the first access from this thread */ TLSEntry entry; entry.data = data = constructFunctor(); entry.destructFunctor = destructFunctor; From 87183a7534322d452dfca88e3e5e44986617c9e3 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 19:50:49 -0500 Subject: [PATCH 02/10] replaced some std::log/exp calls by the math::fastlog/exp equivalent --- src/integrators/pssmlt/pssmlt_sampler.cpp | 2 +- src/libcore/warp.cpp | 2 +- src/rfilters/gaussian.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/integrators/pssmlt/pssmlt_sampler.cpp b/src/integrators/pssmlt/pssmlt_sampler.cpp index 2b4e8aad..98288e03 100644 --- a/src/integrators/pssmlt/pssmlt_sampler.cpp +++ b/src/integrators/pssmlt/pssmlt_sampler.cpp @@ -50,7 +50,7 @@ void PSSMLTSampler::serialize(Stream *stream, InstanceManager *manager) const { } void PSSMLTSampler::configure() { - m_logRatio = -std::log(m_s2/m_s1); + m_logRatio = -math::fastlog(m_s2/m_s1); m_time = 0; m_largeStepTime = 0; m_largeStep = false; diff --git a/src/libcore/warp.cpp b/src/libcore/warp.cpp index e10f766a..65872c3d 100644 --- a/src/libcore/warp.cpp +++ b/src/libcore/warp.cpp @@ -137,7 +137,7 @@ Point2 Warp::squareToStdNormal(const Point2 &sample) { } Float Warp::squareToStdNormalPdf(const Point2 &pos) { - return INV_TWOPI * std::exp(-(pos.x*pos.x + pos.y*pos.y)/2.0f); + return INV_TWOPI * math::fastexp(-(pos.x*pos.x + pos.y*pos.y)/2.0f); } static Float intervalToTent(Float sample) { diff --git a/src/rfilters/gaussian.cpp b/src/rfilters/gaussian.cpp index a9cc046b..5ec166aa 100644 --- a/src/rfilters/gaussian.cpp +++ b/src/rfilters/gaussian.cpp @@ -52,8 +52,8 @@ public: Float eval(Float x) const { Float alpha = -1.0f / (2.0f * m_stddev*m_stddev); return std::max((Float) 0.0f, - std::exp(alpha * x * x) - - std::exp(alpha * m_radius * m_radius)); + math::fastexp(alpha * x * x) - + math::fastexp(alpha * m_radius * m_radius)); } std::string toString() const { From 4897f1d290c7813d7f18e5b2d76d7b2dbaa1defc Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 19:51:14 -0500 Subject: [PATCH 03/10] removed some trailing spaces --- include/mitsuba/core/stream.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mitsuba/core/stream.h b/include/mitsuba/core/stream.h index 112efc3b..a1c6826b 100644 --- a/include/mitsuba/core/stream.h +++ b/include/mitsuba/core/stream.h @@ -472,7 +472,7 @@ public: template void readArray(T *array, size_t count); /** - * \brief Read a known-size array from the stream (uses partial template + * \brief Read a known-size array from the stream (uses partial template * specialization to select a method appropriate to the data type) */ template inline void readArray(T (&arr)[N]) { @@ -484,9 +484,9 @@ public: * specialization to select a method appropriate to the data type) */ template void writeArray(const T *array, size_t count); - + /** - * \brief Write a known-size array to the stream (uses partial template + * \brief Write a known-size array to the stream (uses partial template * specialization to select a method appropriate to the data type) */ template inline void writeArray(const T (&arr)[N]) { From 1a2580faab53157222c868a058a40754b728efeb Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 19:55:52 -0500 Subject: [PATCH 04/10] some minor cleanups, added a cache flushing mechanism for serialized.cpp --- include/mitsuba/core/tls.h | 3 ++- include/mitsuba/render/scenehandler.h | 3 +++ include/mitsuba/render/trimesh.h | 7 ++++--- src/librender/scenehandler.cpp | 16 ++++++++++++++++ src/librender/trimesh.cpp | 11 +++++------ src/shapes/serialized.cpp | 13 +++++++++---- 6 files changed, 39 insertions(+), 14 deletions(-) diff --git a/include/mitsuba/core/tls.h b/include/mitsuba/core/tls.h index 00c81a1b..a5d2b8b6 100644 --- a/include/mitsuba/core/tls.h +++ b/include/mitsuba/core/tls.h @@ -141,7 +141,8 @@ protected: } inline static void destruct(void *data) { - delete static_cast(data); + if (data) + delete static_cast(data); } protected: detail::ThreadLocalBase m_base; diff --git a/include/mitsuba/render/scenehandler.h b/include/mitsuba/render/scenehandler.h index c8a4a149..38ebae2e 100644 --- a/include/mitsuba/render/scenehandler.h +++ b/include/mitsuba/render/scenehandler.h @@ -101,6 +101,9 @@ public: /// Free the memory taken up by staticInitialization() static void staticShutdown(); + /// Push a cleanup handler to be executed after loading the scene is done + static void pushCleanupHandler(void (*cleanup)()); + // ----------------------------------------------------------------------- // Implementation of the SAX DocumentHandler interface // ----------------------------------------------------------------------- diff --git a/include/mitsuba/render/trimesh.h b/include/mitsuba/render/trimesh.h index 33556342..4f6a8606 100644 --- a/include/mitsuba/render/trimesh.h +++ b/include/mitsuba/render/trimesh.h @@ -312,9 +312,10 @@ protected: /** * \brief Reads the header information of a compressed file, returning - * the version ID. This function assumes the stream is at the beginning - * of the compressed file and leaves the stream located right after the - * header. + * the version ID. + * + * This function assumes the stream is at the beginning of the compressed + * file and leaves the stream located right after the header. */ static short readHeader(Stream *stream); diff --git a/src/librender/scenehandler.cpp b/src/librender/scenehandler.cpp index 30017839..299ea7c2 100644 --- a/src/librender/scenehandler.cpp +++ b/src/librender/scenehandler.cpp @@ -31,6 +31,7 @@ #include #include #include +#include MTS_NAMESPACE_BEGIN XERCES_CPP_NAMESPACE_USE @@ -46,6 +47,10 @@ XERCES_CPP_NAMESPACE_USE level, NULL, __FILE__, __LINE__, fmt, ## __VA_ARGS__) #endif +typedef void (*CleanupFun) (); +typedef boost::unordered_set CleanupSet; +static PrimitiveThreadLocal __cleanup_tls; + SceneHandler::SceneHandler(const SAXParser *parser, const ParameterMap ¶ms, NamedObjectMap *namedObjects, bool isIncludedFile) : m_parser(parser), m_params(params), @@ -155,6 +160,13 @@ void SceneHandler::startDocument() { void SceneHandler::endDocument() { SAssert(m_scene != NULL); + + /* Call cleanup handlers */ + CleanupSet &cleanup = __cleanup_tls.get(); + for (CleanupSet::iterator it = cleanup.begin(); + it != cleanup.end(); ++it) + (*it)(); + cleanup.clear(); } void SceneHandler::characters(const XMLCh* const name, @@ -247,6 +259,10 @@ void SceneHandler::startElement(const XMLCh* const xmlName, m_context.push(context); } +void SceneHandler::pushCleanupHandler(void (*cleanup)()) { + __cleanup_tls.get().insert(cleanup); +} + void SceneHandler::endElement(const XMLCh* const xmlName) { std::string name = transcode(xmlName); ParseContext &context = m_context.top(); diff --git a/src/librender/trimesh.cpp b/src/librender/trimesh.cpp index c38bb2e3..79d660d4 100644 --- a/src/librender/trimesh.cpp +++ b/src/librender/trimesh.cpp @@ -176,7 +176,7 @@ void TriMesh::loadCompressed(Stream *_stream, int index) { if (stream->getByteOrder() != Stream::ELittleEndian) Log(EError, "Tried to unserialize a shape from a stream, " - "which was not previously set to little endian byte order!"); + "which was not previously set to little endian byte order!"); const short version = readHeader(stream); @@ -305,7 +305,7 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version, + sizeof(char) // Name + 2*sizeof(uint64_t) // Number of vertices and triangles + 3*sizeof(float) // One vertex - + 3*sizeof(uint32_t)); // One triange + + 3*sizeof(uint32_t)); // One triangle if (streamSize >= minSize) { outOffsets.resize(count); @@ -314,9 +314,8 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version, if (typeid(size_t) == typeid(uint64_t)) { stream->readArray(&outOffsets[0], count); } else { - for (size_t i = 0; i < count; ++i) { - outOffsets[i] = static_cast(stream->readSize()); - } + for (size_t i = 0; i < count; ++i) + outOffsets[i] = stream->readSize(); } } else { stream->seek(stream->getSize() - sizeof(uint32_t) * (count + 1)); @@ -325,7 +324,7 @@ int TriMesh::readOffsetDictionary(Stream *stream, short version, stream->readArray(&outOffsets[0], count); } else { for (size_t i = 0; i < count; ++i) { - outOffsets[i] = stream->readUInt(); + outOffsets[i] = (size_t) stream->readUInt(); } } } diff --git a/src/shapes/serialized.cpp b/src/shapes/serialized.cpp index 7635558c..4c44a254 100644 --- a/src/shapes/serialized.cpp +++ b/src/shapes/serialized.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -211,16 +212,15 @@ public: private: /** - * Helper class for loading serialized meshes from the same file + * Helper class for loading serialized meshes from the same file * repeatedly: it is common for scene to load multiple meshes from the same - * file, most times even in ascending order. This class loads the mesh + * file, most times even in ascending order. This class loads the mesh * offsets dictionary only once and keeps the stream open. * * Instances of this class are not thread safe. */ class MeshLoader { public: - MeshLoader(const fs::path& filePath) { m_fstream = new FileStream(filePath, FileStream::EReadOnly); m_fstream->setByteOrder(Stream::ELittleEndian); @@ -264,6 +264,11 @@ private: &boost::make_shared) {} }; + /// Release all currently held offset caches / file streams + static void flushCache() { + m_cache.set(NULL); + } + /// Loads the mesh from the thread-local file stream cache void loadCompressed(const fs::path& filePath, const int idx) { if (EXPECT_NOT_TAKEN(idx < 0)) { @@ -276,6 +281,7 @@ private: if (EXPECT_NOT_TAKEN(cache == NULL)) { cache = new FileStreamCache(); m_cache.set(cache); + SceneHandler::pushCleanupHandler(&SerializedMesh::flushCache); } boost::shared_ptr meshLoader = cache->get(filePath); @@ -288,7 +294,6 @@ private: ThreadLocal SerializedMesh::m_cache; - MTS_IMPLEMENT_CLASS_S(SerializedMesh, false, TriMesh) MTS_EXPORT_PLUGIN(SerializedMesh, "Serialized mesh loader"); MTS_NAMESPACE_END From 5fc2db638778f056d43862cb6a4506af9eaaa0d6 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 20:21:52 -0500 Subject: [PATCH 05/10] better error messages for Transform::lookAt() --- include/mitsuba/core/vector.h | 28 ++++++++++++++++++++++++++++ src/libcore/transform.cpp | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/include/mitsuba/core/vector.h b/include/mitsuba/core/vector.h index a7933056..df8a10e3 100644 --- a/include/mitsuba/core/vector.h +++ b/include/mitsuba/core/vector.h @@ -189,6 +189,13 @@ template inline TVector1 normalize(const TVector1 &v) { return v / v.length(); } +template inline TVector1 normalizeStrict(const TVector1 &v, const char *errMsg) { + Float length = v.length(); + if (length == 0) + SLog(EError, "normalizeStrict(): %s", errMsg); + return v / length; +} + template <> inline TVector1 TVector1::operator/(int s) const { #ifdef MTS_DEBUG if (s == 0) @@ -380,6 +387,13 @@ template inline TVector2 normalize(const TVector2 &v) { return v / v.length(); } +template inline TVector2 normalizeStrict(const TVector2 &v, const char *errMsg) { + Float length = v.length(); + if (length == 0) + SLog(EError, "normalizeStrict(): %s", errMsg); + return v / length; +} + template <> inline TVector2 TVector2::operator/(int s) const { #ifdef MTS_DEBUG if (s == 0) @@ -582,6 +596,13 @@ template inline TVector3 normalize(const TVector3 &v) { return v / v.length(); } +template inline TVector3 normalizeStrict(const TVector3 &v, const char *errMsg) { + Float length = v.length(); + if (length == 0) + SLog(EError, "normalizeStrict(): %s", errMsg); + return v / length; +} + template <> inline TVector3 TVector3::operator/(int s) const { #ifdef MTS_DEBUG if (s == 0) @@ -781,6 +802,13 @@ template inline TVector4 normalize(const TVector4 &v) { return v / v.length(); } +template inline TVector4 normalizeStrict(const TVector4 &v, const char *errMsg) { + Float length = v.length(); + if (length == 0) + SLog(EError, "normalizeStrict(): %s", errMsg); + return v / length; +} + template <> inline TVector4 TVector4::operator/(int s) const { #ifdef MTS_DEBUG if (s == 0) diff --git a/src/libcore/transform.cpp b/src/libcore/transform.cpp index 71004bec..5f056310 100644 --- a/src/libcore/transform.cpp +++ b/src/libcore/transform.cpp @@ -189,8 +189,8 @@ Transform Transform::glOrthographic(Float clipLeft, Float clipRight, } Transform Transform::lookAt(const Point &p, const Point &t, const Vector &up) { - Vector dir = normalize(t-p); - Vector left = normalize(cross(up, dir)); + Vector dir = normalizeStrict(t-p, "lookAt(): 'origin' and 'target' coincide!"); + Vector left = normalizeStrict(cross(up, dir), "lookAt(): the forward and upward direction must be linearly independent!"); Vector newUp = cross(dir, left); Matrix4x4 result, inverse; From 1505fd7c02df8f4d92d630acd20ba7e5ed5e249c Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 20:46:52 -0500 Subject: [PATCH 06/10] vector vs point confusion in constvolume.cpp --- src/volume/constvolume.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/volume/constvolume.cpp b/src/volume/constvolume.cpp index 94608910..a788f753 100644 --- a/src/volume/constvolume.cpp +++ b/src/volume/constvolume.cpp @@ -58,7 +58,7 @@ public: if (m_type == Properties::EFloat) m_float = props.getFloat("value"); - else if (m_type == Properties::EPoint) + else if (m_type == Properties::EVector) m_vector = props.getVector("value"); else if (m_type == Properties::ESpectrum) m_spectrum = props.getSpectrum("value"); @@ -72,7 +72,7 @@ public: m_type = stream->readInt(); if (m_type == Properties::EFloat) m_float = stream->readFloat(); - else if (m_type == Properties::EPoint) + else if (m_type == Properties::EVector) m_vector = Vector(stream); else if (m_type == Properties::ESpectrum) m_spectrum = Spectrum(stream); From 4bc95de8dcaa09f1e5031447d96351dc06e1f57a Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 21:10:59 -0500 Subject: [PATCH 07/10] BSDF sampling: increased resilience to numerical corner-cases --- src/bsdfs/coating.cpp | 6 +++--- src/bsdfs/plastic.cpp | 4 ++-- src/bsdfs/roughcoating.cpp | 2 +- src/bsdfs/roughplastic.cpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bsdfs/coating.cpp b/src/bsdfs/coating.cpp index 1d4722d1..1c4f77c2 100644 --- a/src/bsdfs/coating.cpp +++ b/src/bsdfs/coating.cpp @@ -318,11 +318,11 @@ public: Point2 sample(_sample); if (sampleSpecular && sampleNested) { - if (sample.x > probSpecular) { + if (sample.x < probSpecular) { + sample.x /= probSpecular; + } else { sample.x = (sample.x - probSpecular) / (1 - probSpecular); choseSpecular = false; - } else { - sample.x /= probSpecular; } } diff --git a/src/bsdfs/plastic.cpp b/src/bsdfs/plastic.cpp index bb12a1a9..4f11f242 100644 --- a/src/bsdfs/plastic.cpp +++ b/src/bsdfs/plastic.cpp @@ -321,7 +321,7 @@ public: (1-Fi) * (1-m_specularSamplingWeight)); /* Importance sample wrt. the Fresnel reflectance */ - if (sample.x <= probSpecular) { + if (sample.x < probSpecular) { bRec.sampledComponent = 0; bRec.sampledType = EDeltaReflection; bRec.wo = reflect(bRec.wi); @@ -384,7 +384,7 @@ public: (1-Fi) * (1-m_specularSamplingWeight)); /* Importance sample wrt. the Fresnel reflectance */ - if (sample.x <= probSpecular) { + if (sample.x < probSpecular) { bRec.sampledComponent = 0; bRec.sampledType = EDeltaReflection; bRec.wo = reflect(bRec.wi); diff --git a/src/bsdfs/roughcoating.cpp b/src/bsdfs/roughcoating.cpp index ff811c7f..0622316d 100644 --- a/src/bsdfs/roughcoating.cpp +++ b/src/bsdfs/roughcoating.cpp @@ -391,7 +391,7 @@ public: (probSpecular*m_specularSamplingWeight + (1-probSpecular) * (1-m_specularSamplingWeight)); - if (sample.y <= probSpecular) { + if (sample.y < probSpecular) { sample.y /= probSpecular; } else { sample.y = (sample.y - probSpecular) / (1 - probSpecular); diff --git a/src/bsdfs/roughplastic.cpp b/src/bsdfs/roughplastic.cpp index 5cbf2b97..97cb4753 100644 --- a/src/bsdfs/roughplastic.cpp +++ b/src/bsdfs/roughplastic.cpp @@ -447,7 +447,7 @@ public: (probSpecular*m_specularSamplingWeight + (1-probSpecular) * (1-m_specularSamplingWeight)); - if (sample.y <= probSpecular) { + if (sample.y < probSpecular) { sample.y /= probSpecular; } else { sample.y = (sample.y - probSpecular) / (1 - probSpecular); From f9733089fd1eb076c379d924d9503960354f65c5 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 27 Jan 2013 23:26:00 -0500 Subject: [PATCH 08/10] fixed an annoying error message about the 'focalLength' parameter when duplicating the tab of a scene made in Blender --- src/librender/sensor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librender/sensor.cpp b/src/librender/sensor.cpp index 2d8fcbb1..552c98d2 100644 --- a/src/librender/sensor.cpp +++ b/src/librender/sensor.cpp @@ -260,6 +260,7 @@ void PerspectiveCamera::configure() { SLog(EError, "Could not parse the focal length (must be of the form " "mm, where is a positive integer)!"); + m_properties.removeProperty("focalLength"); setDiagonalFov(2 * 180/M_PI* std::atan(std::sqrt((Float) (36*36+24*24)) / (2*value))); } } From 2141fce492bf98df2ff10f3773f2467e73611869 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 28 Jan 2013 00:44:53 -0500 Subject: [PATCH 09/10] got the python plugin to run on OSX without the need to declare DYLD_LIBRARY_PATH --- data/darwin/add-icl-libraries.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/data/darwin/add-icl-libraries.sh b/data/darwin/add-icl-libraries.sh index 947ad417..9db846ad 100755 --- a/data/darwin/add-icl-libraries.sh +++ b/data/darwin/add-icl-libraries.sh @@ -1,5 +1,6 @@ #!/bin/bash cp /opt/intel/composer_xe_*/compiler/lib/libiomp5.dylib Mitsuba.app/Contents/Frameworks +install_name_tool -id @rpath/libiomp5.dylib Mitsuba.app/Contents/Frameworks/libiomp5.dylib find Mitsuba.app/Contents/MacOS/ Mitsuba.app/plugins -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib find Mitsuba.app/Contents/Frameworks/libmitsuba-* -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib find Mitsuba.app/python -type f | xargs -n 1 install_name_tool -change libiomp5.dylib @rpath/libiomp5.dylib From 9824c000fdfd33467d19148fda651e034aa1be20 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 28 Jan 2013 00:52:59 -0500 Subject: [PATCH 10/10] fixed some invalid conditionals in RoughDiffuse, which kept texturing from working --- src/bsdfs/roughdiffuse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bsdfs/roughdiffuse.cpp b/src/bsdfs/roughdiffuse.cpp index df4c02e5..a107a1f8 100644 --- a/src/bsdfs/roughdiffuse.cpp +++ b/src/bsdfs/roughdiffuse.cpp @@ -254,7 +254,7 @@ public: if (child->getClass()->derivesFrom(MTS_CLASS(Texture))) { if (name == "reflectance" || name == "diffuseReflectance") m_reflectance = static_cast(child); - if (name == "alpha") + else if (name == "alpha") m_alpha = static_cast(child); else BSDF::addChild(name, child);