Commit c5a33101 authored by Robert Menzel's avatar Robert Menzel

refactored shader type detection, added compute shader detection

parent 8efc265e
......@@ -41,6 +41,12 @@ namespace FileHelpers
*/
bool stringEndsWith( const std::string &theString, const std::string &theEnding );
/*
* Returns the lowercase fileending if the filename has a '.' in it, otherwise
* an empty string.
*/
std::string getFileEnding( const std::string &_fileName );
/*
* Checks if a string begins with a certain prefix.
*/
......
......@@ -31,14 +31,6 @@ namespace OpenGL{
class ShaderProgramControlFiles : public Resource::MultiFileController<ShaderProgram>
{
struct ShaderEndings
{
const char *ending;
GLenum type;
};
static const unsigned int sShaderEndingsSize; // size of the array sShaderEndings
static const ShaderEndings sShaderEndings[]; // all supported endings (see .cc file)
// ========================================================================================================= \/
// ============================================================================================ CONSTRUCTORS \/
// ========================================================================================================= \/
......
......@@ -46,8 +46,40 @@ uint32_t getOpenGLMajorVersionNumber();
// returns the combined version number as 10*major + minor for easy comparing
uint32_t getOpenGLVersionNumber();
// query support for specific shader stages:
bool doesSupportGeometryShader();
bool doesSupportTessellationShader();
bool doesSupportComputeShader();
struct ShaderEndings
{
const char *ending;
GLenum type;
};
const ShaderEndings sShaderEndings[ ] = {
{"vsh", GL_VERTEX_SHADER},
{"vert", GL_VERTEX_SHADER},
{"tcsh", GL_TESS_CONTROL_SHADER},
{"tcs", GL_TESS_CONTROL_SHADER},
{"tesh", GL_TESS_EVALUATION_SHADER},
{"tes", GL_TESS_EVALUATION_SHADER},
{"gsh", GL_GEOMETRY_SHADER},
{"geo", GL_GEOMETRY_SHADER},
{"fsh", GL_FRAGMENT_SHADER},
{"frag", GL_FRAGMENT_SHADER},
{"csh", GL_COMPUTE_SHADER},
{"cs", GL_COMPUTE_SHADER}
};
// returns the GL_TESS_CONTROL_SHADER GL_TESS_EVALUATION_SHADER GL_GEOMETRY_SHADER GL_COMPUTE_SHADER
// GL_VERTEX_SHADER GL_FRAGMENT_SHADER or GL_INVALID_VALUE in case the shadertype was not detected
// if _ignoreUnsupportedShaderTypes is true, types unsupported by the current runtime will return
// an GL_INVALID_ENUM also.
GLenum getShaderTypeByFileEnding( const std::string _fileName, bool _ignoreUnsupportedShaderTypes = true );
// looks up the enum and gives a human readable version
const GLubyte* acglShaderTypeString( GLenum _shaderType );
// for every OpenGL error enum this will return a human readable version of it
// similar to gluErrorString, but that function is not available on all plattforms
......
......@@ -8,6 +8,8 @@
#include <cstdio> // fopen etc.
#include <string>
#include <algorithm> // transform
#include <cctype> // tolower
#include <vector>
#include <sstream>
#include <iostream>
......@@ -59,6 +61,18 @@ namespace FileHelpers
return false;
}
std::string getFileEnding( const std::string &_fileName )
{
size_t lastDot = _fileName.rfind('.');
if (lastDot == std::string::npos) {
return "";
}
std::string ending = _fileName.substr( lastDot+1, _fileName.size() );
std::transform(ending.begin(), ending.end(), ending.begin(), ::tolower);
return ending;
}
/*
bool stringBeginsWith( const std::string &theString, const std::string &thePrefix )
{
......
......@@ -6,6 +6,7 @@
#include <ACGL/OpenGL/Controller/ShaderControlFile.hh>
#include <ACGL/Base/StringOperations.hh>
#include <ACGL/OpenGL/Tools.hh>
using namespace ACGL::Base;
using namespace ACGL::OpenGL;
......@@ -14,37 +15,14 @@ SharedShader ShaderControlFile::create(void)
{
updateFileModificationTime();
if(mType == GL_INVALID_ENUM)
if (mType == GL_INVALID_ENUM)
{
std::string filename;
std::string extension;
if(!StringOperations::splitFileExtension(mFilename, filename, extension))
return SharedShader();
if(extension == "vsh")
mType = GL_VERTEX_SHADER;
else if(extension == "fsh")
mType = GL_FRAGMENT_SHADER;
#if (ACGL_OPENGL_VERSION >= 43)
else if(extension == "csh")
mType = GL_COMPUTE_SHADER;
#endif
#if (ACGL_OPENGL_VERSION >= 40)
else if(extension == "tcsh")
mType = GL_TESS_CONTROL_SHADER;
else if(extension == "tesh")
mType = GL_TESS_EVALUATION_SHADER;
#endif
#if (ACGL_OPENGL_VERSION >= 32)
else if(extension == "gsh")
mType = GL_GEOMETRY_SHADER;
#endif
else
return SharedShader();
mType = ACGL::OpenGL::getShaderTypeByFileEnding( mFilename );
if (mType == GL_INVALID_ENUM) return SharedShader();
}
SharedShader shader(new Shader(mType));
if(shader->setFromFile(mFullFilePath))
if (shader->setFromFile(mFullFilePath))
return shader;
return SharedShader();
}
......
......@@ -6,6 +6,7 @@
#include <ACGL/OpenGL/Controller/ShaderProgramControlFiles.hh>
#include <ACGL/OpenGL/Controller/ShaderControlFile.hh>
#include <ACGL/OpenGL/Tools.hh>
#include <ACGL/Resource/FileManager.hh>
#include <ACGL/OpenGL/Managers.hh>
#include <ACGL/Base/Settings.hh>
......@@ -17,37 +18,11 @@
using namespace ACGL::Base;
using namespace ACGL::OpenGL;
#ifndef ACGL_OPENGL_ES
#if (ACGL_OPENGL_VERSION >= 43)
const unsigned int ShaderProgramControlFiles::sShaderEndingsSize = 9;
#else
const unsigned int ShaderProgramControlFiles::sShaderEndingsSize = 8;
#endif
#else
const unsigned int ShaderProgramControlFiles::sShaderEndingsSize = 4;
#endif
const ShaderProgramControlFiles::ShaderEndings ShaderProgramControlFiles::sShaderEndings[ ShaderProgramControlFiles::sShaderEndingsSize ] = {
#ifndef ACGL_OPENGL_ES
{"tcsh", GL_TESS_CONTROL_SHADER},
{"tesh", GL_TESS_EVALUATION_SHADER},
{"gsh", GL_GEOMETRY_SHADER},
{"geo", GL_GEOMETRY_SHADER},
#if (ACGL_OPENGL_VERSION >= 43)
{"csh", GL_COMPUTE_SHADER},
#endif
#endif
{"vsh", GL_VERTEX_SHADER},
{"vert", GL_VERTEX_SHADER},
{"fsh", GL_FRAGMENT_SHADER},
{"frag", GL_FRAGMENT_SHADER}
};
ShaderProgramControlFiles& ShaderProgramControlFiles::autoFiles(const std::string &_fileName)
{
//Utils::debug() << "autoFiles: " << _fileName << std::endl;
std::string baseFileName = _fileName + ".";
for (unsigned int ending = 0; ending < sShaderEndingsSize; ++ending)
for (unsigned int ending = 0; ending < sizeof(sShaderEndings) / sizeof(ShaderEndings); ++ending)
{
std::string fileName = baseFileName + sShaderEndings[ending].ending;
if ( FileHelpers::fileExists( mBasePath + fileName ) )
......@@ -71,14 +46,7 @@ SharedShaderProgram ShaderProgramControlFiles::create(void)
if ( mShaderType[file] == GL_INVALID_VALUE ) {
// guess the shader type:
for (unsigned int ending = 0; ending < sShaderEndingsSize; ++ending)
{
if ( FileHelpers::stringEndsWith( mFileNames[file], sShaderEndings[ending].ending ) )
{
mShaderType[file] = sShaderEndings[ending].type;
continue;
}
}
mShaderType[file] = ACGL::OpenGL::getShaderTypeByFileEnding( mFileNames[file] );
}
}
......
......@@ -6,6 +6,7 @@
#include <ACGL/ACGL.hh>
#include <ACGL/OpenGL/Tools.hh>
#include <ACGL/Base/FileHelpers.hh>
namespace ACGL{
namespace OpenGL{
......@@ -14,7 +15,7 @@ namespace OpenGL{
// This is a "private" function that should not be called from outside of this file.
//
// glGetIntegerv(GL_MAJOR_VERSION... and glGetIntegerv(GL_MINOR_VERSION... are great, but
// require OpenGL 3.0 and are not supported on ES :-( so the VERSION string has to get parsed...
// require OpenGL 3.0 and are not supported on ES 2 :-( so the VERSION string has to get parsed...
//
// OpenGL spec:
// The VERSION ... strings are laid out as follows:
......@@ -104,6 +105,60 @@ bool doesSupportTessellationShader()
#endif
}
bool doesSupportComputeShader()
{
#ifdef ACGL_OPENGL_ES
return false;
#else
# if defined(ACGL_USE_GLEW)
return ( GLEW_ARB_compute_shader || (getOpenGLVersionNumber() >= 43));
# else
return (getOpenGLVersionNumber() >= 43);
# endif
#endif
}
GLenum getShaderTypeByFileEnding( const std::string _fileName, bool _ignoreUnsupportedShaderTypes )
{
std::string fileEnding = ACGL::Base::FileHelpers::getFileEnding( _fileName );
if( fileEnding.size() == 0 ) return GL_INVALID_ENUM;
GLenum foundType = GL_INVALID_ENUM;
// guess the shader type:
for (unsigned int ending = 0; ending < sizeof(sShaderEndings) / sizeof(ShaderEndings); ++ending)
{
if ( fileEnding == sShaderEndings[ending].ending )
{
foundType = sShaderEndings[ending].type;
break;
}
}
if (_ignoreUnsupportedShaderTypes) {
if (foundType == GL_GEOMETRY_SHADER && !doesSupportGeometryShader() ) return GL_INVALID_ENUM;
if (foundType == GL_TESS_CONTROL_SHADER && !doesSupportTessellationShader()) return GL_INVALID_ENUM;
if (foundType == GL_TESS_EVALUATION_SHADER && !doesSupportTessellationShader()) return GL_INVALID_ENUM;
if (foundType == GL_COMPUTE_SHADER && !doesSupportComputeShader() ) return GL_INVALID_ENUM;
}
return foundType;
}
const GLubyte* acglShaderTypeString( GLenum _shaderType )
{
if (_shaderType == GL_VERTEX_SHADER) { return (GLubyte*) "vertex shader"; }
else if (_shaderType == GL_TESS_CONTROL_SHADER) { return (GLubyte*) "tessellation control shader"; }
else if (_shaderType == GL_TESS_EVALUATION_SHADER) { return (GLubyte*) "tessellation evaluation shader"; }
else if (_shaderType == GL_GEOMETRY_SHADER) { return (GLubyte*) "geometry shader"; }
else if (_shaderType == GL_FRAGMENT_SHADER) { return (GLubyte*) "fragment shader"; }
else if (_shaderType == GL_COMPUTE_SHADER) { return (GLubyte*) "compute shader"; }
else {
return (GLubyte*) "unknown shader type";
}
}
const GLubyte* acglErrorString( GLenum _errorCode )
{
// no gluErrorString on iOS, problems on visual studio...
......
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