summaryrefslogtreecommitdiff
path: root/src/mesa/program
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/arbprogparse.h6
-rw-r--r--src/mesa/program/ir_to_mesa.cpp159
-rw-r--r--src/mesa/program/ir_to_mesa.h7
-rw-r--r--src/mesa/program/nvfragparse.h5
-rw-r--r--src/mesa/program/nvvertparse.h5
-rw-r--r--src/mesa/program/prog_cache.h3
-rw-r--r--src/mesa/program/prog_execute.c12
-rw-r--r--src/mesa/program/prog_instruction.h2
-rw-r--r--src/mesa/program/prog_optimize.h3
-rw-r--r--src/mesa/program/prog_statevars.c30
-rw-r--r--src/mesa/program/prog_statevars.h5
-rw-r--r--src/mesa/program/program.c1
-rw-r--r--src/mesa/program/symbol_table.c85
-rw-r--r--src/mesa/program/symbol_table.h4
14 files changed, 302 insertions, 25 deletions
diff --git a/src/mesa/program/arbprogparse.h b/src/mesa/program/arbprogparse.h
index 08e25a1c16..4c0c300720 100644
--- a/src/mesa/program/arbprogparse.h
+++ b/src/mesa/program/arbprogparse.h
@@ -26,7 +26,11 @@
#ifndef ARBPROGPARSE_H
#define ARBPROGPARSE_H
-#include "main/mtypes.h"
+#include "main/glheader.h"
+
+struct gl_context;
+struct gl_fragment_program;
+struct gl_vertex_program;
extern void
_mesa_parse_arb_vertex_program(struct gl_context *ctx, GLenum target,
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index a5b17bb328..786fdfbd23 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -295,6 +295,8 @@ public:
bool process_move_condition(ir_rvalue *ir);
+ void copy_propagate(void);
+
void *mem_ctx;
};
@@ -1574,7 +1576,13 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir)
break;
offset += type_size(struct_type->fields.structure[i].type);
}
- this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
+
+ /* If the type is smaller than a vec4, replicate the last channel out. */
+ if (ir->type->is_scalar() || ir->type->is_vector())
+ this->result.swizzle = swizzle_for_size(ir->type->vector_elements);
+ else
+ this->result.swizzle = SWIZZLE_NOOP;
+
this->result.index += offset;
}
@@ -2171,9 +2179,14 @@ ir_to_mesa_visitor::visit(ir_discard *ir)
{
struct gl_fragment_program *fp = (struct gl_fragment_program *)this->prog;
- assert(ir->condition == NULL); /* FINISHME */
+ if (ir->condition) {
+ ir->condition->accept(this);
+ this->result.negate = ~this->result.negate;
+ ir_to_mesa_emit_op1(ir, OPCODE_KIL, ir_to_mesa_undef_dst, this->result);
+ } else {
+ ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
+ }
- ir_to_mesa_emit_op0(ir, OPCODE_KIL_NV);
fp->UsesKill = GL_TRUE;
}
@@ -2610,6 +2623,133 @@ set_uniform_initializers(struct gl_context *ctx,
talloc_free(mem_ctx);
}
+/*
+ * On a basic block basis, tracks available PROGRAM_TEMPORARY register
+ * channels for copy propagation and updates following instructions to
+ * use the original versions.
+ *
+ * The ir_to_mesa_visitor lazily produces code assuming that this pass
+ * will occur. As an example, a TXP production before this pass:
+ *
+ * 0: MOV TEMP[1], INPUT[4].xyyy;
+ * 1: MOV TEMP[1].w, INPUT[4].wwww;
+ * 2: TXP TEMP[2], TEMP[1], texture[0], 2D;
+ *
+ * and after:
+ *
+ * 0: MOV TEMP[1], INPUT[4].xyyy;
+ * 1: MOV TEMP[1].w, INPUT[4].wwww;
+ * 2: TXP TEMP[2], INPUT[4].xyyw, texture[0], 2D;
+ *
+ * which allows for dead code elimination on TEMP[1]'s writes.
+ */
+void
+ir_to_mesa_visitor::copy_propagate(void)
+{
+ ir_to_mesa_instruction **acp = talloc_zero_array(mem_ctx,
+ ir_to_mesa_instruction *,
+ this->next_temp * 4);
+
+ foreach_iter(exec_list_iterator, iter, this->instructions) {
+ ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get();
+
+ /* First, do any copy propagation possible into the src regs. */
+ for (int r = 0; r < 3; r++) {
+ ir_to_mesa_instruction *first = NULL;
+ bool good = true;
+ int acp_base = inst->src_reg[r].index * 4;
+
+ if (inst->src_reg[r].file != PROGRAM_TEMPORARY ||
+ inst->src_reg[r].reladdr)
+ continue;
+
+ /* See if we can find entries in the ACP consisting of MOVs
+ * from the same src register for all the swizzled channels
+ * of this src register reference.
+ */
+ for (int i = 0; i < 4; i++) {
+ int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ ir_to_mesa_instruction *copy_chan = acp[acp_base + src_chan];
+
+ if (!copy_chan) {
+ good = false;
+ break;
+ }
+
+ if (!first) {
+ first = copy_chan;
+ } else {
+ if (first->src_reg[0].file != copy_chan->src_reg[0].file ||
+ first->src_reg[0].index != copy_chan->src_reg[0].index) {
+ good = false;
+ break;
+ }
+ }
+ }
+
+ if (good) {
+ /* We've now validated that we can copy-propagate to
+ * replace this src register reference. Do it.
+ */
+ inst->src_reg[r].file = first->src_reg[0].file;
+ inst->src_reg[r].index = first->src_reg[0].index;
+
+ int swizzle = 0;
+ for (int i = 0; i < 4; i++) {
+ int src_chan = GET_SWZ(inst->src_reg[r].swizzle, i);
+ ir_to_mesa_instruction *copy_inst = acp[acp_base + src_chan];
+ swizzle |= (GET_SWZ(copy_inst->src_reg[0].swizzle, src_chan) <<
+ (3 * i));
+ }
+ inst->src_reg[r].swizzle = swizzle;
+ }
+ }
+
+ switch (inst->op) {
+ case OPCODE_BGNLOOP:
+ case OPCODE_ENDLOOP:
+ case OPCODE_ELSE:
+ case OPCODE_ENDIF:
+ /* End of a basic block, clear the ACP entirely. */
+ memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
+ break;
+
+ default:
+ /* Continuing the block, clear any written channels from
+ * the ACP.
+ */
+ if (inst->dst_reg.file == PROGRAM_TEMPORARY) {
+ if (inst->dst_reg.reladdr) {
+ memset(acp, 0, sizeof(*acp) * this->next_temp * 4);
+ } else {
+ for (int i = 0; i < 4; i++) {
+ if (inst->dst_reg.writemask & (1 << i)) {
+ acp[4 * inst->dst_reg.index + i] = NULL;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ /* If this is a copy, add it to the ACP. */
+ if (inst->op == OPCODE_MOV &&
+ inst->dst_reg.file == PROGRAM_TEMPORARY &&
+ !inst->dst_reg.reladdr &&
+ !inst->saturate &&
+ !inst->src_reg[0].reladdr &&
+ !inst->src_reg[0].negate) {
+ for (int i = 0; i < 4; i++) {
+ if (inst->dst_reg.writemask & (1 << i)) {
+ acp[4 * inst->dst_reg.index + i] = inst;
+ }
+ }
+ }
+ }
+
+ talloc_free(acp);
+}
+
/**
* Convert a shader's GLSL IR into a Mesa gl_program.
@@ -2709,6 +2849,8 @@ get_mesa_program(struct gl_context *ctx,
mesa_instruction_annotation = talloc_array(v.mem_ctx, ir_instruction *,
num_instructions);
+ v.copy_propagate();
+
/* Convert ir_mesa_instructions into prog_instructions.
*/
mesa_inst = mesa_instructions;
@@ -2849,8 +2991,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
/* Lowering */
do_mat_op_to_vec(ir);
- lower_instructions(ir, MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
- | LOG_TO_LOG2);
+ lower_instructions(ir, (MOD_TO_FRACT | DIV_TO_MUL_RCP | EXP_TO_EXP2
+ | LOG_TO_LOG2
+ | ((options->EmitNoPow) ? POW_TO_EXP2 : 0)));
progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress;
@@ -2858,8 +3001,10 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
progress = lower_quadop_vector(ir, true) || progress;
- if (options->EmitNoIfs)
- progress = do_if_to_cond_assign(ir) || progress;
+ if (options->EmitNoIfs) {
+ progress = lower_discard(ir) || progress;
+ progress = lower_if_to_cond_assign(ir) || progress;
+ }
if (options->EmitNoNoise)
progress = lower_noise(ir) || progress;
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
index 7197615f94..7410e14973 100644
--- a/src/mesa/program/ir_to_mesa.h
+++ b/src/mesa/program/ir_to_mesa.h
@@ -25,8 +25,11 @@
extern "C" {
#endif
-#include "main/config.h"
-#include "main/mtypes.h"
+#include "main/glheader.h"
+
+struct gl_context;
+struct gl_shader;
+struct gl_shader_program;
void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh);
void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog);
diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h
index 3e85dd2c30..088e7527d5 100644
--- a/src/mesa/program/nvfragparse.h
+++ b/src/mesa/program/nvfragparse.h
@@ -30,7 +30,10 @@
#ifndef NVFRAGPARSE_H
#define NVFRAGPARSE_H
-#include "main/mtypes.h"
+#include "main/glheader.h"
+
+struct gl_context;
+struct gl_fragment_program;
extern void
_mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target,
diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h
index e98e867320..7318e14941 100644
--- a/src/mesa/program/nvvertparse.h
+++ b/src/mesa/program/nvvertparse.h
@@ -29,7 +29,10 @@
#ifndef NVVERTPARSE_H
#define NVVERTPARSE_H
-#include "main/mtypes.h"
+#include "main/glheader.h"
+
+struct gl_context;
+struct gl_vertex_program;
extern void
_mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target,
diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h
index 4907ae3030..0167334827 100644
--- a/src/mesa/program/prog_cache.h
+++ b/src/mesa/program/prog_cache.h
@@ -30,8 +30,9 @@
#define PROG_CACHE_H
-#include "main/mtypes.h"
+#include "main/glheader.h"
+struct gl_context;
/** Opaque type */
struct gl_program_cache;
diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c
index c20347fe67..e7553c69db 100644
--- a/src/mesa/program/prog_execute.c
+++ b/src/mesa/program/prog_execute.c
@@ -1674,6 +1674,18 @@ _mesa_execute_program(struct gl_context * ctx,
fetch_texel(ctx, machine, inst, texcoord, lodBias, color);
+ if (DEBUG_PROG) {
+ printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]"
+ " bias %g\n",
+ color[0], color[1], color[2], color[3],
+ inst->TexSrcUnit,
+ texcoord[0],
+ texcoord[1],
+ texcoord[2],
+ texcoord[3],
+ lodBias);
+ }
+
store_vector4(inst, machine, color);
}
break;
diff --git a/src/mesa/program/prog_instruction.h b/src/mesa/program/prog_instruction.h
index ca90de7ce1..a383828e34 100644
--- a/src/mesa/program/prog_instruction.h
+++ b/src/mesa/program/prog_instruction.h
@@ -247,7 +247,7 @@ typedef enum prog_opcode {
* Number of bits for the src/dst register Index field.
* This limits the size of temp/uniform register files.
*/
-#define INST_INDEX_BITS 10
+#define INST_INDEX_BITS 11
/**
diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h
index 00f1080449..463f5fc51c 100644
--- a/src/mesa/program/prog_optimize.h
+++ b/src/mesa/program/prog_optimize.h
@@ -27,9 +27,10 @@
#include "main/config.h"
-#include "main/mtypes.h"
+#include "main/glheader.h"
+struct gl_context;
struct gl_program;
struct prog_instruction;
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index baac29ff0d..c310acb01d 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -572,6 +572,24 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
value[3] = 0.0F;
return;
+ case STATE_FB_WPOS_Y_TRANSFORM:
+ /* A driver may negate this conditional by using ZW swizzle
+ * instead of XY (based on e.g. some other state). */
+ if (ctx->DrawBuffer->Name != 0) {
+ /* Identity (XY) followed by flipping Y upside down (ZW). */
+ value[0] = 1.0F;
+ value[1] = 0.0F;
+ value[2] = -1.0F;
+ value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ } else {
+ /* Flipping Y upside down (XY) followed by identity (ZW). */
+ value[0] = -1.0F;
+ value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
+ value[2] = 1.0F;
+ value[3] = 0.0F;
+ }
+ return;
+
case STATE_ROT_MATRIX_0:
{
const int unit = (int) state[2];
@@ -695,6 +713,7 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
return _NEW_PIXEL;
case STATE_FB_SIZE:
+ case STATE_FB_WPOS_Y_TRANSFORM:
return _NEW_BUFFERS;
default:
@@ -900,6 +919,9 @@ append_token(char *dst, gl_state_index k)
case STATE_FB_SIZE:
append(dst, "FbSize");
break;
+ case STATE_FB_WPOS_Y_TRANSFORM:
+ append(dst, "FbWposYTransform");
+ break;
case STATE_ROT_MATRIX_0:
append(dst, "rotMatrixRow0");
break;
@@ -1046,7 +1068,9 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
* Loop over all the parameters in a parameter list. If the parameter
* is a GL state reference, look up the current value of that state
* variable and put it into the parameter's Value[4] array.
- * This would be called at glBegin time when using a fragment program.
+ * Other parameter types never change or are explicitly set by the user
+ * with glUniform() or glProgramParameter(), etc.
+ * This would be called at glBegin time.
*/
void
_mesa_load_state_parameters(struct gl_context *ctx,
@@ -1057,12 +1081,10 @@ _mesa_load_state_parameters(struct gl_context *ctx,
if (!paramList)
return;
- /*assert(ctx->Driver.NeedFlush == 0);*/
-
for (i = 0; i < paramList->NumParameters; i++) {
if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
_mesa_fetch_state(ctx,
- (gl_state_index *) paramList->Parameters[i].StateIndexes,
+ paramList->Parameters[i].StateIndexes,
paramList->ParameterValues[i]);
}
}
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index 6e5be53630..f2407af9c8 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -25,8 +25,10 @@
#ifndef PROG_STATEVARS_H
#define PROG_STATEVARS_H
-#include "main/mtypes.h"
+#include "main/glheader.h"
+struct gl_context;
+struct gl_program_parameter_list;
/**
* Number of STATE_* values we need to address any GL state.
@@ -117,6 +119,7 @@ typedef enum gl_state_index_ {
STATE_PT_BIAS, /**< Pixel transfer RGBA bias */
STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
STATE_FB_SIZE, /**< (width-1, height-1, 0, 0) */
+ STATE_FB_WPOS_Y_TRANSFORM, /**< (1, 0, -1, height-1) if a FBO is bound, (-1, height-1, 1, 0) otherwise */
STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c
index 9ffa49bb01..52254e9365 100644
--- a/src/mesa/program/program.c
+++ b/src/mesa/program/program.c
@@ -32,6 +32,7 @@
#include "main/glheader.h"
#include "main/context.h"
#include "main/hash.h"
+#include "main/mfeatures.h"
#include "program.h"
#include "prog_cache.h"
#include "prog_parameter.h"
diff --git a/src/mesa/program/symbol_table.c b/src/mesa/program/symbol_table.c
index 09e7cb44ef..004f1f8fa7 100644
--- a/src/mesa/program/symbol_table.c
+++ b/src/mesa/program/symbol_table.c
@@ -336,12 +336,12 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
check_symbol_table(table);
if (hdr == NULL) {
- hdr = calloc(1, sizeof(*hdr));
- hdr->name = strdup(name);
+ hdr = calloc(1, sizeof(*hdr));
+ hdr->name = strdup(name);
- hash_table_insert(table->ht, hdr, hdr->name);
- hdr->next = table->hdr;
- table->hdr = hdr;
+ hash_table_insert(table->ht, hdr, hdr->name);
+ hdr->next = table->hdr;
+ table->hdr = hdr;
}
check_symbol_table(table);
@@ -376,6 +376,81 @@ _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *table,
}
+int
+_mesa_symbol_table_add_global_symbol(struct _mesa_symbol_table *table,
+ int name_space, const char *name,
+ void *declaration)
+{
+ struct symbol_header *hdr;
+ struct symbol *sym;
+ struct symbol *curr;
+ struct scope_level *top_scope;
+
+ check_symbol_table(table);
+
+ hdr = find_symbol(table, name);
+
+ check_symbol_table(table);
+
+ if (hdr == NULL) {
+ hdr = calloc(1, sizeof(*hdr));
+ hdr->name = strdup(name);
+
+ hash_table_insert(table->ht, hdr, hdr->name);
+ hdr->next = table->hdr;
+ table->hdr = hdr;
+ }
+
+ check_symbol_table(table);
+
+ /* If the symbol already exists in this namespace at this scope, it cannot
+ * be added to the table.
+ */
+ for (sym = hdr->symbols
+ ; (sym != NULL) && (sym->name_space != name_space)
+ ; sym = sym->next_with_same_name) {
+ /* empty */
+ }
+
+ if (sym && sym->depth == 0)
+ return -1;
+
+ /* Find the top-level scope */
+ for (top_scope = table->current_scope
+ ; top_scope->next != NULL
+ ; top_scope = top_scope->next) {
+ /* empty */
+ }
+
+ sym = calloc(1, sizeof(*sym));
+ sym->next_with_same_scope = top_scope->symbols;
+ sym->hdr = hdr;
+ sym->name_space = name_space;
+ sym->data = declaration;
+
+ assert(sym->hdr == hdr);
+
+ /* Since next_with_same_name is ordered by scope, we need to append the
+ * new symbol to the _end_ of the list.
+ */
+ if (hdr->symbols == NULL) {
+ hdr->symbols = sym;
+ } else {
+ for (curr = hdr->symbols
+ ; curr->next_with_same_name != NULL
+ ; curr = curr->next_with_same_name) {
+ /* empty */
+ }
+ curr->next_with_same_name = sym;
+ }
+ top_scope->symbols = sym;
+
+ check_symbol_table(table);
+ return 0;
+}
+
+
+
struct _mesa_symbol_table *
_mesa_symbol_table_ctor(void)
{
diff --git a/src/mesa/program/symbol_table.h b/src/mesa/program/symbol_table.h
index 1d570fc1a0..f9d91649bb 100644
--- a/src/mesa/program/symbol_table.h
+++ b/src/mesa/program/symbol_table.h
@@ -33,6 +33,10 @@ extern void _mesa_symbol_table_pop_scope(struct _mesa_symbol_table *table);
extern int _mesa_symbol_table_add_symbol(struct _mesa_symbol_table *symtab,
int name_space, const char *name, void *declaration);
+extern int _mesa_symbol_table_add_global_symbol(
+ struct _mesa_symbol_table *symtab, int name_space, const char *name,
+ void *declaration);
+
extern int _mesa_symbol_table_symbol_scope(struct _mesa_symbol_table *table,
int name_space, const char *name);