simplify gitignore
[vg.git] / src / vg / vg_shader.h
index 0f1303bc3c540768e3218c57f5047af7c3c3e462..516d1a84c67587c7e44d56fe2853c870de252138 100644 (file)
@@ -1,69 +1,47 @@
 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
 
-const char *vg_shader_gl_ver = "#version 330 core\n";
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wreturn-type"
-static inline int static_str_index( const char *list[], int len, 
-      const char *str )
-{
-    for( int i = 0; i < len; i ++ )
-    {
-        if( !strcmp(list[i],str) )
-            return i;
-    }
-    
-    #ifndef VG_RELEASE
-    fprintf( stderr, "That was not a static string index!! (%s)\n", str );
-    abort();
-    #endif
-}
-#pragma GCC diagnostic pop
+#ifndef VG_SHADER_H
+#define VG_SHADER_H
 
-#define SHADER_NAME( NAME ) (NAME##_static_shader.program)
-#define SHADER_USE( NAME ) glUseProgram( NAME##_static_shader.program )
+#include "vg/vg.h"
+#include "vg/vg_platform.h"
 
-#define SHADER_UNIFORM( NAME, U ) \
-   NAME##_shader_uniforms[ STR_STATIC_INDEX( NAME##_shader_names, U ) ]
-#define SHADER_UNIFORM_NAME( NAME, UID ) NAME##_shader_names[ UID ]
-#define STR_STATIC_INDEX( LIST, STR ) \
-   static_str_index( LIST, vg_list_size(LIST), STR )
+#if 0
+#define STB_INCLUDE_IMPLEMENTATION
+#define STB_INCLUDE_LINE_GLSL
+#define STB_MALLOC  vg_alloc
+#define STB_FREE    vg_free
+#define STB_REALLOC vg_realloc
+#include "stb/stb_include.h"
+#endif
 
-#define UNIFORMS(...) __VA_ARGS__
-
-#define SHADER_DEFINE( NAME, VERT, FRAG, UNIFORMS )                                                    \
-       const char * NAME##_shader_names[] = UNIFORMS;                                                          \
-       GLint NAME##_shader_uniforms[ vg_list_size( NAME##_shader_names ) ];    \
-       struct vg_shader NAME##_static_shader = {                                                                               \
-               .src_vert = VERT, .src_frag = FRAG,                                                                                     \
-               .sym = #NAME "_static.shader",                                                                                          \
-               .uniform_names = NAME##_shader_names,                                                                           \
-               .uniforms = NAME##_shader_uniforms,                                                                                     \
-               .uniform_count = vg_list_size( NAME##_shader_names ),                                   \
-       };
-
-#define SHADER_INIT( NAME ) arrpush( vg_shaders_active, &NAME##_static_shader )
+const char *vg_shader_gl_ver = "#version 330 core\n";
 
-#define SHADER_STATUS_NONE 0x00
-#define SHADER_STATUS_COMPILED 0x1
+typedef struct vg_shader vg_shader;
 
-struct vg_shader
+struct
 {
-       GLuint program;
-
-       const char *src_vert;
-       const char *src_frag;
-       const char *src_geo;
-       const char *sym;
-       
-       const char **uniform_names;
-       GLint *uniforms;
-       u32 uniform_count;
-       u32 status;
+   struct vg_shader
+   {
+      GLuint id;
+      const char *name;
+
+      struct vg_subshader
+      {
+         const char *orig_file,
+                    *static_src;
+      }
+      vs, fs;
+
+      void (*link)(void);
+      int compiled;
+   }
+   * shaders[32];
+   u32 count;
 }
-** vg_shaders_active = NULL;
+static vg_shaders;
 
-static GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
+VG_STATIC GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
 {
        GLint shader = glCreateShader( gliShaderType );
 
@@ -73,7 +51,7 @@ static GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
       return 0;
    }
 
-       glShaderSource( shader, 2, (const char *[2]){ vg_shader_gl_ver, src }, NULL );
+       glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL );
        glCompileShader( shader );
 
        GLint status;
@@ -92,92 +70,150 @@ static GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
        return shader;
 }
 
-static int vg_shader_compile( struct vg_shader *shader )
+VG_STATIC int vg_shader_compile( struct vg_shader *shader )
 {
-       vg_info( "Compile shader '%s'\n", shader->sym );
+       vg_info( "Compile shader '%s'\n", shader->name );
        
-       GLuint vert, frag, geo = 0;
+       GLuint program, vert, frag;
+   const char *svs, *sfs;
+   char *avs, *afs;
+
+   int static_src = 1;
+   
+   /* If we are compiling this again, we obviously need to try to take the src
+    * from the disk instead.
+    *
+    * Only do this if we have filenames set on the shader, so engine shaders 
+    * dont have to do it (text.. etc).
+    */
+   if( shader->compiled )
+   {
+      if( shader->vs.orig_file && shader->fs.orig_file )
+         static_src = 0;
+      else return 1;
+   }
+
+   if( static_src )
+   {
+      svs = shader->vs.static_src;
+      sfs = shader->fs.static_src;
+   }
+   else
+   {
+      vg_fatal_exit_loop( "Unimplemented" );
+
+#if 0
+      char error[260];
+      char path[260];
+      strcpy( path, shader->vs.orig_file );
+      avs = stb_include_file( path, "", "../../shaders", error );
+
+      strcpy( path, shader->fs.orig_file );
+      afs = stb_include_file( path, "", "../../shaders", error );
+   
+      if( !avs || !afs )
+      {
+         vg_error( "Could not find shader source files (%s)\n",
+               shader->vs.orig_file );
+
+         vg_free( avs );
+         vg_free( afs );
+         return 0;
+      }
+
+      svs = avs;
+      sfs = afs;
+#endif
+   }
        
-       vert = vg_shader_subshader( shader->src_vert, GL_VERTEX_SHADER );
-       frag = vg_shader_subshader( shader->src_frag, GL_FRAGMENT_SHADER );
+       vert = vg_shader_subshader( svs, GL_VERTEX_SHADER );
+       frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER );
        
+#if 0
+   if( !static_src )
+   {
+      free( avs );
+      free( afs );
+   }
+#endif
+
        if( !vert || !frag )
                return 0;
        
-       if( shader->src_geo )
-       {
-               geo = vg_shader_subshader( shader->src_geo, GL_GEOMETRY_SHADER );
-               
-               if( !geo )
-                       return 0;
-       }
-       
-       shader->program = glCreateProgram();
-       if( geo )
-               glAttachShader( shader->program, geo );
+       program = glCreateProgram();
                
-       glAttachShader( shader->program, vert );
-       glAttachShader( shader->program, frag );
-       glLinkProgram( shader->program );
+       glAttachShader( program, vert );
+       glAttachShader( program, frag );
+       glLinkProgram( program );
        
        glDeleteShader( vert );
        glDeleteShader( frag );
-       
-       if( geo )
-               glDeleteShader( geo );
                
        /* Check for link errors */
        char infoLog[ 512 ];
        int success_link = 1;
        
-       glGetProgramiv( shader->program, GL_LINK_STATUS, &success_link );
+       glGetProgramiv( program, GL_LINK_STATUS, &success_link );
        if( !success_link )
        {
-               glGetProgramInfoLog( shader->program, 512, NULL, infoLog );
+               glGetProgramInfoLog( program, 512, NULL, infoLog );
                vg_error( "Link failed: %s\n", infoLog );
-               glDeleteProgram( shader->program );
-               
+               glDeleteProgram( program );
                return 0;
        }
        
-       /* Complete linkeage */
-       for( int i = 0; i < shader->uniform_count; i ++ )
-   {
-               shader->uniforms[ i ] = 
-         glGetUniformLocation( shader->program, shader->uniform_names[i] );
-   }
-
-       shader->status |= SHADER_STATUS_COMPILED;
+   if( shader->compiled )
+      glDeleteProgram( shader->id );
+   
+   shader->id = program;
+       shader->compiled = 1;
+   if( shader->link ) 
+      shader->link();
        return 1;
 }
 
-static void vg_shaders_free(void)
+VG_STATIC void vg_free_shader( struct vg_shader *shader )
 {
-       for( int i = 0; i < arrlen( vg_shaders_active ); i ++ )
-       {
-               struct vg_shader *shader = vg_shaders_active[i];
-               
-               if( shader->status & SHADER_STATUS_COMPILED )
-                       glDeleteProgram( shader->program );
-       }
-       
-       arrfree( vg_shaders_active );
+   if( shader->compiled )
+   {
+      glDeleteProgram( shader->id );
+      shader->compiled = 0;
+   }
 }
 
-static int vg_shaders_compile(void)
+VG_STATIC void vg_shaders_compile(void)
 {
        vg_info( "Compiling shaders\n" );
 
-       for( int i = 0; i < arrlen( vg_shaders_active ); i ++ )
+       for( int i=0; i<vg_shaders.count; i ++ )
        {
-               struct vg_shader *shader = vg_shaders_active[i];
+               vg_shader *shader = vg_shaders.shaders[i];
+
                if( !vg_shader_compile( shader ) )
-               {
-                       vg_shaders_free();
-                       return 0;
-               }
+         vg_fatal_exit_loop( "Failed to compile shader" );
        }
-       
-       vg_register_exit( &vg_shaders_free, "vg_shaders_free" );
-       return 1;
 }
+
+VG_STATIC int vg_shaders_live_recompile(int argc, const char *argv[])
+{
+   vg_info( "Recompiling shaders\n" );
+   for( int i=0; i<vg_shaders.count; i ++ )
+   {
+      struct vg_shader *shader = vg_shaders.shaders[i];
+      vg_shader_compile( shader );
+   }
+
+   return 0;
+}
+
+VG_STATIC void vg_shader_register( struct vg_shader *shader )
+{
+   if( vg_shaders.count == vg_list_size(vg_shaders.shaders) )
+      vg_fatal_exit_loop( "Too many shaders" );
+
+   shader->compiled = 0;
+   shader->id = 0;         /* TODO: make this an error shader */
+   vg_shaders.shaders[ vg_shaders.count ++ ] = shader;
+}
+
+#endif /* VG_SHADER_H */