Changeset 775


Ignore:
Timestamp:
Jun 13, 2011, 9:35:36 PM (8 years ago)
Author:
sam
Message:

shader: write a minimalist shader patcher for future GLSL 1.20 compatibility.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/shader.cpp

    r758 r775  
    1414
    1515#include <cmath>
     16#include <cstring>
     17#include <cstdio>
    1618
    1719#ifdef WIN32
     
    3739    GLuint prog_id, vert_id, frag_id;
    3840    uint32_t vert_crc, frag_crc;
     41
     42    /* Shader patcher */
     43    static int GetVersion();
     44    static void Patch(char *dst, char const *src);
    3945
    4046    /* Global shader cache */
     
    7884{
    7985    char buf[4096];
     86    char const *shader = buf;
    8087    GLsizei len;
    8188
    8289#if !defined __CELLOS_LV2__
    83     data->vert_crc = Hash::Crc32(vert);
     90
     91    /* Compile vertex shader and fragment shader */
     92    ShaderData::Patch(buf, vert);
     93    data->vert_crc = Hash::Crc32(buf);
    8494    data->vert_id = glCreateShader(GL_VERTEX_SHADER);
    85     glShaderSource(data->vert_id, 1, &vert, NULL);
     95    glShaderSource(data->vert_id, 1, &shader, NULL);
    8696    glCompileShader(data->vert_id);
    8797
     
    90100        Log::Error("failed to compile vertex shader: %s", buf);
    91101
    92     data->frag_crc = Hash::Crc32(frag);
     102    ShaderData::Patch(buf, frag);
     103    data->frag_crc = Hash::Crc32(buf);
    93104    data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
    94     glShaderSource(data->frag_id, 1, &frag, NULL);
     105    glShaderSource(data->frag_id, 1, &shader, NULL);
    95106    glCompileShader(data->frag_id);
    96107
     
    149160}
    150161
     162/* Try to detect shader compiler features */
     163int ShaderData::GetVersion()
     164{
     165    static int version = 0;
     166
     167    if (!version)
     168    {
     169        char buf[4096];
     170        GLsizei len;
     171
     172        int id = glCreateShader(GL_VERTEX_SHADER);
     173
     174        /* Can we compile 1.30 shaders? */
     175        char const *test130 =
     176            "#version 130\n"
     177            "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
     178        glShaderSource(id, 1, &test130, NULL);
     179        glCompileShader(id);
     180        glGetShaderInfoLog(id, sizeof(buf), &len, buf);
     181        if (len <= 0)
     182            version = 130;
     183
     184        /* If not, can we compile 1.20 shaders? */
     185        if (!version)
     186        {
     187            char const *test120 =
     188                "#version 120\n"
     189                "void main() { gl_Position = vec4(0.0, 0.0, 0.0, 0.0); }";
     190            glShaderSource(id, 1, &test120, NULL);
     191            glCompileShader(id);
     192            glGetShaderInfoLog(id, sizeof(buf), &len, buf);
     193            if (len <= 0)
     194                version = 120;
     195        }
     196
     197        /* Otherwise, assume we can compile 1.10 shaders. */
     198        if (!version)
     199            version = 110;
     200
     201        glDeleteShader(id);
     202    }
     203
     204    return version;
     205}
     206
     207/* Simple shader source patching for old GLSL versions.
     208 * If supported version is 1.30, do nothing.
     209 * If supported version is 1.20:
     210 *  - replace "#version 130" with "#version 120"
     211 */
     212void ShaderData::Patch(char *dst, char const *src)
     213{
     214    int version = GetVersion();
     215
     216    if (version >= 130)
     217    {
     218        strcpy(dst, src);
     219        return;
     220    }
     221
     222    if (version == 120)
     223    {
     224        static char const * const replaces[] =
     225        {
     226            "#version 130", "#version 120",
     227            "\nin vec2", "\nvec2",
     228            "\nin vec3", "\nvec3",
     229            "\nin vec4", "\nvec4",
     230            "\nin mat4", "\nmat4",
     231            NULL
     232        };
     233
     234        while (*src)
     235        {
     236            for (char const * const *rep = replaces; rep[0]; rep += 2)
     237            {
     238                size_t l0 = strlen(rep[0]);
     239                if (!strncmp(src, rep[0], l0))
     240                {
     241                    src += l0;
     242                    dst += sprintf(dst, "%s", rep[1]);
     243                    goto next;
     244                }
     245            }
     246
     247            *dst++ = *src++;
     248
     249            next: continue;
     250        }
     251        *dst = '\0';
     252    }
     253}
     254
    151255} /* namespace lol */
    152256
Note: See TracChangeset for help on using the changeset viewer.