summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang
diff options
context:
space:
mode:
authorMichal Krol <mjkrol@gmail.org>2006-04-04 10:18:07 +0000
committerMichal Krol <mjkrol@gmail.org>2006-04-04 10:18:07 +0000
commitb4e9750bf4996ca5bb622bbbe28be4f071811bc6 (patch)
treee0c595b22aeee885b4910267c8dc0995e3d362d5 /src/mesa/shader/slang
parent607b61a994d8dca150d5611b18db9b55755f73b4 (diff)
More GLSL code:
- add support for varyings; GLSL fixes: - pow was wrongly computed in x86 back-end;
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r--src/mesa/shader/slang/slang_analyse.c8
-rw-r--r--src/mesa/shader/slang/slang_execute_x86.c27
-rw-r--r--src/mesa/shader/slang/slang_export.c52
-rw-r--r--src/mesa/shader/slang/slang_export.h39
-rw-r--r--src/mesa/shader/slang/slang_link.c133
-rw-r--r--src/mesa/shader/slang/slang_link.h22
6 files changed, 247 insertions, 34 deletions
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 <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.
@@ -59,6 +59,43 @@ 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;
@@ -224,6 +221,97 @@ static GLboolean gather_active_uniforms (slang_active_uniforms *u, slang_export_
}
/*
+ * 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
@@ -65,6 +65,27 @@ typedef struct
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;
GLuint frag_address;
} slang_texture_usage;
@@ -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];