summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c62
-rw-r--r--src/mesa/shader/slang/slang_emit.c67
-rw-r--r--src/mesa/shader/slang/slang_ir.c18
3 files changed, 79 insertions, 68 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 6261aab23c4..d4d2e34dee4 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1410,6 +1410,27 @@ slang_find_asm_info(const char *name)
/**
+ * Return the default swizzle mask for accessing a variable of the
+ * given size (in floats). If size = 1, comp is used to identify
+ * which component [0..3] of the register holds the variable.
+ */
+static GLuint
+_slang_var_swizzle(GLint size, GLint comp)
+{
+ switch (size) {
+ case 1:
+ return MAKE_SWIZZLE4(comp, comp, comp, comp);
+ case 2:
+ return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL);
+ case 3:
+ return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL);
+ default:
+ return SWIZZLE_XYZW;
+ }
+}
+
+
+/**
* Some write-masked assignments are simple, but others are hard.
* Simple example:
* vec3 v;
@@ -3063,6 +3084,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
int dbg = 0;
const GLenum datatype = _slang_gltype_from_specifier(&var->type.specifier);
const GLint texIndex = sampler_to_texture_index(var->type.specifier.type);
+ const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
if (texIndex != -1) {
/* This is a texture sampler variable...
@@ -3076,8 +3098,8 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
}
else if (var->type.qualifier == SLANG_QUAL_UNIFORM) {
/* Uniform variable */
- const GLint size = _slang_sizeof_type_specifier(&var->type.specifier)
- * MAX2(var->array_len, 1);
+ const GLint totalSize = size * MAX2(var->array_len, 1);
+ const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
if (prog) {
/* user-defined uniform */
if (datatype == GL_NONE) {
@@ -3106,8 +3128,10 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
}
else {
GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
- size, datatype);
- store = _slang_new_ir_storage(PROGRAM_UNIFORM, uniformLoc, size);
+ totalSize, datatype);
+ store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
+ totalSize, swizzle);
+ printf("GLOBAL USER UNIFORM %s size %d\n", varName, totalSize);
}
}
else {
@@ -3115,33 +3139,40 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
/* We know it's a uniform, but don't allocate storage unless
* it's really used.
*/
- store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size);
+ store = _slang_new_ir_storage_swz(PROGRAM_STATE_VAR, -1,
+ totalSize, swizzle);
}
- if (dbg) printf("UNIFORM (sz %d) ", size);
+ if (dbg) printf("UNIFORM (sz %d) ", totalSize);
}
else if (var->type.qualifier == SLANG_QUAL_VARYING) {
- const GLint size = 4; /* XXX fix */
if (prog) {
/* user-defined varying */
GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, size);
- store = _slang_new_ir_storage(PROGRAM_VARYING, varyingLoc, size);
+ GLuint swizzle = _slang_var_swizzle(size, 0);
+ store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
+ size, swizzle);
}
else {
/* pre-defined varying, like gl_Color or gl_TexCoord */
if (type == SLANG_UNIT_FRAGMENT_BUILTIN) {
+ /* fragment program input */
GLuint swizzle;
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
assert(index >= 0);
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
assert(index < FRAG_ATTRIB_MAX);
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index,
+ size, swizzle);
}
else {
+ /* vertex program output */
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
+ GLuint swizzle = _slang_var_swizzle(size, 0);
assert(index >= 0);
- assert(type == SLANG_UNIT_VERTEX_BUILTIN);
- store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
assert(index < VERT_RESULT_MAX);
+ assert(type == SLANG_UNIT_VERTEX_BUILTIN);
+ store = _slang_new_ir_storage_swz(PROGRAM_OUTPUT, index,
+ size, swizzle);
}
if (dbg) printf("V/F ");
}
@@ -3150,7 +3181,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
if (prog) {
/* user-defined vertex attribute */
- const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
const GLint attr = -1; /* unknown */
GLint index = _mesa_add_attribute(prog->Attributes, varName,
size, attr);
@@ -3163,7 +3193,6 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLuint swizzle;
GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB,
&swizzle);
- GLint size = 4; /* XXX? */
assert(index >= 0);
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
}
@@ -3173,27 +3202,24 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
GLuint swizzle = SWIZZLE_XYZW; /* silence compiler warning */
GLint index = _slang_input_index(varName, GL_FRAGMENT_PROGRAM_ARB,
&swizzle);
- GLint size = 4; /* XXX? */
store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
if (dbg) printf("INPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDOUTPUT) {
if (type == SLANG_UNIT_VERTEX_BUILTIN) {
GLint index = _slang_output_index(varName, GL_VERTEX_PROGRAM_ARB);
- GLint size = 4; /* XXX? */
store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
}
else {
GLint index = _slang_output_index(varName, GL_FRAGMENT_PROGRAM_ARB);
- GLint size = 4; /* XXX? */
+ GLint specialSize = 4; /* treat all fragment outputs as float[4] */
assert(type == SLANG_UNIT_FRAGMENT_BUILTIN);
- store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, size);
+ store = _slang_new_ir_storage(PROGRAM_OUTPUT, index, specialSize);
}
if (dbg) printf("OUTPUT ");
}
else if (var->type.qualifier == SLANG_QUAL_CONST && !prog) {
/* pre-defined global constant, like gl_MaxLights */
- const GLint size = _slang_sizeof_type_specifier(&var->type.specifier);
store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, size);
if (dbg) printf("CONST ");
}
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index ec8ed0b4e88..291fd7c6ddf 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -171,21 +171,33 @@ free_temp_storage(slang_var_table *vt, slang_ir_node *n)
/**
- * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
- * Ex: fix_swizzle("zyNN") -> "zyyy"
- * XXX should put in the default component for the position...
+ * Remove any SWIZZLE_NIL terms from given swizzle mask.
+ * For a swizzle like .z??? generate .zzzz (replicate single component).
+ * Else, for .wx?? generate .wxzw (insert default component for the position).
*/
static GLuint
fix_swizzle(GLuint swizzle)
{
- GLuint swz[4], i;
- for (i = 0; i < 4; i++) {
- swz[i] = GET_SWZ(swizzle, i);
- if (swz[i] == SWIZZLE_NIL) {
- swz[i] = swz[i - 1];
- }
+ GLuint c0 = GET_SWZ(swizzle, 0),
+ c1 = GET_SWZ(swizzle, 1),
+ c2 = GET_SWZ(swizzle, 2),
+ c3 = GET_SWZ(swizzle, 3);
+ if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {
+ /* smear first component across all positions */
+ c1 = c2 = c3 = c0;
}
- return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
+ else {
+ /* insert default swizzle components */
+ if (c0 == SWIZZLE_NIL)
+ c0 = SWIZZLE_X;
+ if (c1 == SWIZZLE_NIL)
+ c1 = SWIZZLE_Y;
+ if (c2 == SWIZZLE_NIL)
+ c2 = SWIZZLE_Z;
+ if (c3 == SWIZZLE_NIL)
+ c3 = SWIZZLE_W;
+ }
+ return MAKE_SWIZZLE4(c0, c1, c2, c3);
}
@@ -216,6 +228,7 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
assert(size >= 1);
assert(size <= 4);
+
if (size == 1) {
GLuint comp = GET_SWZ(swizzle, 0);
assert(comp < 4);
@@ -233,13 +246,6 @@ storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
static void
storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
{
- static const GLuint defaultSwizzle[4] = {
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
- MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
- };
- const GLint size = st->Size;
const GLboolean relAddr = st->RelAddr;
GLint index = st->Index;
GLuint swizzle = st->Swizzle;
@@ -250,7 +256,6 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
index += st->Index;
swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);
}
- swizzle = fix_swizzle(swizzle);
assert(st->File >= 0);
assert(st->File < PROGRAM_UNDEFINED);
@@ -259,20 +264,14 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
assert(index >= 0);
src->Index = index;
- assert(size >= 1);
- assert(size <= 4);
+ swizzle = fix_swizzle(swizzle);
+ assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);
+ assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);
+ src->Swizzle = swizzle;
src->RelAddr = relAddr;
-
- if (swizzle != SWIZZLE_NOOP)
- src->Swizzle = swizzle;
- else
- src->Swizzle = defaultSwizzle[size - 1]; /*XXX really need this?*/
-
- assert(GET_SWZ(src->Swizzle, 0) <= 3);
- assert(GET_SWZ(src->Swizzle, 1) <= 3);
- assert(GET_SWZ(src->Swizzle, 2) <= 3);
- assert(GET_SWZ(src->Swizzle, 3) <= 3);
}
@@ -582,8 +581,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
/* result storage */
if (!n->Store) {
- GLint size = n->Children[0]->Store
- ? n->Children[0]->Store->Size : info->ResultSize;
+ GLint size = info->ResultSize;
if (!alloc_temp_storage(emitInfo, n, size))
return NULL;
#if 0000 /* this should work, but doesn't yet */
@@ -591,6 +589,8 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
n->Writemask = WRITEMASK_XY;
else if (size == 3)
n->Writemask = WRITEMASK_XYZ;
+ else if (size == 1)
+ n->Writemask = WRITEMASK_X << GET_SWZ(n->Store->Swizzle,0);
#endif
}
@@ -1045,10 +1045,9 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
assert(n->Children[0]->Store->Index >= 0);
/* use tighter writemask when possible */
-#if 0000 /* XXX enable this after more testing... */
if (n->Writemask == WRITEMASK_XYZW)
n->Writemask = inst->DstReg.WriteMask;
-#endif
+
storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
return inst;
}
diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c
index ce4a198025e..a414036a362 100644
--- a/src/mesa/shader/slang/slang_ir.c
+++ b/src/mesa/shader/slang/slang_ir.c
@@ -240,20 +240,6 @@ _slang_free_ir_tree(slang_ir_node *n)
static const char *
-swizzle_string(GLuint swizzle)
-{
- static char s[6];
- GLuint i;
- s[0] = '.';
- for (i = 1; i < 5; i++) {
- s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
- }
- s[i] = 0;
- return s;
-}
-
-
-static const char *
writemask_string(GLuint writemask)
{
static char s[6];
@@ -410,7 +396,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
case IR_VAR:
printf("VAR %s%s at %s store %p\n",
(n->Var ? (char *) n->Var->a_name : "TEMP"),
- swizzle_string(n->Store->Swizzle),
+ _mesa_swizzle_string(n->Store->Swizzle, 0, 0),
storage_string(n->Store), (void*) n->Store);
break;
case IR_VAR_DECL:
@@ -437,7 +423,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
break;
case IR_SWIZZLE:
printf("SWIZZLE %s of (store %p) \n",
- swizzle_string(n->Store->Swizzle), (void*) n->Store);
+ _mesa_swizzle_string(n->Store->Swizzle, 0, 0), (void*) n->Store);
_slang_print_ir_tree(n->Children[0], indent + 3);
break;
default: