NV fp parser: Add support for condition codes

Conditional write masks and the condition-code based KIL instruction
are all supported.  The specific behavior of KIL in the following
shader may or may not match the behavior of other implementations:

!!ARBfp1.0
	TEMP	GT;
	MOVC	GT, fragment.texcoord[0];
	KIL	GT.x;
	END

Should be it interpreted as 'KIL srcReg' or as 'KIL ccTest'?  The
current parser will interpret it as 'KIL srcReg'.
This commit is contained in:
Ian Romanick
2009-09-10 15:04:24 -07:00
parent cdb7193994
commit 81722c5d7e
4 changed files with 1427 additions and 1125 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -202,6 +202,8 @@ static struct asm_instruction *asm_instruction_copy_ctor(
%type <sym> addrReg
%type <swiz_mask> addrComponent addrWriteMask
%type <dst_reg> ccMaskRule ccTest ccMaskRule2 ccTest2 optionalCcMask
%type <result> resultBinding resultColBinding
%type <integer> optFaceType optColorType
%type <integer> optResultFaceType optResultColorType
@@ -447,6 +449,14 @@ KIL_instruction: KIL swizzleSrcReg
$$ = asm_instruction_ctor(OPCODE_KIL, NULL, & $2, NULL, NULL);
state->fragment.UsesKill = 1;
}
| KIL ccTest
{
$$ = asm_instruction_ctor(OPCODE_KIL_NV, NULL, NULL, NULL, NULL);
$$->Base.DstReg.CondMask = $2.CondMask;
$$->Base.DstReg.CondSwizzle = $2.CondSwizzle;
$$->Base.DstReg.CondSrc = $2.CondSrc;
state->fragment.UsesKill = 1;
}
;
TXD_instruction: TXD_OP maskedDstReg ',' swizzleSrcReg ',' swizzleSrcReg ',' swizzleSrcReg ',' texImageUnit ',' texTarget
@@ -607,10 +617,13 @@ swizzleSrcReg: optionalSign srcReg swizzleSuffix
;
maskedDstReg: dstReg optionalMask
maskedDstReg: dstReg optionalMask optionalCcMask
{
$$ = $1;
$$.WriteMask = $2.mask;
$$.CondMask = $3.CondMask;
$$.CondSwizzle = $3.CondSwizzle;
$$.CondSrc = $3.CondSrc;
if ($$.File == PROGRAM_OUTPUT) {
/* Technically speaking, this should check that it is in
@@ -984,6 +997,82 @@ optionalMask: MASK4 | MASK3 | MASK2 | MASK1
| { $$.swizzle = SWIZZLE_NOOP; $$.mask = WRITEMASK_XYZW; }
;
optionalCcMask: '(' ccTest ')'
{
$$ = $2;
}
| '(' ccTest2 ')'
{
$$ = $2;
}
|
{
$$.CondMask = COND_TR;
$$.CondSwizzle = SWIZZLE_NOOP;
$$.CondSrc = 0;
}
;
ccTest: ccMaskRule swizzleSuffix
{
$$ = $1;
$$.CondSwizzle = $2.swizzle;
}
;
ccTest2: ccMaskRule2 swizzleSuffix
{
$$ = $1;
$$.CondSwizzle = $2.swizzle;
}
;
ccMaskRule: IDENTIFIER
{
const int cond = _mesa_parse_cc($1);
if ((cond == 0) || ($1[2] != '\0')) {
char *const err_str =
make_error_string("invalid condition code \"%s\"", $1);
yyerror(& @1, state, (err_str != NULL)
? err_str : "invalid condition code");
if (err_str != NULL) {
_mesa_free(err_str);
}
YYERROR;
}
$$.CondMask = cond;
$$.CondSwizzle = SWIZZLE_NOOP;
$$.CondSrc = 0;
}
;
ccMaskRule2: USED_IDENTIFIER
{
const int cond = _mesa_parse_cc($1);
if ((cond == 0) || ($1[2] != '\0')) {
char *const err_str =
make_error_string("invalid condition code \"%s\"", $1);
yyerror(& @1, state, (err_str != NULL)
? err_str : "invalid condition code");
if (err_str != NULL) {
_mesa_free(err_str);
}
YYERROR;
}
$$.CondMask = cond;
$$.CondSwizzle = SWIZZLE_NOOP;
$$.CondSrc = 0;
}
;
namingStatement: ATTRIB_statement
| PARAM_statement
| TEMP_statement
@@ -2089,8 +2178,15 @@ asm_instruction_set_operands(struct asm_instruction *inst,
inst->Base.DstReg = *dst;
}
/* The only instruction that doesn't have any source registers is the
* condition-code based KIL instruction added by NV_fragment_program_option.
*/
if (src0 != NULL) {
inst->Base.SrcReg[0] = src0->Base;
inst->SrcReg[0] = *src0;
} else {
init_src_reg(& inst->SrcReg[0]);
}
if (src1 != NULL) {
inst->Base.SrcReg[1] = src1->Base;

View File

@@ -94,6 +94,60 @@ _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
}
int
_mesa_parse_cc(const char *s)
{
int cond = 0;
switch (s[0]) {
case 'E':
if (s[1] == 'Q') {
cond = COND_EQ;
}
break;
case 'F':
if (s[1] == 'L') {
cond = COND_FL;
}
break;
case 'G':
if (s[1] == 'E') {
cond = COND_GE;
} else if (s[1] == 'T') {
cond = COND_GT;
}
break;
case 'L':
if (s[1] == 'E') {
cond = COND_LE;
} else if (s[1] == 'T') {
cond = COND_LT;
}
break;
case 'N':
if (s[1] == 'E') {
cond = COND_NE;
}
break;
case 'T':
if (s[1] == 'R') {
cond = COND_TR;
}
break;
default:
break;
}
return ((cond == 0) || (s[2] != '\0')) ? 0 : cond;
}
int
_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
{

View File

@@ -278,4 +278,17 @@ extern int _mesa_ARBfp_parse_option(struct asm_parser_state *state,
extern int _mesa_parse_instruction_suffix(const struct asm_parser_state *state,
const char *suffix, struct prog_instruction *inst);
/**
* Parses a condition code name
*
* The condition code names (e.g., \c LT, \c GT, \c NE) were added to assembly
* shaders with the \c GL_NV_fragment_program_option extension. This function
* converts a string representation into one of the \c COND_ macros.
*
* \return
* One of the \c COND_ macros defined in prog_instruction.h on success or zero
* on failure.
*/
extern int _mesa_parse_cc(const char *s);
/*@}*/