diff --git a/src/shader.cpp b/src/shader.cpp index 399c2798..f57a4b10 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -82,33 +82,40 @@ void Shader::Destroy(Shader *shader) Shader::Shader(char const *vert, char const *frag) : data(new ShaderData()) { - char buf[4096]; + char buf[4096], errbuf[4096]; char const *shader = buf; GLsizei len; #if !defined __CELLOS_LV2__ - - /* Compile vertex shader and fragment shader */ + /* Compile vertex shader */ ShaderData::Patch(buf, vert); data->vert_crc = Hash::Crc32(buf); data->vert_id = glCreateShader(GL_VERTEX_SHADER); glShaderSource(data->vert_id, 1, &shader, NULL); glCompileShader(data->vert_id); - glGetShaderInfoLog(data->vert_id, sizeof(buf), &len, buf); + glGetShaderInfoLog(data->vert_id, sizeof(errbuf), &len, errbuf); if (len > 0) - Log::Error("failed to compile vertex shader: %s", buf); + { + Log::Error("failed to compile vertex shader: %s", errbuf); + Log::Error("shader source:\n%s\n", buf); + } + /* Compile fragment shader */ ShaderData::Patch(buf, frag); data->frag_crc = Hash::Crc32(buf); data->frag_id = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(data->frag_id, 1, &shader, NULL); glCompileShader(data->frag_id); - glGetShaderInfoLog(data->frag_id, sizeof(buf), &len, buf); + glGetShaderInfoLog(data->frag_id, sizeof(errbuf), &len, errbuf); if (len > 0) - Log::Error("failed to compile fragment shader: %s", buf); + { + Log::Error("failed to compile fragment shader: %s", errbuf); + Log::Error("shader source:\n%s\n", buf); + } + /* Create program */ data->prog_id = glCreateProgram(); glAttachShader(data->prog_id, data->vert_id); glAttachShader(data->prog_id, data->frag_id); @@ -213,42 +220,99 @@ void ShaderData::Patch(char *dst, char const *src) { int version = GetVersion(); + strcpy(dst, src); if (version >= 130) - { - strcpy(dst, src); return; - } - if (version == 120) + if (version >= 110) { - static char const * const replaces[] = + char *parser, *main; + char const *end = dst + strlen(dst) + 1; + + /* Find main() */ + parser = strstr(dst, "main"); + if (!parser) return; + parser = strstr(parser, "("); + if (!parser) return; + parser = strstr(parser, ")"); + if (!parser) return; + parser = strstr(parser, "{"); + if (!parser) return; + main = parser + 1; + + /* Perform main() replaces */ + static char const * const main_replaces[] = { - "#version 130", "#version 120", - "\nin vec2", "\nvec2", - "\nin vec3", "\nvec3", - "\nin vec4", "\nvec4", - "\nin mat4", "\nmat4", + "in vec2 in_Vertex;", "vec2 in_Vertex = gl_Vertex.xy;", + "in vec3 in_Vertex;", "vec3 in_Vertex = gl_Vertex.xyz;", + "in vec4 in_Vertex;", "vec4 in_Vertex = gl_Vertex.xyzw;", + + "in vec2 in_Color;", "vec2 in_Color = gl_Color.xy;", + "in vec3 in_Color;", "vec3 in_Color = gl_Color.xyz;", + "in vec4 in_Color;", "vec4 in_Color = gl_Color.xyzw;", + + "in vec2 in_MultiTexCoord0;", + "vec2 in_MultiTexCoord0 = gl_MultiTexCoord0.xy;", + "in vec2 in_MultiTexCoord1;", + "vec2 in_MultiTexCoord1 = gl_MultiTexCoord1.xy;", + "in vec2 in_MultiTexCoord2;", + "vec2 in_MultiTexCoord2 = gl_MultiTexCoord2.xy;", + "in vec2 in_MultiTexCoord3;", + "vec2 in_MultiTexCoord3 = gl_MultiTexCoord3.xy;", + "in vec2 in_MultiTexCoord4;", + "vec2 in_MultiTexCoord4 = gl_MultiTexCoord4.xy;", + "in vec2 in_MultiTexCoord5;", + "vec2 in_MultiTexCoord5 = gl_MultiTexCoord5.xy;", + "in vec2 in_MultiTexCoord6;", + "vec2 in_MultiTexCoord6 = gl_MultiTexCoord6.xy;", + "in vec2 in_MultiTexCoord7;", + "vec2 in_MultiTexCoord7 = gl_MultiTexCoord7.xy;", + NULL }; - while (*src) + for (char const * const *rep = main_replaces; rep[0]; rep += 2) { - for (char const * const *rep = replaces; rep[0]; rep += 2) + char *match = strstr(dst, rep[0]); + if (match && match < main) { size_t l0 = strlen(rep[0]); - if (!strncmp(src, rep[0], l0)) - { - src += l0; - dst += sprintf(dst, "%s", rep[1]); - goto next; - } + size_t l1 = strlen(rep[1]); + memmove(main + l1, main, end - main); + memcpy(main, rep[1], l1); + memset(match, ' ', l0); + main += l1; + end += l1; } + } - *dst++ = *src++; + /* Perform small replaces */ + static char const * const fast_replaces[] = + { + "#version 130", "#version 120", + "\nin vec2", "\n vec2", + "\nin vec3", "\n vec3", + "\nin vec4", "\n vec4", + "\nin mat4", "\n mat4", + NULL + }; - next: continue; + for (char const * const *rep = fast_replaces; rep[0]; rep += 2) + { + char *match; + while ((match = strstr(dst, rep[0]))) + { + size_t l0 = strlen(rep[0]); + size_t l1 = strlen(rep[1]); + + if (l1 > l0) + memmove(match + l1, match + l0, (end - match) - l0); + memcpy(match, rep[1], l1); + if (l1 < l0) + memset(match + l0, ' ', l1 - l0); + end += l1 - l0; + } } - *dst = '\0'; } }