Commit 232d1722 authored by schultezub's avatar schultezub

* made Processor execution time measurement runtime-configurable

* fixed transfer function shader
* let processor unlock call after execution be handled by seperate thread

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@494 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent dffa84eb
......@@ -38,7 +38,8 @@ namespace campvis {
namespace {
const int COLUMN_NAME = 0;
const int COLUMN_ENABLED_STATE = 1;
const int COLUMN_DESCRIPTION = 2;
const int COLUMN_CLOCK_STATE = 2;
const int COLUMN_DESCRIPTION = 3;
}
// = TreeModel items ==============================================================================
......@@ -102,6 +103,8 @@ namespace campvis {
case Qt::CheckStateRole:
if (column == COLUMN_ENABLED_STATE)
return _processor->getEnabled() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked);
else if (column == COLUMN_CLOCK_STATE)
return _processor->getClockExecutionTime() ? QVariant(Qt::Checked) : QVariant(Qt::Unchecked);
else
return QVariant();
case Qt::UserRole:
......@@ -121,6 +124,12 @@ namespace campvis {
return true;
}
}
else if (column == COLUMN_CLOCK_STATE) {
if (role == Qt::CheckStateRole) {
_processor->setClockExecutionTime(value == Qt::Checked ? true : false);
return true;
}
}
return false;
}
......@@ -136,6 +145,8 @@ namespace campvis {
return QVariant(QString("Description"));
else if (column == COLUMN_ENABLED_STATE)
return QVariant(QString("Enabled"));
else if (column == COLUMN_CLOCK_STATE)
return QVariant(QString("Clock"));
}
return QVariant();
......@@ -184,6 +195,8 @@ namespace campvis {
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
case COLUMN_ENABLED_STATE:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
case COLUMN_CLOCK_STATE:
return QAbstractItemModel::flags(index) | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
}
return 0;
......@@ -241,7 +254,7 @@ namespace campvis {
}
int PipelineTreeModel::columnCount(const QModelIndex &parent /*= QModelIndex()*/) const {
return 3;
return 4;
}
void PipelineTreeModel::setData(const std::vector<AbstractPipeline*>& pipelines) {
......
......@@ -43,9 +43,9 @@ struct TFParameters2D {
*/
float mapIntensityToTFDomain(in vec2 intensityDomain, in float intensity) {
if(intensity < intensityDomain.x)
return 0.0;
return -1.0;
else if(intensity > intensityDomain.y)
return 1.0;
return -1.0;
else
return (intensity - intensityDomain.x) / (intensityDomain.y - intensityDomain.x);
}
......
......@@ -88,7 +88,7 @@ namespace campvis {
void AbstractPipeline::onProcessorInvalidated(AbstractProcessor* processor) {
if (processor->getEnabled())
SimpleJobProc.enqueueJob(makeJob(this, &AbstractPipeline::executeProcessor, processor));
SimpleJobProc.enqueueJob(makeJob(this, &AbstractPipeline::executeProcessor, processor, false));
s_PipelineInvalidated();
}
......@@ -101,14 +101,13 @@ namespace campvis {
return _data;
}
void AbstractPipeline::executeProcessor(AbstractProcessor* processor) {
void AbstractPipeline::executeProcessor(AbstractProcessor* processor, bool unlockInExtraThred) {
tgtAssert(processor != 0, "Processor must not be 0.");
if (processor->getEnabled() && !processor->isLocked() && processor->hasInvalidResult()) {
processor->lockProcessor();
#ifdef CAMPVIS_DEBUG
clock_t startTime = clock();
#endif
try {
processor->process(_data);
}
......@@ -119,14 +118,17 @@ namespace campvis {
LERROR("Caught unhandled exception while executing processor " << processor->getName() << ": unknown exception");
}
#ifdef CAMPVIS_DEBUG
clock_t endTime = clock();
#endif
processor->unlockProcessor();
if (processor->getClockExecutionTime()) {
clock_t endTime = clock();
LDEBUG("Executed processor " << processor->getName() << " duration: " << (endTime - startTime));
}
#ifdef CAMPVIS_DEBUG
LDEBUG("Executed processor " << processor->getName() << " duration: " << (endTime - startTime));
#endif
// Unlocking processors might be expensive, since a long chain of invalidations might be started
// -> do this in another thread...
if (unlockInExtraThred)
SimpleJobProc.enqueueJob(makeJob(processor, &AbstractProcessor::unlockProcessor));
else
processor->unlockProcessor();
}
}
......
......@@ -152,8 +152,9 @@ namespace campvis {
/**
* Executes the processor \a processor on the pipeline's data and locks its properties meanwhile.
* \param processor Processor to execute.
* \param unlockInExtraThred If true, the call to processor->unlock() will be done in an extra thread.
*/
void executeProcessor(AbstractProcessor* processor);
void executeProcessor(AbstractProcessor* processor, bool unlockInExtraThred);
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
......
......@@ -41,6 +41,7 @@ namespace campvis {
: HasPropertyCollection()
{
_enabled = true;
_clockExecutionTime = false;
_locked = 0;
_level = VALID;
}
......@@ -116,5 +117,13 @@ namespace campvis {
s_validated(this);
}
bool AbstractProcessor::getClockExecutionTime() const {
return _clockExecutionTime;
}
void AbstractProcessor::setClockExecutionTime(bool value) {
_clockExecutionTime = value;
}
}
......@@ -123,6 +123,18 @@ namespace campvis {
* \param enabled New flag whether this processor is currently enabled.
*/
void setEnabled(bool enabled);
/**
* Returns whether to measure the execution time of this processor.
* \return _clockExecutionTime
*/
bool getClockExecutionTime() const;
/**
* Sets whether to measure the execution time of this processor.
* \param value The new flag vlaue whether to measure the execution time of this processor.
*/
void setClockExecutionTime(bool value);
/**
*
......@@ -245,6 +257,7 @@ namespace campvis {
protected:
tbb::atomic<bool> _enabled; ///< flag whether this processor is currently enabled
tbb::atomic<bool> _clockExecutionTime; ///< flag whether to measure the execution time of this processor
/// Flag whether this processor is currently locked
/// (This implies, that all properties are locked and it is not valid to call process())
......
......@@ -138,11 +138,11 @@ namespace campvis {
if (node->second->_isVisualizationProcessor) {
GLJobProc.enqueueJob(
_canvas,
makeJobOnHeap<DigraphVisualizationPipeline, AbstractProcessor*>(this, &DigraphVisualizationPipeline::executeProcessor, processor),
makeJobOnHeap<DigraphVisualizationPipeline, AbstractProcessor*, bool>(this, &DigraphVisualizationPipeline::executeProcessor, processor, true),
OpenGLJobProcessor::SerialJob);
}
else {
SimpleJobProc.enqueueJob(makeJob<DigraphVisualizationPipeline, AbstractProcessor*>(this, &DigraphVisualizationPipeline::executeProcessor, processor));
SimpleJobProc.enqueueJob(makeJob<DigraphVisualizationPipeline, AbstractProcessor*, bool>(this, &DigraphVisualizationPipeline::executeProcessor, processor, false));
}
}
else {
......
......@@ -127,7 +127,7 @@ namespace campvis {
tgtAssert(_canvas != 0, "Set a valid canvas before calling this method!");
GLJobProc.enqueueJob(
_canvas,
makeJobOnHeap<VisualizationPipeline, AbstractProcessor*>(this, &VisualizationPipeline::executeProcessor, processor),
makeJobOnHeap<VisualizationPipeline, AbstractProcessor*, bool>(this, &VisualizationPipeline::executeProcessor, processor, true),
OpenGLJobProcessor::SerialJob);
}
......@@ -185,7 +185,7 @@ namespace campvis {
OpenGLJobProcessor::SerialJob);
}
else {
SimpleJobProc.enqueueJob(makeJob<VisualizationPipeline, AbstractProcessor*>(this, &VisualizationPipeline::executeProcessor, processor));
SimpleJobProc.enqueueJob(makeJob<VisualizationPipeline, AbstractProcessor*, bool>(this, &VisualizationPipeline::executeProcessor, processor, false));
}
}
else {
......@@ -200,7 +200,7 @@ namespace campvis {
}
void VisualizationPipeline::executeProcessorAndCheckOpenGLState(AbstractProcessor* processor) {
AbstractPipeline::executeProcessor(processor);
AbstractPipeline::executeProcessor(processor, true);
#ifdef CAMPVIS_DEBUG
// tgtAssert(getGlBool(GL_DEPTH_TEST) == false, "Invalid OpenGL state after processor execution, GL_DEPTH_TEST != false.");
......
......@@ -167,18 +167,60 @@ namespace campvis {
void (*_callee)(A1); ///< Function to call
A1 _arg1; ///< Argument to pass to \a callee
};
/**
* Specific job, that is calling a member function pasing a single argument.
*/
template<class A1, class A2>
class CallFunc2ArgJob : public AbstractJob {
template<class T, class A1, class A2>
class CallMemberFunc2ArgJob : public AbstractJob {
public:
/**
* Creates an new job, that is calling \a callee on \a target pasing \a arg1 as single argument.
* Creates an new job, that is calling \a callee on \a target pasing \a arg1 and \a arg2 as arguments.
* \param target Target object
* \param callee Member function to call
* \param arg1 Argument to pass to \a callee
* \param arg1 First argument to pass to \a callee
* \param arg2 Second argument to pass to \a callee
*/
CallMemberFunc2ArgJob(T* target, void (T::*callee)(A1, A2), A1 arg1, A2 arg2)
: _target(target)
, _callee(callee)
, _arg1(arg1)
, _arg2(arg2)
{
tgtAssert(_target != 0, "Target object must not be 0.");
tgtAssert(_callee != 0, "Target member function pointer must not be 0.");
}
/**
* Destructor, nothing to do here
*/
~CallMemberFunc2ArgJob() {};
/**
* Executes this job by calling the member function.
*/
virtual void execute() {
(_target->*_callee)(_arg1, _arg2);
}
protected:
T* _target; ///< Target object
void (T::*_callee)(A1, A2); ///< Member function to call
A1 _arg1; ///< First argument to pass to \a callee
A2 _arg2; ///< Second argument to pass to \a callee
};
/**
* Specific job, that is calling a function passing two arguments.
*/
template<class A1, class A2>
class CallFunc2ArgJob : public AbstractJob {
public:
/**
* Creates an new job, that is calling \a callee passing \a arg1 and \a arg2 as arguments.
* \param callee Function to call
* \param arg1 First argument to pass to \a callee
* \param arg2 Second argument to pass to \a callee
*/
CallFunc2ArgJob(void (*callee)(A1, A2), A1 arg1, A2 arg2)
: _callee(callee)
......@@ -194,14 +236,14 @@ namespace campvis {
~CallFunc2ArgJob() {};
/**
* Executes this job by calling the member function.
* Executes this job by calling the function.
*/
virtual void execute() {
(*_callee)(_arg1, _arg2);
}
protected:
void (*_callee)(A1, A2); ///< Function to call
void (*_callee)(A1, A2); ///< Function to call
A1 _arg1; ///< First Argument to pass to \a callee
A2 _arg2; ///< Second Argument to pass to \a callee
};
......@@ -281,6 +323,31 @@ namespace campvis {
return CallFunc1ArgJob<A1>(callee, arg1);
}
/**
* Creates a new CallMemberFunc1ArgJob on the heap for the object \a target.
* \note The caller takes ownership of the returned pointer.
* \param target Target object to call method from.
* \param callee Pointer to method to call.
* \param arg1 First argument to pass to \callee.
* \return Pointer to the newly created CallMemberFunc1ArgJob. Caller has ownership!
*/
template<class T, class A1, class A2>
CallMemberFunc2ArgJob<T, A1, A2>* makeJobOnHeap(T* target, void (T::*callee)(A1, A2), A1 arg1, A2 arg2) {
return new CallMemberFunc2ArgJob<T, A1, A2>(target, callee, arg1, arg2);
}
/**
* Creates a new CallMemberFunc1ArgJob on the stack for the object \a target.
* \param target Target object to call method from.
* \param callee Pointer to method to call.
* \param arg1 First argument to pass to \callee.
* \return The newly created CallMemberFunc1ArgJob.
*/
template<class T, class A1, class A2>
CallMemberFunc2ArgJob<T, A1, A2> makeJob(T* target, void (T::*callee)(A1, A2), A1 arg1, A2 arg2) {
return CallMemberFunc2ArgJob<T, A1, A2>(target, callee, arg1, arg2);
}
/**
* Creates a new CallFunc2ArgJob on the heap for the object \a target.
* \note The caller takes ownership of the returned pointer.
......
......@@ -152,7 +152,7 @@ namespace campvis {
ss << p_sourcePath.getValue() << "\\" << "export" << std::setfill('0') << std::setw(4) << path << ".bmp";
_usReader.p_url.setValue(ss.str());
executeProcessor(&_usReader);
executeProcessor(&_usReader, false);
DataHandle dh = _data.getData(_usReader.p_targetImageID.getValue());
if (dh.getData() != 0) {
......@@ -161,11 +161,11 @@ namespace campvis {
}
}
executeProcessor(&_confidenceGenerator);
executeProcessor(&_usBlurFilter);
executeProcessor(&_confidenceGenerator, false);
executeProcessor(&_usBlurFilter, false);
_usFusion.p_view.selectById("mappingLAB");
executeProcessor(&_usFusion);
executeProcessor(&_usFusion, false);
save(path, p_targetPathColor.getValue());
// _usFusion.p_view.selectById("mappingSharpness");
......
......@@ -115,7 +115,7 @@ vec4 performRaycasting(in vec3 entryPoint, in vec3 exitPoint, in vec2 texCoords)
float formerT = t - _samplingStepSize;
// we just left the void, perform intersection refinement
for (float stepPower = 0.5; stepPower > 0.05; stepPower /= 2.0) {
for (float stepPower = 0.5; stepPower > 0.1; stepPower /= 2.0) {
// compute refined sample position
float newT = formerT + _samplingStepSize * stepPower;
vec3 newSamplePosition = entryPoint.rgb + newT * direction;
......
......@@ -72,10 +72,10 @@ namespace campvis {
_imageReader.p_targetImageID.setValue("reader.output");
_imageReader.p_targetImageID.connect(&_vr.p_inputVolume);
// Geometry1DTransferFunction* dvrTF = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .05f));
// dvrTF->addGeometry(TFGeometry1D::createQuad(tgt::vec2(.4f, .42f), tgt::col4(255, 0, 0, 255), tgt::col4(255, 0, 0, 255)));
// dvrTF->addGeometry(TFGeometry1D::createQuad(tgt::vec2(.45f, .5f), tgt::col4(0, 255, 0, 255), tgt::col4(0, 255, 0, 255)));
// _dvrNormal.p_transferFunction.replaceTF(dvrTF);
Geometry1DTransferFunction* dvrTF = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .05f));
dvrTF->addGeometry(TFGeometry1D::createQuad(tgt::vec2(.1f, .125f), tgt::col4(255, 0, 0, 32), tgt::col4(255, 0, 0, 32)));
dvrTF->addGeometry(TFGeometry1D::createQuad(tgt::vec2(.4f, .5f), tgt::col4(0, 255, 0, 128), tgt::col4(0, 255, 0, 128)));
static_cast<TransferFunctionProperty*>(_vr.getProperty("transferFunction"))->replaceTF(dvrTF);
_trackballEH->setViewportSize(_effectiveRenderTargetSize.getValue());
_effectiveRenderTargetSize.s_changed.connect<VolumeRendererDemo>(this, &VolumeRendererDemo::onRenderTargetSizeChanged);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment