mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 22:38:05 +02:00
mesa: fix a GLSL vector subscript/writemask bug
This fixes a failure for cases like: vec4 v; v[1] *= 2.0; The v[1] actually acts like a writemask, equivalent to v.y The fix is a bit convoluted, but will do for now. cherry-picked from master
This commit is contained in:
parent
eeefe175de
commit
66b48202c2
1 changed files with 90 additions and 47 deletions
|
|
@ -1355,45 +1355,6 @@ slang_find_asm_info(const char *name)
|
|||
}
|
||||
|
||||
|
||||
static GLuint
|
||||
make_writemask(const char *field)
|
||||
{
|
||||
GLuint mask = 0x0;
|
||||
while (*field) {
|
||||
switch (*field) {
|
||||
case 'x':
|
||||
case 's':
|
||||
case 'r':
|
||||
mask |= WRITEMASK_X;
|
||||
break;
|
||||
case 'y':
|
||||
case 't':
|
||||
case 'g':
|
||||
mask |= WRITEMASK_Y;
|
||||
break;
|
||||
case 'z':
|
||||
case 'p':
|
||||
case 'b':
|
||||
mask |= WRITEMASK_Z;
|
||||
break;
|
||||
case 'w':
|
||||
case 'q':
|
||||
case 'a':
|
||||
mask |= WRITEMASK_W;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "invalid writemask in make_writemask()");
|
||||
return 0;
|
||||
}
|
||||
field++;
|
||||
}
|
||||
if (mask == 0x0)
|
||||
return WRITEMASK_XYZW;
|
||||
else
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Some write-masked assignments are simple, but others are hard.
|
||||
* Simple example:
|
||||
|
|
@ -1493,6 +1454,88 @@ swizzle_to_writemask(GLuint swizzle,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively traverse 'oper' to produce a swizzle mask in the event
|
||||
* of any vector subscripts and swizzle suffixes.
|
||||
* Ex: for "vec4 v", "v[2].x" resolves to v.z
|
||||
*/
|
||||
static GLuint
|
||||
resolve_swizzle(const slang_operation *oper)
|
||||
{
|
||||
if (oper->type == SLANG_OPER_FIELD) {
|
||||
/* writemask from .xyzw suffix */
|
||||
slang_swizzle swz;
|
||||
if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) {
|
||||
GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
|
||||
swz.swizzle[1],
|
||||
swz.swizzle[2],
|
||||
swz.swizzle[3]);
|
||||
GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
|
||||
GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle);
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return SWIZZLE_XYZW;
|
||||
}
|
||||
else if (oper->type == SLANG_OPER_SUBSCRIPT &&
|
||||
oper->children[1].type == SLANG_OPER_LITERAL_INT) {
|
||||
/* writemask from [index] */
|
||||
GLuint child_swizzle = resolve_swizzle(&oper->children[0]);
|
||||
GLuint i = (GLuint) oper->children[1].literal[0];
|
||||
GLuint swizzle;
|
||||
GLuint s;
|
||||
switch (i) {
|
||||
case 0:
|
||||
swizzle = SWIZZLE_XXXX;
|
||||
break;
|
||||
case 1:
|
||||
swizzle = SWIZZLE_YYYY;
|
||||
break;
|
||||
case 2:
|
||||
swizzle = SWIZZLE_ZZZZ;
|
||||
break;
|
||||
case 3:
|
||||
swizzle = SWIZZLE_WWWW;
|
||||
break;
|
||||
default:
|
||||
swizzle = SWIZZLE_XYZW;
|
||||
}
|
||||
s = _slang_swizzle_swizzle(child_swizzle, swizzle);
|
||||
return s;
|
||||
}
|
||||
else {
|
||||
return SWIZZLE_XYZW;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but produce a writemask.
|
||||
*/
|
||||
static GLuint
|
||||
resolve_writemask(const slang_operation *oper)
|
||||
{
|
||||
GLuint swizzle = resolve_swizzle(oper);
|
||||
GLuint writemask, swizzleOut;
|
||||
swizzle_to_writemask(swizzle, &writemask, &swizzleOut);
|
||||
return writemask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively descend through swizzle nodes to find the node's storage info.
|
||||
*/
|
||||
static slang_ir_storage *
|
||||
get_store(const slang_ir_node *n)
|
||||
{
|
||||
if (n->Opcode == IR_SWIZZLE) {
|
||||
return get_store(n->Children[0]);
|
||||
}
|
||||
return n->Store;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate IR tree for an asm instruction/operation such as:
|
||||
* __asm vec4_dot __retVal.x, v1, v2;
|
||||
|
|
@ -1547,19 +1590,19 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
|
|||
slang_ir_node *n0;
|
||||
|
||||
dest_oper = &oper->children[0];
|
||||
while (dest_oper->type == SLANG_OPER_FIELD) {
|
||||
/* writemask */
|
||||
writemask &= make_writemask((char*) dest_oper->a_id);
|
||||
dest_oper = &dest_oper->children[0];
|
||||
}
|
||||
|
||||
writemask = resolve_writemask(dest_oper);
|
||||
|
||||
n0 = _slang_gen_operation(A, dest_oper);
|
||||
assert(n0->Var);
|
||||
assert(n0->Store);
|
||||
if (!n0)
|
||||
return NULL;
|
||||
|
||||
assert(!n->Store);
|
||||
n->Store = n0->Store;
|
||||
n->Store = get_store(n0);
|
||||
n->Writemask = writemask;
|
||||
|
||||
assert(n->Store->File != PROGRAM_UNDEFINED);
|
||||
|
||||
_slang_free(n0);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue