Saxum/extern/acgl/include/ACGL/OpenGL/Objects/Query.hh
2014-10-20 17:31:26 +02:00

190 lines
6.0 KiB
C++

/***********************************************************************
* Copyright 2011-2012 Computer Graphics Group RWTH Aachen University. *
* All rights reserved. *
* Distributed under the terms of the MIT License (see LICENSE.TXT). *
**********************************************************************/
#ifndef ACGL_OPENGL_OBJECTS_QUERY_HH
#define ACGL_OPENGL_OBJECTS_QUERY_HH
#include <ACGL/ACGL.hh>
#include <ACGL/Base/Macros.hh>
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>
#ifndef ACGL_OPENGLES_VERSION_20
namespace ACGL{
namespace OpenGL{
/**
* A generic OpenGL asynchronous query, target types can be:
* SAMPLES_PASSED
* ANY_SAMPLES_PASSED
* PRIMITIVES_GENERATED
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
* TIME_ELAPSED
*
* See specialized queries below.
*
* Note: * Indexed queries are not jet supported.
* * Only one query per type is alowed to be active at any time.
* * Before the result can get read out, the query must end() !
*/
class AsynchronousQuery {
public:
AsynchronousQuery( GLenum _defaultTarget )
: mTarget(_defaultTarget)
{
glGenQueries( 1, &mObjectName );
}
virtual ~AsynchronousQuery() {
glDeleteQueries( 1, &mObjectName );
}
//! start the query, only one query per type is allowed to be active at any time.
void begin(void) {
glBeginQuery( mTarget, mObjectName );
}
//! end the query
void end(void) {
glEndQuery( mTarget );
}
//! returns true if the result of the query is available, if not, trying to get the result will stall the CPU
GLboolean isResultAvailable(void) {
GLint resultAvailable;
glGetQueryObjectiv(mObjectName, GL_QUERY_RESULT_AVAILABLE, &resultAvailable);
return (GLboolean) resultAvailable;
}
//! get the query result, what it is depents on the query target
GLuint getResult(void) {
GLuint queryResult;
glGetQueryObjectuiv( mObjectName, GL_QUERY_RESULT, &queryResult );
return queryResult;
}
//! get the query result in 64 bit, what it is depents on the query target
GLuint64 getResult64(void) {
#if (ACGL_OPENGL_VERSION >= 33)
GLuint64 queryResult;
glGetQueryObjectui64v( mObjectName, GL_QUERY_RESULT, &queryResult );
return queryResult;
#else
return (GLuint64) getResult(); // default to 32 bit version on pre GL 3.3 systems
#endif
}
//! returns the raw object name to be used directly in OpenGL functions
inline GLuint getObjectName(void) const { return mObjectName; }
protected:
GLuint mObjectName;
GLenum mTarget;
};
ACGL_SMARTPOINTER_TYPEDEFS(AsynchronousQuery)
/**
* Occlusion queries count the fragments that pass the z-test.
*
* There are two variants:
* GL_SAMPLES_PASSED - will count the fragments
* GL_ANY_SAMPLES_PASSED - will just tell whether fragments have passed the z-test, not how many (0 or any number)
*/
class OcclusionQuery : public AsynchronousQuery {
public:
OcclusionQuery() : AsynchronousQuery( GL_SAMPLES_PASSED ) {}
OcclusionQuery( GLenum _queryType ) : AsynchronousQuery( _queryType ) {
setType( _queryType );
}
//! _queryType has to be GL_SAMPLES_PASSED or GL_ANY_SAMPLES_PASSED
void setType( GLenum _queryType ) {
#if (ACGL_OPENGL_VERSION >= 33)
if (_queryType == GL_ANY_SAMPLES_PASSED) _queryType = GL_SAMPLES_PASSED; // GL_ANY_SAMPLES_PASSED is OpenGL 3.3 or later! But GL_SAMPLES_PASSED is a good substitute
#endif
if (_queryType != GL_SAMPLES_PASSED) {
Utils::error() << "OcclusionQuery type " << _queryType << " not supported" << std::endl;
_queryType = GL_SAMPLES_PASSED;
}
mTarget = _queryType;
}
//! get the actual number of fragments, unless the type is GL_ANY_SAMPLES_PASSED, than it only tells 0 or any value
GLuint samplesPassed(void) {
return getResult();
}
};
ACGL_SMARTPOINTER_TYPEDEFS(OcclusionQuery)
#if (ACGL_OPENGL_VERSION >= 33)
/**
* TimerQueries can get the GPU timestamp and measure GPU execution speed.
*
* Only available since OpenGL 3.3 or GL_ARB_timer_query (on OpenGL 3.2)
*/
class TimerQuery : public AsynchronousQuery {
public:
TimerQuery() : AsynchronousQuery( GL_TIME_ELAPSED ) {}
//! Mark the moment in the pipeline of which the time should get queried.
void saveTimestamp(void) {
glQueryCounter( mObjectName, GL_TIMESTAMP );
}
//! Get the current GPU timestamp.
GLint64 getCurrentTimestamp(void) {
GLint64 time;
glGetInteger64v( GL_TIMESTAMP, &time );
return time;
}
//! Get the timestamp saved by 'saveTimestamp'.
GLuint64 getSavedTimestamp(void) {
return getResult64();
}
};
ACGL_SMARTPOINTER_TYPEDEFS(TimerQuery)
#endif // OpenGL >= 3.3
#if (ACGL_OPENGL_VERSION >= 31)
/**
* Primitive queries count the number of processed geometry. Sounds trivial as the app should
* know the number from the glDraw* calls, but this query will also count geometry generated
* by geometry/tessellation shaders.
*
* During transform feedback let one query of each type run and compare the results: if more
* primitives were generated than written to the TF buffer, the buffer overflowd.
*/
class PrimitiveQuery : public AsynchronousQuery {
public:
PrimitiveQuery() : AsynchronousQuery( GL_PRIMITIVES_GENERATED ) {}
PrimitiveQuery( GLenum _queryType ) : AsynchronousQuery( _queryType ) {
setType( _queryType );
}
//! _queryType has to be GL_PRIMITIVES_GENERATED or GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
void setType( GLenum _queryType ) {
if ((_queryType != GL_PRIMITIVES_GENERATED) && (_queryType != GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)) {
Utils::error() << "PrimitiveQuery type " << _queryType << " not supported" << std::endl;
_queryType = GL_PRIMITIVES_GENERATED;
}
mTarget = _queryType;
}
};
ACGL_SMARTPOINTER_TYPEDEFS(PrimitiveQuery)
#endif // OpenGL >= 3.1
} // OpenGL
} // ACGL
#endif // ES 2.0
#endif // ACGL_OPENGL_OBJECTS_QUERY_HH