Bunch more work (ARB1 profile, OpenGL glue, and general fixes). trunk
authorRyan C. Gordon <icculus@icculus.org>
Mon, 02 Jun 2008 00:14:02 -0400
branchtrunk
changeset 347 f8d9d0ae6ba8
parent 346 77e7fd7b2bcc
child 348 dbb278bdba57
Bunch more work (ARB1 profile, OpenGL glue, and general fixes). ARB1 OpenGL glue should be good to go now, and all the generalization of the code is taken care of (including some long standing FIXMEs). Still need a little fragment program work to be done with ARB1, though.
mojoshader.c
mojoshader_opengl.c
--- a/mojoshader.c	Sat May 31 01:57:51 2008 -0400
+++ b/mojoshader.c	Mon Jun 02 00:14:02 2008 -0400
@@ -185,6 +185,12 @@
 // one state function for each opcode where we have state machine updates.
 typedef void (*state_function)(Context *ctx);
 
+// one function for varnames in each profile.
+typedef const char *(*varname_function)(Context *c, RegisterType t, int num);
+
+// one function for const var array in each profile.
+typedef const char *(*const_array_varname_function)(Context *c);
+
 typedef struct
 {
     const char *name;
@@ -196,6 +202,8 @@
     emit_sampler sampler_emitter;
     emit_attribute attribute_emitter;
     emit_finalize finalize_emitter;
+    varname_function get_varname;
+    const_array_varname_function get_const_array_varname;
 } Profile;
 
 typedef enum
@@ -1179,6 +1187,24 @@
 } // make_D3D_srcarg_string
 
 
+static const char *get_D3D_varname(Context *ctx, RegisterType rt, int regnum)
+{
+    char regnum_str[16];
+    const char *regtype_str = get_D3D_register_string(ctx, rt, regnum,
+                                              regnum_str, sizeof (regnum_str));
+
+    char *retval = get_scratch_buffer(ctx);
+    snprintf(retval, SCRATCH_BUFFER_SIZE, "%s%s", regtype_str, regnum_str);
+    return retval;
+} // get_D3D_varname
+
+static const char *get_D3D_const_array_varname(Context *ctx)
+{
+    fail(ctx, "BUG: D3D profile shouldn't ever have a relative array");
+    return "c";
+} // get_D3D_const_array_varname
+
+
 static void emit_D3D_start(Context *ctx)
 {
     const uint major = (uint) ctx->major_ver;
@@ -1199,6 +1225,7 @@
 static void emit_D3D_end(Context *ctx)
 {
     output_line(ctx, "end");
+    ctx->uniform_array = 0;  // in case anything changed this during parse.
 } // emit_D3D_end
 
 
@@ -1607,7 +1634,11 @@
         memcpy(ctx->output_bytes, ctx->tokens, ctx->output_len);
 } // emit_PASSTHROUGH_start
 
-static void emit_PASSTHROUGH_end(Context *ctx) {}
+static void emit_PASSTHROUGH_end(Context *ctx)
+{
+    ctx->uniform_array = 0;  // in case anything changed this during parse.
+} // emit_PASSTHROUGH_end
+
 static void emit_PASSTHROUGH_finalize(Context *ctx) {}
 static void emit_PASSTHROUGH_global(Context *ctx, RegisterType t, int n) {}
 static void emit_PASSTHROUGH_relative(Context *ctx, int size) {}
@@ -1616,6 +1647,23 @@
 static void emit_PASSTHROUGH_attribute(Context *ctx, RegisterType t, int n,
                                        MOJOSHADER_usage u, int i, int w) {}
 
