source: trunk/src/shader.cpp @ 670

Last change on this file since 670 was 670, checked in by sam, 9 years ago

Cache shader source CRCs to avoid costly recompilations.

File size: 3.2 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cmath>
16#include <cstdio>
17
18#ifdef WIN32
19#   define WIN32_LEAN_AND_MEAN
20#   include <windows.h>
21#endif
22#if defined __APPLE__ && defined __MACH__
23#   include <OpenGL/gl.h>
24#else
25#   define GL_GLEXT_PROTOTYPES
26#   include <GL/gl.h>
27#endif
28
29#include "core.h"
30
31/*
32 * Shader implementation class
33 */
34
35class ShaderData
36{
37    friend class Shader;
38
39private:
40    GLuint prog_id, vert_id, frag_id;
41    uint32_t vert_crc, frag_crc;
42
43    /* Global shader cache */
44    static Shader *shaders[];
45    static int nshaders;
46};
47
48Shader *ShaderData::shaders[256];
49int ShaderData::nshaders = 0;
50
51/*
52 * Public Shader class
53 */
54
55Shader *Shader::Create(char const *vert, char const *frag)
56{
57    uint32_t new_vert_crc = Hash::Crc32(vert);
58    uint32_t new_frag_crc = Hash::Crc32(frag);
59
60    for (int n = 0; n < ShaderData::nshaders; n++)
61    {
62        if (ShaderData::shaders[n]->data->vert_crc == new_vert_crc
63             && ShaderData::shaders[n]->data->frag_crc == new_frag_crc)
64            return ShaderData::shaders[n];
65    }
66
67    Shader *ret = new Shader(vert, frag);
68    ShaderData::shaders[ShaderData::nshaders] = ret;
69    ShaderData::nshaders++;
70    return ret;
71}
72
73void Shader::Destroy(Shader *shader)
74{
75    /* XXX: do nothing! the shader should remain in cache */
76    (void)shader;
77}
78
79Shader::Shader(char const *vert, char const *frag)
80  : data(new ShaderData())
81{
82    char buf[4096];
83    GLsizei len;
84
85    data->vert_crc = Hash::Crc32(vert);
86    data->vert_id = glCreateShader(GL_VERTEX_SHADER);
87    glShaderSource(data->vert_id, 1, &vert, NULL);
88    glCompileShader(data->vert_id);
89
90    glGetShaderInfoLog(data->vert_id, sizeof(buf), &len, buf);
91    if (len > 0)
92        fprintf(stderr, "ERROR: failed to compile vertex shader: %s", buf);
93
94    data->frag_crc = Hash::Crc32(frag);
95    data->frag_id = glCreateShader(GL_FRAGMENT_SHADER);
96    glShaderSource(data->frag_id, 1, &frag, NULL);
97    glCompileShader(data->frag_id);
98
99    glGetShaderInfoLog(data->frag_id, sizeof(buf), &len, buf);
100    if (len > 0)
101        fprintf(stderr, "ERROR: failed to compile fragment shader: %s", buf);
102
103    data->prog_id = glCreateProgram();
104    glAttachShader(data->prog_id, data->vert_id);
105    glAttachShader(data->prog_id, data->frag_id);
106
107    glLinkProgram(data->prog_id);
108    glValidateProgram(data->prog_id);
109}
110
111int Shader::GetAttribLocation(char const *attr) const
112{
113    return glGetAttribLocation(data->prog_id, attr);
114}
115
116int Shader::GetUniformLocation(char const *uni) const
117{
118    return glGetUniformLocation(data->prog_id, uni);
119}
120
121void Shader::Bind() const
122{
123    glUseProgram(data->prog_id);
124}
125
126Shader::~Shader()
127{
128    glDetachShader(data->prog_id, data->vert_id);
129    glDetachShader(data->prog_id, data->frag_id);
130    glDeleteShader(data->vert_id);
131    glDeleteShader(data->frag_id);
132    glDeleteProgram(data->prog_id);
133    delete data;
134}
135
Note: See TracBrowser for help on using the repository browser.