#ifndef _GFX_H_
#define _GFX_H_
#include <alias/memory.h>
#include <alias/math.h>
#include <stdbool.h>
#include "glad.h"
#define THIN_GL_MAX_ATTRIBUTES 16
#define THIN_GL_MAX_BINDINGS 2
#define THIN_GL_MAX_UNIFORMS 16
#define THIN_GL_MAX_IMAGES 16
#define THIN_GL_MAX_BUFFERS 16
#define THIN_GL_VERTEX_BIT 0x01
#define THIN_GL_GEOMETRY_BIT 0x02
#define THIN_GL_TESSC_BIT 0x04
#define THIN_GL_TESSE_BIT 0x08
#define THIN_GL_FRAGMENT_BIT 0x10
#define THIN_GL_LOCAL_GROUP_SIZE_SUBGROUP_SIZE 0xFFFFFFFF
typedef void (*GL_VoidFn)(void);
enum GL_Type {
GL_Type_Unused,
GL_Type_Float,
GL_Type_Float2,
GL_Type_Float3,
GL_Type_Float4,
GL_Type_Double,
GL_Type_Double2,
GL_Type_Double3,
GL_Type_Double4,
GL_Type_Int,
GL_Type_Int2,
GL_Type_Int3,
GL_Type_Int4,
GL_Type_Uint,
GL_Type_Uint2,
GL_Type_Uint3,
GL_Type_Uint4,
GL_Type_Bool,
GL_Type_Bool2,
GL_Type_Bool3,
GL_Type_Bool4,
GL_Type_Float2x2,
GL_Type_Float3x3,
GL_Type_Float4x4,
GL_Type_Float2x3,
GL_Type_Float2x4,
GL_Type_Float3x2,
GL_Type_Float3x4,
GL_Type_Float4x2,
GL_Type_Float4x3,
GL_Type_Double2x2,
GL_Type_Double3x3,
GL_Type_Double4x4,
GL_Type_Double2x3,
GL_Type_Double2x4,
GL_Type_Double3x2,
GL_Type_Double3x4,
GL_Type_Double4x2,
GL_Type_Double4x3,
GL_Type_Sampler1D,
GL_Type_Sampler2D,
GL_Type_Sampler3D,
GL_Type_SamplerCube,
GL_Type_Sampler1DShadow,
GL_Type_Sampler2DShadow,
GL_Type_Sampler1DArray,
GL_Type_Sampler2DArray,
GL_Type_SamplerCubeArray,
GL_Type_Sampler1DArrayShadow,
GL_Type_Sampler2DArrayShadow,
GL_Type_Sampler2DMultisample,
GL_Type_Sampler2DMultisampleArray,
GL_Type_SamplerCubeShadow,
GL_Type_SamplerCubeArrayShadow,
GL_Type_SamplerBuffer,
GL_Type_Sampler2DRect,
GL_Type_Sampler2DRectShadow,
GL_Type_IntSampler1D,
GL_Type_IntSampler2D,
GL_Type_IntSampler3D,
GL_Type_IntSamplerCube,
GL_Type_IntSampler1DArray,
GL_Type_IntSampler2DArray,
GL_Type_IntSamplerCubeMapArray,
GL_Type_IntSampler2DMultisample,
GL_Type_IntSampler2DMultisampleArray,
GL_Type_IntSamplerBuffer,
GL_Type_IntSampler2DRect,
GL_Type_UintSampler1D,
GL_Type_UintSampler2D,
GL_Type_UintSampler3D,
GL_Type_UintSamplerCube,
GL_Type_UintSampler1DArray,
GL_Type_UintSampler2DArray,
GL_Type_UintSamplerCubeMapArray,
GL_Type_UintSampler2DMultisample,
GL_Type_UintSampler2DMultisampleArray,
GL_Type_UintSamplerBuffer,
GL_Type_UintSampler2DRect,
GL_Type_Image1D,
GL_Type_Image2D,
GL_Type_Image3D,
GL_Type_Image2DRect,
GL_Type_ImageCube,
GL_Type_ImageBuffer,
GL_Type_Image1DArray,
GL_Type_Image2DArray,
GL_Type_ImageCubeArray,
GL_Type_Image2DMultisample,
GL_Type_Image2DMultisampleArray,
GL_Type_IntImage1D,
GL_Type_IntImage2D,
GL_Type_IntImage3D,
GL_Type_IntImage2DRect,
GL_Type_IntImageCube,
GL_Type_IntImageBuffer,
GL_Type_IntImage1DArray,
GL_Type_IntImage2DArray,
GL_Type_IntImageCubeArray,
GL_Type_IntImage2DMultisample,
GL_Type_IntImage2DMultisampleArray,
GL_Type_UintImage1D,
GL_Type_UintImage2D,
GL_Type_UintImage3D,
GL_Type_UintImage2DRect,
GL_Type_UintImageCube,
GL_Type_UintImageBuffer,
GL_Type_UintImage1DArray,
GL_Type_UintImage2DArray,
GL_Type_UintImageCubeArray,
GL_Type_UintImage2DMultisample,
GL_Type_UintImage2DMultisampleArray,
GL_Type_AtomicUint,
GL_Type_InlineStructure, GL_Type_ShaderStorageBuffer
};
struct GL_UniformData {
const void *pointer;
GLboolean transpose;
const struct GL_Buffer *buffer;
union {
float _float;
float vec[4];
float mat[16];
GLint _int;
GLint ivec[4];
GLint imat[16];
GLuint uint;
GLuint uvec[4];
GLuint umat[16];
};
};
struct GL_ShaderSnippet {
const struct GL_ShaderSnippet *requires[8];
const char *code;
uint32_t structure_size;
GLuint emit_index;
};
struct GL_Shader {
const struct GL_ShaderSnippet *requires[8];
const char *code;
GLuint object;
};
struct GL_ShaderResource {
enum GL_Type type;
const char *name;
GLsizei count;
union {
struct {
GL_VoidFn prepare;
uint32_t prepare_draw_index;
struct GL_UniformData data;
} uniform;
struct {
struct GL_ShaderSnippet *snippet;
union {
struct GL_Buffer *buffer;
struct GL_Buffer *buffers[THIN_GL_MAX_BUFFERS];
};
} block;
};
};
#define THIN_GL_PIPILINE_STATE_FIELDS \
struct { \
GLbitfield stage_bits; \
enum GL_Type type; \
const char *name; \
GLsizei count; \
const struct GL_ShaderSnippet *struture; \
} uniform[THIN_GL_MAX_UNIFORMS]; \
struct { \
GLbitfield stage_bits; \
struct GL_ShaderResource *resource; \
} global[THIN_GL_MAX_UNIFORMS]; \
struct { \
GLbitfield stage_bits; \
enum GL_Type type; \
const char *name; \
} image[THIN_GL_MAX_IMAGES]; \
\
GLuint program_object;
struct GL_PipelineState {
THIN_GL_PIPILINE_STATE_FIELDS
};
#define THIN_GL_STAGE_FIELDS \
const char *source; \
\
GLuint shader_object;
struct GL_VertexStage {
THIN_GL_STAGE_FIELDS
GLenum primitive;
struct {
GLuint binding;
alias_memory_Format format;
GLint size;
const GLchar *name;
GLuint offset;
} attribute[THIN_GL_MAX_ATTRIBUTES];
struct {
GLsizei stride;
GLuint divisor;
} binding[THIN_GL_MAX_BINDINGS];
GLuint vertex_array_object;
};
struct GL_DrawState {
THIN_GL_PIPILINE_STATE_FIELDS
GLenum primitive;
struct {
GLuint binding;
alias_memory_Format format;
GLint size;
const GLchar *name;
GLuint offset;
} attribute[THIN_GL_MAX_ATTRIBUTES];
struct {
GLsizei stride;
GLuint divisor;
} binding[THIN_GL_MAX_BINDINGS];
const struct GL_Shader *vertex_shader;
bool depth_test_enable;
bool depth_mask;
float depth_range_min;
float depth_range_max;
const struct GL_Shader *fragment_shader;
bool blend_enable;
GLenum blend_src_factor;
GLenum blend_dst_factor;
GLuint vertex_shader_object;
GLuint fragment_shader_object;
GLuint vertex_array_object;
};
struct GL_ComputeState {
THIN_GL_PIPILINE_STATE_FIELDS
const struct GL_Shader *shader;
GLuint local_group_x;
GLuint local_group_y;
GLuint local_group_z;
GLuint shader_object;
};
struct GL_Buffer {
enum {
GL_Buffer_Static, GL_Buffer_Temporary, GL_Buffer_GPU, GL_Buffer_CPU, } kind;
GLuint buffer;
GLsizei size;
void *mapping;
GLintptr offset;
bool dirty;
};
#define THIN_GL_PIPILINE_ASSETS_FIELDS \
GLuint image[THIN_GL_MAX_IMAGES]; \
struct GL_UniformData uniforms[THIN_GL_MAX_UNIFORMS];
struct GL_PipelineAssets {
THIN_GL_PIPILINE_ASSETS_FIELDS
};
struct GL_DrawAssets {
THIN_GL_PIPILINE_ASSETS_FIELDS
const struct GL_Buffer *element_buffer;
uint32_t element_buffer_offset;
const struct GL_Buffer *vertex_buffers[THIN_GL_MAX_BINDINGS];
};
struct GL_ComputeAssets {
THIN_GL_PIPILINE_ASSETS_FIELDS
};
void GL_initialize_draw_state(const struct GL_DrawState *state);
GLbitfield GL_apply_draw_state(const struct GL_DrawState *state);
GLbitfield GL_apply_draw_assets(const struct GL_DrawState *state, const struct GL_DrawAssets *assets);
void GL_draw_arrays(const struct GL_DrawState *state, const struct GL_DrawAssets *assets, GLint first, GLsizei count,
GLsizei instancecount, GLuint baseinstance);
void GL_draw_elements(const struct GL_DrawState *state, const struct GL_DrawAssets *assets, GLsizei count,
GLsizei instancecount, GLint basevertex, GLuint baseinstance);
void GL_draw_elements_indirect(const struct GL_DrawState *state, const struct GL_DrawAssets *assets,
const struct GL_Buffer *indirect, GLsizei indirect_offset);
void GL_initialize_compute_state(const struct GL_ComputeState *state);
GLbitfield GL_apply_compute_state(const struct GL_ComputeState *state);
GLbitfield GL_apply_compute_assets(const struct GL_ComputeState *state, const struct GL_ComputeAssets *assets);
void GL_compute(const struct GL_ComputeState *state, const struct GL_ComputeAssets *assets, GLuint num_groups_x,
GLuint num_groups_y, GLuint num_groups_z);
void GL_compute_indirect(const struct GL_ComputeState *state, const struct GL_ComputeAssets *assets,
const struct GL_Buffer *indirect, GLsizei indirect_offset);
struct GL_Buffer GL_allocate_static_buffer(GLenum type, GLsizei size, const void *data);
struct GL_Buffer GL_allocate_temporary_buffer(GLenum type, GLsizei size);
struct GL_Buffer GL_allocate_temporary_buffer_from(GLenum type, GLsizei size, const void *data);
void *GL_update_buffer_begin(const struct GL_Buffer *buffer, GLintptr offset, GLsizei size);
void GL_update_buffer_end(const struct GL_Buffer *buffer, GLintptr offset, GLsizei size);
GLbitfield GL_flush_buffer(const struct GL_Buffer *buffer, GLbitfield read_barrier_bits);
void GL_free_buffer(const struct GL_Buffer *buffer);
void GL_reset_temporary_buffers(void);
void GL_temporary_buffer_stats(GLenum type, uint32_t *total_allocated, uint32_t *used);
void GL_destroy_buffer(const struct GL_Buffer *buffer);
void GL_ShaderResource_prepare(const struct GL_ShaderResource *resource);
static inline void GL_matrix_construct(float xx, float yx, float zx, float wx, float xy, float yy, float zy, float wy,
float xz, float yz, float zz, float wz, float xw, float yw, float zw, float ww,
float result[16]) {
result[0] = xx;
result[1] = xy;
result[2] = xz;
result[3] = xw;
result[4] = yx;
result[5] = yy;
result[6] = yz;
result[7] = yw;
result[8] = zx;
result[9] = zy;
result[10] = zz;
result[11] = zw;
result[12] = wx;
result[13] = wy;
result[14] = wz;
result[15] = ww;
}
static inline void GL_matrix_identity(float result[16]) {
GL_matrix_construct(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_translation(float x, float y, float z, float result[16]) {
GL_matrix_construct(
1, 0, 0, x,
0, 1, 0, y,
0, 0, 1, z,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_scale(float x, float y, float z, float result[16]) {
GL_matrix_construct(
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_rotation(float angle, float x, float y, float z, float result[16]) {
double magnitude = sqrt(x * x + y * y + z * z);
if(magnitude < alias_R_MIN) {
GL_matrix_identity(result);
return;
}
double one_over_magnitude = 1.0 / magnitude;
double a = angle * 0.01745329251;
x *= one_over_magnitude;
y *= one_over_magnitude;
z *= one_over_magnitude;
double s = sin(a);
double c = cos(a);
double one_minus_c = 1.0 - c;
double xs = x * s;
double ys = y * s;
double zs = z * s;
double xc = x * one_minus_c;
double yc = y * one_minus_c;
double zc = z * one_minus_c;
double m_xx = (xc * x) + c;
double m_xy = (xc * y) + zs;
double m_xz = (xc * z) - ys;
double m_yx = (yc * x) - zs;
double m_yy = (yc * y) + c;
double m_yz = (yc * z) + xs;
double m_zx = (zc * x) + ys;
double m_zy = (zc * y) - xs;
double m_zz = (zc * z) + c;
GL_matrix_construct(
m_xx, m_yx, m_zx, 0,
m_xy, m_yy, m_zy, 0,
m_xz, m_yz, m_zz, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_rotation_x(float angle, float result[16]) {
float a = angle * 0.01745329251;
float s = sin(a);
float c = cos(a);
GL_matrix_construct(
1, 0, 0, 0,
0, c, -s, 0,
0, s, c, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_rotation_y(float angle, float result[16]) {
float a = angle * 0.01745329251;
float s = sin(a);
float c = cos(a);
GL_matrix_construct(
c, 0, s, 0,
0, 1, 0, 0,
-s, 0, c, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_rotation_z(float angle, float result[16]) {
float a = angle * 0.01745329251;
float s = sin(a);
float c = cos(a);
GL_matrix_construct(
c, -s, 0, 0,
s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_frustum(float left, float right, float bottom, float top, float znear, float zfar,
float result[16]) {
float x = (2 * znear) / (right - left);
float y = (2 * znear) / (top - bottom);
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(zfar + znear) / (zfar - znear);
float d = -(2 * zfar * znear) / (zfar - znear);
GL_matrix_construct(
x, 0, a, 0,
0, y, b, 0,
0, 0, c, d,
0, 0, -1, 0,
result
);
}
static inline void GL_matrix_ortho(float left, float right, float bottom, float top, float znear, float zfar,
float result[16]) {
float x = 2 / (right - left);
float y = 2 / (top - bottom);
float z = -2 / (zfar - znear);
float a = -(right + left) / (right - left);
float b = -(top + bottom) / (top - bottom);
float c = -(zfar + znear) / (zfar - znear);
GL_matrix_construct(
x, 0, 0, a,
0, y, 0, b,
0, 0, z, c,
0, 0, 0, 1,
result
);
}
static inline void GL_matrix_multiply(const float a[16], const float b[16], float result[16]) {
float m[16];
for(uint32_t i = 0; i < 4; i++) {
float row[4] = {a[0 + i], a[4 + i], a[8 + i], a[12 + i]};
m[ 0 + i] = row[0] * b[ 0 + 0] + row[1] * b[ 0 + 1] + row[2] * b[ 0 + 2] + row[3] * b[ 0 + 3];
m[ 4 + i] = row[0] * b[ 4 + 0] + row[1] * b[ 4 + 1] + row[2] * b[ 4 + 2] + row[3] * b[ 4 + 3];
m[ 8 + i] = row[0] * b[ 8 + 0] + row[1] * b[ 8 + 1] + row[2] * b[ 8 + 2] + row[3] * b[ 8 + 3];
m[12 + i] = row[0] * b[12 + 0] + row[1] * b[12 + 1] + row[2] * b[12 + 2] + row[3] * b[12 + 3];
}
alias_memory_copy(result, sizeof(float) * 16, m, sizeof(float) * 16);
}
static inline void GL_translate(float matrix[16], float x, float y, float z) {
float temp[16];
GL_matrix_translation(x, y, z, temp);
GL_matrix_multiply(matrix, temp, matrix);
}
static inline void GL_rotate(float matrix[16], float angle, float x, float y, float z) {
float temp[16];
GL_matrix_rotation(angle, x, y, z, temp);
GL_matrix_multiply(matrix, temp, matrix);
}
static inline void GL_rotate_x(float matrix[16], float angle) {
float temp[16];
GL_matrix_rotation_x(angle, temp);
GL_matrix_multiply(matrix, temp, matrix);
}
static inline void GL_rotate_y(float matrix[16], float angle) {
float temp[16];
GL_matrix_rotation_y(angle, temp);
GL_matrix_multiply(matrix, temp, matrix);
}
static inline void GL_rotate_z(float matrix[16], float angle) {
float temp[16];
GL_matrix_rotation_z(angle, temp);
GL_matrix_multiply(matrix, temp, matrix);
}
#endif