+static const char *get_PASSTHROUGH_varname(Context *ctx, RegisterType rt, int regnum)
+{
+    char regnum_str[16];
+    const char *regtype_str = get_D3D_register_string(ctx, rt, regnum,
+                                              regnum_str, sizeof (regnum_str));
+
+    char *retval = get_scratch_buffer(ctx);
+    snprintf(retval, SCRATCH_BUFFER_SIZE, "%s%s", regtype_str, regnum_str);
+    return retval;
+} // get_PASSTHROUGH_varname
+
+static const char *get_PASSTHROUGH_const_array_varname(Context *ctx)
+{
+    fail(ctx, "BUG: PASSTHROUGH profile shouldn't ever have a relative array");
+    return "c";
+} // get_PASSTHROUGH_const_array_varname
+
 #define EMIT_PASSTHROUGH_OPCODE_FUNC(op) \
     static void emit_PASSTHROUGH_##op(Context *ctx) {}
 
@@ -3770,7 +3818,10 @@
     else
     {
         // !!! FIXME: this only works if you have no bool or int uniforms.
-        output_line(ctx, "PARAM %s = program.env[%d];", varname, regnum);
+        if (regtype != REG_TYPE_CONST)
+            fail(ctx, "BUG: non-float uniforms not supported in arb1 at the moment");
+        else
+            output_line(ctx, "PARAM %s = program.env[%d];", varname, regnum);
     } // else
 
     pop_output(ctx);
@@ -4315,7 +4366,17 @@
 } // emit_ARB1_DCL
 
 EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(TEXCRD)
-EMIT_ARB1_OPCODE_UNIMPLEMENTED_FUNC(TEXLD)
+
+static void emit_ARB1_TEXLD(Context *ctx)
+{
+    // this opcode looks and acts differently depending on the shader model.
+    if (shader_version_atleast(ctx, 2, 0))
+        emit_D3D_opcode_dss(ctx, "texld");
+    else if (shader_version_atleast(ctx, 1, 4))
+        emit_D3D_opcode_ds(ctx, "texld");
+    else
+        emit_D3D_opcode_d(ctx, "tex");
+} // emit_ARB1_TEXLD
 
 #endif  // SUPPORT_PROFILE_ARB1
 
@@ -4334,6 +4395,8 @@
     emit_##prof##_sampler, \
     emit_##prof##_attribute, \
     emit_##prof##_finalize, \
+    get_##prof##_varname, \
+    get_##prof##_const_array_varname, \
 },
 
 static const Profile profiles[] =
@@ -5981,8 +6044,8 @@
 
 static char *alloc_varname(Context *ctx, const RegisterList *reg)
 {
-    // !!! FIXME: may not be GLSL...
-    const char *varname = get_GLSL_varname(ctx, reg->regtype, reg->regnum);
+    const char *varname = ctx->profile->get_varname(ctx, reg->regtype,
+                                                    reg->regnum);
     const size_t len = strlen(varname) + 1;
     char *retval = (char *) Malloc(ctx, len);
     if (retval != NULL)
@@ -6057,14 +6120,15 @@
 
         if (ctx->uniform_array)
         {
-            char *name = (char *) Malloc(ctx, 16);  // !!! FIXME
-            if (name != NULL)
+            const char *name = ctx->profile->get_const_array_varname(ctx);
+            char *namecpy = (char *) Malloc(ctx, strlen(name) + 1);
+            if (namecpy != NULL)
             {
-                strcpy(name, get_GLSL_const_array_varname(ctx)); // !!! FIXME
+                strcpy(namecpy, name);
                 wptr->type = type;
-                wptr->index = index;
+                wptr->index = 0;
                 wptr->array_count = ctx->max_constreg + 1;
-                wptr->name = name;
+                wptr->name = namecpy;
                 ctx->uniform_count -= (array_items - 1);
             } // if
         } // if
@@ -6401,13 +6465,29 @@
                                       (TextureType) item->index);
     } // for
 
