gl: switch to bind-attribute style + option for debug output
This commit is contained in:
parent
a755c28113
commit
f13096dd6e
|
@ -14,8 +14,12 @@
|
|||
|
||||
On GINT_CG, the window size can be 396x224, 198x112 or 132x75 and this
|
||||
configures the rendering engine for super-resolution. Returns non-zero if
|
||||
the size is not one of these. */
|
||||
int azur_init(char const *title, int window_width, int window_height);
|
||||
the size is not one of these.
|
||||
|
||||
On OpenGL platforms, if debug is set the OpenGL debug extension is enabled
|
||||
and OpenGL messages are automatically logged to stderr. */
|
||||
int azur_init(
|
||||
char const *title, int window_width, int window_height, bool debug = false);
|
||||
|
||||
/* azur_main_loop(): Run the update/render loop.
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <azur/gl/gl.h>
|
||||
#include <azur/log.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
@ -92,11 +93,13 @@ public:
|
|||
|
||||
/* Compile all provided code. */
|
||||
bool compile();
|
||||
/* Link compiled code (usually after binding attribute locations). */
|
||||
bool link();
|
||||
|
||||
/* Check whether the program has been compiled successfully. */
|
||||
/* Check whether the program has been linked successfully. */
|
||||
bool isCompiled() const
|
||||
{
|
||||
return (m_prog != 0);
|
||||
return (m_prog != 0) && m_linked;
|
||||
}
|
||||
|
||||
/*** Configuration ***/
|
||||
|
@ -116,25 +119,26 @@ public:
|
|||
glVertexAttribPointer(). */
|
||||
template<typename U>
|
||||
void bindVertexAttributeFP(U VertexAttr::*x, GLint size, GLenum type,
|
||||
GLboolean normalized, char const *name) {
|
||||
glVertexAttribPointer(getAttribute(name), size, type, normalized,
|
||||
sizeof(VertexAttr), offsetOf(x));
|
||||
GLboolean normalized, GLuint id) {
|
||||
glEnableVertexAttribArray(id);
|
||||
glVertexAttribPointer(id, size, type, normalized, sizeof(VertexAttr),
|
||||
offsetOf(x));
|
||||
}
|
||||
|
||||
/* Same for integer attributes, using glVertexAttribIPointer(). */
|
||||
template<typename U>
|
||||
void bindVertexAttributeInt(
|
||||
U VertexAttr::*x, GLint size, GLenum type, char const *name) {
|
||||
U VertexAttr::*x, GLint size, GLenum type, GLuint id) {
|
||||
glVertexAttribIPointer(
|
||||
getAttribute(name), size, type, sizeof(VertexAttr), offsetOf(x));
|
||||
id, size, type, sizeof(VertexAttr), offsetOf(x));
|
||||
}
|
||||
|
||||
/* Shortcuts for binding attributes of common types, which automatically
|
||||
provide the type details. */
|
||||
void bindVertexAttribute(float VertexAttr::*x, char const *name);
|
||||
void bindVertexAttribute(glm::vec2 VertexAttr::*x, char const *name);
|
||||
void bindVertexAttribute(glm::vec3 VertexAttr::*x, char const *name);
|
||||
void bindVertexAttribute(glm::vec4 VertexAttr::*x, char const *name);
|
||||
void bindVertexAttribute(float VertexAttr::*x, GLuint id);
|
||||
void bindVertexAttribute(glm::vec2 VertexAttr::*x, GLuint id);
|
||||
void bindVertexAttribute(glm::vec3 VertexAttr::*x, GLuint id);
|
||||
void bindVertexAttribute(glm::vec4 VertexAttr::*x, GLuint id);
|
||||
|
||||
/* Set uniforms. */
|
||||
void setUniform(char const *name, float f);
|
||||
|
@ -213,6 +217,7 @@ public:
|
|||
protected:
|
||||
/* Program ID */
|
||||
GLuint m_prog = 0;
|
||||
bool m_linked = false;
|
||||
/* Vertex Array Object and Vertex Buffer Object with parameters */
|
||||
GLuint m_vao = 0, m_vbo = 0;
|
||||
/* Size of the VBO on the GPU */
|
||||
|
@ -222,6 +227,8 @@ private:
|
|||
/* Map from program type (vertex/etc/fragment shader) to code during the
|
||||
construction phase. */
|
||||
std::map<GLuint, std::string> m_code;
|
||||
/* List of shader descriptors between compiling and linking. */
|
||||
std::vector<GLuint> m_shaders;
|
||||
/* List of vertices during rendering. */
|
||||
std::vector<VertexAttr> m_vertices;
|
||||
/* Map of attribute names to shader locations. */
|
||||
|
@ -260,8 +267,6 @@ bool ShaderProgram<T>::addSourceFile(
|
|||
template<typename T>
|
||||
bool ShaderProgram<T>::compile()
|
||||
{
|
||||
/* List of shader descriptors obtained from OpenGL. */
|
||||
std::vector<GLuint> m_shaders;
|
||||
bool success = true;
|
||||
|
||||
for(auto const &[type, code]: m_code) {
|
||||
|
@ -272,12 +277,70 @@ bool ShaderProgram<T>::compile()
|
|||
success = false;
|
||||
}
|
||||
|
||||
// TODO: No link error detection?
|
||||
m_prog = success ? link(m_shaders.data(), m_shaders.size()) : 0;
|
||||
/* Generate a new program */
|
||||
if(success) {
|
||||
m_prog = glCreateProgram();
|
||||
if(m_prog == 0) {
|
||||
azlog(ERROR, "glCreateProgram failed\n");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto id: m_shaders)
|
||||
glDeleteShader(id);
|
||||
/* Attach all shaders */
|
||||
if(success) {
|
||||
for(int i = 0; i < m_shaders.size(); i++)
|
||||
glAttachShader(m_prog, m_shaders[i]);
|
||||
}
|
||||
else {
|
||||
for(auto id: m_shaders)
|
||||
glDeleteShader(id);
|
||||
m_shaders.clear();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ShaderProgram<T>::link()
|
||||
{
|
||||
if(!m_shaders.size())
|
||||
return false;
|
||||
|
||||
GLint rc = GL_FALSE;
|
||||
GLsizei log_length = 0;
|
||||
bool success = true;
|
||||
|
||||
azlog(INFO, "Linking program\n");
|
||||
glLinkProgram(m_prog);
|
||||
|
||||
glGetProgramiv(m_prog, GL_LINK_STATUS, &rc);
|
||||
if(rc == GL_FALSE) {
|
||||
azlog(ERROR, "link failed!\n");
|
||||
success = false;
|
||||
}
|
||||
|
||||
glGetProgramiv(m_prog, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if(log_length > 0) {
|
||||
GLchar *log = new GLchar[log_length + 1];
|
||||
glGetProgramInfoLog(m_prog, log_length, &log_length, log);
|
||||
if(log_length > 0) {
|
||||
azlogc(ERROR, "%s", log);
|
||||
if(log[log_length - 1] != '\n')
|
||||
azlogc(ERROR, "\n");
|
||||
}
|
||||
delete[] log;
|
||||
}
|
||||
|
||||
/* Detach all shaders */
|
||||
for(int i = 0; i < m_shaders.size(); i++) {
|
||||
glDetachShader(m_prog, m_shaders[i]);
|
||||
glDeleteShader(m_shaders[i]);
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
glDeleteProgram(m_prog);
|
||||
m_prog = 0;
|
||||
}
|
||||
m_linked = success;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -293,27 +356,27 @@ GLuint ShaderProgram<T>::getAttribute(char const *name)
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void ShaderProgram<T>::bindVertexAttribute(float T::*x, char const *name)
|
||||
void ShaderProgram<T>::bindVertexAttribute(float T::*x, GLuint id)
|
||||
{
|
||||
bindVertexAttributeFP(x, 1, GL_FLOAT, GL_FALSE, name);
|
||||
bindVertexAttributeFP(x, 1, GL_FLOAT, GL_FALSE, id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec2 T::*x, char const *name)
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec2 T::*x, GLuint id)
|
||||
{
|
||||
bindVertexAttributeFP(x, 2, GL_FLOAT, GL_FALSE, name);
|
||||
bindVertexAttributeFP(x, 2, GL_FLOAT, GL_FALSE, id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec3 T::*x, char const *name)
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec3 T::*x, GLuint id)
|
||||
{
|
||||
bindVertexAttributeFP(x, 3, GL_FLOAT, GL_FALSE, name);
|
||||
bindVertexAttributeFP(x, 3, GL_FLOAT, GL_FALSE, id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec4 T::*x, char const *name)
|
||||
void ShaderProgram<T>::bindVertexAttribute(glm::vec4 T::*x, GLuint id)
|
||||
{
|
||||
bindVertexAttributeFP(x, 4, GL_FLOAT, GL_FALSE, name);
|
||||
bindVertexAttributeFP(x, 4, GL_FLOAT, GL_FALSE, id);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
static SDL_Window *window = NULL;
|
||||
static SDL_GLContext glcontext = NULL;
|
||||
|
||||
|
@ -39,7 +41,40 @@ static void enter_fullscreen(SDL_Window *window)
|
|||
}
|
||||
#endif /* AZUR_PLATFORM_EMSCRIPTEN */
|
||||
|
||||
int azur_init(char const *title, int window_width, int window_height)
|
||||
static void gl_debug_callback(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLsizei length, const GLchar *message, const GLvoid *)
|
||||
{
|
||||
std::string source_str {"OtherSource"};
|
||||
std::string type_str {"other-type"};
|
||||
std::string severity_str {"?"};
|
||||
(void)id;
|
||||
(void)length;
|
||||
|
||||
if(source == GL_DEBUG_SOURCE_API) source_str = "API";
|
||||
if(source == GL_DEBUG_SOURCE_WINDOW_SYSTEM) source_str = "WM";
|
||||
if(source == GL_DEBUG_SOURCE_SHADER_COMPILER) source_str = "Compiler";
|
||||
if(source == GL_DEBUG_SOURCE_THIRD_PARTY) source_str = "ThirdParty";
|
||||
if(source == GL_DEBUG_SOURCE_APPLICATION) source_str = "App";
|
||||
|
||||
if(type == GL_DEBUG_TYPE_ERROR) type_str = "error";
|
||||
if(type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR) type_str = "deprecation";
|
||||
if(type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR) type_str = "ub";
|
||||
if(type == GL_DEBUG_TYPE_PORTABILITY) type_str = "non-portable";
|
||||
if(type == GL_DEBUG_TYPE_PERFORMANCE) type_str = "performance";
|
||||
if(type == GL_DEBUG_TYPE_MARKER) type_str = "marker";
|
||||
if(type == GL_DEBUG_TYPE_PUSH_GROUP) type_str = "push-group";
|
||||
if(type == GL_DEBUG_TYPE_POP_GROUP) type_str = "pop-group";
|
||||
|
||||
if(severity == GL_DEBUG_SEVERITY_HIGH) severity_str = "high";
|
||||
if(severity == GL_DEBUG_SEVERITY_MEDIUM) severity_str = "medium";
|
||||
if(severity == GL_DEBUG_SEVERITY_LOW) severity_str = "low";
|
||||
if(severity == GL_DEBUG_SEVERITY_NOTIFICATION) severity_str = "note";
|
||||
|
||||
fprintf(stderr, "[OpenGL/%s/%s/%s] %s\n",
|
||||
source_str.c_str(), type_str.c_str(), severity_str.c_str(), message);
|
||||
}
|
||||
|
||||
int azur_init(char const *title, int window_width, int window_height, bool dbg)
|
||||
{
|
||||
int rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
if(rc < 0) {
|
||||
|
@ -79,6 +114,9 @@ int azur_init(char const *title, int window_width, int window_height)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(dbg)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
|
||||
glcontext = SDL_GL_CreateContext(window);
|
||||
if(!glcontext) {
|
||||
azlog(FATAL, "SDL_GL_CreateContext: %s\n", SDL_GetError());
|
||||
|
@ -98,6 +136,11 @@ int azur_init(char const *title, int window_width, int window_height)
|
|||
}
|
||||
#endif
|
||||
|
||||
if(dbg) {
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(gl_debug_callback, nullptr);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
|
Loading…
Reference in New Issue