enhanced customizable rendering statistics

metadata
Wenzel Jakob 2013-01-28 16:07:25 -05:00
parent 8d1ef9809c
commit b36db49600
17 changed files with 209 additions and 71 deletions

View File

@ -185,6 +185,10 @@ public:
/// Return one of the parameters (converting it to a string if necessary, with default value) /// Return one of the parameters (converting it to a string if necessary, with default value)
std::string getAsString(const std::string &name, const std::string &defVal) const; std::string getAsString(const std::string &name, const std::string &defVal) const;
/// Copy an attribute from another Properties object and potentially rename it
void copyAttribute(const Properties &properties,
const std::string &sourceName, const std::string &targetName);
/// Store an array containing the names of all stored properties /// Store an array containing the names of all stored properties
void putPropertyNames(std::vector<std::string> &results) const; void putPropertyNames(std::vector<std::string> &results) const;

View File

@ -110,6 +110,9 @@ extern MTS_EXPORT_CORE int getCoreCount();
/// Return the host name of this machine /// Return the host name of this machine
extern MTS_EXPORT_CORE std::string getHostName(); extern MTS_EXPORT_CORE std::string getHostName();
/// Return the process private memory usage in bytes
extern MTS_EXPORT_CORE size_t getPrivateMemoryUsage();
/// Return the fully qualified domain name of this machine /// Return the fully qualified domain name of this machine
extern MTS_EXPORT_CORE std::string getFQDN(); extern MTS_EXPORT_CORE std::string getFQDN();

View File

