The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 9f3fff0d authored by Jakob Weiss's avatar Jakob Weiss
Browse files

Added basic support for OpenGL 4.3 Compute Shaders

* Adapted cgt::Shader to be able to represent and store CS objects
* cgt::ImageUnit manages the GPU image units in use
* GpuCapabilities has been updated for some related queries
* GLTextureFormatTraits simplify lookup of relevant info for a known internalFormat of a texture
parent a23b1e70
......@@ -98,7 +98,7 @@ namespace campvis {
// converting from GL representation
GenericImageRepresentationLocal<BASETYPE, NUMCHANNELS>* toReturn = nullptr;
GLJobProc.enqueueJobBlocking([&]() {
if (cgt::Texture::calcMatchingDataType(tester->getTexture()->getInternalFormat()) != TypeTraits<BASETYPE, NUMCHANNELS>::glDataType)
if (cgt::Texture::calcMatchingPixelDataType(tester->getTexture()->getInternalFormat()) != TypeTraits<BASETYPE, NUMCHANNELS>::glDataType)
LDEBUGC("CAMPVis.core.datastructures.GenericLocalConversion", "Performing conversion between data types, you may lose information or the resulting data may show other unexpected features.");
WeaklyTypedPointer wtp = tester->getWeaklyTypedPointerConvert(TypeTraits<BASETYPE, NUMCHANNELS>::glDataType);
......
......@@ -201,15 +201,15 @@ namespace campvis {
}
const WeaklyTypedPointer ImageRepresentationGL::getWeaklyTypedPointerCopy() const {
GLint format = cgt::Texture::calcMatchingFormat(_texture->getInternalFormat());
GLenum dataType = cgt::Texture::calcMatchingDataType(_texture->getInternalFormat());
GLint format = cgt::Texture::calcMatchingPixelFormat(_texture->getInternalFormat());
GLenum dataType = cgt::Texture::calcMatchingPixelDataType(_texture->getInternalFormat());
GLubyte* data = _texture->downloadTextureToBuffer(format, dataType);
return WeaklyTypedPointer(WeaklyTypedPointer::baseType(dataType), _texture->getNumChannels(), data);
}
const WeaklyTypedPointer ImageRepresentationGL::getWeaklyTypedPointerConvert(GLenum dataType) const {
GLint format = cgt::Texture::calcMatchingFormat(_texture->getInternalFormat());
GLint format = cgt::Texture::calcMatchingPixelFormat(_texture->getInternalFormat());
GLubyte* data = _texture->downloadTextureToBuffer(format, dataType);
return WeaklyTypedPointer(WeaklyTypedPointer::baseType(dataType), _texture->getNumChannels(), data);
......
......@@ -29,8 +29,10 @@ SET(CGT_SOURCES
frustum.cpp
glcanvas.cpp
glcontextmanager.cpp
gltextureformattraits.cpp
gpucapabilities.cpp
gpucapabilitieswindows.cpp
imageunit.cpp
init.cpp
logmanager.cpp
job.cpp
......
/**********************************************************************
* *
* cgt - CAMP Graphics Toolbox, Copyright (C) 2012-2015 *
* Chair for Computer Aided Medical Procedures *
* Technische Universitaet Muenchen, Germany. *
* <http://campar.in.tum.de/> *
* *
* forked from tgt - Tiny Graphics Toolbox, Copyright (C) 2006-2011 *
* Visualization and Computer Graphics Group, Department of *
* Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the cgt library. This library is free *
* software; you can redistribute it and/or modify it under the terms *
* of the GNU Lesser General Public License version 2.1 as published *
* by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License in the file "LICENSE.txt" along with this library. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
**********************************************************************/
#pragma once
#include <GL/glew.h>
#include <string>
namespace cgt {
class GLTextureFormatTraits {
public:
/// Constructor for unknown format
GLTextureFormatTraits(GLint internalFormat__)
: known_{ false }
, internalFormatName_{ "Unknown" }
, bpp_{ 0 }
, channels_{ 0 }
, internalFormat_{ internalFormat__ }
, pixelFormat_{ -1 }
, pixelDataType_{ -1 }
, glslFormatQualifier_{ "Unknown" }
{};
/// Constructor for known formats
GLTextureFormatTraits(GLint internalFormat__, const char* internalFormatName__, int bpp__, int channels__, GLint pixelFormat__, GLint pixelDataType__, const char* glslFormatQualifier__)
: internalFormatName_{ internalFormatName__ }
, known_{ true }
, bpp_{ bpp__ }
, channels_{ channels__ }
, internalFormat_{ internalFormat__ }
, pixelFormat_{ pixelFormat__ }
, pixelDataType_{ pixelDataType__ }
, glslFormatQualifier_{ glslFormatQualifier__ }
{};
static GLTextureFormatTraits get(GLint internalFormat);
/**
* Whether the specified GLint is a valid internal format
*/
bool known() const { return known_; };
/**
* The name of the macro as a string
*/
std::string internalFormatName() const { return internalFormatName_; } ;
/**
* Number of bytes per pixel
*/
int bpp() const { return bpp_; };
/**
* Number of channels (1-4)
*/
int channels() const { return channels_; };
/**
* GLint of the internal format
*/
GLint internalFormat() const { return internalFormat_; };
/**
* Matching pixel format (GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, GL_RED_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, GL_BGRA_INTEGER, GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL)
*/
GLint pixelFormat() const { return pixelFormat_; };
/**
* Matching pixel data type (GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV)
*/
GLint pixelDataType() const { return pixelDataType_; };
/**
* Matching write format qualifier for use in glsl with image read/write operations. (rgba32f, r16, r8u, ...)
*/
std::string glslFormatQualifier() const { return glslFormatQualifier_; };
private:
bool known_;
const std::string internalFormatName_;
const int bpp_;
const int channels_;
const GLint internalFormat_;
const GLint pixelFormat_;
const GLint pixelDataType_;
const std::string glslFormatQualifier_;
};
}; // namspace cgt
\ No newline at end of file
......@@ -107,6 +107,11 @@ bool GpuCapabilities::areShadersSupported() {
return shaderSupport_;
}
bool GpuCapabilities::areComputeShadersSupported()
{
return computeShaderSupport_;
}
bool GpuCapabilities::areShadersSupportedARB() {
return shaderSupportARB_;
}
......@@ -139,6 +144,11 @@ int GpuCapabilities::getNumTextureUnits() {
return numTextureUnits_;
}
int GpuCapabilities::getNumImageUnits()
{
return numImageUnits_;
}
bool GpuCapabilities::isNpotSupported() {
return npotTextures_;
}
......@@ -291,6 +301,7 @@ void GpuCapabilities::detectCapabilities() {
shaderSupport_ = (glVersion_ >= GlVersion::CGT_GL_VERSION_2_0);
shaderSupportARB_ = (isExtensionSupported("GL_ARB_vertex_program") &&
isExtensionSupported("GL_ARB_fragment_program"));
computeShaderSupport_ = (glVersion_ >= GlVersion::CGT_GL_VERSION_4_3);
if (!shaderVersion_.parseVersionString(glslVersionString_)) {
LERROR("Malformed GLSL version string: " << glslVersionString_);
......@@ -336,6 +347,8 @@ void GpuCapabilities::detectCapabilities() {
if (numTextureUnits_ < 0)
glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *) &numTextureUnits_);
glGetIntegerv(GL_MAX_IMAGE_UNITS, (GLint*)&numImageUnits_);
npotTextures_ = (isExtensionSupported("GL_ARB_texture_non_power_of_two"));
#if defined(__APPLE__) || defined(__linux__)
// No NPOT support on older ATI Macs and Linux.
......
......@@ -258,13 +258,19 @@ public:
std::string getShadingLanguageVersionString();
/**
* Returns wether shaders are supported, which
* Returns whether shaders are supported, which
* is true for OpenGL version 2.0 or later.
*/
bool areShadersSupported();
/**
* Returns wether the ARB shader extensions
* Returns whether shaders are supported, which
* is true for OpenGL version 4.3 or later.
*/
bool areComputeShadersSupported();
/**
* Returns whether the ARB shader extensions
* are supported (GL_ARB_vertex_program and
* GL_ARB_fragment_program).
*
......@@ -326,6 +332,12 @@ public:
*/
int getNumTextureUnits();
/**
* Returns the number of image units
* provided by the GPU.
*/
int getNumImageUnits();
/**
* Returns wether non-power-of-two textures
* are supported (extension GL_ARB_texture_non_power_of_two).
......@@ -429,6 +441,7 @@ private:
bool shaderSupport_;
bool shaderSupportARB_;
bool computeShaderSupport_;
GlVersion shaderVersion_;
ShaderModel shaderModel_;
......@@ -436,6 +449,7 @@ private:
bool texturing3D_;
int max3DTexSize_;
int numTextureUnits_;
int numImageUnits_;
bool npotTextures_;
bool textureRectangles_;
bool anisotropicFiltering_;
......
#include "imageunit.h"
#include "imageunit.h"
/**********************************************************************
* *
* cgt - CAMP Graphics Toolbox, Copyright (C) 2012-2015 *
* Chair for Computer Aided Medical Procedures *
* Technische Universitaet Muenchen, Germany. *
* <http://campar.in.tum.de/> *
* *
* forked from tgt - Tiny Graphics Toolbox, Copyright (C) 2006-2011 *
* Visualization and Computer Graphics Group, Department of *
* Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the cgt library. This library is free *
* software; you can redistribute it and/or modify it under the terms *
* of the GNU Lesser General Public License version 2.1 as published *
* by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License in the file "LICENSE.txt" along with this library. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
**********************************************************************/
#include "cgt/imageunit.h"
#include "cgt/gpucapabilities.h"
#include "cgt/assert.h"
namespace cgt {
bool ImageUnit::initialized_ = false;
unsigned short ImageUnit::totalActive_ = 0;
unsigned short ImageUnit::maxTexUnits_ = 0;
unsigned short ImageUnit::numKeptUnits_ = 0;
std::vector<bool> ImageUnit::busyUnits_ = std::vector<bool>();
tbb::spin_mutex ImageUnit::mutex_ = tbb::spin_mutex();
ImageUnit::ImageUnit(bool keep)
: number_(0)
, assigned_(false)
{
if (!initialized_)
init();
}
void ImageUnit::init() {
tbb::spin_mutex::scoped_lock lock(mutex_);
if (initialized_)
return;
maxTexUnits_ = GpuCaps.getNumImageUnits();
busyUnits_ = std::vector<bool>(maxTexUnits_, false);
numKeptUnits_ = 0;
initialized_ = true;
}
ImageUnit::~ImageUnit() {
if(assigned_)
releaseUnit();
}
ImageUnit::ImageUnit(ImageUnit && other)
{
*this = std::move(other);
}
ImageUnit & ImageUnit::operator=(ImageUnit && rhs)
{
if (this == &rhs)
return *this;
if (assigned_)
releaseUnit();
assigned_ = rhs.assigned_;
number_ = rhs.number_;
rhs.assigned_ = false;
rhs.number_ = 0;
return *this;
}
GLint ImageUnit::getUnitNumber() const {
if (!assigned_)
assignUnit();
return number_;
}
void ImageUnit::cleanup() {
tbb::spin_mutex::scoped_lock lock(mutex_);
for (size_t i = 0; i < maxTexUnits_; i++) {
if (busyUnits_.at(i))
busyUnits_.at(i) = false;
}
totalActive_ = 0;
numKeptUnits_ = 0;
}
bool ImageUnit::unused() {
return (totalActive_ == 0);
}
unsigned short ImageUnit::numLocalActive() {
return (totalActive_ - numKeptUnits_);
}
void ImageUnit::assignUnit() const {
tbb::spin_mutex::scoped_lock lock(mutex_);
cgtAssert(totalActive_ <= maxTexUnits_, "No more texture units available");
assigned_ = true;
for (size_t i = 0; i < maxTexUnits_; i++) {
if (!busyUnits_.at(i)) {
number_ = (GLint)i;
busyUnits_.at(i) = true;
totalActive_++;
break;
}
}
}
void ImageUnit::releaseUnit()
{
tbb::spin_mutex::scoped_lock lock(mutex_);
busyUnits_.at(number_) = false;
totalActive_--;
}
} // namespace
/**********************************************************************
* *
* cgt - CAMP Graphics Toolbox, Copyright (C) 2012-2015 *
* Chair for Computer Aided Medical Procedures *
* Technische Universitaet Muenchen, Germany. *
* <http://campar.in.tum.de/> *
* *
* forked from tgt - Tiny Graphics Toolbox, Copyright (C) 2006-2011 *
* Visualization and Computer Graphics Group, Department of *
* Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the cgt library. This library is free *
* software; you can redistribute it and/or modify it under the terms *
* of the GNU Lesser General Public License version 2.1 as published *
* by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License in the file "LICENSE.txt" along with this library. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
**********************************************************************/
#ifndef CGT_IMAGEUNIT_H
#define CGT_IMAGEUNIT_H
#include <string>
#include <tbb/spin_mutex.h>
#include "cgt/cgt_gl.h"
#include "cgt/shadermanager.h"
namespace cgt {
/**
* OpenGL Image Unit
*/
class CGT_API ImageUnit {
public:
ImageUnit(bool keep = false);
~ImageUnit();
void releaseUnit();
// copy construction and assignment is not allowed
ImageUnit(const ImageUnit& other) = delete;
ImageUnit& operator=(const ImageUnit& other) = delete;
// move construction and assignment is possible
ImageUnit(ImageUnit&& other);
ImageUnit& operator=(ImageUnit&& rhs);
GLint getUnitNumber() const;
static void cleanup();
static unsigned short numLocalActive();
/**
* Returns true if no texture units are currently assigned.
*/
static bool unused();
protected:
void assignUnit() const;
static void init();
mutable GLint number_;
mutable bool assigned_;
static bool initialized_;
static unsigned short totalActive_;
static unsigned short maxTexUnits_;
static unsigned short numKeptUnits_;
static std::vector<bool> busyUnits_;
static tbb::spin_mutex mutex_;
};
} // namespace cgt
#endif // CGT_IMAGEUNIT_H
......@@ -32,6 +32,7 @@
#include <iostream>
#include <fstream>
#include <memory>
using std::string;
......@@ -602,9 +603,9 @@ void Shader::loadSeparate(const string& vert_filename, const string& geom_filena
const string& frag_filename, const string& customHeader, const std::string& customGlslVersion)
throw (Exception)
{
ShaderObject* frag = 0;
ShaderObject* vert = 0;
ShaderObject* geom = 0;
ShaderObject* frag = nullptr;
ShaderObject* vert = nullptr;
ShaderObject* geom = nullptr;
if (!vert_filename.empty()) {
vert = new ShaderObject(vert_filename, ShaderObject::VERTEX_SHADER);
......@@ -752,6 +753,68 @@ void Shader::loadSeparate(const string& vert_filename, const string& geom_filena
}
}
void Shader::loadCompute(const string& compFilename, const string& customHeader, const string& customGlslVersion)
throw (Exception)
{
ShaderObject *comp;
if (!compFilename.empty()) {
comp = new ShaderObject(compFilename, ShaderObject::COMPUTE_SHADER);
if (!customHeader.empty()) {
comp->setHeader(customHeader);
}
if (!customGlslVersion.empty()) {
comp->setCustomGlslVersion(customGlslVersion);
}
else {
comp->setCustomGlslVersion("430");
}
try {
comp->loadSourceFromFile(compFilename);
}
catch (const Exception& e) {
LDEBUG("Failed to load compute shader " << compFilename << ": " << e.what());
delete comp;
throw Exception("Failed to load vertex shader " + compFilename + ": " + e.what());
}
comp->uploadSource();
if (!comp->compileShader()) {
LERROR("Failed to compile Compute shader " << compFilename);
LERROR("Compiler Log: \n" << comp->getCompilerLog());
delete comp;
throw Exception("Failed to compile vertex shader: " + compFilename);
}
}
// Attach ShaderObjects, dtor will take care of freeing them
if (comp)
attachObject(comp);
if (!linkProgram()) {
LERROR("Failed to link shader (" << compFilename << ")");
LERROR(comp->filename_ << " Compute shader compiler log: \n" << comp->getCompilerLog());
detachObject(comp);
LERROR("Linker Log: \n" << getLinkerLog());
throw Exception("Failed to link shader (" + compFilename + ")");
}
if (comp && comp->getCompilerLog().size() > 1) {
LDEBUG("Compute shader compiler log for file '" << compFilename << "': \n" << comp->getCompilerLog());
}
if (getLinkerLog().size() > 1) {
LDEBUG("Linker log for '" << compFilename << "': \n" << getLinkerLog());
}
}
GLint Shader::getUniformLocation(const string& name) {
GLint l;
l = glGetUniformLocation(id_, name.c_str());
......@@ -1316,6 +1379,45 @@ Shader* ShaderManager::load(const std::string& vertFilename, const std::string&
return loadWithCustomGlslVersion(vertFilename, geomFilename, fragFilename, customHeader, "");
}
Shader * ShaderManager::loadCompute(const std::string& compFilename, const std::string & customHeader, const std::string & customGlslVersion) throw(Exception)
{
//LDEBUG("Loading files " << vertFilename << " and " << fragFilename);
if (!GpuCaps.areComputeShadersSupported()) {
LERROR("Compute Shaders are not supported (Requires OpenGL 4.3 capable device).");
throw Exception("Compute Shaders are not supported.");
}
// create a somewhat unique identifier for this shader triple
string identifier = compFilename;
if (isLoaded(identifier)) {
LDEBUG("Shader already loaded. Increase usage count.");
increaseUsage(identifier);
return get(identifier);
}
Shader* shdr = new Shader();
// searching in all paths for every shader
string completeFilename;
if (!compFilename.empty())
completeFilename = completePath(compFilename);
// loading and linking found shaders
try {
shdr->loadCompute(completeFilename, customHeader, customGlslVersion);
// register even when caching is disabled, needed for rebuildFromFile()
reg(shdr, identifier);
return shdr;
}
catch (const Exception& /*e*/) {
delete shdr;
throw;
}
}
Shader* ShaderManager::loadWithCustomGlslVersion(const std::string& vertFilename, const std::string& geomFilename, const std::string& fragFilename, const std::string& customHeader, const std::string& customGlslVersion) throw(Exception) {
//LDEBUG("Loading files " << vertFilename << " and " << fragFilename);
if (!GpuCaps.areShadersSupported()) {
......
......@@ -71,7 +71,8 @@ public:
enum ShaderType {
VERTEX_SHADER = GL_VERTEX_SHADER,
FRAGMENT_SHADER = GL_FRAGMENT_SHADER,
GEOMETRY_SHADER = GL_GEOMETRY_SHADER_EXT