From 919af2d227546728c9005b29e71ffc013a7033e5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 2 Jun 2008 00:14:02 -0400 Subject: [PATCH] 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. --HG-- branch : trunk --- mojoshader.c | 110 ++++++++++++++++++++++++++++++++++++++------ mojoshader_opengl.c | 90 ++++++++++++++++++++++++------------ 2 files changed, 156 insertions(+), 44 deletions(-) diff --git a/mojoshader.c b/mojoshader.c index c9a2302c..2b237672 100644 --- a/mojoshader.c +++ b/mojoshader.c @@ -185,6 +185,12 @@ typedef int (*args_function)(Context *ctx); // 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 @@ typedef struct 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 @@ static const char *make_D3D_srcarg_string(Context *ctx, const int idx) } // 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_start(Context *ctx) 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 @@ static void emit_PASSTHROUGH_start(Context *ctx) 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_sampler(Context *ctx, int s, TextureType ttype) {} 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 @@ static void emit_ARB1_uniform(Context *ctx, RegisterType regtype, int regnum) 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 @@ static void emit_ARB1_DCL(Context *ctx) } // 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_ARB1_OPCODE_UNIMPLEMENTED_FUNC(TEXLD) 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 *build_output(Context *ctx) 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 @@ static MOJOSHADER_uniform *build_uniforms(Context *ctx) 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 @@ static void process_definitions(Context *ctx) (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 diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index ccc8e13f..c2aa607c 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -172,12 +172,14 @@ struct MOJOSHADER_glContext 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_MaxUniforms(MOJOSHADER_shaderType shader_type); 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_MaxUniforms(MOJOSHADER_shaderType shader_type); 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_Uniform1i(const MOJOSHADER_parseData *pd, GLint loc, GLint 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 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, 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 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, 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 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile, 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 @@ static void program_unref(MOJOSHADER_glProgram *program) } // 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 @@ static void lookup_uniforms(MOJOSHADER_glProgram *program, 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 @@ static void lookup_uniforms(MOJOSHADER_glProgram *program, } // 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 @@ static void lookup_samplers(MOJOSHADER_glProgram *program, 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 @@ static void lookup_samplers(MOJOSHADER_glProgram *program, } // 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 @@ static void lookup_attributes(MOJOSHADER_glProgram *program) 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 @@ void MOJOSHADER_glSetPixelShaderUniformB(unsigned int idx, const int *data, } // 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_Uniform1i(const MOJOSHADER_parseData *pd, GLint loc, 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 @@ void MOJOSHADER_glProgramReady(void) { 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