@ -61,7 +61,7 @@ public:
virtual void setDestinationFile(const fs::path &filename, uint32_t blockSize) = 0; virtual void setDestinationFile(const fs::path &filename, uint32_t blockSize) = 0;
/// Develop the film and write the result to the previously specified filename /// Develop the film and write the result to the previously specified filename
virtual void develop() = 0; virtual void develop(const Scene *scene, Float renderTime) = 0;
/** /**
* \brief Develop the contents of a subregion of the film and store * \brief Develop the contents of a subregion of the film and store

View File

@ -75,7 +75,7 @@ public:
bool interactive = false); bool interactive = false);
/// Write out the current (partially rendered) image /// Write out the current (partially rendered) image
inline void flush() { m_scene->flush(); } inline void flush() { m_scene->flush(m_queue, this); }
/// Cancel a running render job /// Cancel a running render job
inline void cancel() { m_scene->cancel(); } inline void cancel() { m_scene->cancel(); }

View File

@ -76,6 +76,9 @@ public:
/// Remove a (finished) render job from the queue /// Remove a (finished) render job from the queue
void removeJob(RenderJob *thr, bool wasCancelled); void removeJob(RenderJob *thr, bool wasCancelled);
/// Return the amount of time spent rendering the given job (in seconds)
Float getRenderTime(const RenderJob *job) const;
/// Register a render listener /// Register a render listener
void registerListener(RenderListener *listener); void registerListener(RenderListener *listener);

View File

@ -133,7 +133,7 @@ public:
int sceneResID, int sensorResID, int samplerResID); int sceneResID, int sensorResID, int samplerResID);
/// Write out the current (partially rendered) image /// Write out the current (partially rendered) image
void flush(); void flush(RenderQueue *queue, const RenderJob *job);
/** /**
* \brief Cancel a running rendering job * \brief Cancel a running rendering job

View File

@ -22,6 +22,7 @@
#include <mitsuba/core/statistics.h> #include <mitsuba/core/statistics.h>
#include <mitsuba/hw/font.h> #include <mitsuba/hw/font.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <mitsuba/render/scene.h>
#include "banner.h" #include "banner.h"
MTS_NAMESPACE_BEGIN MTS_NAMESPACE_BEGIN
@ -235,20 +236,11 @@ public:
std::vector<std::string> keys = props.getPropertyNames(); std::vector<std::string> keys = props.getPropertyNames();
for (size_t i=0; i<keys.size(); ++i) { for (size_t i=0; i<keys.size(); ++i) {
std::string key = boost::to_lower_copy(keys[i]); std::string key = boost::to_lower_copy(keys[i]);
key.erase(std::remove_if(key.begin(), key.end(), ::isspace), key.end());
if (boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) { if ((boost::starts_with(key, "tag('") && boost::ends_with(key, "')")) ||
m_tags[keys[i].substr(5, key.length()-7)] = props.getString(keys[i]); (boost::starts_with(key, "text(") && boost::ends_with(key, ")")))
} else if (boost::starts_with(key, "text(") && boost::ends_with(key, ")")) { props.markQueried(keys[i]);
std::vector<std::string> args = tokenize(key.substr(5, key.length()-6), " ,");
if (args.size() != 2)
Log(EError, "Text command '%s' has an invalid number of arguments!", key.c_str());
Annotation annotation;
annotation.offset = Point2i(atoi(args[0].c_str()), atoi(args[1].c_str()));
annotation.text = props.getString(keys[i]);
m_annotations.push_back(annotation);
}
} }
m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize); m_storage = new ImageBlock(Bitmap::ESpectrumAlphaWeight, m_cropSize);
@ -350,7 +342,7 @@ public:
m_destFile = destFile; m_destFile = destFile;
} }
void develop() { void develop(const Scene *scene, Float renderTime) {
Log(EDebug, "Developing film .."); Log(EDebug, "Developing film ..");
ref<Bitmap> bitmap = m_storage->getBitmap()->convert( ref<Bitmap> bitmap = m_storage->getBitmap()->convert(
@ -368,23 +360,6 @@ public:
} }
} }
if (!m_annotations.empty()) {
ref<Font> font = new Font(Font::EBitstreamVeraMono14);
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), 1.0f);
for (size_t i=0; i<m_annotations.size(); ++i) {
const Point2i &offset = m_annotations[i].offset;
const std::string &text = m_annotations[i].text;
Vector2i size = font->getSize(text);
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
font->drawText(bitmap, offset, text);
}
}
for (std::map<std::string, std::string>::const_iterator it = m_tags.begin();
it != m_tags.end(); ++it)
bitmap->setMetadataString(it->first, it->second);
fs::path filename = m_destFile; fs::path filename = m_destFile;
std::string extension = boost::to_lower_copy(filename.extension().string()); std::string extension = boost::to_lower_copy(filename.extension().string());
std::string properExtension = (m_fileFormat == Bitmap::EOpenEXR) ? ".exr" : ".rgbe"; std::string properExtension = (m_fileFormat == Bitmap::EOpenEXR) ? ".exr" : ".rgbe";
@ -394,13 +369,115 @@ public:
Log(EInfo, "Writing image to \"%s\" ..", filename.string().c_str()); Log(EInfo, "Writing image to \"%s\" ..", filename.string().c_str());
ref<FileStream> stream = new FileStream(filename, FileStream::ETruncWrite); ref<FileStream> stream = new FileStream(filename, FileStream::ETruncWrite);
/* Attach the custom annotations */
Properties &metadata = bitmap->getMetadata();
std::vector<std::string> keys = m_properties.getPropertyNames();
ref<Font> font;
Float gamma = 1.0f; /// XXX
for (size_t i=0; i<keys.size(); ++i) {
std::string key = keys[i];
key.erase(std::remove_if(key.begin(), key.end(), ::isspace), key.end());
std::string lkey = boost::to_lower_copy(key);
Point2i offset(0, 0);
bool labelAnnotation = false;
if (boost::starts_with(lkey, "metadata['") && boost::ends_with(lkey, "']")) {
key = key.substr(10, key.length()-12);
} else if (boost::starts_with(lkey, "label[") && boost::ends_with(lkey, "]")) {
std::vector<std::string> args = tokenize(key.substr(6, key.length()-7), " ,");
if (args.size() != 2)
Log(EError, "Label command '%s' has an invalid number of arguments!", key.c_str());
char *end_ptr = NULL;
offset.x = strtol(args[0].c_str(), &end_ptr, 10);
if (*end_ptr != '\0')
Log(EError, "Label command '%s' has an invalid position argument!", key.c_str());
offset.y = strtol(args[1].c_str(), &end_ptr, 10);
if (*end_ptr != '\0')
Log(EError, "Label command '%s' has an invalid position argument!", key.c_str());
labelAnnotation = true;
if (font == NULL) {
font = new Font(Font::EBitstreamVeraMono14);
font->convert(bitmap->getPixelFormat(), bitmap->getComponentFormat(), gamma);
}
} else {
continue;
}
Properties::EPropertyType type = m_properties.getType(keys[i]);
if (type == Properties::EString) {
std::string value = m_properties.getString(keys[i]);
while (true) {
char *strt;
if (!(strt = strchr((char *) value.c_str(), '$')))
break;
if (strncasecmp(strt, "$rendertime", 11) == 0) {
value.replace(strt-value.c_str(), 11, timeString(renderTime));
} else if (strncasecmp(strt, "$memusage", 11) == 0) {
value.replace(strt-value.c_str(), 11, memString(getPrivateMemoryUsage()));
} else {
char *par1, *par2;
if (!(par1 = strchr(strt, '[')))
break;
if (!(par2 = strchr(par1, ']')))
break;
std::string propSource = value.substr(strt-value.c_str()+1, par1-strt-1);
std::string propKey = value.substr(par1-value.c_str()+1, par2-par1-1);
propSource.erase(std::remove_if(propSource.begin(), propSource.end(), ::isspace), propSource.end());
propKey.erase(std::remove_if(propKey.begin(), propKey.end(), ::isspace), propKey.end());
if (!boost::starts_with(propKey, "'") || !boost::ends_with(propKey, "'"))
Log(EError, "Encountered invalid key '%s'", propKey.c_str());
propKey = propKey.substr(1, propKey.length()-2);
const ConfigurableObject *source = NULL;
if (propSource == "film")
source = scene->getFilm();
else if (propSource == "sampler")
source = scene->getSampler();
else if (propSource == "sensor")
source = scene->getSensor();
else if (propSource == "integrator")
source = scene->getIntegrator();
else
Log(EError, "Unknown data source '%s' (must be film/sampler/sensor/integrator)", propSource.c_str());
std::string replacement;
if (propKey == "type")
replacement = source->getProperties().getPluginName();
else
replacement = source->getProperties().getAsString(propKey);
value.replace(strt-value.c_str(), par2-strt+1, replacement);
}
cout << value << endl;
}
if (labelAnnotation) {
Vector2i size = font->getSize(value);
bitmap->fillRect(offset-Vector2i(4, 4), size + Vector2i(8, 8), Spectrum(0.0f));
font->drawText(bitmap, offset, value);
} else {
metadata.setString(key, value);
}
} else {
if (labelAnnotation)
Log(EError, "Only string-valued label annotations are supported!");
metadata.copyAttribute(m_properties, keys[i], key);
}
}
/* Attach the log file to the image if this is requested */ /* Attach the log file to the image if this is requested */
Logger *logger = Thread::getThread()->getLogger(); Logger *logger = Thread::getThread()->getLogger();
std::string log; std::string log;
if (m_attachLog && logger->readLog(log)) { if (m_attachLog && logger->readLog(log)) {
log += "\n\n"; log += "\n\n";
log += Statistics::getInstance()->getStats(); log += Statistics::getInstance()->getStats();
bitmap->setMetadataString("log", log); metadata.setString("log", log);
} }
bitmap->write(m_fileFormat, stream); bitmap->write(m_fileFormat, stream);
@ -451,9 +528,6 @@ protected:
bool m_attachLog; bool m_attachLog;
fs::path m_destFile; fs::path m_destFile;
ref<ImageBlock> m_storage; ref<ImageBlock> m_storage;
std::vector<Annotation> m_annotations;
std::map<std::string, std::string> m_tags;
}; };
MTS_IMPLEMENT_CLASS_S(HDRFilm, false, Film) MTS_IMPLEMENT_CLASS_S(HDRFilm, false, Film)

