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;
159 typedef std::shared_ptr<CompilerInfo> CompilerInfoRef;
161 static CompilerInfoRef getOrCreateCompilerInfo(
GL&
gl)
noexcept {
164 CompilerInfoRef ci = std::static_pointer_cast<CompilerInfo>(o);
167 CompilerInfoRef ci = std::make_shared<CompilerInfo>();
168 if (
gl.glProfile().hasGLSL()) {
170 glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, ¶m);
171 const GLenum err = glGetError();
172 const size_t numFormats = GL_NO_ERROR == err ? param : 0;
174 ci->binFormats.reserve(numFormats);
175 ci->binFormats.resize(numFormats);
177 glGetIntegerv(GL_SHADER_BINARY_FORMATS, il.data());
178 for(
size_t i=0; i<numFormats; ++i) {
179 ci->binFormats[i] = (GLenum)il[i];
183 if(gl.glProfile().isGLES2()) {
185 glGetBooleanv(GL_SHADER_COMPILER, ¶m);
186 const GLenum err = glGetError();
187 const bool v = GL_NO_ERROR == err && param!=0;
188 ci->shaderCompilerAvail = v || ci->binFormats.empty();
189 }
else if( gl.glProfile().isGL2ES2() ) {
190 ci->shaderCompilerAvail =
true;
192 ci->shaderCompilerAvail =
false;
194 gl.attachObject(compilerInfoKey, ci);
205 const CompilerInfoRef& ci = getOrCreateCompilerInfo(
gl);
206 return ci->binFormats;
211 const CompilerInfoRef& ci = getOrCreateCompilerInfo(
gl);
212 return ci->shaderCompilerAvail;
218 gl.isExtensionAvailable(
"ARB_geometry_shader4");
225 const size_t count = source.size();
230 std::vector<GLint> lengths(count, 0);
231 for(
size_t i=0; i<count; ++i) {
232 size_t l = source[i].length();
234 lengths[i] = (GLint)l;
236 std::vector<GLchar*> sourcePtr(count,
nullptr);
237 for(
size_t i = 0; i<count; ++i) {
238 sourcePtr[i] = (GLchar*)source[i].
data();
240 glShaderSource(shader, (GLsizei)count, sourcePtr.data(), lengths.data());
244 const size_t sourceNum = sources.size();
245 const size_t shaderNum = shaders.size();
246 if(shaderNum==0 || sourceNum==0 || shaderNum!=sourceNum) {
247 throw RenderException(
"Invalid number of shaders and/or sources: shaders="+
248 std::to_string(shaderNum)+
", sources="+std::to_string(sourceNum),
E_FILE_LINE);
250 for(
size_t i=0; i<sourceNum; ++i) {
260 const size_t shaderNum = shaders.size();
268 const size_t binLength = bin.size();
273 glShaderBinary((GLsizei)shaderNum, shaders.data(), binFormat, bin.data(), (GLsizei)binLength);
277 for (GLuint shader : shaders) {
278 glCompileShader(shader);
283 for (GLuint shader : shaders) {
284 glAttachShader(program, shader);
289 for (GLuint shader : shaders) {
290 glDetachShader(program, shader);
295 for (GLuint shader : shaders) {
296 glDeleteShader(shader);
304 GLenum err = glGetError();
305 if(err!=GL_NO_ERROR &&
verbose) {
311 if(err!=GL_NO_ERROR) {
318 if(err!=GL_NO_ERROR &&
verbose) {
319 jau::PLAIN_PRINT(
true,
"createAndLoadShader: ShaderBinary failed, GL Error: 0x%x", err);
321 return err == GL_NO_ERROR;
328 GLenum err = glGetError();
329 if(err!=GL_NO_ERROR &&
verbose) {
335 if(err!=GL_NO_ERROR) {
340 if(err!=GL_NO_ERROR) {
346 if(err!=GL_NO_ERROR &&
verbose) {
347 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 to_hexstring(value_type const &v, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
void PLAIN_PRINT(const bool printPrefix, const char *format,...) noexcept
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.