12#ifndef GAMP_GLSLSHADERUTIL_HPP_
13#define GAMP_GLSLSHADERUTIL_HPP_
19 using namespace gamp::render::gl;
46 GLint infoLogLength = 0;
47 glGetShaderiv(shaderObj, GL_INFO_LOG_LENGTH, &infoLogLength);
49 if(infoLogLength==0) {
50 return "(no info log)";
52 GLsizei charsWritten = 0;
54 infoLog.reserve(infoLogLength + 1);
55 infoLog.resize(infoLogLength);
56 glGetShaderInfoLog(shaderObj, infoLogLength, &charsWritten, &infoLog[0]);
61 GLint infoLogLength = 0;
62 glGetShaderiv(programObj, GL_INFO_LOG_LENGTH, &infoLogLength);
64 if(infoLogLength==0) {
65 return "(no info log)";
67 GLsizei charsWritten = 0;
69 infoLog.reserve(infoLogLength + 1);
70 infoLog.resize(infoLogLength);
71 glGetProgramInfoLog(programObj, infoLogLength, &charsWritten, &infoLog[0]);
77 glGetShaderiv(shaderObj,
name, &ires);
79 const bool res = ires==1;
88 for (GLuint s : shaders) {
96 glGetProgramiv(programObj,
name, &ires);
97 const bool res = ires==1;
105 if(!glIsProgram(programObj)) {
133 glValidateProgram(programObj);
145 for (GLuint & shader : shaders) {
146 shader = glCreateShader(type);
151 static constexpr const char* compilerInfoKey =
"gamp.renderer.gl.glsl.CompilerInfo";
155 bool shaderCompilerAvail;
160 typedef std::shared_ptr<CompilerInfo> CompilerInfoRef;
162 static CompilerInfoRef getOrCreateCompilerInfo(
GL&
gl)
noexcept {
165 CompilerInfoRef ci = std::static_pointer_cast<CompilerInfo>(o);
168 CompilerInfoRef ci = std::make_shared<CompilerInfo>();
169 if (
gl.glProfile().hasGLSL()) {
171 glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, ¶m);
172 const GLenum err = glGetError();
173 const size_t numFormats = GL_NO_ERROR == err ? param : 0;
175 ci->binFormats.reserve(numFormats);
176 ci->binFormats.resize(numFormats);
178 glGetIntegerv(GL_SHADER_BINARY_FORMATS, il.data());
179 for(
size_t i=0; i<numFormats; ++i) {
180 ci->binFormats[i] = (GLenum)il[i];
184 if(gl.glProfile().isGLES2()) {
186 glGetBooleanv(GL_SHADER_COMPILER, ¶m);
187 const GLenum err = glGetError();
188 const bool v = GL_NO_ERROR == err && param!=0;
189 ci->shaderCompilerAvail = v || ci->binFormats.empty();
190 }
else if( gl.glProfile().isGL2ES2() ) {
191 ci->shaderCompilerAvail =
true;
193 ci->shaderCompilerAvail =
false;
195 gl.attachObject(compilerInfoKey, ci);
206 const CompilerInfoRef& ci = getOrCreateCompilerInfo(
gl);
207 return ci->binFormats;
212 const CompilerInfoRef& ci = getOrCreateCompilerInfo(
gl);
213 return ci->shaderCompilerAvail;
219 gl.isExtensionAvailable(
"ARB_geometry_shader4");
226 const size_t count = source.size();
231 std::vector<GLint> lengths(count, 0);
232 for(
size_t i=0; i<count; ++i) {
233 size_t l = source[i].length();
235 lengths[i] = (GLint)l;
237 std::vector<GLchar*> sourcePtr(count,
nullptr);
238 for(
size_t i = 0; i<count; ++i) {
239 sourcePtr[i] = (GLchar*)source[i].
data();
241 glShaderSource(shader, (GLsizei)count, sourcePtr.data(), lengths.data());
245 const size_t sourceNum = sources.size();
246 const size_t shaderNum = shaders.size();
247 if(shaderNum==0 || sourceNum==0 || shaderNum!=sourceNum) {
248 throw RenderException(
"Invalid number of shaders and/or sources: shaders="+
249 std::to_string(shaderNum)+
", sources="+std::to_string(sourceNum),
E_FILE_LINE);
251 for(
size_t i=0; i<sourceNum; ++i) {
261 const size_t shaderNum = shaders.size();
269 const size_t binLength = bin.size();
274 glShaderBinary((GLsizei)shaderNum, shaders.data(), binFormat, bin.data(), (GLsizei)binLength);
278 for (GLuint shader : shaders) {
279 glCompileShader(shader);
284 for (GLuint shader : shaders) {
285 glAttachShader(program, shader);
290 for (GLuint shader : shaders) {
291 glDetachShader(program, shader);
296 for (GLuint shader : shaders) {
297 glDeleteShader(shader);
305 GLenum err = glGetError();
306 if(err!=GL_NO_ERROR &&
verbose) {
312 if(err!=GL_NO_ERROR) {
319 if(err!=GL_NO_ERROR &&
verbose) {
320 jau::PLAIN_PRINT(
true,
"createAndLoadShader: ShaderBinary failed, GL Error: 0x%x", err);
322 return err == GL_NO_ERROR;
329 GLenum err = glGetError();
330 if(err!=GL_NO_ERROR &&
verbose) {
336 if(err!=GL_NO_ERROR) {
341 if(err!=GL_NO_ERROR) {
347 if(err!=GL_NO_ERROR &&
verbose) {
348 jau::PLAIN_PRINT(
true,
"createAndCompileShader: CompileShader failed, GL Error: 0x%x", err);
static bool createAndCompileShader(GL &gl, shader_list_t &shader, GLenum shaderType, const source_list_t &sources, bool verbose=false)
Creates shader.size() new shaders, stored in the shader list.
static bool isShaderStatusValid(GL &gl, const shader_list_t &shaders, GLenum name, bool verbose=false) noexcept
static std::string getShaderInfoLog(GL &, GLuint shaderObj) noexcept
static void deleteShader(GL &, const shader_list_t &shaders) noexcept
static bool createAndLoadShader(GL &gl, shader_list_t &shader, GLenum shaderType, GLenum binFormat, const bytes_t &bin, bool verbose=false)
Creates shader.size() new shaders, stored in the shader list.
static void compileShader(GL &, const shader_list_t &shaders) noexcept
static void shaderBinary(GL &gl, const shader_list_t &shaders, GLenum binFormat, const bytes_t &bin)
static bool isProgramStatusValid(GL &gl, GLuint programObj, GLenum name, bool verbose=false) noexcept
static name_list_t getShaderBinaryFormats(GL &gl) noexcept
If supported, queries the natively supported shader binary formats using GL2ES2#GL_NUM_SHADER_BINARY_...
static std::string getProgramInfoLog(GL &, GLuint programObj) noexcept
static void shaderSource(GL &gl, GLuint shader, const string_list_t &source)
static bool isGeometryShaderSupported(GL &gl) noexcept
Returns true if GeometryShader is supported, i.e.
static void attachShader(GL &, GLuint program, const shader_list_t &shaders) noexcept
static void detachShader(GL &, GLuint program, const shader_list_t &shaders) noexcept
static bool isShaderStatusValid(GL &gl, GLuint shaderObj, GLenum name, bool verbose=false) noexcept
static void createShader(GL &, GLenum type, shader_list_t &shaders) noexcept
Creates shaders.size() new shaders and stores them in the shaders list.
static bool isProgramExecStatusValid(GL &gl, GLuint programObj, bool verbose=false) noexcept
Performs GL2ES2#glValidateProgram(int).
static bool isProgramLinkStatusValid(GL &gl, GLuint programObj, bool verbose=false) noexcept
static void shaderSource(GL &gl, const shader_list_t &shaders, const source_list_t &sources)
static bool isShaderCompilerAvailable(GL &gl) noexcept
Returns true if a hader compiler is available, otherwise false.
Generic type information using either Runtime type information (RTTI) or Compile time type informatio...
consteval_cxx20 std::string_view name() noexcept
const jau::type_info & static_ctti() noexcept
Returns a static global reference of make_ctti<T>(true) w/ identity instance.
std::vector< uint8_t > bytes_t
std::vector< GLenum > name_list_t
std::vector< GLfloat > float_list_t
std::string_view stringview_t
std::vector< GLint > int_list_t
std::vector< stringview_t > stringview_list_t
const jau::type_info & vectorSignature() noexcept
Returns type signature of std::vector<T>.
std::vector< string_t > string_list_t
std::vector< GLuint > shader_list_t
std::vector< string_list_t > source_list_t
static constexpr jau::util::VersionNumber Version3_2
Version 3.2.
@ verbose
Verbose operations (debugging).
std::shared_ptr< Attachable > AttachableRef
void throwOnOverflow(T has)
std::string toHexString(const void *data, const nsize_t length, const lb_endian_t byteOrder=lb_endian_t::big, const LoUpCase capitalization=LoUpCase::lower, const PrefixOpt prefix=PrefixOpt::prefix) noexcept
Produce a hexadecimal string representation of the given lsb-first byte values.
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.