-    // ...and attributes...
+    // ...and attributes... (find POSITION0 here, so it's always first).
     for (item = ctx->attributes.next; item != NULL; item = item->next)
     {
-        ctx->attribute_count++;
-        ctx->profile->attribute_emitter(ctx, item->regtype, item->regnum,
-                                        item->usage, item->index,
-                                        item->writemask);
+        if ((item->usage == MOJOSHADER_USAGE_POSITION) && (item->index == 0))
+        {
+            ctx->attribute_count++;
+            ctx->profile->attribute_emitter(ctx, item->regtype, item->regnum,
+                                            MOJOSHADER_USAGE_POSITION, 0,
+                                            item->writemask);
+            break;
+        } // if
+    } // for
+
+    // ...and attributes... (everything but POSITION0).
+    for (item = ctx->attributes.next; item != NULL; item = item->next)
+    {
+        if ((item->usage != MOJOSHADER_USAGE_POSITION) || (item->index != 0))
+        {
+            ctx->attribute_count++;
+            ctx->profile->attribute_emitter(ctx, item->regtype, item->regnum,
+                                            item->usage, item->index,
+                                            item->writemask);
+        } // if
     } // for
 } // process_definitions
 
--- a/mojoshader_opengl.c	Sat May 31 01:57:51 2008 -0400
+++ b/mojoshader_opengl.c	Mon Jun 02 00:14:02 2008 -0400
@@ -172,12 +172,14 @@
     int (*profileCompileShader)(const MOJOSHADER_parseData *pd, GLuint *s);
     void (*profileDeleteShader)(const GLuint shader);
     void (*profileDeleteProgram)(const GLuint program);
-    GLint (*profileGetUniformLocation)(GLuint, const MOJOSHADER_parseData *, int);
+    GLint (*profileGetAttribLocation)(MOJOSHADER_glProgram *program, int idx);
+    GLint (*profileGetUniformLocation)(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
+    GLint (*profileGetSamplerLocation)(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
     GLuint (*profileLinkProgram)(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
     void (*profileUseProgramObject)(MOJOSHADER_glProgram *program);
-    void (*profileUniform4fv)(const MOJOSHADER_parseData *pd, GLint loc, GLsizei siz, GLfloat *v);
-    void (*profileUniform4iv)(const MOJOSHADER_parseData *pd, GLint loc, GLsizei siz, GLint *v);
-    void (*profileUniform1i)(const MOJOSHADER_parseData *pd, GLint loc, GLint v);
+    void (*profileUniform4fv)(const MOJOSHADER_parseData *, GLint, GLsizei, GLfloat *);
+    void (*profileUniform4iv)(const MOJOSHADER_parseData *, GLint, GLsizei, GLint *);
+    void (*profileUniform1i)(const MOJOSHADER_parseData *, GLint, GLint);
     void (*profileSetSampler)(GLint loc, GLuint sampler);
 };
 
@@ -186,7 +188,9 @@
 static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s);
 static void impl_GLSL_DeleteShader(const GLuint shader);
 static void impl_GLSL_DeleteProgram(const GLuint program);
-static GLint impl_GLSL_GetUniformLocation(GLuint, const MOJOSHADER_parseData *, int);
+static GLint impl_GLSL_GetAttribLocation(MOJOSHADER_glProgram *, int);
+static GLint impl_GLSL_GetUniformLocation(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
+static GLint impl_GLSL_GetSamplerLocation(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
 static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
 static void impl_GLSL_UseProgramObject(MOJOSHADER_glProgram *program);
 static void impl_GLSL_Uniform4fv(const MOJOSHADER_parseData *pd, GLint loc, GLsizei siz, GLfloat *v);
@@ -198,7 +202,9 @@
 static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s);
 static void impl_ARB1_DeleteShader(const GLuint shader);
 static void impl_ARB1_DeleteProgram(const GLuint program);
-static GLint impl_ARB1_GetUniformLocation(GLuint, const MOJOSHADER_parseData *, int);
+static GLint impl_ARB1_GetAttribLocation(MOJOSHADER_glProgram *, int);
+static GLint impl_ARB1_GetUniformLocation(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
+static GLint impl_ARB1_GetSamplerLocation(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
 static GLuint impl_ARB1_LinkProgram(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
 static void impl_ARB1_UseProgramObject(MOJOSHADER_glProgram *program);
 static void impl_ARB1_Uniform4fv(const MOJOSHADER_parseData *pd, GLint loc, GLsizei siz, GLfloat *v);
@@ -207,10 +213,8 @@
 static void impl_ARB1_SetSampler(GLint loc, GLuint sampler);
 
 
-
 static MOJOSHADER_glContext *ctx = NULL;
 
-
 // Error state...
 static char error_buffer[1024] = { '\0' };
 
@@ -512,7 +516,9 @@
         ctx->profileCompileShader = impl_GLSL_CompileShader;
         ctx->profileDeleteShader = impl_GLSL_DeleteShader;
         ctx->profileDeleteProgram = impl_GLSL_DeleteProgram;
+        ctx->profileGetAttribLocation = impl_GLSL_GetAttribLocation;
         ctx->profileGetUniformLocation = impl_GLSL_GetUniformLocation;
+        ctx->profileGetSamplerLocation = impl_GLSL_GetSamplerLocation;
         ctx->profileLinkProgram = impl_GLSL_LinkProgram;
         ctx->profileUseProgramObject = impl_GLSL_UseProgramObject;
         ctx->profileUniform4fv = impl_GLSL_Uniform4fv;
@@ -529,7 +535,9 @@
         ctx->profileCompileShader = impl_ARB1_CompileShader;
         ctx->profileDeleteShader = impl_ARB1_DeleteShader;
         ctx->profileDeleteProgram = impl_ARB1_DeleteProgram;
+        ctx->profileGetAttribLocation = impl_ARB1_GetAttribLocation;
         ctx->profileGetUniformLocation = impl_ARB1_GetUniformLocation;
+        ctx->profileGetSamplerLocation = impl_ARB1_GetSamplerLocation;
         ctx->profileLinkProgram = impl_ARB1_LinkProgram;
         ctx->profileUseProgramObject = impl_ARB1_UseProgramObject;
         ctx->profileUniform4fv = impl_ARB1_Uniform4fv;
@@ -547,7 +555,9 @@
     assert(ctx->profileCompileShader != NULL);
     assert(ctx->profileDeleteShader != NULL);
     assert(ctx->profileDeleteProgram != NULL);
+    assert(ctx->profileGetAttribLocation != NULL);
     assert(ctx->profileGetUniformLocation != NULL);
+    assert(ctx->profileGetSamplerLocation != NULL);
     assert(ctx->profileLinkProgram != NULL);
     assert(ctx->profileUseProgramObject != NULL);
     assert(ctx->profileUniform4fv != NULL);
@@ -774,17 +784,19 @@
 } // program_unref
 
 
-static GLint impl_GLSL_GetUniformLocation(GLuint handle,
-                                       const MOJOSHADER_parseData *pd, int idx)
+static GLint impl_GLSL_GetUniformLocation(MOJOSHADER_glProgram *program,
+                                          MOJOSHADER_glShader *shader, int idx)
 {
-    return ctx->glGetUniformLocation(handle, pd->uniforms[idx].name);
+    return ctx->glGetUniformLocation(program->handle,
+                                     shader->parseData->uniforms[idx].name);
 } // impl_GLSL_GetUniformLocation
 
-static GLint impl_ARB1_GetUniformLocation(GLuint handle,
-                                       const MOJOSHADER_parseData *pd, int idx)
+
+static GLint impl_ARB1_GetUniformLocation(MOJOSHADER_glProgram *program,
+                                          MOJOSHADER_glShader *shader, int idx)
 {
-    // !!! FIXME: this only works if you have no bool or int uniforms.
-    return idx;
+    assert(shader->parseData->uniforms[idx].type == MOJOSHADER_UNIFORM_FLOAT);
+    return shader->parseData->uniforms[idx].index;  // !!! FIXME: doesn't work if there are int or bool uniforms!
 } // impl_ARB1_GetUniformLocation
 
 
@@ -794,12 +806,11 @@
     const MOJOSHADER_parseData *pd = shader->parseData;
     const MOJOSHADER_uniform *u = pd->uniforms;
     const MOJOSHADER_shaderType shader_type = pd->shader_type;
-    const GLuint handle = program->handle;
     int i;
 
     for (i = 0; i < pd->uniform_count; i++)
     {
-        const GLint loc = ctx->profileGetUniformLocation(handle, pd, i);
+        const GLint loc = ctx->profileGetUniformLocation(program, shader, i);
         if (loc != -1)  // maybe the Uniform was optimized out?
         {
             UniformMap *map = &program->uniforms[program->uniform_count];
@@ -812,6 +823,21 @@
 } // lookup_uniforms
 
 
+static GLint impl_GLSL_GetSamplerLocation(MOJOSHADER_glProgram *program,
+                                          MOJOSHADER_glShader *shader, int idx)
+{
+    return ctx->glGetUniformLocation(program->handle,
+                                     shader->parseData->samplers[idx].name);
+} // impl_GLSL_GetSamplerLocation
+
+
+static GLint impl_ARB1_GetSamplerLocation(MOJOSHADER_glProgram *program,
+                                          MOJOSHADER_glShader *shader, int idx)
+{
+    return shader->parseData->samplers[idx].index;
+} // impl_ARB1_GetSamplerLocation
+
+
 static void lookup_samplers(MOJOSHADER_glProgram *program,
                             MOJOSHADER_glShader *shader)
 {
@@ -822,7 +848,7 @@
 
     for (i = 0; i < pd->sampler_count; i++)
     {
-        const GLint loc = ctx->glGetUniformLocation(program->handle, s[i].name);
+        const GLint loc = ctx->profileGetSamplerLocation(program, shader, i);
         if (loc != -1)  // maybe the Sampler was optimized out?
         {
             SamplerMap *map = &program->samplers[program->sampler_count];
@@ -835,6 +861,19 @@
 } // lookup_samplers
 
 
+static GLint impl_GLSL_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
+{
+    const MOJOSHADER_parseData *pd = program->vertex->parseData;
+    const MOJOSHADER_attribute *a = pd->attributes;
+    return ctx->glGetAttribLocation(program->handle, a[idx].name);
+} // impl_GLSL_GetAttribLocation
+
+static GLint impl_ARB1_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
+{
+    return idx;  // map to vertex arrays in the same order as the parseData.
+} // impl_ARB1_GetAttribLocation
+
+
 static void lookup_attributes(MOJOSHADER_glProgram *program)
 {
     int i;
@@ -843,7 +882,7 @@
 
     for (i = 0; i < pd->attribute_count; i++)
     {
-        const GLint loc = ctx->glGetAttribLocation(program->handle, a[i].name);
+        const GLint loc = ctx->profileGetAttribLocation(program, i);
         if (loc != -1)  // maybe the Attribute was optimized out?
         {
             AttributeMap *map = &program->attributes[program->attribute_count];
@@ -1121,14 +1160,6 @@
 } // MOJOSHADER_glSetPixelShaderUniformB
 
 
-void MOJOSHADER_glSetSampler(unsigned int idx, unsigned int unit)
-{
-    const uint maxregs = STATICARRAYLEN(ctx->sampler_reg_file);
-    if (idx < maxregs)
-        ctx->sampler_reg_file[idx] = (GLuint) unit;
-} // MOJOSHADER_glSetSampler
-
-
 static inline GLenum opengl_attr_type(const MOJOSHADER_attributeType type)
 {
     switch (type)
@@ -1259,7 +1290,8 @@
 
 static void impl_ARB1_SetSampler(GLint loc, GLuint sampler)
 {
-    // !!! FIXME: write me
+    // no-op in this profile...arb1 uses the texture units as-is.
+    assert(loc == (GLint) sampler);
 } // impl_ARB1_SetSampler
 
 
@@ -1366,7 +1398,7 @@
     {
         const SamplerMap *map = &ctx->bound_program->samplers[i];
         const MOJOSHADER_sampler *s = map->sampler;
-        ctx->profileSetSampler(map->location, ctx->sampler_reg_file[s->index]);
+        ctx->profileSetSampler(map->location, s->index);
     } // for
 } // MOJOSHADER_glProgramReady