Commit f8433075 authored by Hossain Mahmud's avatar Hossain Mahmud Committed by Christian Schulte zu Berge
Browse files

Added test class for ConcurrentHistrogram and GlReduction, GlReduction needs massive review

parent b6aa8f03
......@@ -35,7 +35,7 @@ namespace campvis {
/**
* Generic implementation of thread-safe n-D histograms.
* After successfull creation ConcurrentGenericHistogramND ensures:
* After successful creation ConcurrentGenericHistogramND ensures:
* * Calling addSample() is thread-safe.
*
* \tparam T Base data type of the histogram elements
......
......@@ -43,16 +43,24 @@ namespace campvis {
const std::string GlReduction::loggerCat_ = "CAMPVis.modules.registration.GlReduction";
GlReduction::GlReduction(ReductionOperator reductionOperator)
GlReduction::GlReduction(ReductionOperator reductionOperator, bool isForTesting)
: _reductionOperator(reductionOperator)
, _shader1d(0)
, _shader2d(0)
, _shader3d(0)
, _fbo(0)
{
_shader1d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_1D\n");
_shader2d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_2D\n");
_shader3d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_3D\n");
//TODO: discuss details, and generalize this
if(!isForTesting) {
_shader1d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_1D\n");
_shader2d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_2D\n");
_shader3d = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_3D\n");
}
else {
_shader1d = ShdrMgr.load("../src/core/glsl/passthrough.vert", "../src/core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_1D\n");
_shader2d = ShdrMgr.load("../src/core/glsl/passthrough.vert", "../src/core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_2D\n");
_shader3d = ShdrMgr.load("../src/core/glsl/passthrough.vert", "../src/core/glsl/tools/glreduction.frag", generateGlslHeader(_reductionOperator) + "#define REDUCTION_3D\n");
}
if (_shader1d == 0 || _shader2d == 0 || _shader3d == 0) {
LERROR("Could not load Shader for OpenGL reduction. Reduction will not work!");
return;
......
......@@ -63,7 +63,7 @@ namespace campvis {
* Constructor
* \param reductionOperator Operation to be performed by reduction
*/
GlReduction(ReductionOperator reductionOperator);
GlReduction(ReductionOperator reductionOperator, bool isForTesting = false);
/**
* Destructor
......
......@@ -41,8 +41,8 @@
namespace campvis {
/**
* Struct for handling void pointers slightly more typesafe.
* Therfore it stores an enum value together with the pointer for deducing its data type.
* Struct for handling void pointers slightly more type safe.
* Therefore it stores an enum value together with the pointer for deducing its data type.
* \note WeaklyTypedPointer takes _not_ take ownership of its pointer, hence it won't take care of deleting it!
*/
struct CAMPVIS_CORE_API WeaklyTypedPointer {
......@@ -62,7 +62,7 @@ namespace campvis {
/**
* Returns the number of bytes occupied by one element of the type \a bt with \a numChannels channels.
*
* \note There is a compiletime version in WeaklyTypedPointerTraits.
* \note There is a compile time version in WeaklyTypedPointerTraits.
* \sa WeaklyTypedPointerTraits::numBytes()
* \param bt Image base type
* \param numChannels Number of channels per element.
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// 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.
//
// ================================================================================================
/**
* Author: Hossain Mahmud <mahmud@in.tum.de>
* Date: April 2014
*/
#include "gtest/gtest.h"
#include "core/tools/concurrenthistogram.h"
#include <tbb/tbb.h>
using namespace campvis;
/**
* Test class for ConcurrentGenericHistogramND. Initializes a uniform distribution
* over ND dimensional space. Buckets are chosen in each unit, i.e. number of buckets
* is range+1.
*/
template<size_t ND>
class ConcurrentHistogramND {
protected:
ConcurrentHistogramND()
{
max = new int[ND];
min = new int[ND];
numBuckets = new size_t[ND];
for (int i = 0; i < ND; i++) { min[i] = 0; }
for (int i = 0; i < ND; i++) { max[i] = 100; }
for (int i = 0; i < ND; i++) {
numBuckets[i] = max[i] - min[i] + 1;
}
numSamples = static_cast<int>(pow(max[0]-min[0]+1, ND));
initSamples();
histogram = new int[static_cast<int>(pow(max[0]-min[0]+1, ND))];
computeHistogram();
_cgh = new campvis::ConcurrentGenericHistogramND<int, ND>(min, max, numBuckets);
}
~ConcurrentHistogramND() {
delete max;
delete min;
delete numBuckets;
delete histogram;
}
virtual void SetUp() {
}
virtual void TearDown() {
}
void initSamples() {
int range = max[0] - min[0] + 1;
for(int i = 0; i < numSamples; i++) {
std::vector<int> sample;
int x = i;
for(int j = ND-1; j >= 0; j--) {
sample.push_back(x / static_cast<int>(pow(range, j)));
x = x % static_cast<int>(pow(range, j));
}
samples.push_back(sample);
}
}
void computeHistogram() {
for (int i = 0; i < numSamples; i++) {
histogram[i] = 1;
}
}
int getND() {return ND;}
protected:
int *max, *min;
size_t *numBuckets;
campvis::ConcurrentGenericHistogramND<int, ND>* _cgh;
int numSamples;
std::vector<std::vector<int> > samples;
int *histogram;
};
/**
* Test class 1D system.
*/
class ConcurrentHistogram1DTest : public ConcurrentHistogramND<1>, public ::testing::Test {
public:
ConcurrentHistogram1DTest() {
}
};
/**
* Expected number of elements at each bucket should be 1
*/
TEST_F(ConcurrentHistogram1DTest, concurrentAddSampleTest) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, samples.size()), [&] (const tbb::blocked_range<size_t>& range) {
for (size_t i = range.begin(); i != range.end(); ++i) {
std::vector<int> vec = samples[i];
int value[10];
for (int k = 0; k < getND(); k++) {
value[k] = vec[k];
}
_cgh->addSample(&(samples[i].front()));
}
});
for (int i = 0; i < getND(); i++) {
for(int j = 0; j < numBuckets[i]; j ++) {
EXPECT_EQ(histogram[i], _cgh->getNumElements(j));
}
}
}
/**
* Test class 2D system.
*/
class ConcurrentHistogram2DTest : public ConcurrentHistogramND<2>, public ::testing::Test {
public:
ConcurrentHistogram2DTest() {
}
};
/**
* Expected number of elements at each bucket should be 1
*/
TEST_F(ConcurrentHistogram2DTest, concurrentAddSampleTest) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, samples.size()), [&] (const tbb::blocked_range<size_t>& range) {
for (size_t i = range.begin(); i != range.end(); ++i) {
std::vector<int> vec = samples[i];
int value[10];
for (int k = 0; k < getND(); k++) {
value[k] = vec[k];
}
_cgh->addSample(&(samples[i].front()));
}
});
for (int i = 0; i < getND(); i++) {
for(int j = 0; j < numBuckets[i]; j ++) {
EXPECT_EQ(histogram[i], _cgh->getNumElements(j));
}
break;
}
}
\ No newline at end of file
......@@ -24,84 +24,128 @@
/**
* Author: Hossain Mahmud <mahmud@in.tum.de>
* Date: March 2014
* Date: April 2014
*/
#include "gtest/gtest.h"
#include "core/datastructures/renderdata.h"
#include "core/tools/glreduction.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include "tgt/framebufferobject.h"
using namespace campvis;
class RenderDataTest : public testing::Test {
/**
* Test class for GlReduction. Creates an ImageData with a local representation
* and known data. Then compares the output of GlReduction::reduce() with
* expected values.
*/
class GlReductionTest : public ::testing::Test {
protected:
RenderDataTest() {
//_fbo = new tgt::FramebufferObject();
//_fbo->attachTexture();
//_renderData1 = campvis::RenderData(_fbo);
//_renderData2 = campvis::RenderData(_fbo);
//_renderData3 = campvis::RenderData(_fbo);
GlReductionTest() {
name = new tgt::FramebufferObject();
width = 10;
height = 10;
depth = 1;
rawData = new float[width * height * depth];
initData(rawData, width * height * depth);
imgData = new ImageData(2, tgt::svec3(width, height, depth), 1);
localRep = ImageRepresentationLocal::create(imgData, WeaklyTypedPointer(WeaklyTypedPointer::BaseType::FLOAT, 1, rawData));
glReduction = nullptr;
}
~RenderDataTest() {
//delete _fbo;
~GlReductionTest() {
//delete localRep;
delete imgData;
//delete rawData;
delete glReduction;
}
// If the constructor and destructor are not enough for setting up
// and cleaning up each test, you can define the following two methods
virtual void SetUp() {
}
virtual void TearDown() {
}
void initData(float* data, int size) {
memset(data, 0x0F, sizeof(float)*size);
data[0] = 1;
}
protected:
//campvis::RenderData _renderData1, _renderData2, _renderData3;
tgt::FramebufferObject* _fbo;
};
tgt::FramebufferObject *name;
TEST_F(RenderDataTest, getLocalMemoryFootprintTest) {
SUCCEED();
}
TEST_F(RenderDataTest, getVideoMemoryFootprintTest) {
SUCCEED();
}
TEST_F(RenderDataTest, cloneTest) {
}
TEST_F(RenderDataTest, getNumColorTexturesTest) {
}
int width, height, depth;
float* rawData;
ImageData* imgData;
ImageRepresentationLocal *localRep;
TEST_F(RenderDataTest, getColorTextureTest) {
}
GlReduction* glReduction;
};
TEST_F(RenderDataTest, getColorDataHandleTest) {
/**
* Checks whether the OpenGL context is valid here.
*/
TEST_F(GlReductionTest, isScopedLockWorking) {
if(name->getId() != 0){
SUCCEED();
} else
FAIL();
}
TEST_F(RenderDataTest, hasDepthTextureTest) {
/**
* Checks whether the local representation is valid.
*/
TEST_F(GlReductionTest, localRepCreationTest) {
EXPECT_NE(nullptr, localRep);
}
TEST_F(RenderDataTest, getDepthTextureTest) {
}
/**
* Tests for ReducationOperator::MIN.
*/
TEST_F(GlReductionTest, minTest) {
glReduction = new GlReduction(GlReduction::ReductionOperator::MIN, true);
std::vector<float> reduced = glReduction->reduce(imgData);
TEST_F(RenderDataTest, getDepthDataHandleTest) {
ASSERT_NEAR(0, reduced[0], 0.0001);
ASSERT_NEAR(0, reduced[1], 0.0001);
}
TEST_F(RenderDataTest, addColorTextureTest) {
}
/**
* Tests for ReducationOperator::MAX.
*/
TEST_F(GlReductionTest, maxTest) {
glReduction = new GlReduction(GlReduction::ReductionOperator::MAX, true);
std::vector<float> reduced = glReduction->reduce(imgData);
TEST_F(RenderDataTest, setDepthTextureTest) {
ASSERT_NEAR(1, reduced[0], 0.0001);
ASSERT_NEAR(0, reduced[1], 0.0001);
}
TEST_F(RenderDataTest, bindColorTextureTest) {
}
/**
* Tests for ReducationOperator::PLUS.
*/
TEST_F(GlReductionTest, sumTest) {
glReduction = new GlReduction(GlReduction::ReductionOperator::PLUS, true);
std::vector<float> reduced = glReduction->reduce(imgData);
TEST_F(RenderDataTest, bindDepthTextureTest) {
ASSERT_NEAR(1, reduced[0], 0.0001);
ASSERT_NEAR(0, reduced[1], 0.0001);
}
TEST_F(RenderDataTest, bindTest) {
}
/**
* Tests for ReducationOperator::MULTIPLICATION.
*/
TEST_F(GlReductionTest, multTest) {
glReduction = new GlReduction(GlReduction::ReductionOperator::MULTIPLICATION, true);
std::vector<float> reduced = glReduction->reduce(imgData);
ASSERT_NEAR(0, reduced[0], 0.0001);
ASSERT_NEAR(0, reduced[1], 0.0001);
}
\ No newline at end of file
......@@ -29,7 +29,7 @@
#include "gtest/gtest.h"
#include "core/tools//stringutils.h"
#include "core/tools/stringutils.h"
using namespace campvis;
......
......@@ -98,21 +98,13 @@ void init() {
if (GpuCaps.getShaderVersion() < tgt::GpuCapabilities::GlVersion::SHADER_VERSION_330) {
LERROR("Your system does not support GLSL Shader Version 3.30, which is mandatory. CAMPVis will probably not work as intended.");
}
/**?
* had to change macro in original file, else OpenGLJobProcessor is not known here
* unless "using" statement is written on the top.
*/
GLJobProc.start();
GLJobProc.registerContext(_localContext);
_initialized = true;
}
void deinit() {
tgtAssert(_initialized, "Tried to deinitialize uninitialized CampVisApplication.");
GLJobProc.stop();
/**?
* Grrrrrrrrrrrrrrrr :#
......@@ -146,10 +138,14 @@ GTEST_API_ int main(int argc, char **argv) {
app = new QApplication(argc, argv);
testing::InitGoogleTest(&argc, argv);
init();
int ret;
int ret= RUN_ALL_TESTS();
init();
{
tgt::GLContextScopedLock lock(_localContext);
ret= RUN_ALL_TESTS();
}
deinit();
//getchar();
......
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