Skip to content
Permalink
Browse files
Expose true constant arrays in parseData, load them at link time for …
…GLSL.

--HG--
branch : trunk
  • Loading branch information
icculus committed Jul 31, 2008
1 parent 3bb0c36 commit e414a2d9e0095e51636beaed92b8d25cbf864bef
Showing with 65 additions and 27 deletions.
  1. +5 −19 mojoshader.c
  2. +5 −0 mojoshader.h
  3. +52 −6 mojoshader_opengl.c
  4. +3 −2 testparse.c
@@ -2377,25 +2377,10 @@ static void emit_GLSL_const_array(Context *ctx, const ConstantsList *clist,
else
#endif
{
// stock GLSL 1.0 can't do constant arrays, so make a global array
// and assign all entries at the start of the mainline...
// stock GLSL 1.0 can't do constant arrays, so make a uniform array
// and have the OpenGL glue assign it at link time. Lame!
push_output(ctx, &ctx->globals);
output_line(ctx, "vec4 %s[%d];", varname, size);
pop_output(ctx);

push_output(ctx, &ctx->mainline_intro);
ctx->indent++;
for (i = 0; i < size; i++)
{
while (clist->constant.type != MOJOSHADER_UNIFORM_FLOAT)
clist = clist->next;
assert(clist->constant.index == (base + i));
cstr = get_GLSL_varname(ctx, REG_TYPE_CONST, clist->constant.index);
output_line(ctx, "%s[%d] = %s;", varname, i, cstr);
clist = clist->next;
ctx->scratchidx = origscratch;
} // for
ctx->indent--;
output_line(ctx, "uniform vec4 %s[%d];", varname, size);
pop_output(ctx);
} // else
} // emit_GLSL_const_array
@@ -7112,7 +7097,7 @@ static MOJOSHADER_uniform *build_uniforms(Context *ctx)
int written = 0;
for (var = ctx->variables; var != NULL; var = var->next)
{
if ((!var->constant) && (var->used))
if (var->used)
{
const char *name = ctx->profile->get_const_array_varname(ctx,
var->index, var->count);
@@ -7123,6 +7108,7 @@ static MOJOSHADER_uniform *build_uniforms(Context *ctx)
wptr->type = MOJOSHADER_UNIFORM_FLOAT;
wptr->index = var->index;
wptr->array_count = var->count;
wptr->constant = (var->constant != NULL) ? 1 : 0;
wptr->name = namecpy;
wptr++;
written++;
@@ -92,6 +92,10 @@ typedef enum
* just a single uniform. To be extra difficult, you'll need to fill in the
* correct values from the MOJOSHADER_constant data into the appropriate
* parts of the array, overriding the constant register file. Fun!
* (constant) says whether this is a constant array; these need to be loaded
* once at creation time, from the constant list and not ever updated from
* the constant register file. This is a workaround for limitations in some
* profiles.
* (name) is a profile-specific variable name; it may be NULL if it isn't
* applicable to the requested profile.
*/
@@ -100,6 +104,7 @@ typedef struct
MOJOSHADER_uniformType type;
int index;
int array_count;
int constant;
const char *name;
} MOJOSHADER_uniform;

@@ -196,6 +196,7 @@ struct MOJOSHADER_glContext
void (*profileUniform4iv)(const MOJOSHADER_parseData *, GLint, GLsizei, GLint *);
void (*profileUniform1i)(const MOJOSHADER_parseData *, GLint, GLint);
void (*profileSetSampler)(GLint loc, GLuint sampler);
int (*profileMustLoadConstantArrays)(void);
};


@@ -259,6 +260,8 @@ static inline GLenum glsl_shader_type(const MOJOSHADER_shaderType t)
} // glsl_shader_type


static int impl_GLSL_MustLoadConstantArrays(void) { return 1; }

static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type)
{
GLenum pname = GL_NONE;
@@ -407,6 +410,7 @@ static inline GLenum arb1_shader_type(const MOJOSHADER_shaderType t)
return GL_NONE;
} // arb1_shader_type

static int impl_ARB1_MustLoadConstantArrays(void) { return 0; }

static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type)
{
@@ -942,6 +946,7 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
ctx->profileUniform4iv = impl_GLSL_Uniform4iv;
ctx->profileUniform1i = impl_GLSL_Uniform1i;
ctx->profileSetSampler = impl_GLSL_SetSampler;
ctx->profileMustLoadConstantArrays = impl_GLSL_MustLoadConstantArrays;
} // if
#endif

@@ -964,6 +969,7 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
ctx->profileUniform4iv = impl_ARB1_Uniform4iv;
ctx->profileUniform1i = impl_ARB1_Uniform1i;
ctx->profileSetSampler = impl_ARB1_SetSampler;
ctx->profileMustLoadConstantArrays = impl_ARB1_MustLoadConstantArrays;

// GL_NV_gpu_program4 has integer uniform loading support.
if (strcmp(profile, MOJOSHADER_PROFILE_NV4) == 0)
@@ -988,6 +994,7 @@ MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
assert(ctx->profileUniform4iv != NULL);
assert(ctx->profileUniform1i != NULL);
assert(ctx->profileSetSampler != NULL);
assert(ctx->profileMustLoadConstantArrays != NULL);

retval = ctx;
ctx = current_ctx;
@@ -1097,24 +1104,59 @@ static void program_unref(MOJOSHADER_glProgram *program)
} // program_unref


static void fill_constant_array(GLfloat *f, const int base, const int size,
const MOJOSHADER_parseData *pd)
{
int i;
int filled = 0;
for (i = 0; i < pd->constant_count; i++)
{
const MOJOSHADER_constant *c = &pd->constants[i];
if (c->type != MOJOSHADER_UNIFORM_FLOAT)
continue;
else if (c->index < base)
continue;
else if (c->index >= (base+size))
continue;
memcpy(&f[(c->index-base) * 4], &c->value.f, sizeof (c->value.f));
filled++;
} // for

assert(filled == size);
} // fill_constant_array


static void lookup_uniforms(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader)
{
const MOJOSHADER_parseData *pd = shader->parseData;
const MOJOSHADER_uniform *u = pd->uniforms;
const MOJOSHADER_shaderType shader_type = pd->shader_type;
int i;

for (i = 0; i < pd->uniform_count; i++)
{
const MOJOSHADER_uniform *u = &pd->uniforms[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];
map->shader_type = shader_type;
map->uniform = &u[i];
map->location = (GLuint) loc;
program->uniform_count++;
// only do constants once, at link time. These aren't changed ever.
if ( (u->constant) && (ctx->profileMustLoadConstantArrays()) )
{
const int base = u->index;
const int size = u->array_count;
GLfloat *f = (GLfloat *) alloca(sizeof (GLfloat) * size * 4);
fill_constant_array(f, base, size, pd);
ctx->profileUseProgramObject(program);
ctx->profileUniform4fv(pd, loc, size, f);
} // if
else
{
UniformMap *map = &program->uniforms[program->uniform_count];
map->shader_type = shader_type;
map->uniform = u;
map->location = (GLuint) loc;
program->uniform_count++;
} // else
} // if
} // for
} // lookup_uniforms
@@ -1177,6 +1219,8 @@ static int build_constants_lists(MOJOSHADER_glProgram *program)
const MOJOSHADER_uniform *u = map->uniform;
const int size = u->array_count;

assert(!u->constant);

if (size == 0)
continue; // nothing to see here.

@@ -1506,6 +1550,8 @@ void MOJOSHADER_glProgramReady(void)
GLint *regi;
GLint *regb;

assert(!u->constant);

if (shader_type == MOJOSHADER_TYPE_VERTEX)
{
pd = ctx->bound_program->vertex->parseData;
@@ -141,6 +141,7 @@ static int do_parse(const unsigned char *buf, const int len, const char *prof)
static const char *typenames[] = { "float", "int", "bool" };
const MOJOSHADER_uniform *u = &pd->uniforms[i];
const char *arrayof = "";
const char *constant = u->constant ? "const " : "";
char arrayrange[64] = { '\0' };
if (u->array_count > 0)
{
@@ -149,8 +150,8 @@ static int do_parse(const unsigned char *buf, const int len, const char *prof)
u->array_count);
} // if

printf(" * %d: %s%s%s", u->index, arrayof, arrayrange,
typenames[(int) u->type]);
printf(" * %d: %s%s%s%s", u->index, constant, arrayof,
arrayrange, typenames[(int) u->type]);
if (u->name != NULL)
printf(" (\"%s\")", u->name);
printf("\n");

0 comments on commit e414a2d

Please sign in to comment.