503 lines
23 KiB
C++
Executable File
503 lines
23 KiB
C++
Executable File
// =====================================================================================================================
|
|
// glw, an open-source library that wraps OpenGL structures into classes.
|
|
// Copyright (C) 2024 Medusa Slockbower
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
// =====================================================================================================================
|
|
|
|
#ifndef GLW_SHADER_H
|
|
#define GLW_SHADER_H
|
|
|
|
#include <string>
|
|
#include <format>
|
|
|
|
#include <glm/vec2.hpp>
|
|
#include <glm/vec3.hpp>
|
|
#include <glm/vec4.hpp>
|
|
#include <glm/mat2x2.hpp>
|
|
#include <glm/mat2x3.hpp>
|
|
#include <glm/mat2x4.hpp>
|
|
#include <glm/mat3x2.hpp>
|
|
#include <glm/mat3x3.hpp>
|
|
#include <glm/mat3x4.hpp>
|
|
#include <glm/mat4x2.hpp>
|
|
#include <glm/mat4x3.hpp>
|
|
#include <glm/mat4x4.hpp>
|
|
|
|
#include "common.h"
|
|
|
|
namespace ocu = open_cpp_utils;
|
|
|
|
namespace glw
|
|
{
|
|
|
|
// =====================================================================================================================
|
|
// Definitions
|
|
// =====================================================================================================================
|
|
|
|
|
|
// Typedefs ------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
// Enums ---------------------------------------------------------------------------------------------------------------
|
|
|
|
enum source_type
|
|
{
|
|
vertex = GL_VERTEX_SHADER
|
|
, tess_ctrl = GL_TESS_CONTROL_SHADER
|
|
, tess_eval = GL_TESS_EVALUATION_SHADER
|
|
, geometry = GL_GEOMETRY_SHADER
|
|
, fragment = GL_FRAGMENT_SHADER
|
|
, compute = GL_COMPUTE_SHADER
|
|
};
|
|
|
|
enum uniform_type
|
|
{
|
|
// bool ----------------------------------------------------------------------------------------------------------------
|
|
|
|
b = GL_BOOL
|
|
, bvec2 = GL_BOOL_VEC2
|
|
, bvec3 = GL_BOOL_VEC3
|
|
, bvec4 = GL_BOOL_VEC4
|
|
|
|
|
|
// int -----------------------------------------------------------------------------------------------------------------
|
|
|
|
, i = GL_INT
|
|
, ivec2 = GL_INT_VEC2
|
|
, ivec3 = GL_INT_VEC3
|
|
, ivec4 = GL_INT_VEC4
|
|
|
|
|
|
// unsigned int --------------------------------------------------------------------------------------------------------
|
|
|
|
, u = GL_UNSIGNED_INT
|
|
, uvec2 = GL_UNSIGNED_INT_VEC2
|
|
, uvec3 = GL_UNSIGNED_INT_VEC3
|
|
, uvec4 = GL_UNSIGNED_INT_VEC4
|
|
|
|
|
|
// float ---------------------------------------------------------------------------------------------------------------
|
|
|
|
, f = GL_FLOAT
|
|
, vec2 = GL_FLOAT_VEC2
|
|
, vec3 = GL_FLOAT_VEC3
|
|
, vec4 = GL_FLOAT_VEC4
|
|
, mat2 = GL_FLOAT_MAT2
|
|
, mat3 = GL_FLOAT_MAT3
|
|
, mat4 = GL_FLOAT_MAT4
|
|
, mat2x3 = GL_FLOAT_MAT2x3
|
|
, mat2x4 = GL_FLOAT_MAT2x4
|
|
, mat3x2 = GL_FLOAT_MAT3x2
|
|
, mat3x4 = GL_FLOAT_MAT3x4
|
|
, mat4x2 = GL_FLOAT_MAT4x2
|
|
, mat4x3 = GL_FLOAT_MAT4x3
|
|
|
|
|
|
// double --------------------------------------------------------------------------------------------------------------
|
|
|
|
, d = GL_DOUBLE
|
|
, dvec2 = GL_DOUBLE_VEC2
|
|
, dvec3 = GL_DOUBLE_VEC3
|
|
, dvec4 = GL_DOUBLE_VEC4
|
|
, dmat2 = GL_DOUBLE_MAT2
|
|
, dmat3 = GL_DOUBLE_MAT3
|
|
, dmat4 = GL_DOUBLE_MAT4
|
|
, dmat2x3 = GL_DOUBLE_MAT2x3
|
|
, dmat2x4 = GL_DOUBLE_MAT2x4
|
|
, dmat3x2 = GL_DOUBLE_MAT3x2
|
|
, dmat3x4 = GL_DOUBLE_MAT3x4
|
|
, dmat4x2 = GL_DOUBLE_MAT4x2
|
|
, dmat4x3 = GL_DOUBLE_MAT4x3
|
|
|
|
|
|
// sampler -------------------------------------------------------------------------------------------------------------
|
|
|
|
, sampler1D = GL_SAMPLER_1D
|
|
, sampler1DShadow = GL_SAMPLER_1D_SHADOW
|
|
, sampler1DArray = GL_SAMPLER_1D_ARRAY
|
|
, sampler1DArrayShadow = GL_SAMPLER_1D_ARRAY_SHADOW
|
|
|
|
, sampler2D = GL_SAMPLER_2D
|
|
, sampler2DShadow = GL_SAMPLER_2D_SHADOW
|
|
, sampler2DRect = GL_SAMPLER_2D_RECT
|
|
, sampler2DRectShadow = GL_SAMPLER_2D_RECT_SHADOW
|
|
, sampler2DArray = GL_SAMPLER_2D_ARRAY
|
|
, sampler2DArrayShadow = GL_SAMPLER_2D_ARRAY_SHADOW
|
|
, sampler2DMS = GL_SAMPLER_2D_MULTISAMPLE
|
|
, sampler2DMSArray = GL_SAMPLER_2D_MULTISAMPLE_ARRAY
|
|
|
|
, samplerCube = GL_SAMPLER_CUBE
|
|
, samplerCubeShadow = GL_SAMPLER_CUBE_SHADOW
|
|
, samplerCubeArray = GL_SAMPLER_CUBE_MAP_ARRAY
|
|
|
|
, sampler3D = GL_SAMPLER_3D
|
|
|
|
|
|
// isampler ------------------------------------------------------------------------------------------------------------
|
|
|
|
, isampler1D = GL_INT_SAMPLER_1D
|
|
, isampler1DArray = GL_INT_SAMPLER_1D_ARRAY
|
|
|
|
, isampler2D = GL_INT_SAMPLER_2D
|
|
, isampler2DRect = GL_INT_SAMPLER_2D_RECT
|
|
, isampler2DArray = GL_INT_SAMPLER_2D_ARRAY
|
|
, isampler2DMS = GL_INT_SAMPLER_2D_MULTISAMPLE
|
|
, isampler2DMSArray = GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
|
|
|
|
, isamplerCube = GL_INT_SAMPLER_CUBE
|
|
, isamplerCubeArray = GL_INT_SAMPLER_CUBE_MAP_ARRAY
|
|
|
|
, isampler3D = GL_INT_SAMPLER_3D
|
|
|
|
|
|
// usampler ------------------------------------------------------------------------------------------------------------
|
|
|
|
, usampler1D = GL_UNSIGNED_INT_SAMPLER_1D
|
|
, usampler1DArray = GL_UNSIGNED_INT_SAMPLER_1D_ARRAY
|
|
|
|
, usampler2D = GL_UNSIGNED_INT_SAMPLER_2D
|
|
, usampler2DRect = GL_UNSIGNED_INT_SAMPLER_2D_RECT
|
|
, usampler2DArray = GL_UNSIGNED_INT_SAMPLER_2D_ARRAY
|
|
, usampler2DMS = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE
|
|
, usampler2DMSArray = GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
|
|
|
|
, usamplerCube = GL_UNSIGNED_INT_SAMPLER_CUBE
|
|
, usamplerCubeArray = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY
|
|
|
|
, usampler3D = GL_UNSIGNED_INT_SAMPLER_3D
|
|
|
|
|
|
// image ---------------------------------------------------------------------------------------------------------------
|
|
|
|
, image1D = GL_IMAGE_1D
|
|
, image1DArray = GL_IMAGE_1D_ARRAY
|
|
|
|
, image2D = GL_IMAGE_2D
|
|
, image2DRect = GL_IMAGE_2D_RECT
|
|
, image2DArray = GL_IMAGE_2D_ARRAY
|
|
, image2DMS = GL_IMAGE_2D_MULTISAMPLE
|
|
, image2DMSArray = GL_IMAGE_2D_MULTISAMPLE_ARRAY
|
|
|
|
, imageCube = GL_IMAGE_CUBE
|
|
, imageCubeArray = GL_IMAGE_CUBE_MAP_ARRAY
|
|
|
|
, image3D = GL_IMAGE_3D
|
|
|
|
|
|
// iimage --------------------------------------------------------------------------------------------------------------
|
|
|
|
, iimage1D = GL_INT_IMAGE_1D
|
|
, iimage1DArray = GL_INT_IMAGE_1D_ARRAY
|
|
|
|
, iimage2D = GL_INT_IMAGE_2D
|
|
, iimage2DRect = GL_INT_IMAGE_2D_RECT
|
|
, iimage2DArray = GL_INT_IMAGE_2D_ARRAY
|
|
, iimage2DMS = GL_INT_IMAGE_2D_MULTISAMPLE
|
|
, iimage2DMSArray = GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY
|
|
|
|
, iimageCube = GL_INT_IMAGE_CUBE
|
|
, iimageCubeArray = GL_INT_IMAGE_CUBE_MAP_ARRAY
|
|
|
|
, iimage3D = GL_INT_IMAGE_3D
|
|
|
|
|
|
// uimage --------------------------------------------------------------------------------------------------------------
|
|
|
|
, uimage1D = GL_UNSIGNED_INT_IMAGE_1D
|
|
, uimage1DArray = GL_UNSIGNED_INT_IMAGE_1D_ARRAY
|
|
|
|
, uimage2D = GL_UNSIGNED_INT_IMAGE_2D
|
|
, uimage2DRect = GL_UNSIGNED_INT_IMAGE_2D_RECT
|
|
, uimage2DArray = GL_UNSIGNED_INT_IMAGE_2D_ARRAY
|
|
, uimage2DMS = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE
|
|
, uimage2DMSArray = GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY
|
|
|
|
, uimageCube = GL_UNSIGNED_INT_IMAGE_CUBE
|
|
, uimageCubeArray = GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY
|
|
|
|
, uimage3D = GL_UNSIGNED_INT_IMAGE_3D
|
|
|
|
|
|
// atomic --------------------------------------------------------------------------------------------------------------
|
|
|
|
, atomic_uint = GL_UNSIGNED_INT_ATOMIC_COUNTER
|
|
};
|
|
|
|
|
|
// Buffer Definition ---------------------------------------------------------------------------------------------------
|
|
|
|
class shader
|
|
{
|
|
// Typedefs ============================================================================================================
|
|
|
|
public:
|
|
struct uniform
|
|
{
|
|
public:
|
|
uniform() : shader_(0), name_(""), type_(int8), location_(-1) { }
|
|
uniform(const std::string& str) : shader_(0), name_(str), type_(int8), location_(-1) { }
|
|
uniform(shader& shader, const std::string& name, enum_t type);
|
|
uniform(const uniform& u) : shader_(u.shader_), name_(u.name_), type_(u.type_), location_(u.location_) { }
|
|
~uniform() = default;
|
|
|
|
template<typename T>
|
|
inline uniform& operator=(T v) { assert(false); return *this; }
|
|
|
|
const std::string& name() const { return name_; }
|
|
enum_t type() const { return type_; }
|
|
index_t location() const { return location_; }
|
|
|
|
private:
|
|
handle_t shader_;
|
|
std::string name_;
|
|
enum_t type_;
|
|
index_t location_;
|
|
};
|
|
|
|
// OpenGL Built Ins
|
|
static constexpr char gl_NumWorkGroups[] = "gl_NumWorkGroups";
|
|
static constexpr char gl_WorkGroupID[] = "gl_WorkGroupID";
|
|
static constexpr char gl_LocalInvocationID[] = "gl_LocalInvocationID";
|
|
static constexpr char gl_GlobalInvocationID[] = "gl_GlobalInvocationID";
|
|
static constexpr char gl_LocalInvocationIndex[] = "gl_LocalInvocationIndex";
|
|
|
|
// GLW Built Ins
|
|
static constexpr char glw_RequestedInvocations[] = "glw_RequestedInvocations";
|
|
static inline const std::string built_ins_compute = std::format("uniform ivec3 {};", glw_RequestedInvocations);
|
|
|
|
private:
|
|
using uniform_map = std::unordered_map<std::string, uniform>;
|
|
|
|
|
|
// Functions ===========================================================================================================
|
|
|
|
public:
|
|
|
|
shader();
|
|
~shader();
|
|
|
|
bool attach_source(enum_t type, size_t count, const char** source, const size_t* lengths);
|
|
bool attach_source(enum_t type, const std::vector<std::string>& source);
|
|
bool link();
|
|
|
|
void bind() const;
|
|
|
|
void dispatch(int x = 1, int y = 1, int z = 1);
|
|
|
|
uniform operator[](const std::string& str);
|
|
|
|
const std::string& get_error_string() const { return error_; }
|
|
|
|
inline static std::string group_size(int x, int y, int z)
|
|
{ return std::format("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", x, y, z); }
|
|
|
|
private:
|
|
handle_t handle_;
|
|
std::string error_;
|
|
int work_group_size_[3];
|
|
bool pass_requested_invocations_;
|
|
uniform_map uniforms_;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// =====================================================================================================================
|
|
// Implementation
|
|
// =====================================================================================================================
|
|
|
|
|
|
// uniform -------------------------------------------------------------------------------------------------------------
|
|
|
|
inline shader::uniform::uniform(shader& shader, const std::string& name, enum_t type)
|
|
: shader_(shader.handle_)
|
|
, name_(name)
|
|
, type_(type)
|
|
, location_(0)
|
|
{
|
|
location_ = glGetUniformLocation(shader_, name_.c_str());
|
|
}
|
|
|
|
#define validate(handle, type) if(handle == 0) return *this; assert(type_ == type);
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<bool>(bool v) { validate(shader_, uniform_type::b); glProgramUniform1i(shader_, location_, v); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec2>(glm::bvec2 v) { validate(shader_, uniform_type::bvec2); glProgramUniform2i(shader_, location_, v.x, v.y); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec3>(glm::bvec3 v) { validate(shader_, uniform_type::bvec3); glProgramUniform3i(shader_, location_, v.x, v.y, v.z); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::bvec4>(glm::bvec4 v) { validate(shader_, uniform_type::bvec4); glProgramUniform4i(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<int>(int v) { validate(shader_, uniform_type::i); glProgramUniform1i(shader_, location_, v); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec2>(glm::ivec2 v) { validate(shader_, uniform_type::ivec2); glProgramUniform2i(shader_, location_, v.x, v.y); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec3>(glm::ivec3 v) { validate(shader_, uniform_type::ivec3); glProgramUniform3i(shader_, location_, v.x, v.y, v.z); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::ivec4>(glm::ivec4 v) { validate(shader_, uniform_type::ivec4); glProgramUniform4i(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::uint>(glm::uint v) { validate(shader_, uniform_type::u); glProgramUniform1ui(shader_, location_, v); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec2>(glm::uvec2 v) { validate(shader_, uniform_type::uvec2); glProgramUniform2ui(shader_, location_, v.x, v.y); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec3>(glm::uvec3 v) { validate(shader_, uniform_type::uvec3); glProgramUniform3ui(shader_, location_, v.x, v.y, v.z); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::uvec4>(glm::uvec4 v) { validate(shader_, uniform_type::uvec4); glProgramUniform4ui(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<float>(float v) { validate(shader_, uniform_type::f); glProgramUniform1f(shader_, location_, v); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::vec2>(glm::vec2 v) { validate(shader_, uniform_type::vec2); glProgramUniform2f(shader_, location_, v.x, v.y); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::vec3>(glm::vec3 v) { validate(shader_, uniform_type::vec3); glProgramUniform3f(shader_, location_, v.x, v.y, v.z); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::vec4>(glm::vec4 v) { validate(shader_, uniform_type::vec4); glProgramUniform4f(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<double>(double v) { validate(shader_, uniform_type::d); glProgramUniform1d(shader_, location_, v); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec2>(glm::dvec2 v) { validate(shader_, uniform_type::dvec2); glProgramUniform2d(shader_, location_, v.x, v.y); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec3>(glm::dvec3 v) { validate(shader_, uniform_type::dvec3); glProgramUniform3d(shader_, location_, v.x, v.y, v.z); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dvec4>(glm::dvec4 v) { validate(shader_, uniform_type::dvec4); glProgramUniform4d(shader_, location_, v.x, v.y, v.z, v.w); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2> (glm::mat2 v) { validate(shader_, uniform_type::mat2); glProgramUniformMatrix2fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2x3>(glm::mat2x3 v) { validate(shader_, uniform_type::mat2x3); glProgramUniformMatrix2x3fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat2x4>(glm::mat2x4 v) { validate(shader_, uniform_type::mat2x4); glProgramUniformMatrix2x4fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3x2>(glm::mat3x2 v) { validate(shader_, uniform_type::mat3x2); glProgramUniformMatrix3x2fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3> (glm::mat3 v) { validate(shader_, uniform_type::mat3); glProgramUniformMatrix3fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat3x4>(glm::mat3x4 v) { validate(shader_, uniform_type::mat3x4); glProgramUniformMatrix3x4fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4x2>(glm::mat4x2 v) { validate(shader_, uniform_type::mat4x2); glProgramUniformMatrix4x2fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4x3>(glm::mat4x3 v) { validate(shader_, uniform_type::mat4x3); glProgramUniformMatrix4x3fv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::mat4> (glm::mat4 v) { validate(shader_, uniform_type::mat4); glProgramUniformMatrix4fv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2> (glm::dmat2 v) { validate(shader_, uniform_type::dmat2); glProgramUniformMatrix2dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2x3>(glm::dmat2x3 v) { validate(shader_, uniform_type::dmat2x3); glProgramUniformMatrix2x3dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat2x4>(glm::dmat2x4 v) { validate(shader_, uniform_type::dmat2x4); glProgramUniformMatrix2x4dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3x2>(glm::dmat3x2 v) { validate(shader_, uniform_type::dmat3x2); glProgramUniformMatrix3x2dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3> (glm::dmat3 v) { validate(shader_, uniform_type::dmat3); glProgramUniformMatrix3dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat3x4>(glm::dmat3x4 v) { validate(shader_, uniform_type::dmat3x4); glProgramUniformMatrix3x4dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4x2>(glm::dmat4x2 v) { validate(shader_, uniform_type::dmat4x2); glProgramUniformMatrix4x2dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4x3>(glm::dmat4x3 v) { validate(shader_, uniform_type::dmat4x3); glProgramUniformMatrix4x3dv(shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
template<> inline shader::uniform& shader::uniform::operator=<glm::dmat4> (glm::dmat4 v) { validate(shader_, uniform_type::dmat4); glProgramUniformMatrix4dv (shader_, location_, 1, GL_FALSE, &v[0][0]); return *this; }
|
|
|
|
|
|
// shader --------------------------------------------------------------------------------------------------------------
|
|
|
|
inline shader::shader()
|
|
: handle_(glCreateProgram())
|
|
, work_group_size_{ 1 }
|
|
, pass_requested_invocations_(false)
|
|
{
|
|
|
|
}
|
|
|
|
inline shader::~shader()
|
|
{
|
|
glDeleteProgram(handle_);
|
|
}
|
|
|
|
inline bool shader::attach_source(enum_t type, size_t count, const char** source, const size_t* lengths)
|
|
{
|
|
handle_t shader = glCreateShader(type);
|
|
glShaderSource(shader, count, source, lengths);
|
|
glCompileShader(shader);
|
|
|
|
int result; glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
|
|
|
if(result) glAttachShader(handle_, shader);
|
|
else
|
|
{
|
|
int res; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &res);
|
|
error_.resize(res);
|
|
glGetShaderInfoLog(shader, res, &res, error_.data());
|
|
}
|
|
|
|
glDeleteShader(shader);
|
|
|
|
return result;
|
|
}
|
|
|
|
inline bool shader::attach_source(enum_t type, const std::vector<std::string>& source)
|
|
{
|
|
std::vector<const char*> src; src.reserve(source.size());
|
|
std::vector<size_t> len; len.reserve(source.size());
|
|
|
|
for(const std::string& str : source)
|
|
{
|
|
src.push_back(str.c_str());
|
|
len.push_back(static_cast<int>(str.length()));
|
|
}
|
|
|
|
return attach_source(type, static_cast<int>(source.size()), src.data(), len.data());
|
|
}
|
|
|
|
inline bool shader::link()
|
|
{
|
|
glLinkProgram(handle_);
|
|
|
|
int result; glGetProgramiv(handle_, GL_LINK_STATUS, &result);
|
|
|
|
if(!result)
|
|
{
|
|
int res; glGetProgramiv(handle_, GL_INFO_LOG_LENGTH, &res);
|
|
error_.resize(res);
|
|
glGetProgramInfoLog(handle_, res, &res, error_.data());
|
|
|
|
return false;
|
|
}
|
|
|
|
glGetProgramiv(handle_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &result);
|
|
std::string buffer(result + 1, '\0');
|
|
size_t max_length = static_cast<int>(buffer.capacity());
|
|
char* str = buffer.data();
|
|
glGetProgramiv(handle_, GL_ACTIVE_UNIFORMS, &result);
|
|
|
|
for(int i = 0; i < result; ++i)
|
|
{
|
|
enum_t type; size_t length, size;
|
|
glGetActiveUniform(handle_, i, max_length, &length, &size, &type, str);
|
|
std::string res = buffer.substr(0, length).c_str();
|
|
uniforms_[res] = uniform(*this, res, type);
|
|
|
|
const bool len = length == sizeof(glw_RequestedInvocations) - 1;
|
|
const bool cmp = (strncmp(buffer.c_str(), glw_RequestedInvocations, length) == 0);
|
|
pass_requested_invocations_ |= (len && cmp);
|
|
}
|
|
|
|
glGetProgramiv(handle_, GL_COMPUTE_WORK_GROUP_SIZE, work_group_size_);
|
|
|
|
return true;
|
|
}
|
|
|
|
inline void shader::bind() const
|
|
{
|
|
glUseProgram(handle_);
|
|
}
|
|
|
|
inline void shader::dispatch(int x, int y, int z)
|
|
{
|
|
int num_groups_x = ceil_div(x, work_group_size_[0]);
|
|
int num_groups_y = ceil_div(y, work_group_size_[1]);
|
|
int num_groups_z = ceil_div(z, work_group_size_[2]);
|
|
|
|
bind();
|
|
|
|
if(pass_requested_invocations_)
|
|
this->operator[](glw_RequestedInvocations) = glm::ivec3(x, y, z);
|
|
|
|
glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
|
|
}
|
|
|
|
inline shader::uniform shader::operator[](const std::string &str)
|
|
{
|
|
auto it = uniforms_.find(str);
|
|
|
|
if(it != uniforms_.end())
|
|
return it->second;
|
|
|
|
return uniform();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#endif //SHADER_H
|