summaryrefslogtreecommitdiffstats
path: root/src/mesa/program
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/ir_to_mesa.cpp9
-rw-r--r--src/mesa/program/prog_execute.c34
-rw-r--r--src/mesa/program/prog_opt_constant_fold.c2
-rw-r--r--src/mesa/program/prog_print.c10
-rw-r--r--src/mesa/program/program.c59
-rw-r--r--src/mesa/program/program.h80
-rw-r--r--src/mesa/program/program_parse_extra.c50
7 files changed, 211 insertions, 33 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 3bffe90ff1f..b8b082e2a59 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -534,6 +534,7 @@ type_size(const struct glsl_type *type)
return size;
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
+ case GLSL_TYPE_SUBROUTINE:
/* Samplers take up one slot in UNIFORMS[], but they're baked in
* at link time.
*/
@@ -1343,6 +1344,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
case ir_unop_dFdx_fine:
case ir_unop_dFdy_coarse:
case ir_unop_dFdy_fine:
+ case ir_unop_subroutine_to_int:
assert(!"not supported");
break;
@@ -2385,7 +2387,7 @@ _mesa_generate_parameters_list_for_uniforms(struct gl_shader_program
ir_variable *var = node->as_variable();
if ((var == NULL) || (var->data.mode != ir_var_uniform)
- || var->is_in_uniform_block() || (strncmp(var->name, "gl_", 3) == 0))
+ || var->is_in_buffer_block() || (strncmp(var->name, "gl_", 3) == 0))
continue;
add.process(var);
@@ -2452,6 +2454,7 @@ _mesa_associate_uniform_storage(struct gl_context *ctx,
break;
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
+ case GLSL_TYPE_SUBROUTINE:
format = uniform_native;
columns = 1;
break;
@@ -2912,7 +2915,7 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput
|| options->EmitNoIndirectTemp || options->EmitNoIndirectUniform)
progress =
- lower_variable_index_to_cond_assign(ir,
+ lower_variable_index_to_cond_assign(prog->_LinkedShaders[i]->Stage, ir,
options->EmitNoIndirectInput,
options->EmitNoIndirectOutput,
options->EmitNoIndirectTemp,
@@ -2977,6 +2980,8 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
if (prog->LinkStatus) {
if (!ctx->Driver.LinkShader(ctx, prog)) {
prog->LinkStatus = GL_FALSE;
+ } else {
+ build_program_resource_list(ctx, prog);
}
}
diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
index 46260b54882..2c52d0db508 100644
--- a/src/mesa/program/prog_execute.c
+++ b/src/mesa/program/prog_execute.c
@@ -623,7 +623,7 @@ _mesa_execute_program(struct gl_context * ctx,
GLfloat a[4], result[4];
fetch_vector1(&inst->SrcReg[0], machine, a);
result[0] = result[1] = result[2] = result[3]
- = (GLfloat) cos(a[0]);
+ = cosf(a[0]);
store_vector4(inst, machine, result);
}
break;
@@ -723,7 +723,7 @@ _mesa_execute_program(struct gl_context * ctx,
* result.z = result.x * APPX(result.y)
* We do what the ARB extension says.
*/
- q[2] = (GLfloat) pow(2.0, t[0]);
+ q[2] = exp2f(t[0]);
}
q[1] = t[0] - floor_t0;
q[3] = 1.0F;
@@ -734,7 +734,7 @@ _mesa_execute_program(struct gl_context * ctx,
{
GLfloat a[4], result[4], val;
fetch_vector1(&inst->SrcReg[0], machine, a);
- val = (GLfloat) pow(2.0, a[0]);
+ val = exp2f(a[0]);
/*
if (IS_INF_OR_NAN(val))
val = 1.0e10;
@@ -776,7 +776,7 @@ _mesa_execute_program(struct gl_context * ctx,
if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) {
GLfloat a[4];
fetch_vector1(&inst->SrcReg[0], machine, a);
- cond = (a[0] != 0.0);
+ cond = (a[0] != 0.0F);
}
else {
cond = eval_condition(machine, inst);
@@ -834,7 +834,7 @@ _mesa_execute_program(struct gl_context * ctx,
val = -FLT_MAX;
}
else {
- val = (float)(log(a[0]) * 1.442695F);
+ val = logf(a[0]) * 1.442695F;
}
result[0] = result[1] = result[2] = result[3] = val;
store_vector4(inst, machine, result);
@@ -853,10 +853,10 @@ _mesa_execute_program(struct gl_context * ctx,
result[1] = a[0];
/* XXX we could probably just use pow() here */
if (a[0] > 0.0F) {
- if (a[1] == 0.0 && a[3] == 0.0)
+ if (a[1] == 0.0F && a[3] == 0.0F)
result[2] = 1.0F;
else
- result[2] = (GLfloat) pow(a[1], a[3]);
+ result[2] = powf(a[1], a[3]);
}
else {
result[2] = 0.0F;
@@ -886,12 +886,12 @@ _mesa_execute_program(struct gl_context * ctx,
int exponent;
GLfloat mantissa = frexpf(t[0], &exponent);
q[0] = (GLfloat) (exponent - 1);
- q[1] = (GLfloat) (2.0 * mantissa); /* map [.5, 1) -> [1, 2) */
+ q[1] = 2.0F * mantissa; /* map [.5, 1) -> [1, 2) */
/* The fast LOG2 macro doesn't meet the precision
* requirements.
*/
- q[2] = (float)(log(t[0]) * 1.442695F);
+ q[2] = logf(t[0]) * 1.442695F;
}
}
else {
@@ -1051,7 +1051,7 @@ _mesa_execute_program(struct gl_context * ctx,
fetch_vector1(&inst->SrcReg[0], machine, a);
fetch_vector1(&inst->SrcReg[1], machine, b);
result[0] = result[1] = result[2] = result[3]
- = (GLfloat) pow(a[0], b[0]);
+ = powf(a[0], b[0]);
store_vector4(inst, machine, result);
}
break;
@@ -1095,10 +1095,10 @@ _mesa_execute_program(struct gl_context * ctx,
{
GLfloat a[4], result[4];
fetch_vector1(&inst->SrcReg[0], machine, a);
- result[0] = (GLfloat) cos(a[0]);
- result[1] = (GLfloat) sin(a[0]);
- result[2] = 0.0; /* undefined! */
- result[3] = 0.0; /* undefined! */
+ result[0] = cosf(a[0]);
+ result[1] = sinf(a[0]);
+ result[2] = 0.0F; /* undefined! */
+ result[3] = 0.0F; /* undefined! */
store_vector4(inst, machine, result);
}
break;
@@ -1161,7 +1161,7 @@ _mesa_execute_program(struct gl_context * ctx,
GLfloat a[4], result[4];
fetch_vector1(&inst->SrcReg[0], machine, a);
result[0] = result[1] = result[2] = result[3]
- = (GLfloat) sin(a[0]);
+ = sinf(a[0]);
store_vector4(inst, machine, result);
}
break;
@@ -1360,7 +1360,7 @@ _mesa_execute_program(struct gl_context * ctx,
* zero, we'd probably be fine except for an assert in
* IROUND_POS() which gets triggered by the inf values created.
*/
- if (texcoord[3] != 0.0) {
+ if (texcoord[3] != 0.0F) {
texcoord[0] /= texcoord[3];
texcoord[1] /= texcoord[3];
texcoord[2] /= texcoord[3];
@@ -1380,7 +1380,7 @@ _mesa_execute_program(struct gl_context * ctx,
fetch_vector4(&inst->SrcReg[0], machine, texcoord);
if (inst->TexSrcTarget != TEXTURE_CUBE_INDEX &&
- texcoord[3] != 0.0) {
+ texcoord[3] != 0.0F) {
texcoord[0] /= texcoord[3];
texcoord[1] /= texcoord[3];
texcoord[2] /= texcoord[3];
diff --git a/src/mesa/program/prog_opt_constant_fold.c b/src/mesa/program/prog_opt_constant_fold.c
index 3811c0d8aa6..e2518e660e6 100644
--- a/src/mesa/program/prog_opt_constant_fold.c
+++ b/src/mesa/program/prog_opt_constant_fold.c
@@ -38,6 +38,8 @@ src_regs_are_constant(const struct prog_instruction *inst, unsigned num_srcs)
for (i = 0; i < num_srcs; i++) {
if (inst->SrcReg[i].File != PROGRAM_CONSTANT)
return false;
+ if (inst->SrcReg[i].RelAddr)
+ return false;
}
return true;
diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c
index e4faa63c06f..bb7c2c6e527 100644
--- a/src/mesa/program/prog_print.c
+++ b/src/mesa/program/prog_print.c
@@ -147,6 +147,8 @@ arb_input_attrib_string(GLuint index, GLenum progType)
"fragment.(twenty-one)", /* VARYING_SLOT_VIEWPORT */
"fragment.(twenty-two)", /* VARYING_SLOT_FACE */
"fragment.(twenty-three)", /* VARYING_SLOT_PNTC */
+ "fragment.(twenty-four)", /* VARYING_SLOT_TESS_LEVEL_OUTER */
+ "fragment.(twenty-five)", /* VARYING_SLOT_TESS_LEVEL_INNER */
"fragment.varying[0]",
"fragment.varying[1]",
"fragment.varying[2]",
@@ -272,6 +274,8 @@ arb_output_attrib_string(GLuint index, GLenum progType)
"result.(twenty-one)", /* VARYING_SLOT_VIEWPORT */
"result.(twenty-two)", /* VARYING_SLOT_FACE */
"result.(twenty-three)", /* VARYING_SLOT_PNTC */
+ "result.(twenty-four)", /* VARYING_SLOT_TESS_LEVEL_OUTER */
+ "result.(twenty-five)", /* VARYING_SLOT_TESS_LEVEL_INNER */
"result.varying[0]",
"result.varying[1]",
"result.varying[2]",
@@ -1015,6 +1019,12 @@ _mesa_write_shader_to_file(const struct gl_shader *shader)
case MESA_SHADER_FRAGMENT:
type = "frag";
break;
+ case MESA_SHADER_TESS_CTRL:
+ type = "tesc";
+ break;
+ case MESA_SHADER_TESS_EVAL:
+ type = "tese";
+ break;
case MESA_SHADER_VERTEX:
type = "vert";
break;
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index c13e61b1630..2d03bba3d12 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -286,6 +286,38 @@ _mesa_init_compute_program(struct gl_context *ctx,
/**
+ * Initialize a new tessellation control program object.
+ */
+struct gl_program *
+_mesa_init_tess_ctrl_program(struct gl_context *ctx,
+ struct gl_tess_ctrl_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog) {
+ init_program_struct(&prog->Base, target, id);
+ return &prog->Base;
+ }
+ return NULL;
+}
+
+
+/**
+ * Initialize a new tessellation evaluation program object.
+ */
+struct gl_program *
+_mesa_init_tess_eval_program(struct gl_context *ctx,
+ struct gl_tess_eval_program *prog,
+ GLenum target, GLuint id)
+{
+ if (prog) {
+ init_program_struct(&prog->Base, target, id);
+ return &prog->Base;
+ }
+ return NULL;
+}
+
+
+/**
* Initialize a new geometry program object.
*/
struct gl_program *
@@ -333,6 +365,16 @@ _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id)
CALLOC_STRUCT(gl_geometry_program),
target, id);
break;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ prog = _mesa_init_tess_ctrl_program(ctx,
+ CALLOC_STRUCT(gl_tess_ctrl_program),
+ target, id);
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ prog = _mesa_init_tess_eval_program(ctx,
+ CALLOC_STRUCT(gl_tess_eval_program),
+ target, id);
+ break;
case GL_COMPUTE_PROGRAM_NV:
prog = _mesa_init_compute_program(ctx,
CALLOC_STRUCT(gl_compute_program),
@@ -554,6 +596,23 @@ _mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog)
gpc->UsesStreams = gp->UsesStreams;
}
break;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ {
+ const struct gl_tess_ctrl_program *tcp = gl_tess_ctrl_program_const(prog);
+ struct gl_tess_ctrl_program *tcpc = gl_tess_ctrl_program(clone);
+ tcpc->VerticesOut = tcp->VerticesOut;
+ }
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ {
+ const struct gl_tess_eval_program *tep = gl_tess_eval_program_const(prog);
+ struct gl_tess_eval_program *tepc = gl_tess_eval_program(clone);
+ tepc->PrimitiveMode = tep->PrimitiveMode;
+ tepc->Spacing = tep->Spacing;
+ tepc->VertexOrder = tep->VertexOrder;
+ tepc->PointMode = tep->PointMode;
+ }
+ break;
default:
_mesa_problem(NULL, "Unexpected target in _mesa_clone_program");
}
diff --git a/src/mesa/program/program.h b/src/mesa/program/program.h
index 2d92ab2f118..a894147cafd 100644
--- a/src/mesa/program/program.h
+++ b/src/mesa/program/program.h
@@ -79,6 +79,16 @@ _mesa_init_fragment_program(struct gl_context *ctx,
GLenum target, GLuint id);
extern struct gl_program *
+_mesa_init_tess_ctrl_program(struct gl_context *ctx,
+ struct gl_tess_ctrl_program *prog,
+ GLenum target, GLuint id);
+
+extern struct gl_program *
+_mesa_init_tess_eval_program(struct gl_context *ctx,
+ struct gl_tess_eval_program *prog,
+ GLenum target, GLuint id);
+
+extern struct gl_program *
_mesa_init_geometry_program(struct gl_context *ctx,
struct gl_geometry_program *prog,
GLenum target, GLuint id);
@@ -147,6 +157,25 @@ _mesa_reference_compprog(struct gl_context *ctx,
(struct gl_program *) prog);
}
+
+static inline void
+_mesa_reference_tesscprog(struct gl_context *ctx,
+ struct gl_tess_ctrl_program **ptr,
+ struct gl_tess_ctrl_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
+static inline void
+_mesa_reference_tesseprog(struct gl_context *ctx,
+ struct gl_tess_eval_program **ptr,
+ struct gl_tess_eval_program *prog)
+{
+ _mesa_reference_program(ctx, (struct gl_program **) ptr,
+ (struct gl_program *) prog);
+}
+
extern struct gl_program *
_mesa_clone_program(struct gl_context *ctx, const struct gl_program *prog);
@@ -157,6 +186,20 @@ _mesa_clone_vertex_program(struct gl_context *ctx,
return (struct gl_vertex_program *) _mesa_clone_program(ctx, &prog->Base);
}
+static inline struct gl_tess_ctrl_program *
+_mesa_clone_tess_ctrl_program(struct gl_context *ctx,
+ const struct gl_tess_ctrl_program *prog)
+{
+ return (struct gl_tess_ctrl_program *) _mesa_clone_program(ctx, &prog->Base);
+}
+
+static inline struct gl_tess_eval_program *
+_mesa_clone_tess_eval_program(struct gl_context *ctx,
+ const struct gl_tess_eval_program *prog)
+{
+ return (struct gl_tess_eval_program *) _mesa_clone_program(ctx, &prog->Base);
+}
+
static inline struct gl_geometry_program *
_mesa_clone_geometry_program(struct gl_context *ctx,
const struct gl_geometry_program *prog)
@@ -216,6 +259,10 @@ _mesa_program_enum_to_shader_stage(GLenum v)
return MESA_SHADER_FRAGMENT;
case GL_GEOMETRY_PROGRAM_NV:
return MESA_SHADER_GEOMETRY;
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ return MESA_SHADER_TESS_CTRL;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ return MESA_SHADER_TESS_EVAL;
case GL_COMPUTE_PROGRAM_NV:
return MESA_SHADER_COMPUTE;
default:
@@ -235,6 +282,10 @@ _mesa_shader_stage_to_program(unsigned stage)
return GL_FRAGMENT_PROGRAM_ARB;
case MESA_SHADER_GEOMETRY:
return GL_GEOMETRY_PROGRAM_NV;
+ case MESA_SHADER_TESS_CTRL:
+ return GL_TESS_CONTROL_PROGRAM_NV;
+ case MESA_SHADER_TESS_EVAL:
+ return GL_TESS_EVALUATION_PROGRAM_NV;
case MESA_SHADER_COMPUTE:
return GL_COMPUTE_PROGRAM_NV;
}
@@ -244,7 +295,9 @@ _mesa_shader_stage_to_program(unsigned stage)
}
-/* Cast wrappers from gl_program to gl_vertex/geometry/fragment_program */
+/* Cast wrappers from gl_program to derived program types.
+ * (e.g. gl_vertex_program)
+ */
static inline struct gl_fragment_program *
gl_fragment_program(struct gl_program *prog)
@@ -297,6 +350,31 @@ gl_compute_program_const(const struct gl_program *prog)
return (const struct gl_compute_program *) prog;
}
+static inline struct gl_tess_ctrl_program *
+gl_tess_ctrl_program(struct gl_program *prog)
+{
+ return (struct gl_tess_ctrl_program *) prog;
+}
+
+static inline const struct gl_tess_ctrl_program *
+gl_tess_ctrl_program_const(const struct gl_program *prog)
+{
+ return (const struct gl_tess_ctrl_program *) prog;
+}
+
+
+static inline struct gl_tess_eval_program *
+gl_tess_eval_program(struct gl_program *prog)
+{
+ return (struct gl_tess_eval_program *) prog;
+}
+
+static inline const struct gl_tess_eval_program *
+gl_tess_eval_program_const(const struct gl_program *prog)
+{
+ return (const struct gl_tess_eval_program *) prog;
+}
+
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/mesa/program/program_parse_extra.c b/src/mesa/program/program_parse_extra.c
index 32b54afc57b..71f86d13ace 100644
--- a/src/mesa/program/program_parse_extra.c
+++ b/src/mesa/program/program_parse_extra.c
@@ -163,6 +163,8 @@ _mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
int
_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
{
+ unsigned fog_option;
+
/* All of the options currently supported start with "ARB_". The code is
* currently structured with nested if-statements because eventually options
* that start with "NV_" will be supported. This structure will result in
@@ -177,20 +179,42 @@ _mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
if (strncmp(option, "fog_", 4) == 0) {
option += 4;
- if (state->option.Fog == OPTION_NONE) {
- if (strcmp(option, "exp") == 0) {
- state->option.Fog = OPTION_FOG_EXP;
- return 1;
- } else if (strcmp(option, "exp2") == 0) {
- state->option.Fog = OPTION_FOG_EXP2;
- return 1;
- } else if (strcmp(option, "linear") == 0) {
- state->option.Fog = OPTION_FOG_LINEAR;
- return 1;
- }
- }
+ if (strcmp(option, "exp") == 0) {
+ fog_option = OPTION_FOG_EXP;
+ } else if (strcmp(option, "exp2") == 0) {
+ fog_option = OPTION_FOG_EXP2;
+ } else if (strcmp(option, "linear") == 0) {
+ fog_option = OPTION_FOG_LINEAR;
+ } else {
+ /* invalid option */
+ return 0;
+ }
- return 0;
+ if (state->option.Fog == OPTION_NONE) {
+ state->option.Fog = fog_option;
+ return 1;
+ }
+
+ /* The ARB_fragment_program specification instructs us to handle
+ * redundant options in two seemingly contradictory ways:
+ *
+ * Section 3.11.4.5.1 says:
+ * "Only one fog application option may be specified by any given
+ * fragment program. A fragment program that specifies more than one
+ * of the program options "ARB_fog_exp", "ARB_fog_exp2", and
+ * "ARB_fog_linear", will fail to load."
+ *
+ * Issue 27 says:
+ * "The three mandatory options are ARB_fog_exp, ARB_fog_exp2, and
+ * ARB_fog_linear. As these options are mutually exclusive by
+ * nature, specifying more than one is not useful. If more than one
+ * is specified, the last one encountered in the <optionSequence>
+ * will be the one to actually modify the execution environment."
+ *
+ * We choose to allow programs to specify the same OPTION redundantly,
+ * but fail to load programs that specify contradictory options.
+ */
+ return state->option.Fog == fog_option ? 1 : 0;
} else if (strncmp(option, "precision_hint_", 15) == 0) {
option += 15;