Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

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

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
GEOMETRY_SHADER = GL_GEOMETRY_SHADER_EXT,
COMPUTE_SHADER = GL_COMPUTE_SHADER
};
// Helper for resolving line number when includes are used in shader files
......@@ -433,6 +434,16 @@ protected:
const std::string& fragFilename, const std::string& customHeader = "", const std::string& customGlslVersion = "")
throw (Exception);
/**
* Load compute shader \p compFilename
*
* @param customHeader header to be put in front of the shader source
*
* @throw Exception if loading failed
*/
void loadCompute(const std::string& compFilename, const std::string& customHeader, const std::string& customGlslVersion = "")
throw (Exception);
typedef std::list<ShaderObject*> ShaderObjects;
ShaderObjects objects_;
......@@ -494,6 +505,22 @@ public:
const std::string& customHeader)
throw(Exception);
/**
* Load the given compute shader.
* Empty file names will be ignored (not loaded and linked). You have to pass the complete
* file names, inclusive file extensions (".vert", ".geom", frag").
*
* Only works if OpenGL 4.3 or higher is supported.
*
* \param compFilename Compute shader file name
* \param customHeader Custom header to add (may be empty)
* \param customGlslVersion Custom GLSL version for all shaders (leave empty to use default GLSL version from ShaderManager).
* \throw Exception if loading failed.
* \return The newly created shader.
*/
Shader* loadCompute(const std::string& compFilename, const std::string& customHeader, const std::string& customGlslVersion = "")
throw(Exception);
/**
* Load given shaders from file and link them.
* Empty file names will be ignored (not loaded and linked). You have to pass the complete
......
This diff is collapsed.
......@@ -33,6 +33,8 @@
#include "cgt/cgt_gl.h"
#include "cgt/types.h"
#include "cgt/vector.h"
#include "cgt/imageunit.h"
#include "cgt/gltextureformattraits.h"
namespace cgt {
......@@ -58,6 +60,12 @@ public:
MIRRORED_REPEAT = GL_MIRRORED_REPEAT
};
enum ElementTypeClass {
SIGNED,
UNSIGNED,
FLOAT
};
/**
* Creates an empty texture with the given parameters.
*
......@@ -99,8 +107,20 @@ public:
/// calculates the number of channels from the passed internal format
static int calcNumChannels(GLint internalFormat);
static GLint calcMatchingFormat(GLint internalFormat);
static GLenum calcMatchingDataType(GLint internalFormat);
static GLint calcMatchingPixelFormat(GLint internalFormat);
static GLenum calcMatchingPixelDataType(GLint internalFormat);
/**
* Returns a matching write format string that can be used inside a shader to specify the write format as a layout specifier.
* Basically, this implements Table 1 from https://www.opengl.org/sdk/docs/man4/html/glBindImageTexture.xhtml and can be used
* when auto-generating shader code.
*/
static std::string calcMatchingWriteFormat(GLint internalFormat);
/**
* Returns the matching element type class for a given internal format
*/
static ElementTypeClass calcElementType(GLint internalFormat);
/**
* Determines the best-matching internal format for the given OpenGL format and data type
......@@ -121,6 +141,18 @@ public:
glBindTexture(type_ , id_);
}
/**
* Bind the texture to the active image unit and target. This is required when image Load/Store operations are being used in the shaders.
*
* @param unit The image unit to bind against
* @param level the level of the texture that is to be bound
* @param access the access type for the texture, may be set to GL_READ_ONLY, GL_WRITE_ONLY, or GL_READ_WRITE
* @param format format to be used when performing formatted stores from the shader. Must match the format used in the shader, see @glBindImageTexture
*/
void bindImage(const ImageUnit& unit, GLenum access = GL_READ_WRITE, GLint level = 0) const {
glBindImageTexture(unit.getUnitNumber(), id_, level, GL_FALSE, 0, access, internalformat_);
}
/**
* unbind the current texture from the active texture unit and target.
*/
......
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