View File

@ -306,7 +306,7 @@ public:
m_destFile = destFile; m_destFile = destFile;
} }
void develop() { void develop(const Scene *scene, Float renderTime) {
Log(EDebug, "Developing film .."); Log(EDebug, "Developing film ..");
ref<Bitmap> bitmap = m_storage->getBitmap(); ref<Bitmap> bitmap = m_storage->getBitmap();

View File

@ -238,7 +238,7 @@ public:
m_destFile = destFile; m_destFile = destFile;
} }
void develop() { void develop(const Scene *scene, Float renderTime) {
Log(EDebug, "Developing film .."); Log(EDebug, "Developing film ..");
fs::path filename = m_destFile; fs::path filename = m_destFile;

View File

@ -156,7 +156,7 @@ public:
} }
virtual ~TiledHDRFilm() { virtual ~TiledHDRFilm() {
develop(); develop(NULL, 0);
} }
void serialize(Stream *stream, InstanceManager *manager) const { void serialize(Stream *stream, InstanceManager *manager) const {
@ -167,7 +167,7 @@ public:
void setDestinationFile(const fs::path &destFile, uint32_t blockSize) { void setDestinationFile(const fs::path &destFile, uint32_t blockSize) {
if (m_output) if (m_output)
develop(); develop(NULL, 0);
Bitmap::EPixelFormat pixelFormat = m_pixelFormat; Bitmap::EPixelFormat pixelFormat = m_pixelFormat;
#if SPECTRUM_SAMPLES == 3 #if SPECTRUM_SAMPLES == 3
@ -436,7 +436,7 @@ public:
return false; /* Not supported by the tiled EXR film! */ return false; /* Not supported by the tiled EXR film! */
} }
void develop() { void develop(const Scene *scene, Float renderTime) {
if (m_output) { if (m_output) {
Log(EInfo, "Closing EXR file (%u tiles in total, peak memory usage: %u tiles)..", Log(EInfo, "Closing EXR file (%u tiles in total, peak memory usage: %u tiles)..",
m_blocksH * m_blocksV, m_peakUsage); m_blocksH * m_blocksV, m_peakUsage);

View File

@ -1355,7 +1355,7 @@ void Bitmap::writePNG(Stream *stream, int compression) const {
png_text *text = NULL; png_text *text = NULL;
Properties metadata(m_metadata); Properties metadata(m_metadata);
metadata.setString("generated-by", "Mitsuba version " MTS_VERSION); metadata.setString("generatedBy", "Mitsuba version " MTS_VERSION);
std::vector<std::string> keys = metadata.getPropertyNames(); std::vector<std::string> keys = metadata.getPropertyNames();
std::vector<std::string> values(keys.size()); std::vector<std::string> values(keys.size());
@ -1923,7 +1923,7 @@ void Bitmap::writeOpenEXR(Stream *stream,
#endif #endif
Properties metadata(m_metadata); Properties metadata(m_metadata);
metadata.setString("generated-by", "Mitsuba version " MTS_VERSION); metadata.setString("generatedBy", "Mitsuba version " MTS_VERSION);
std::vector<std::string> keys = metadata.getPropertyNames(); std::vector<std::string> keys = metadata.getPropertyNames();

View File

@ -156,7 +156,6 @@ template <typename T> struct FormatConverterImpl : public FormatConverter {
precomp[i] = convertScalar<DestFormat>(detail::safe_cast<SourceFormat>(i), sourceGamma, NULL, multiplier, invDestGamma); precomp[i] = convertScalar<DestFormat>(detail::safe_cast<SourceFormat>(i), sourceGamma, NULL, multiplier, invDestGamma);
} }
const DestFormat zero = convertScalar<DestFormat>(0.0f);
const DestFormat one = convertScalar<DestFormat>(1.0f); const DestFormat one = convertScalar<DestFormat>(1.0f);
Spectrum spec; Spectrum spec;
@ -193,14 +192,14 @@ template <typename T> struct FormatConverterImpl : public FormatConverter {
case Bitmap::EXYZ: case Bitmap::EXYZ:
for (size_t i=0; i<count; ++i) { for (size_t i=0; i<count; ++i) {
DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma); DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma);
*dest++ = zero; *dest++ = value; *dest++ = zero; *dest++ = 0.950456f*value; *dest++ = value; *dest++ = 1.08875f*value;
} }
break; break;
case Bitmap::EXYZA: case Bitmap::EXYZA:
for (size_t i=0; i<count; ++i) { for (size_t i=0; i<count; ++i) {
DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma); DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma);
*dest++ = zero; *dest++ = value; *dest++ = zero; *dest++ = one; *dest++ = 0.950456f*value; *dest++ = value; *dest++ = 1.08875f*value; *dest++ = one;
} }
break; break;
@ -271,7 +270,7 @@ template <typename T> struct FormatConverterImpl : public FormatConverter {
case Bitmap::EXYZ: case Bitmap::EXYZ:
for (size_t i=0; i<count; ++i) { for (size_t i=0; i<count; ++i) {
DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma); DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma);
*dest++ = zero; *dest++ = value; *dest++ = zero; *dest++ = 0.950456f*value; *dest++ = value; *dest++ = 1.08875f*value;
source++; source++;
} }
break; break;
@ -279,7 +278,7 @@ template <typename T> struct FormatConverterImpl : public FormatConverter {
case Bitmap::EXYZA: case Bitmap::EXYZA:
for (size_t i=0; i<count; ++i) { for (size_t i=0; i<count; ++i) {
DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma); DestFormat value = convertScalar<DestFormat>(*source++, sourceGamma, precomp, multiplier, invDestGamma);
*dest++ = zero; *dest++ = value; *dest++ = zero; *dest++ = 0.950456f*value; *dest++ = value; *dest++ = 1.08875f*value;
*dest++ = convertScalar<DestFormat>(*source++); *dest++ = convertScalar<DestFormat>(*source++);
} }
break; break;

View File

@ -246,6 +246,14 @@ void Properties::putPropertyNames(std::vector<std::string> &results) const {
results.push_back((*it).first); results.push_back((*it).first);
} }
void Properties::copyAttribute(const Properties &properties,
const std::string &sourceName, const std::string &targetName) {
std::map<std::string, PropertyElement>::const_iterator it = properties.m_elements->find(sourceName);
if (it == properties.m_elements->end())
SLog(EError, "copyAttribute(): Could not find parameter \"%s\"!", sourceName.c_str());
m_elements->operator[](targetName) = it->second;
}
bool Properties::operator==(const Properties &p) const { bool Properties::operator==(const Properties &p) const {
if (m_pluginName != p.m_pluginName || m_id != p.m_id || m_elements->size() != p.m_elements->size()) if (m_pluginName != p.m_pluginName || m_id != p.m_id || m_elements->size() != p.m_elements->size())
return false; return false;

View File

@ -28,13 +28,15 @@
#if defined(__OSX__) #if defined(__OSX__)
#include <sys/sysctl.h> #include <sys/sysctl.h>
#elif defined(WIN32) #include <mach/mach.h>
#elif defined(__WINDOWS__)
#include <direct.h> #include <direct.h>
#include <psapi.h>
#else #else
#include <malloc.h> #include <malloc.h>
#endif #endif
#if defined(WIN32) #if defined(__WINDOWS__)
# include <windows.h> # include <windows.h>
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h> # include <ws2tcpip.h>
@ -134,7 +136,7 @@ std::string memString(size_t size) {
} }
void * __restrict allocAligned(size_t size) { void * __restrict allocAligned(size_t size) {
#if defined(WIN32) #if defined(__WINDOWS__)
return _aligned_malloc(size, L1_CACHE_LINE_SIZE); return _aligned_malloc(size, L1_CACHE_LINE_SIZE);
#elif defined(__OSX__) #elif defined(__OSX__)
/* OSX malloc already returns 16-byte aligned data suitable /* OSX malloc already returns 16-byte aligned data suitable
@ -146,7 +148,7 @@ void * __restrict allocAligned(size_t size) {
} }
void freeAligned(void *ptr) { void freeAligned(void *ptr) {
#if defined(WIN32) #if defined(__WINDOWS__)
_aligned_free(ptr); _aligned_free(ptr);
#else #else
free(ptr); free(ptr);
@ -154,7 +156,7 @@ void freeAligned(void *ptr) {
} }
int getCoreCount() { int getCoreCount() {
#if defined(WIN32) #if defined(__WINDOWS__)
SYSTEM_INFO sys_info; SYSTEM_INFO sys_info;
GetSystemInfo(&sys_info); GetSystemInfo(&sys_info);
return sys_info.dwNumberOfProcessors; return sys_info.dwNumberOfProcessors;
@ -169,7 +171,45 @@ int getCoreCount() {
#endif #endif
} }
#if defined(WIN32) size_t getPrivateMemoryUsage() {
#if defined(__WINDOWS__)
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
return (size_t) pmc.PrivateUsage;
#elif defined(__OSX__)
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
if (task_info(mach_task_self(), TASK_BASIC_INFO,
(task_info_t)&t_info, &t_info_count) != KERN_SUCCESS)
return 0;
/// XXX todo
#else
FILE* file = fopen("/proc/self/status", "r");
if (!file)
return 0;
char buffer[128];
size_t result = 0;
while (fgets(buffer, sizeof(buffer), file) != NULL) {
if (strncmp(buffer, "VmRSS:", 6) != 0 &&
strncmp(buffer, "VmSwap:", 7) != 0)
continue;
char *line = buffer;
while (*line < '0' || *line > '9')
++line;
line[strlen(line)-3] = '\0';
result += (size_t) atoi(line) * 1024;
}
fclose(file);
return result;
#endif
}
#if defined(__WINDOWS__)
std::string lastErrorText() { std::string lastErrorText() {
DWORD errCode = GetLastError(); DWORD errCode = GetLastError();
char *errorText = NULL; char *errorText = NULL;
@ -192,7 +232,7 @@ std::string lastErrorText() {
bool enableFPExceptions() { bool enableFPExceptions() {
bool exceptionsWereEnabled = false; bool exceptionsWereEnabled = false;
#if defined(WIN32) #if defined(__WINDOWS__)
_clearfp(); _clearfp();
uint32_t cw = _controlfp(0, 0); uint32_t cw = _controlfp(0, 0);
exceptionsWereEnabled = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW); exceptionsWereEnabled = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW);
@ -211,7 +251,7 @@ bool enableFPExceptions() {
bool disableFPExceptions() { bool disableFPExceptions() {
bool exceptionsWereEnabled = false; bool exceptionsWereEnabled = false;
#if defined(WIN32) #if defined(__WINDOWS__)
_clearfp(); _clearfp();
uint32_t cw = _controlfp(0, 0); uint32_t cw = _controlfp(0, 0);
exceptionsWereEnabled = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW); exceptionsWereEnabled = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW);
@ -230,7 +270,7 @@ bool disableFPExceptions() {
void restoreFPExceptions(bool oldState) { void restoreFPExceptions(bool oldState) {
bool currentState; bool currentState;
#if defined(WIN32) #if defined(__WINDOWS__)
uint32_t cw = _controlfp(0, 0); uint32_t cw = _controlfp(0, 0);
currentState = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW); currentState = ~cw & (_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW);
#elif defined(__OSX__) #elif defined(__OSX__)
@ -249,7 +289,7 @@ void restoreFPExceptions(bool oldState) {
std::string getHostName() { std::string getHostName() {
char hostName[128]; char hostName[128];
if (gethostname(hostName, sizeof(hostName)) != 0) if (gethostname(hostName, sizeof(hostName)) != 0)
#if defined(WIN32) #if defined(__WINDOWS__)
SLog(EError, "Could not retrieve the computer's host name: %s!", SLog(EError, "Could not retrieve the computer's host name: %s!",
lastErrorText().c_str()); lastErrorText().c_str());
#else #else
@ -280,7 +320,7 @@ std::string getFQDN() {
fqdn, NI_MAXHOST, NULL, 0, 0); fqdn, NI_MAXHOST, NULL, 0, 0);
if (retVal != 0) { if (retVal != 0) {
freeaddrinfo(addrInfo); freeaddrinfo(addrInfo);
#if defined(WIN32) #if defined(__WINDOWS__)
SLog(EWarn, "Could not retrieve the computer's fully " SLog(EWarn, "Could not retrieve the computer's fully "
"qualified domain name: error %i!", WSAGetLastError()); "qualified domain name: error %i!", WSAGetLastError());
#else #else
@ -304,7 +344,7 @@ std::string formatString(const char *fmt, ...) {
char tmp[512]; char tmp[512];
va_list iterator; va_list iterator;
#if defined(WIN32) #if defined(__WINDOWS__)
va_start(iterator, fmt); va_start(iterator, fmt);
size_t size = _vscprintf(fmt, iterator) + 1; size_t size = _vscprintf(fmt, iterator) + 1;

View File

@ -54,20 +54,28 @@ void RenderQueue::unregisterListener(RenderListener *listener) {
listener->decRef(); listener->decRef();
} }
Float RenderQueue::getRenderTime(const RenderJob *job) const {
LockGuard lock(m_mutex);
std::map<RenderJob *, JobRecord>::const_iterator it = m_jobs.find(const_cast<RenderJob*>(job));
if (it == m_jobs.end())
Log(EError, "RenderQueue::getRenderJob() - job not found!");
unsigned int ms = m_timer->getMilliseconds() - it->second.startTime;
return ms / 1000.0f;
}
void RenderQueue::flush() { void RenderQueue::flush() {
LockGuard lock(m_mutex); LockGuard lock(m_mutex);
std::map<RenderJob *, JobRecord>::iterator it = m_jobs.begin(); std::map<RenderJob *, JobRecord>::iterator it = m_jobs.begin();
for (; it != m_jobs.end(); ++it) { for (; it != m_jobs.end(); ++it)
(*it).first->flush(); (*it).first->flush();
}
} }
void RenderQueue::removeJob(RenderJob *job, bool cancelled) { void RenderQueue::removeJob(RenderJob *job, bool cancelled) {
LockGuard lock(m_mutex); LockGuard lock(m_mutex);
std::map<RenderJob *, JobRecord>::iterator it = m_jobs.find(job); std::map<RenderJob *, JobRecord>::iterator it = m_jobs.find(job);
if (it == m_jobs.end()) { if (it == m_jobs.end())
Log(EError, "RenderQueue::removeRenderJob() - job not found!"); Log(EError, "RenderQueue::removeRenderJob() - job not found!");
}
JobRecord &rec = (*it).second; JobRecord &rec = (*it).second;
unsigned int ms = m_timer->getMilliseconds() - rec.startTime; unsigned int ms = m_timer->getMilliseconds() - rec.startTime;
Log(EInfo, "Render time: %s", timeString(ms/1000.0f, true).c_str()); Log(EInfo, "Render time: %s", timeString(ms/1000.0f, true).c_str());

View File

@ -451,8 +451,8 @@ void Scene::cancel() {
m_integrator->cancel(); m_integrator->cancel();
} }
void Scene::flush() { void Scene::flush(RenderQueue *queue, const RenderJob *job) {
m_sensor->getFilm()->develop(); m_sensor->getFilm()->develop(this, queue->getRenderTime(job));
} }
void Scene::setDestinationFile(const fs::path &name) { void Scene::setDestinationFile(const fs::path &name) {
@ -467,7 +467,7 @@ void Scene::postprocess(RenderQueue *queue, const RenderJob *job,
int sceneResID, int sensorResID, int samplerResID) { int sceneResID, int sensorResID, int samplerResID) {
m_integrator->postprocess(this, queue, job, sceneResID, m_integrator->postprocess(this, queue, job, sceneResID,
sensorResID, samplerResID); sensorResID, samplerResID);
m_sensor->getFilm()->develop(); m_sensor->getFilm()->develop(this, queue->getRenderTime(job));
} }
void Scene::addChild(const std::string &name, ConfigurableObject *child) { void Scene::addChild(const std::string &name, ConfigurableObject *child) {

View File

@ -196,7 +196,6 @@ void SceneHandler::startElement(const XMLCh* const xmlName,
ParseContext context((name == "scene") ? NULL : &m_context.top()); ParseContext context((name == "scene") ? NULL : &m_context.top());
/* Convert attributes to ISO-8859-1 */
for (size_t i=0; i<xmlAttributes.getLength(); i++) { for (size_t i=0; i<xmlAttributes.getLength(); i++) {
std::string attrValue = transcode(xmlAttributes.getValue(i)); std::string attrValue = transcode(xmlAttributes.getValue(i));
if (attrValue.length() > 0 && attrValue.find('$') != attrValue.npos) { if (attrValue.length() > 0 && attrValue.find('$') != attrValue.npos) {
@ -208,7 +207,7 @@ void SceneHandler::startElement(const XMLCh* const xmlName,
++pos; ++pos;
} }
} }
if (attrValue.find('$') != attrValue.npos) if (attrValue.find('$') != attrValue.npos && attrValue.find('[') == attrValue.npos)
XMLLog(EError, "The scene referenced an undefined parameter: \"%s\"", attrValue.c_str()); XMLLog(EError, "The scene referenced an undefined parameter: \"%s\"", attrValue.c_str());
} }