More GLSL code:

- add support for varyings;

GLSL fixes:
- pow was wrongly computed in x86 back-end;
This commit is contained in:
Michal Krol
2006-04-04 10:18:07 +00:00
parent 607b61a994
commit b4e9750bf4
8 changed files with 295 additions and 59 deletions

View File

@@ -2,7 +2,7 @@
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 2004-2005 Brian Paul All Rights Reserved.
* Copyright (C) 2004-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -85,14 +85,15 @@ struct gl2_program_intf
GLboolean (* GetLinkStatus) (struct gl2_program_intf **);
GLboolean (* GetValidateStatus) (struct gl2_program_intf **);
GLvoid (* Link) (struct gl2_program_intf **);
GLvoid (* Validate) (struct gl2_program_intf **);
GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **);
GLvoid (* UpdateFixedAttribute) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
GLboolean);
GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
GLboolean);
GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *);
GLvoid (* Validate) (struct gl2_program_intf **);
GLvoid (* UpdateFixedUniforms) (struct gl2_program_intf **);
GLvoid (* UpdateFixedAttribute) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
GLboolean);
GLvoid (* UpdateFixedVarying) (struct gl2_program_intf **, GLuint, GLvoid *, GLuint, GLuint,
GLboolean);
GLvoid (* GetTextureImageUsage) (struct gl2_program_intf **, GLbitfield *);
GLboolean (* IsShaderPresent) (struct gl2_program_intf **, GLenum);
GLvoid (* UpdateVarying) (struct gl2_program_intf **, GLuint, GLfloat *, GLboolean);
};
struct gl2_fragment_shader_intf

View File

@@ -1150,9 +1150,7 @@ _program_GetTextureImageUsage (struct gl2_program_intf **intf, GLbitfield *texim
{
GLuint n, addr, j;
n = pro->texture_usage.table[i].quant->array_len;
if (n == 0)
n = 1;
n = slang_export_data_quant_elements (pro->texture_usage.table[i].quant);
addr = pro->texture_usage.table[i].frag_address;
for (j = 0; j < n; j++)
{
@@ -1163,7 +1161,7 @@ _program_GetTextureImageUsage (struct gl2_program_intf **intf, GLbitfield *texim
image = (GLuint) *((GLfloat *) mem);
if (image >= 0 && image < ctx->Const.MaxTextureImageUnits)
{
switch (pro->texture_usage.table[i].quant->u.basic_type)
switch (slang_export_data_quant_type (pro->texture_usage.table[i].quant))
{
case GL_SAMPLER_1D_ARB:
case GL_SAMPLER_1D_SHADOW_ARB:
@@ -1204,6 +1202,29 @@ _program_IsShaderPresent (struct gl2_program_intf **intf, GLenum subtype)
}
}
static GLvoid
_program_UpdateVarying (struct gl2_program_intf **intf, GLuint index, GLfloat *value,
GLboolean vert)
{
struct gl2_program_impl *impl = (struct gl2_program_impl *) intf;
slang_program *pro = &impl->_obj.prog;
GLuint addr;
if (index >= pro->varyings.total)
return;
if (vert)
addr = pro->varyings.slots[index].vert_addr / 4;
else
addr = pro->varyings.slots[index].frag_addr / 4;
if (addr != ~0)
{
if (vert)
*value = pro->machines[SLANG_SHADER_VERTEX]->mem[addr]._float;
else
pro->machines[SLANG_SHADER_FRAGMENT]->mem[addr]._float = *value;
}
}
static struct gl2_program_intf _program_vftbl = {
{
{
@@ -1231,7 +1252,8 @@ static struct gl2_program_intf _program_vftbl = {
_program_UpdateFixedAttribute,
_program_UpdateFixedVarying,
_program_GetTextureImageUsage,
_program_IsShaderPresent
_program_IsShaderPresent,
_program_UpdateVarying
};
static void
@@ -1514,10 +1536,10 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
b = &bind->table[loc];
/* TODO: check sizes */
if (b->quant->structure != NULL)
if (slang_export_data_quant_struct (b->quant))
return GL_FALSE;
switch (b->quant->u.basic_type)
switch (slang_export_data_quant_type (b->quant))
{
case GL_BOOL_ARB:
types_match = (type == GL_FLOAT) || (type == GL_INT);
@@ -1556,7 +1578,7 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
types_match = (type == GL_INT);
break;
default:
types_match = (type == b->quant->u.basic_type);
types_match = (type == slang_export_data_quant_type (b->quant));
break;
}
@@ -1581,8 +1603,9 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
const GLfloat *src = (GLfloat *) (data);
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);
GLuint j;
GLuint total = count * slang_export_data_quant_components (b->quant);
for (j = 0; j < count * b->quant->size / 4; j++)
for (j = 0; j < total; j++)
dst[j] = src[j] != 0.0f ? 1.0f : 0.0f;
}
}
@@ -1594,8 +1617,9 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
const GLuint *src = (GLuint *) (data);
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);
GLuint j;
GLuint total = count * slang_export_data_quant_components (b->quant);
for (j = 0; j < count * b->quant->size / 4; j++)
for (j = 0; j < total; j++)
dst[j] = src[j] ? 1.0f : 0.0f;
}
}
@@ -1607,8 +1631,9 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
const GLuint *src = (GLuint *) (data);
GLfloat *dst = (GLfloat *) (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4]);
GLuint j;
GLuint total = count * slang_export_data_quant_components (b->quant);
for (j = 0; j < count * b->quant->size / 4; j++)
for (j = 0; j < total; j++)
dst[j] = (GLfloat) src[j];
}
}
@@ -1618,7 +1643,7 @@ GLboolean _slang_write_uniform (struct gl2_program_intf **pro, GLint loc, GLsize
if (b->address[i] != ~0)
{
_mesa_memcpy (&impl->_obj.prog.machines[i]->mem[b->address[i] / 4], data,
count * b->quant->size);
count * slang_export_data_quant_size (b->quant));
}
}
return GL_TRUE;
@@ -1664,11 +1689,8 @@ GLvoid _slang_get_active_uniform (struct gl2_program_intf **pro, GLuint index, G
name[len] = '\0';
if (length != NULL)
*length = len;
*type = u->quant->u.basic_type;
if (u->quant->array_len == 0)
*size = 1;
else
*size = u->quant->array_len;
*type = slang_export_data_quant_type (u->quant);
*size = slang_export_data_quant_elements (u->quant);
}
void

View File

@@ -49,9 +49,9 @@ GLboolean _slang_analyse_texture_usage (slang_program *prog)
{
slang_uniform_binding *b = &prog->uniforms.table[i];
if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && b->quant->structure == NULL)
if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant))
{
switch (b->quant->u.basic_type)
switch (slang_export_data_quant_type (b->quant))
{
case GL_SAMPLER_1D_ARB:
case GL_SAMPLER_2D_ARB:
@@ -77,9 +77,9 @@ GLboolean _slang_analyse_texture_usage (slang_program *prog)
{
slang_uniform_binding *b = &prog->uniforms.table[i];
if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && b->quant->structure == NULL)
if (b->address[SLANG_SHADER_FRAGMENT] != ~0 && !slang_export_data_quant_struct (b->quant))
{
switch (b->quant->u.basic_type)
switch (slang_export_data_quant_type (b->quant))
{
case GL_SAMPLER_1D_ARB:
case GL_SAMPLER_2D_ARB:

View File

@@ -81,6 +81,12 @@ static GLvoid add_fixup (codegen_ctx *G, GLuint index, GLubyte *csr)
#define RND_NEG_FPU (FAST_X86_FPU | 0x400)
#endif
#if 0
/*
* XXX
* These should produce a valid code that computes powers. Unfortunately, it does not.
*/
static void set_fpu_round_neg_inf (codegen_ctx *G)
{
if (G->fpucntl != RND_NEG_FPU)
@@ -107,6 +113,16 @@ static void emit_x87_ex2 (codegen_ctx *G)
x87_fscale (&G->f); /* 2^a */
}
static void emit_pow (codegen_ctx *G)
{
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fyl2x (&G->f);
emit_x87_ex2 (G);
}
#endif
static GLfloat do_ceilf (GLfloat x)
{
return CEILF (x);
@@ -117,6 +133,11 @@ static GLfloat do_floorf (GLfloat x)
return FLOORF (x);
}
static GLfloat do_powf (GLfloat y, GLfloat x)
{
return (GLfloat) _mesa_pow ((GLdouble) x, (GLdouble) y);
}
static GLvoid do_print_float (GLfloat x)
{
_mesa_printf ("slang print: %f\n", x);
@@ -285,10 +306,8 @@ static GLvoid codegen_assem (codegen_ctx *G, slang_assembly *a)
x87_fstp (&G->f, x86_deref (G->r_esp));
break;
case slang_asm_float_power:
x87_fld (&G->f, x86_deref (G->r_esp));
x87_fld (&G->f, x86_make_disp (G->r_esp, 4));
x87_fyl2x (&G->f);
emit_x87_ex2 (G);
/* TODO: use emit_pow() */
x86_call (&G->f, (GLubyte *) do_powf);
x86_lea (&G->f, G->r_esp, x86_make_disp (G->r_esp, 4));
x87_fstp (&G->f, x86_deref (G->r_esp));
break;

View File

@@ -69,6 +69,45 @@ slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_qu
return &self->structure[n];
}
GLboolean slang_export_data_quant_array (slang_export_data_quant *self)
{
return self->array_len != 0;
}
GLboolean slang_export_data_quant_struct (slang_export_data_quant *self)
{
return self->structure != NULL;
}
GLenum slang_export_data_quant_type (slang_export_data_quant *self)
{
assert (self->structure == NULL);
return self->u.basic_type;
}
GLuint slang_export_data_quant_fields (slang_export_data_quant *self)
{
assert (self->structure != NULL);
return self->u.field_count;
}
GLuint slang_export_data_quant_elements (slang_export_data_quant *self)
{
if (self->array_len == 0)
return 1;
return self->array_len;
}
GLuint slang_export_data_quant_components (slang_export_data_quant *self)
{
return self->size / 4;
}
GLuint slang_export_data_quant_size (slang_export_data_quant *self)
{
return self->size;
}
/*
* slang_export_data_entry
*/
@@ -254,19 +293,19 @@ static GLboolean validate_extracted (slang_export_data_quant *q, GLuint element,
case EXTRACT_BASIC:
return GL_TRUE;
case EXTRACT_ARRAY:
return element < q->array_len;
return element < slang_export_data_quant_elements (q);
case EXTRACT_STRUCT:
return q->structure != NULL;
return slang_export_data_quant_struct (q);
case EXTRACT_STRUCT_ARRAY:
return q->structure != NULL && element < q->array_len;
return slang_export_data_quant_struct (q) && element < slang_export_data_quant_elements (q);
}
return GL_FALSE;
}
static GLuint calculate_offset (slang_export_data_quant *q, GLuint element)
{
if (q->array_len != 0)
return element * q->size;
if (slang_export_data_quant_array (q))
return element * slang_export_data_quant_size (q);
return 0;
}
@@ -277,6 +316,7 @@ static GLboolean find_exported_data (slang_export_data_quant *q, const char *nam
GLuint result, element, i;
const char *end;
slang_atom atom;
const GLuint fields = slang_export_data_quant_fields (q);
result = extract_name (name, parsed, &element, &end);
if (result == EXTRACT_ERROR)
@@ -286,7 +326,7 @@ static GLboolean find_exported_data (slang_export_data_quant *q, const char *nam
if (atom == SLANG_ATOM_NULL)
return GL_FALSE;
for (i = 0; i < q->u.field_count; i++)
for (i = 0; i < fields; i++)
if (q->structure[i].name == atom)
{
if (!validate_extracted (&q->structure[i], element, result))

View File

@@ -35,7 +35,7 @@ extern "C" {
* Basic data quantity to transfer between application and assembly.
* The <size> is the actual size of the data quantity including padding, if any. It is
* used to calculate offsets from the beginning of the data.
* The <array_len> is not 0, the data quantity is an array of <array_len> size.
* If the <array_len> is not 0, the data quantity is an array of <array_len> size.
* If the <structure> is not NULL, the data quantity is a struct. The <basic_type> is
* invalid and the <field_count> holds the size of the <structure> array.
* The <basic_type> values match those of <type> parameter for glGetActiveUniformARB.
@@ -58,6 +58,43 @@ GLvoid slang_export_data_quant_ctr (slang_export_data_quant *);
GLvoid slang_export_data_quant_dtr (slang_export_data_quant *);
slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *);
/*
* Returns GL_FALSE if the quant is not an array.
*/
GLboolean slang_export_data_quant_array (slang_export_data_quant *);
/*
* Returns GL_FALSE if the quant is not a structure.
*/
GLboolean slang_export_data_quant_struct (slang_export_data_quant *);
/*
* Returns basic type of the quant. It must not be a structure.
*/
GLenum slang_export_data_quant_type (slang_export_data_quant *);
/*
* Returns number of fields in the quant that is a structure.
*/
GLuint slang_export_data_quant_fields (slang_export_data_quant *);
/*
* Return number of elements in the quant.
* For arrays, return the size of the array.
* For scalars, return 1.
*/
GLuint slang_export_data_quant_elements (slang_export_data_quant *);
/*
* Returns total number of components withing the quant element.
*/
GLuint slang_export_data_quant_components (slang_export_data_quant *);
/*
* Returns size of the quant element.
*/
GLuint slang_export_data_quant_size (slang_export_data_quant *);
/*
* Data access pattern. Specifies how data is accessed at what frequency.
*/

View File

@@ -79,46 +79,42 @@ static GLboolean slang_uniform_bindings_add (slang_uniform_bindings *self, slang
return GL_TRUE;
}
static GLboolean insert_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,
static GLboolean insert_uniform_binding (slang_uniform_bindings *bind, slang_export_data_quant *q,
char *name, slang_atom_pool *atoms, GLuint index, GLuint addr)
{
GLuint count, i;
slang_string_concat (name, slang_atom_pool_id (atoms, q->name));
if (q->array_len == 0)
count = 1;
else
count = q->array_len;
count = slang_export_data_quant_elements (q);
for (i = 0; i < count; i++)
{
GLuint save;
save = slang_string_length (name);
if (q->array_len != 0)
if (slang_export_data_quant_array (q))
_mesa_sprintf (name + slang_string_length (name), "[%d]", i);
if (q->structure != NULL)
if (slang_export_data_quant_struct (q))
{
GLuint save, i;
const GLuint fields = slang_export_data_quant_fields (q);
slang_string_concat (name, ".");
save = slang_string_length (name);
for (i = 0; i < q->u.field_count; i++)
for (i = 0; i < fields; i++)
{
if (!insert_binding (bind, &q->structure[i], name, atoms, index, addr))
if (!insert_uniform_binding (bind, &q->structure[i], name, atoms, index, addr))
return GL_FALSE;
name[save] = '\0';
addr += q->structure[i].size;
addr += slang_export_data_quant_size (&q->structure[i]);
}
}
else
{
if (!slang_uniform_bindings_add (bind, q, name, index, addr))
return GL_FALSE;
addr += q->size;
addr += slang_export_data_quant_size (q);
}
name[save] = '\0';
}
@@ -126,8 +122,8 @@ static GLboolean insert_binding (slang_uniform_bindings *bind, slang_export_data
return GL_TRUE;
}
static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, slang_export_data_table *tbl,
GLuint index)
static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind,
slang_export_data_table *tbl, GLuint index)
{
GLuint i;
@@ -136,7 +132,7 @@ static GLboolean gather_uniform_bindings (slang_uniform_bindings *bind, slang_ex
{
char name[1024] = "";
if (!insert_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,
if (!insert_uniform_binding (bind, &tbl->entries[i].quant, name, tbl->atoms, index,
tbl->entries[i].address))
return GL_FALSE;
}
@@ -184,17 +180,18 @@ static GLboolean insert_uniform (slang_active_uniforms *u, slang_export_data_qua
slang_atom_pool *atoms)
{
slang_string_concat (name, slang_atom_pool_id (atoms, q->name));
if (q->array_len != 0)
if (slang_export_data_quant_array (q))
slang_string_concat (name, "[0]");
if (q->structure != NULL)
if (slang_export_data_quant_struct (q))
{
GLuint save, i;
const GLuint fields = slang_export_data_quant_fields (q);
slang_string_concat (name, ".");
save = slang_string_length (name);
for (i = 0; i < q->u.field_count; i++)
for (i = 0; i < fields; i++)
{
if (!insert_uniform (u, &q->structure[i], name, atoms))
return GL_FALSE;
@@ -223,6 +220,97 @@ static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_
return GL_TRUE;
}
/*
* slang_varying_bindings
*/
static GLvoid slang_varying_bindings_ctr (slang_varying_bindings *self)
{
self->count = 0;
self->total = 0;
}
static GLvoid slang_varying_bindings_dtr (slang_varying_bindings *self)
{
GLuint i;
for (i = 0; i < self->count; i++)
slang_alloc_free (self->table[i].name);
}
static GLvoid update_varying_slots (slang_varying_slot *slots, GLuint count, GLboolean vert,
GLuint address, GLuint do_offset)
{
GLuint i;
for (i = 0; i < count; i++)
if (vert)
slots[i].vert_addr = address + i * 4 * do_offset;
else
slots[i].frag_addr = address + i * 4 * do_offset;
}
static GLboolean slang_varying_bindings_add (slang_varying_bindings *self,
slang_export_data_quant *q, const char *name, GLboolean vert, GLuint address)
{
const GLuint n = self->count;
const GLuint total_components =
slang_export_data_quant_components (q) * slang_export_data_quant_elements (q);
GLuint i;
for (i = 0; i < n; i++)
if (slang_string_compare (self->table[i].name, name) == 0)
{
/* TODO: data quantities must match, or else link fails */
update_varying_slots (&self->slots[self->table[i].slot], total_components, vert,
address, 1);
return GL_TRUE;
}
if (self->total + total_components > MAX_VARYING_FLOATS)
{
/* TODO: info log: error: MAX_VARYING_FLOATS exceeded */
return GL_FALSE;
}
self->table[n].quant = q;
self->table[n].slot = self->total;
self->table[n].name = slang_string_duplicate (name);
if (self->table[n].name == NULL)
return GL_FALSE;
self->count++;
update_varying_slots (&self->slots[self->table[n].slot], total_components, vert, address, 1);
update_varying_slots (&self->slots[self->table[n].slot], total_components, !vert, ~0, 0);
self->total += total_components;
return GL_TRUE;
}
static GLboolean entry_has_gl_prefix (slang_atom name, slang_atom_pool *atoms)
{
const char *str = slang_atom_pool_id (atoms, name);
return str[0] == 'g' && str[1] == 'l' && str[2] == '_';
}
static GLboolean gather_varying_bindings (slang_varying_bindings *bind,
slang_export_data_table *tbl, GLboolean vert)
{
GLuint i;
for (i = 0; i < tbl->count; i++)
if (tbl->entries[i].access == slang_exp_varying &&
!entry_has_gl_prefix (tbl->entries[i].quant.name, tbl->atoms))
{
if (!slang_varying_bindings_add (bind, &tbl->entries[i].quant,
slang_atom_pool_id (tbl->atoms, tbl->entries[i].quant.name), vert,
tbl->entries[i].address))
return GL_FALSE;
}
return GL_TRUE;
}
/*
* slang_texture_bindings
*/
@@ -248,6 +336,7 @@ GLvoid slang_program_ctr (slang_program *self)
slang_uniform_bindings_ctr (&self->uniforms);
slang_active_uniforms_ctr (&self->active_uniforms);
slang_varying_bindings_ctr (&self->varyings);
slang_texture_usages_ctr (&self->texture_usage);
for (i = 0; i < SLANG_SHADER_MAX; i++)
{
@@ -270,6 +359,7 @@ GLvoid slang_program_dtr (slang_program *self)
{
slang_uniform_bindings_dtr (&self->uniforms);
slang_active_uniforms_dtr (&self->active_uniforms);
slang_varying_bindings_dtr (&self->varyings);
slang_texture_usages_dtr (&self->texture_usage);
}
@@ -423,12 +513,17 @@ GLboolean _slang_link (slang_program *prog, slang_translation_unit **units, GLui
return GL_FALSE;
if (!gather_active_uniforms (&prog->active_uniforms, &units[i]->exp_data))
return GL_FALSE;
if (!gather_varying_bindings (&prog->varyings, &units[i]->exp_data,
index == SLANG_SHADER_VERTEX))
return GL_FALSE;
resolve_common_fixed (prog->common_fixed_entries[index], &units[i]->exp_data);
resolve_common_code (prog->code[index], &units[i]->exp_code);
prog->machines[index] = units[i]->machine;
prog->assemblies[index] = units[i]->assembly;
}
/* TODO: all varyings read by fragment shader must be written by vertex shader */
if (!_slang_analyse_texture_usage (prog))
return GL_FALSE;

View File

@@ -63,6 +63,27 @@ typedef struct
GLuint count;
} slang_active_uniforms;
typedef struct
{
GLuint vert_addr;
GLuint frag_addr;
} slang_varying_slot;
typedef struct
{
slang_export_data_quant *quant;
char *name;
GLuint slot;
} slang_varying_binding;
typedef struct
{
slang_varying_binding table[MAX_VARYING_FLOATS];
GLuint count;
slang_varying_slot slots[MAX_VARYING_FLOATS];
GLuint total;
} slang_varying_bindings;
typedef struct
{
slang_export_data_quant *quant;
@@ -173,6 +194,7 @@ typedef struct
{
slang_uniform_bindings uniforms;
slang_active_uniforms active_uniforms;
slang_varying_bindings varyings;
slang_texture_usages texture_usage;
GLuint common_fixed_entries[SLANG_SHADER_MAX][SLANG_COMMON_FIXED_MAX];
GLuint vertex_fixed_entries[SLANG_VERTEX_FIXED_MAX];