Message ID | 20220814160747.52093-2-kunalagarwal1072002@gmail.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Hi Kunal, Quoting Kunal Agarwal via libcamera-devel (2022-08-14 17:07:43) > Shader Class which includes functions for building, > activating, deleting and compiling shaders Great, Thanks for working on this, I've been looking forwards to how we can integrate shaders directly into pipelines! > Signed-off-by: Kunal Agarwal <kunalagarwal1072002@gmail.com> > --- > src/libcamera/pipeline/simple/shader.cpp | 110 +++++++++++++++++++++++ > src/libcamera/pipeline/simple/shader.h | 34 +++++++ > 2 files changed, 144 insertions(+) > create mode 100644 src/libcamera/pipeline/simple/shader.cpp > create mode 100644 src/libcamera/pipeline/simple/shader.h > > diff --git a/src/libcamera/pipeline/simple/shader.cpp b/src/libcamera/pipeline/simple/shader.cpp > new file mode 100644 > index 00000000..f0079618 > --- /dev/null > +++ b/src/libcamera/pipeline/simple/shader.cpp > @@ -0,0 +1,110 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2022, Kunal Agarwal > + * > + * shader.cpp - Shader Handling > + */ > + > +#include "shader.h" > + > +#include <libcamera/base/file.h> > +#include <libcamera/base/log.h> > + > +#include <GLES3/gl3.h> > + > +namespace libcamera { > + > +LOG_DECLARE_CATEGORY(SimplePipeline) It may depend on how the development goes, but I think I'd see the 'Shader' support classes in core libcamera, along with suitable tests that load and test under test/, and 'used' by the Simple Pipeline handler. That said, it probably doesn't hurt for it to start here, and move to core later if / when it gets expanded for it's use cases. > + > +/* Reads a text file and outputs a string with everything in the text file */ > +static std::string get_file_contents(const char *filename) > +{ > + std::string fullname = std::string("/home/pi/Desktop/compile/libcamera/src/libcamera/pipeline/simple/shader/") + filename; Perhaps this needs to be a libcamera defined data path? The path /home/pi/Desktop ... doesn't map to anything useful on my machine... > + > + File file(fullname); > + if (!file.open(File::OpenModeFlag::ReadOnly)) > + return ""; > + > + Span<uint8_t> data = file.map(); > + return std::string(reinterpret_cast<char *>(data.data()), data.size()); At the point this function returns, I think "File file" will destruct, and close - and then from that point on - this data is an invalid use-after-free. > +} > + > +/* Constructor that build the Shader Program from 2 different shaders */ > +void ShaderProgram::callShader(const char *vertexFile, const char *fragmentFile) > +{ > + /* Read vertexFile and fragmentFile and store the strings */ > + std::string vertexCode = get_file_contents(vertexFile); > + std::string fragmentCode = get_file_contents(fragmentFile); > + const char *vertexSource = vertexCode.c_str(); > + const char *fragmentSource = fragmentCode.c_str(); > + > + /* Create the vertex shader, set its source code and compile it. */ > + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); > + glShaderSource(vertexShader, 1, &vertexSource, NULL); > + glCompileShader(vertexShader); > + compileErrors(vertexShader, "VERTEX"); > + > + /* Create the fragment shader, set its source code and compile it. */ > + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); > + glShaderSource(fragmentShader, 1, &fragmentSource, NULL); > + glCompileShader(fragmentShader); > + compileErrors(fragmentShader, "FRAGMENT"); > + > + /* Create Shader Program Object and get its reference */ > + id_ = glCreateProgram(); > + > + /* Attach and wrap-up/link the Vertex and Fragment Shaders to the Shader Program */ > + glAttachShader(id_, vertexShader); > + glAttachShader(id_, fragmentShader); > + glLinkProgram(id_); > + > + /* Checks if Shaders linked succesfully */ > + compileErrors(id_, "PROGRAM"); > + > + /* Delete the Vertex and Fragment Shader objects. Here, they are flagged for deletion > + and will not be deleted until they are detached from the program object. This frees > + up the memory used to store the shader source. */ /* * Multiline comment style should look like * this, and be wrapped at ~80 characters. */ It sounds like the Vertex, and Fragment shader objects are reference counted by OpenGL and so all we're really doing here is releasing our reference, but they'll persist while they are in used by an active shader/program? > + glDeleteShader(vertexShader); > + glDeleteShader(fragmentShader); > +} > + > +/* Activates the Shader Program */ > +void ShaderProgram::activate() > +{ > + glUseProgram(id_); > +} > + > +/* Deletes the Shader Program */ > +void ShaderProgram::deleteProgram() > +{ > + glDeleteProgram(id_); > +} > + > +/* Checks if the different Shaders have compiled properly */ > +void ShaderProgram::compileErrors(unsigned int shader, const char *type) > +{ > + /* Stores status of compilation */ > + GLint hasCompiled; > + GLint logLength; > + /* Character array to store error message in */ > + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); > + char *infoLog = new char[logLength]; > + if (strcmp(type, "PROGRAM") != 0) { > + glGetShaderiv(shader, GL_COMPILE_STATUS, &hasCompiled); > + if (hasCompiled == GL_FALSE) { > + glGetShaderInfoLog(shader, logLength, NULL, infoLog); > + LOG(SimplePipeline, Error) << "SHADER_COMPILATION_ERROR for:" > + << type << "\t" > + << infoLog; > + } > + } else { > + glGetProgramiv(shader, GL_LINK_STATUS, &hasCompiled); > + if (hasCompiled == GL_FALSE) { > + glGetProgramInfoLog(shader, logLength, NULL, infoLog); > + LOG(SimplePipeline, Error) << "SHADER_LINKING_ERROR for:" > + << type << "\t" > + << infoLog; > + } > + } > +} > +} /* namespace libcamera */ > diff --git a/src/libcamera/pipeline/simple/shader.h b/src/libcamera/pipeline/simple/shader.h > new file mode 100644 > index 00000000..921e4040 > --- /dev/null > +++ b/src/libcamera/pipeline/simple/shader.h > @@ -0,0 +1,34 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2022, Kunal Agarwal > + * > + * shader.h - Shader Handling > + */ > + > +#pragma once > + > +#include <iostream> > +#include <string.h> > + > +#include <GL/gl.h> > + > +namespace libcamera { > + > +class ShaderProgram > +{ > +public: > + void callShader(const char *vertexFile, const char *fragmentFile); > + > + void activate(); > + > + void deleteProgram(); > + > + int id() const { return id_; }; > + > +private: > + /* Reference ID of the Shader Program */ > + GLuint id_; > + void compileErrors(unsigned int shader, const char *type); > +}; > + > +} /* namespace libcamera */ > -- > 2.25.1 >
diff --git a/src/libcamera/pipeline/simple/shader.cpp b/src/libcamera/pipeline/simple/shader.cpp new file mode 100644 index 00000000..f0079618 --- /dev/null +++ b/src/libcamera/pipeline/simple/shader.cpp @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Kunal Agarwal + * + * shader.cpp - Shader Handling + */ + +#include "shader.h" + +#include <libcamera/base/file.h> +#include <libcamera/base/log.h> + +#include <GLES3/gl3.h> + +namespace libcamera { + +LOG_DECLARE_CATEGORY(SimplePipeline) + +/* Reads a text file and outputs a string with everything in the text file */ +static std::string get_file_contents(const char *filename) +{ + std::string fullname = std::string("/home/pi/Desktop/compile/libcamera/src/libcamera/pipeline/simple/shader/") + filename; + + File file(fullname); + if (!file.open(File::OpenModeFlag::ReadOnly)) + return ""; + + Span<uint8_t> data = file.map(); + return std::string(reinterpret_cast<char *>(data.data()), data.size()); +} + +/* Constructor that build the Shader Program from 2 different shaders */ +void ShaderProgram::callShader(const char *vertexFile, const char *fragmentFile) +{ + /* Read vertexFile and fragmentFile and store the strings */ + std::string vertexCode = get_file_contents(vertexFile); + std::string fragmentCode = get_file_contents(fragmentFile); + const char *vertexSource = vertexCode.c_str(); + const char *fragmentSource = fragmentCode.c_str(); + + /* Create the vertex shader, set its source code and compile it. */ + GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &vertexSource, NULL); + glCompileShader(vertexShader); + compileErrors(vertexShader, "VERTEX"); + + /* Create the fragment shader, set its source code and compile it. */ + GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &fragmentSource, NULL); + glCompileShader(fragmentShader); + compileErrors(fragmentShader, "FRAGMENT"); + + /* Create Shader Program Object and get its reference */ + id_ = glCreateProgram(); + + /* Attach and wrap-up/link the Vertex and Fragment Shaders to the Shader Program */ + glAttachShader(id_, vertexShader); + glAttachShader(id_, fragmentShader); + glLinkProgram(id_); + + /* Checks if Shaders linked succesfully */ + compileErrors(id_, "PROGRAM"); + + /* Delete the Vertex and Fragment Shader objects. Here, they are flagged for deletion + and will not be deleted until they are detached from the program object. This frees + up the memory used to store the shader source. */ + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); +} + +/* Activates the Shader Program */ +void ShaderProgram::activate() +{ + glUseProgram(id_); +} + +/* Deletes the Shader Program */ +void ShaderProgram::deleteProgram() +{ + glDeleteProgram(id_); +} + +/* Checks if the different Shaders have compiled properly */ +void ShaderProgram::compileErrors(unsigned int shader, const char *type) +{ + /* Stores status of compilation */ + GLint hasCompiled; + GLint logLength; + /* Character array to store error message in */ + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); + char *infoLog = new char[logLength]; + if (strcmp(type, "PROGRAM") != 0) { + glGetShaderiv(shader, GL_COMPILE_STATUS, &hasCompiled); + if (hasCompiled == GL_FALSE) { + glGetShaderInfoLog(shader, logLength, NULL, infoLog); + LOG(SimplePipeline, Error) << "SHADER_COMPILATION_ERROR for:" + << type << "\t" + << infoLog; + } + } else { + glGetProgramiv(shader, GL_LINK_STATUS, &hasCompiled); + if (hasCompiled == GL_FALSE) { + glGetProgramInfoLog(shader, logLength, NULL, infoLog); + LOG(SimplePipeline, Error) << "SHADER_LINKING_ERROR for:" + << type << "\t" + << infoLog; + } + } +} +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/shader.h b/src/libcamera/pipeline/simple/shader.h new file mode 100644 index 00000000..921e4040 --- /dev/null +++ b/src/libcamera/pipeline/simple/shader.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Kunal Agarwal + * + * shader.h - Shader Handling + */ + +#pragma once + +#include <iostream> +#include <string.h> + +#include <GL/gl.h> + +namespace libcamera { + +class ShaderProgram +{ +public: + void callShader(const char *vertexFile, const char *fragmentFile); + + void activate(); + + void deleteProgram(); + + int id() const { return id_; }; + +private: + /* Reference ID of the Shader Program */ + GLuint id_; + void compileErrors(unsigned int shader, const char *type); +}; + +} /* namespace libcamera */
Shader Class which includes functions for building, activating, deleting and compiling shaders Signed-off-by: Kunal Agarwal <kunalagarwal1072002@gmail.com> --- src/libcamera/pipeline/simple/shader.cpp | 110 +++++++++++++++++++++++ src/libcamera/pipeline/simple/shader.h | 34 +++++++ 2 files changed, 144 insertions(+) create mode 100644 src/libcamera/pipeline/simple/shader.cpp create mode 100644 src/libcamera/pipeline/simple/shader.h