From b4e9750bf4996ca5bb622bbbe28be4f071811bc6 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Tue, 4 Apr 2006 10:18:07 +0000 Subject: More GLSL code: - add support for varyings; GLSL fixes: - pow was wrongly computed in x86 back-end; --- src/mesa/shader/slang/slang_analyse.c | 8 +- src/mesa/shader/slang/slang_execute_x86.c | 27 +++++- src/mesa/shader/slang/slang_export.c | 52 ++++++++++-- src/mesa/shader/slang/slang_export.h | 39 ++++++++- src/mesa/shader/slang/slang_link.c | 133 +++++++++++++++++++++++++----- src/mesa/shader/slang/slang_link.h | 22 +++++ 6 files changed, 247 insertions(+), 34 deletions(-) (limited to 'src/mesa/shader/slang') diff --git a/src/mesa/shader/slang/slang_analyse.c b/src/mesa/shader/slang/slang_analyse.c index 164dbec350..76320848b5 100644 --- a/src/mesa/shader/slang/slang_analyse.c +++ b/src/mesa/shader/slang/slang_analyse.c @@ -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: diff --git a/src/mesa/shader/slang/slang_execute_x86.c b/src/mesa/shader/slang/slang_execute_x86.c index eabe368596..b578838e82 100644 --- a/src/mesa/shader/slang/slang_execute_x86.c +++ b/src/mesa/shader/slang/slang_execute_x86.c @@ -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; diff --git a/src/mesa/shader/slang/slang_export.c b/src/mesa/shader/slang/slang_export.c index 43ce35de49..515c03fb64 100644 --- a/src/mesa/shader/slang/slang_export.c +++ b/src/mesa/shader/slang/slang_export.c @@ -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)) diff --git a/src/mesa/shader/slang/slang_export.h b/src/mesa/shader/slang/slang_export.h index 88a74fe26b..c158eb4443 100644 --- a/src/mesa/shader/slang/slang_export.h +++ b/src/mesa/shader/slang/slang_export.h @@ -35,7 +35,7 @@ extern "C" { * Basic data quantity to transfer between application and assembly. * The 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 is not 0, the data quantity is an array of size. + * If the is not 0, the data quantity is an array of size. * If the is not NULL, the data quantity is a struct. The is * invalid and the holds the size of the array. * The values match those of 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. */ diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 58d17c1558..a72ec2eaa0 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -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; diff --git a/src/mesa/shader/slang/slang_link.h b/src/mesa/shader/slang/slang_link.h index 1592aefe2e..e74c256562 100644 --- a/src/mesa/shader/slang/slang_link.h +++ b/src/mesa/shader/slang/slang_link.h @@ -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]; -- cgit v1.2.3