Skip to content

Instantly share code, notes, and snippets.

@jsimmons
Created April 5, 2016 10:24
Show Gist options
  • Save jsimmons/0805d9ac5c07947cc7b02a667dfc8add to your computer and use it in GitHub Desktop.
Save jsimmons/0805d9ac5c07947cc7b02a667dfc8add to your computer and use it in GitHub Desktop.
GLFAST + MINIMAL GL
#include <stdint.h>
#include <stdbool.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <dlfcn.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <time.h>
#define SCRW 800
#define SCRH 600
#ifndef i8
#define i8 int8_t
#endif
#ifndef i16
#define i16 int16_t
#endif
#ifndef i32
#define i32 int32_t
#endif
#ifndef i64
#define i64 int64_t
#endif
#ifndef u8
#define u8 uint8_t
#endif
#ifndef u16
#define u16 uint16_t
#endif
#ifndef u32
#define u32 uint32_t
#endif
#ifndef u64
#define u64 uint64_t
#endif
#ifndef f16
#define f16 uint16_t
#endif
#ifndef f32
#define f32 float
#endif
#ifndef f64
#define f64 double
#endif
#define GL_TRUE 1
#define GL_FALSE 0
#define GL_R8 0x8229
#define GL_R16F 0x822D
#define GL_R32F 0x822E
#define GL_R8I 0x8231
#define GL_R16I 0x8233
#define GL_R32I 0x8235
#define GL_R8UI 0x8232
#define GL_R16UI 0x8234
#define GL_R32UI 0x8236
#define GL_RG8 0x822B
#define GL_RG16F 0x822F
#define GL_RG32F 0x8230
#define GL_RG8I 0x8237
#define GL_RG16I 0x8239
#define GL_RG32I 0x823B
#define GL_RG8UI 0x8238
#define GL_RG16UI 0x823A
#define GL_RG32UI 0x823C
#define GL_RGB16F 0x881B
#define GL_RGB32F 0x8815
#define GL_RGB32I 0x8D83
#define GL_RGB32UI 0x8D71
#define GL_RGBA8 0x8058
#define GL_RGBA16F 0x881A
#define GL_RGBA32F 0x8814
#define GL_RGBA8I 0x8D8E
#define GL_RGBA16I 0x8D88
#define GL_RGBA32I 0x8D82
#define GL_RGBA8UI 0x8D7C
#define GL_RGBA16UI 0x8D76
#define GL_RGBA32UI 0x8D70
#define GL_RGB8 0x8051
#define GL_SRGB8 0x8C41
#define GL_SRGB8_ALPHA8 0x8C43
#define GL_DEPTH_COMPONENT16 0x81A5
#define GL_DEPTH_COMPONENT24 0x81A6
#define GL_DEPTH_COMPONENT32 0x81A7
#define GL_TEXTURE_BUFFER 0x8C2A
#define GL_MAP_WRITE_BIT 0x0002
#define GL_MAP_PERSISTENT_BIT 0x0040
#define GL_MAP_COHERENT_BIT 0x0080
#define GL_FRAMEBUFFER 0x8D40
#define GL_DEPTH_BUFFER_BIT 0x00000100
#define GL_COLOR_BUFFER_BIT 0x00004000
#define GL_DEPTH_ATTACHMENT 0x8D00
#define GL_COLOR_ATTACHMENT0 0x8CE0
#define GL_TEXTURE_2D_ARRAY 0x8C1A
#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
#define GL_RGB 0x1907
#define GL_RGBA 0x1908
#define GL_BGR 0x80E0
#define GL_BGRA 0x80E1
#define GL_BYTE 0x1400
#define GL_UNSIGNED_BYTE 0x1401
#define GL_SHORT 0x1402
#define GL_UNSIGNED_SHORT 0x1403
#define GL_INT 0x1404
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_NEAREST 0x2600
#define GL_LINEAR 0x2601
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_REPEAT 0x2901
#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_VERTEX_SHADER_BIT 0x00000001
#define GL_FRAGMENT_SHADER_BIT 0x00000002
#define GL_CULL_FACE 0x0B44
#define GL_BLEND 0x0BE2
#define GL_DEPTH_TEST 0x0B71
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
#define GL_TRIANGLES 0x0004
#define GL_DEBUG_SOURCE_API 0x8246
#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
#define GL_DEBUG_SEVERITY_HIGH 0x9146
#define GL_DEBUG_TYPE_ERROR 0x824C
#define GLX_RGBA 4
#define GLX_DOUBLEBUFFER 5
#define GLX_DEPTH_SIZE 12
typedef struct {} *GLXContext;
typedef XID GLXDrawable;
#define countof(x) (sizeof(x) / sizeof((x)[0]))
static __inline long __syscall2(long n, long a1, long a2)
{
unsigned long ret;
__asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2)
: "rcx", "r11", "memory");
return ret;
}
static __inline uint64_t time_monotonic(void)
{
struct timespec now;
__syscall2(SYS_clock_gettime, CLOCK_MONOTONIC_RAW, (long)&now);
return now.tv_sec * 1000000 + now.tv_nsec / 1000;
}
static int visual_hints[] = {
GLX_RGBA,
GLX_DEPTH_SIZE, 24,
GLX_DOUBLEBUFFER,
None
};
static const char *sym_names =
"libX11.so\0"
"XOpenDisplay\0"
"XCreateSimpleWindow\0"
"XSelectInput\0"
"XMapWindow\0"
"XPending\0"
"XNextEvent\0"
"XkbKeycodeToKeysym\0"
"\0"
"libGL.so\0"
"glXChooseVisual\0"
"glXCreateContext\0"
"glXMakeCurrent\0"
"glXSwapBuffers\0"
"glClear\0"
"glFinish\0"
"glEnable\0"
"glDisable\0"
"glViewport\0"
"glCreateBuffers\0"
"glCreateTextures\0"
"glCreateSamplers\0"
"glCreateFramebuffers\0"
"glCreateShaderProgramv\0"
"glCreateProgramPipelines\0"
"glDeleteBuffers\0"
"glDeleteTextures\0"
"glDeleteSamplers\0"
"glDeleteFramebuffers\0"
"glDeleteProgram\0"
"glDeleteProgramPipelines\0"
"glBindTextures\0"
"glBindSamplers\0"
"glBindFramebuffer\0"
"glBindProgramPipeline\0"
"glNamedBufferStorage\0"
"glMapNamedBufferRange\0"
"glTextureBuffer\0"
"glTextureStorage3D\0"
"glTextureSubImage3D\0"
"glGetTextureSubImage\0"
"glGenerateTextureMipmap\0"
"glSamplerParameteri\0"
"glNamedFramebufferTextureLayer\0"
"glNamedFramebufferDrawBuffers\0"
"glUseProgramStages\0"
"glDrawArraysInstancedBaseInstance\0"
"glProgramUniform1uiv\0"
"glProgramUniform1iv\0"
"glProgramUniform1dv\0"
"glProgramUniform1fv\0"
"glProgramUniform2fv\0"
"glProgramUniform3fv\0"
"glProgramUniform4fv\0\0\0";
static void *syms[51];
#define _XOpenDisplay ((Display *(*)(const char *))syms[0])
#define _XCreateSimpleWindow ((Window (*)(Display *, Window, int, int, unsigned, unsigned, unsigned, unsigned long, unsigned long))syms[1])
#define _XSelectInput ((int (*)(Display *, Window, long))syms[2])
#define _XMapWindow ((int (*)(Display *, Window))syms[3])
#define _XPending ((int (*)(Display *))syms[4])
#define _XNextEvent ((int (*)(Display *, XEvent *))syms[5])
#define _XkbKeycodeToKeysym ((KeySym (*)(Display *, KeyCode, int, int))syms[6])
#define _glXChooseVisual ((XVisualInfo *(*)(Display *, int, int *))syms[7])
#define _glXCreateContext ((GLXContext (*)(Display *, XVisualInfo *, GLXContext, Bool))syms[8])
#define _glXMakeCurrent ((bool (*)(Display *, GLXDrawable, GLXContext))syms[9])
#define _glXSwapBuffers ((void (*)(Display *, GLXDrawable))syms[10])
#define _glClear ((void (*)(u32))syms[11])
#define _glFinish ((void (*)())syms[12])
#define _glEnable ((void (*)(u32 cap))syms[13])
#define _glDisable ((void (*)(u32 cap))syms[14])
#define _glViewport ((void (*)(i32 x, i32 y, i32 w, i32 h))syms[15])
#define _glCreateBuffers ((void (*)(i32 n, u32 *buffers))syms[16])
#define _glCreateTextures ((void (*)(u32 target, i32 n, u32 *textures))syms[17])
#define _glCreateSamplers ((void (*)(i32 n, u32 *samplers))syms[18])
#define _glCreateFramebuffers ((void (*)(i32 n, u32 * framebuffers))syms[19])
#define _glCreateShaderProgramv ((u32 (*)(u32 type, i32 count, const char ** strings))syms[20])
#define _glCreateProgramPipelines ((void (*)(i32 n, u32 * pipelines))syms[21])
#define _glDeleteBuffers ((void (*)(i32 n, const u32 * buffers))syms[22])
#define _glDeleteTextures ((void (*)(i32 n, const u32 * textures))syms[23])
#define _glDeleteSamplers ((void (*)(i32 n, const u32 * samplers))syms[24])
#define _glDeleteFramebuffers ((void (*)(i32 n, const u32 * framebuffers))syms[25])
#define _glDeleteProgram ((void (*)(u32 program))syms[26])
#define _glDeleteProgramPipelines ((void (*)(i32 n, const u32 * pipelines))syms[27])
#define _glBindTextures ((void (*)(u32 first, i32 count, const u32 * textures))syms[28])
#define _glBindSamplers ((void (*)(u32 first, i32 count, const u32 * samplers))syms[29])
#define _glBindFramebuffer ((void (*)(u32 target, u32 framebuffer))syms[30])
#define _glBindProgramPipeline ((void (*)(u32 pipeline))syms[31])
#define _glNamedBufferStorage ((void (*)(u32 buffer, ptrdiff_t size, const void * data, u32 flags))syms[32])
#define _glMapNamedBufferRange ((void *(*)(u32 buffer, ptrdiff_t offset, ptrdiff_t length, u32 access))syms[33])
#define _glTextureBuffer ((void (*)(u32 texture, u32 internalformat, u32 buffer))syms[34])
#define _glTextureStorage3D ((void (*)(u32 texture, i32 levels, u32 internalformat, i32 width, i32 height, i32 depth))syms[35])
#define _glTextureSubImage3D ((void (*)(u32 texture, i32 level, i32 xoffset, i32 yoffset, i32 zoffset, i32 width, i32 height, i32 depth, u32 format, u32 type, const void * pixels))syms[36])
#define _glGetTextureSubImage ((void (*)(u32 texture, i32 level, i32 xoffset, i32 yoffset, i32 zoffset, i32 width, i32 height, i32 depth, u32 format, u32 type, i32 bufSize, void * pixels))syms[37])
#define _glGenerateTextureMipmap ((void (*)(u32 texture))syms[38])
#define _glSamplerParameteri ((void (*)(u32 sampler, u32 pname, i32 param))syms[39])
#define _glNamedFramebufferTextureLayer ((void (*)(u32 framebuffer, u32 attachment, u32 texture, i32 level, i32 layer))syms[40])
#define _glNamedFramebufferDrawBuffers ((void (*)(u32 framebuffer, i32 n, const u32 * bufs))syms[41])
#define _glUseProgramStages ((void (*)(u32 pipeline, u32 stages, u32 program))syms[42])
#define _glDrawArraysInstancedBaseInstance ((void (*)(u32 mode, i32 first, i32 count, i32 instancecount, u32 baseinstance))syms[43])
#define _glProgramUniform1uiv ((void (*)(u32 program, i32 location, i32 count, const u32 * value))syms[44])
#define _glProgramUniform1iv ((void (*)(u32 program, i32 location, i32 count, const i32 * value))syms[45])
#define _glProgramUniform1dv ((void (*)(u32 program, i32 location, i32 count, const f64 * value))syms[46])
#define _glProgramUniform1fv ((void (*)(u32 program, i32 location, i32 count, const f32 * value))syms[47])
#define _glProgramUniform2fv ((void (*)(u32 program, i32 location, i32 count, const f32 * value))syms[48])
#define _glProgramUniform3fv ((void (*)(u32 program, i32 location, i32 count, const f32 * value))syms[49])
#define _glProgramUniform4fv ((void (*)(u32 program, i32 location, i32 count, const f32 * value))syms[50])
static void dl_load(void)
{
const char *name = sym_names;
void **sym = syms;
do
{
void *dl = dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
for(;;)
{
while(*name++);
if(*name == 0) break;
*sym++ = dlsym(dl, name);
}
} while(*++name);
}
#define x_b8 GL_R8
#define x_f16 GL_R16F
#define x_f32 GL_R32F
#define x_i8 GL_R8I
#define x_i16 GL_R16I
#define x_i32 GL_R32I
#define x_u8 GL_R8UI
#define x_u16 GL_R16UI
#define x_u32 GL_R32UI
#define xy_b8 GL_RG8
#define xy_f16 GL_RG16F
#define xy_f32 GL_RG32F
#define xy_i8 GL_RG8I
#define xy_i16 GL_RG16I
#define xy_i32 GL_RG32I
#define xy_u8 GL_RG8UI
#define xy_u16 GL_RG16UI
#define xy_u32 GL_RG32UI
#define xyz_f32 GL_RGB32F
#define xyz_i32 GL_RGB32I
#define xyz_u32 GL_RGB32UI
#define xyzw_b8 GL_RGBA8
#define xyzw_f16 GL_RGBA16F
#define xyzw_f32 GL_RGBA32F
#define xyzw_i8 GL_RGBA8I
#define xyzw_i16 GL_RGBA16I
#define xyzw_i32 GL_RGBA32I
#define xyzw_u8 GL_RGBA8UI
#define xyzw_u16 GL_RGBA16UI
#define xyzw_u32 GL_RGBA32UI
#define rgb_b8 GL_RGB8
#define rgba_b8 GL_RGBA8
#define srgb_b8 GL_SRGB8
#define srgba_b8 GL_SRGB8_ALPHA8
#define rgba_f16 GL_RGBA16F
#define rgba_f32 GL_RGBA32F
#define depth_b16 GL_DEPTH_COMPONENT16
#define depth_b24 GL_DEPTH_COMPONENT24
#define depth_b32 GL_DEPTH_COMPONENT32
#define GF_TO_STRING(x) #x
#define GF_VERT_HEAD \
"#version 330\n" \
"#extension GL_ARB_shader_precision : enable\n" \
"#extension GL_ARB_separate_shader_objects : enable\n" \
"#extension GL_ARB_shading_language_420pack : enable\n" \
"#extension GL_ARB_explicit_uniform_location : enable\n" \
"out gl_PerVertex { vec4 gl_Position; };\n"
#define GF_FRAG_HEAD \
"#version 330\n" \
"#extension GL_ARB_shader_precision : enable\n" \
"#extension GL_ARB_conservative_depth : enable\n" \
"#extension GL_ARB_texture_cube_map_array : enable\n" \
"#extension GL_ARB_separate_shader_objects : enable\n" \
"#extension GL_ARB_shading_language_420pack : enable\n" \
"#extension GL_ARB_shading_language_packing : enable\n" \
"#extension GL_ARB_explicit_uniform_location : enable\n" \
"layout(depth_unchanged) out float gl_FragDepth;\n"
typedef struct
{
union
{
u8 * ptr;
i8 * as_i8;
u8 * as_u8;
i16 * as_i16;
u16 * as_u16;
i32 * as_i32;
u32 * as_u32;
f32 * as_f32;
struct
{
union { f32 x; f32 u; };
union { f32 y; f32 v; };
} * as_vec2;
struct
{
union { f32 x; f32 r; };
union { f32 y; f32 g; };
union { f32 z; f32 b; };
} * as_vec3;
struct
{
union { f32 x; f32 r; };
union { f32 y; f32 g; };
union { f32 z; f32 b; };
union { f32 w; f32 a; };
} * as_vec4;
};
u32 bytes;
u32 count;
u32 format;
u32 buffer_id;
u32 id;
} gpu_storage_t;
typedef struct
{
i32 w;
i32 h;
i32 count;
u32 format;
i32 mipmap;
u8 cubemap;
u32 id;
} gpu_texture_t;
typedef struct
{
i32 aniso;
i32 min;
i32 mag;
i32 wrap;
u32 id;
} gpu_sampler_t;
typedef struct
{
u32 count;
u32 instance_count;
u32 first;
u32 instance_first;
} gpu_cmd_t;
gpu_storage_t gfStorageCreateFromStruct(gpu_storage_t tbo);
gpu_texture_t gfTextureCreateFromStruct(gpu_texture_t texture);
gpu_sampler_t gfSamplerCreateFromStruct(gpu_sampler_t sampler);
gpu_texture_t gfTextureCreateFromBmp(i32 width, i32 height, i32 mipmap, i32 texture_count, const char ** texture_paths);
gpu_texture_t gfCubemapCreateFromBmp(i32 width, i32 height, i32 mipmap, i32 texture_count, const char ** pos_x_texture_paths, const char ** neg_x_texture_paths, const char ** pos_y_texture_paths, const char ** neg_y_texture_paths, const char ** pos_z_texture_paths, const char ** neg_z_texture_paths);
void gfTextureSetPixels(u32 texture_id, i32 texture_layer, i32 x, i32 y, i32 width, i32 height, u32 pixels_format, u32 pixels_type, const void * data);
void gfTextureGetPixels(u32 texture_id, i32 texture_layer, i32 x, i32 y, i32 width, i32 height, u32 pixels_format, u32 pixels_type, i32 pixels_bytes, void * pixels);
void gfTextureSaveToBmp(u32 texture_id, i32 texture_layer, i32 width, i32 height, const char * bmp_filepath);
u32 gfFboCreate(u32 depth_texture_id, i32 depth_texture_layer, i32 color_texture_count, const u32 * color_texture_ids, const i32 * color_texture_layers);
void gfFboBind(u32 fbo_id);
u32 gfProgramCreateFromFile(u32 shader_type, const char * shader_filepath);
u32 gfProgramCreateFromString(u32 shader_type, const char * shader_string);
u32 gfProgramPipelineCreate(u32 vert_program, u32 frag_program);
void gfClear();
void gfDraw(u32 program_pipeline, u32 gpu_cmd_count, const gpu_cmd_t * gpu_cmd);
void gfFire(u32 program_pipeline, u32 count);
void my_main(int argc, const char **argv)
{
dl_load();
Display *display = _XOpenDisplay(NULL);
int screen = DefaultScreen(display);
Window window = _XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, SCRW, SCRH, 0, 0, 0);
_XSelectInput(display, window, KeyPressMask | KeyReleaseMask);
XVisualInfo *visual_info = _glXChooseVisual(display, screen, visual_hints);
GLXContext context = _glXCreateContext(display, visual_info, NULL, True);
_glXMakeCurrent(display, window, context);
_XMapWindow(display, window);
gpu_storage_t mesh = {0};
mesh.format = xyz_f32;
mesh.count = 3;
mesh = gfStorageCreateFromStruct(mesh);
mesh.as_vec3[0].x = -0.5f;
mesh.as_vec3[0].y = -0.5f;
mesh.as_vec3[0].z = 0.0f;
mesh.as_vec3[1].x = 0.0f;
mesh.as_vec3[1].y = 0.5f;
mesh.as_vec3[1].z = 0.0f;
mesh.as_vec3[2].x = 0.5f;
mesh.as_vec3[2].y = -0.5f;
mesh.as_vec3[2].z = 0.0f;
gpu_cmd_t cmd[1] = {0};
cmd[0].count = mesh.count;
cmd[0].instance_count = 1;
const char * vs_str = GF_VERT_HEAD GF_TO_STRING
(
layout(binding = 0) uniform samplerBuffer s_pos;
void main()
{
vec3 pos = texelFetch(s_pos, gl_VertexID).xyz;
gl_Position = vec4(pos, 1.f);
}
);
const char * fs_str = GF_FRAG_HEAD GF_TO_STRING
(
out vec4 color;
void main()
{
color = vec4(1.f);
}
);
u32 vs = gfProgramCreateFromString(GL_VERTEX_SHADER, vs_str);
u32 fs = gfProgramCreateFromString(GL_FRAGMENT_SHADER, fs_str);
u32 pp = gfProgramPipelineCreate(vs, fs);
u32 state_textures[16] = { mesh.id };
_glBindTextures(0, 16, state_textures);
uint64_t prev = time_monotonic();
uint64_t t = 0;
for(;;)
{
XEvent event;
while(_XPending(display))
{
_XNextEvent(display, &event);
if(event.type == KeyPress)
{
switch(_XkbKeycodeToKeysym(display, event.xkey.keycode, 0, 0))
{
case XK_Escape: goto shutdown;
}
}
}
// draw demo
gfClear();
gfDraw(pp, countof(cmd), cmd);
_glXSwapBuffers(display, window);
t += time_monotonic() - prev;
}
shutdown:
return;
}
gpu_storage_t gfStorageCreateFromStruct(gpu_storage_t tbo)
{
u32 elem_width = 0;
u32 elem_bytes = 0;
switch(tbo.format)
{
case(x_b8): elem_width = 1; elem_bytes = sizeof(u8); break;
case(x_f16): elem_width = 1; elem_bytes = sizeof(f16); break;
case(x_f32): elem_width = 1; elem_bytes = sizeof(f32); break;
case(x_i8): elem_width = 1; elem_bytes = sizeof(i8); break;
case(x_i16): elem_width = 1; elem_bytes = sizeof(i16); break;
case(x_i32): elem_width = 1; elem_bytes = sizeof(i32); break;
case(x_u8): elem_width = 1; elem_bytes = sizeof(u8); break;
case(x_u16): elem_width = 1; elem_bytes = sizeof(u16); break;
case(x_u32): elem_width = 1; elem_bytes = sizeof(u32); break;
case(xy_b8): elem_width = 2; elem_bytes = sizeof(u8); break;
case(xy_f16): elem_width = 2; elem_bytes = sizeof(f16); break;
case(xy_f32): elem_width = 2; elem_bytes = sizeof(f32); break;
case(xy_i8): elem_width = 2; elem_bytes = sizeof(i8); break;
case(xy_i16): elem_width = 2; elem_bytes = sizeof(i16); break;
case(xy_i32): elem_width = 2; elem_bytes = sizeof(i32); break;
case(xy_u8): elem_width = 2; elem_bytes = sizeof(u8); break;
case(xy_u16): elem_width = 2; elem_bytes = sizeof(u16); break;
case(xy_u32): elem_width = 2; elem_bytes = sizeof(u32); break;
case(xyz_f32): elem_width = 3; elem_bytes = sizeof(f32); break;
case(xyz_i32): elem_width = 3; elem_bytes = sizeof(i32); break;
case(xyz_u32): elem_width = 3; elem_bytes = sizeof(u32); break;
case(xyzw_b8): elem_width = 4; elem_bytes = sizeof(u8); break;
case(xyzw_f16): elem_width = 4; elem_bytes = sizeof(f16); break;
case(xyzw_f32): elem_width = 4; elem_bytes = sizeof(f32); break;
case(xyzw_i8): elem_width = 4; elem_bytes = sizeof(i8); break;
case(xyzw_i16): elem_width = 4; elem_bytes = sizeof(i16); break;
case(xyzw_i32): elem_width = 4; elem_bytes = sizeof(i32); break;
case(xyzw_u8): elem_width = 4; elem_bytes = sizeof(u8); break;
case(xyzw_u16): elem_width = 4; elem_bytes = sizeof(u16); break;
case(xyzw_u32): elem_width = 4; elem_bytes = sizeof(u32); break;
}
if(!tbo.bytes)
tbo.bytes = tbo.count * elem_width * elem_bytes;
else
tbo.count = tbo.bytes / elem_width / elem_bytes;
_glCreateBuffers(1, &tbo.buffer_id);
_glCreateTextures(GL_TEXTURE_BUFFER, 1, &tbo.id);
u32 flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
_glNamedBufferStorage(tbo.buffer_id, tbo.bytes, NULL, flags);
tbo.ptr = (u8 *)_glMapNamedBufferRange(tbo.buffer_id, 0, tbo.bytes, flags);
_glTextureBuffer(tbo.id, tbo.format, tbo.buffer_id);
return tbo;
}
gpu_texture_t gfTextureCreateFromStruct(gpu_texture_t texture)
{
if(!texture.count) texture.count = 1;
if(!texture.mipmap) texture.mipmap = 1;
_glCreateTextures(texture.cubemap ? GL_TEXTURE_CUBE_MAP_ARRAY : GL_TEXTURE_2D_ARRAY, 1, &texture.id);
_glTextureStorage3D(texture.id, texture.mipmap, texture.format, texture.w, texture.h, texture.count * (texture.cubemap ? 6 : 1));
return texture;
}
gpu_sampler_t gfSamplerCreateFromStruct(gpu_sampler_t sampler)
{
if(!sampler.aniso) sampler.aniso = 1;
if(!sampler.min) sampler.min = GL_LINEAR_MIPMAP_LINEAR;
if(!sampler.mag) sampler.mag = GL_LINEAR;
if(!sampler.wrap) sampler.wrap = GL_REPEAT;
_glCreateSamplers(1, &sampler.id);
_glSamplerParameteri(sampler.id, GL_TEXTURE_MAX_ANISOTROPY, sampler.aniso);
_glSamplerParameteri(sampler.id, GL_TEXTURE_MIN_FILTER, sampler.min);
_glSamplerParameteri(sampler.id, GL_TEXTURE_MAG_FILTER, sampler.mag);
_glSamplerParameteri(sampler.id, GL_TEXTURE_WRAP_S, sampler.wrap);
_glSamplerParameteri(sampler.id, GL_TEXTURE_WRAP_T, sampler.wrap);
return sampler;
}
void gfTextureSetPixels(
u32 texture_id,
i32 texture_layer,
i32 x,
i32 y,
i32 width,
i32 height,
u32 pixels_format,
u32 pixels_type,
const void * pixels)
{
_glTextureSubImage3D(texture_id, 0, x, y, texture_layer, width, height, 1, pixels_format, pixels_type, pixels);
}
void gfTextureGetPixels(
u32 texture_id,
i32 texture_layer,
i32 x,
i32 y,
i32 width,
i32 height,
u32 pixels_format,
u32 pixels_type,
i32 pixels_bytes,
void * pixels)
{
_glGetTextureSubImage(texture_id, 0, x, y, texture_layer, width, height, 1, pixels_format, pixels_type, pixels_bytes, pixels);
}
u32 gfFboCreate(
u32 depth_texture_id,
i32 depth_texture_layer,
i32 color_texture_count,
const u32 * color_texture_ids,
const i32 * color_texture_layers)
{
u32 fbo;
_glCreateFramebuffers(1, &fbo);
if(depth_texture_id)
_glNamedFramebufferTextureLayer(fbo, GL_DEPTH_ATTACHMENT, depth_texture_id, 0, depth_texture_layer);
if(color_texture_count)
{
u32 attachments[8] = {0};
for(i32 i = 0; i < color_texture_count; ++i)
{
attachments[i] = GL_COLOR_ATTACHMENT0 + (u32)i;
_glNamedFramebufferTextureLayer(fbo, GL_COLOR_ATTACHMENT0 + (u32)i, color_texture_ids[i], 0, color_texture_layers ? color_texture_layers[i] : 0);
}
_glNamedFramebufferDrawBuffers(fbo, color_texture_count, attachments);
}
return fbo;
}
void gfFboBind(u32 fbo_id)
{
_glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
}
u32 gfProgramCreateFromString(
u32 shader_type,
const char * shader_string)
{
return _glCreateShaderProgramv(shader_type, 1, (const char **)&shader_string);
}
u32 gfProgramPipelineCreate(
u32 vert_program,
u32 frag_program)
{
u32 ppo;
_glCreateProgramPipelines(1, &ppo);
if(vert_program) _glUseProgramStages(ppo, GL_VERTEX_SHADER_BIT, vert_program);
if(frag_program) _glUseProgramStages(ppo, GL_FRAGMENT_SHADER_BIT, frag_program);
return ppo;
}
void gfClear()
{
_glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void gfDraw(
u32 program_pipeline,
u32 gpu_cmd_count,
const gpu_cmd_t * gpu_cmd)
{
_glBindProgramPipeline(program_pipeline);
for(u32 i = 0; i < gpu_cmd_count; ++i)
{
gpu_cmd_t cmd = gpu_cmd[i];
_glDrawArraysInstancedBaseInstance(GL_TRIANGLES, (i32)cmd.first, (i32)cmd.count, (i32)cmd.instance_count, cmd.instance_first);
}
_glBindProgramPipeline(0);
}
void gfFire(
u32 program_pipeline,
u32 count)
{
gpu_cmd_t cmd;
cmd.first = 0;
cmd.count = count;
cmd.instance_first = 0;
cmd.instance_count = 1;
gfDraw(program_pipeline, 1, &cmd);
}
asm (
".text\n"
".global _start\n"
"_start:\n"
"xor %rbp,%rbp\n"
"pop %rdi\n"
"mov %rsp,%rsi\n"
"andq $-16,%rsp\n"
"call my_main\n"
"movq $60,%rax\n"
"xor %rdi,%rdi\n"
"syscall\n"
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment