diff options
author | Rob Clark <[email protected]> | 2013-10-24 17:45:27 -0400 |
---|---|---|
committer | Rob Clark <[email protected]> | 2013-10-24 20:21:08 -0400 |
commit | 4317c4e6e05f84a985ff76a7f66e506681d8e37f (patch) | |
tree | 3cbfbd6cdc8409130ea9e79ec4faf8506b03efb9 /src/gallium/drivers/freedreno | |
parent | bfd30935c996f453fff7345c79dcef4e83d89cfb (diff) |
freedreno/a3xx: fix const/rel/const-rel encoding
The encoding of constant, relative, and relative-const src registers is
a bit more complex than originally thought, which gives an extra bit to
encode const reg # at expense of taking a bit from relative offset.
In most cases a3xx seems to actually use a scheme whereby it can encode
an extra bit for const register. You have three possible encodings in
thirteen bits:
register: (11 bits for N.c)
00........... rN.c
relative: (10 bits for N)
010.......... r<a0.x + N>
011.......... c<a0.x + N>
const: (12 bits for N.c)
1............ cN.c
Which means we can deal w/ more consts than previously thought.
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno')
-rw-r--r-- | src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c | 93 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a3xx/instr-a3xx.h | 151 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/a3xx/ir-a3xx.c | 136 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/freedreno_screen.c | 8 |
4 files changed, 300 insertions, 88 deletions
diff --git a/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c b/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c index 4db095f5679..d9bc4992376 100644 --- a/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c +++ b/src/gallium/drivers/freedreno/a3xx/disasm-a3xx.c @@ -111,7 +111,7 @@ static void print_reg(reg_t reg, bool full, bool r, bool c, bool im, * write-after-read (output.. but not 100%).. */ -#define MAX_REG 128 +#define MAX_REG 4096 typedef struct { uint8_t full[MAX_REG/8]; @@ -317,8 +317,7 @@ static void print_instr_cat1(instr_t *instr) { instr_cat1_t *cat1 = &instr->cat1; - // XXX maybe a bug in libllvm disassembler? - if (cat1->src_rel) + if (cat1->ul) printf("(ul)"); if (cat1->src_type == cat1->dst_type) { @@ -355,10 +354,11 @@ static void print_instr_cat1(instr_t *instr) /* I would just use %+d but trying to make it diff'able with * libllvm-a3xx... */ + char type = cat1->src_rel_c ? 'c' : 'r'; if (cat1->off < 0) - printf("c<a0.x - %d>", -cat1->off); + printf("%c<a0.x - %d>", type, -cat1->off); else if (cat1->off > 0) - printf("c<a0.x + %d>", cat1->off); + printf("%c<a0.x + %d>", type, cat1->off); else printf("c<a0.x>"); } else { @@ -399,9 +399,21 @@ static void print_instr_cat2(instr_t *instr) printf("(ei)"); print_reg_dst((reg_t)(cat2->dst), cat2->full ^ cat2->dst_half, false); printf(", "); - print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r, - cat2->src1_c, cat2->src1_im, cat2->src1_neg, - cat2->src1_abs, cat2->src1_rel); + + if (cat2->c1.src1_c) { + print_reg_src((reg_t)(cat2->c1.src1), cat2->full, cat2->src1_r, + cat2->c1.src1_c, cat2->src1_im, cat2->src1_neg, + cat2->src1_abs, false); + } else if (cat2->rel1.src1_rel) { + print_reg_src((reg_t)(cat2->rel1.src1), cat2->full, cat2->src1_r, + cat2->rel1.src1_c, cat2->src1_im, cat2->src1_neg, + cat2->src1_abs, cat2->rel1.src1_rel); + } else { + print_reg_src((reg_t)(cat2->src1), cat2->full, cat2->src1_r, + false, cat2->src1_im, cat2->src1_neg, + cat2->src1_abs, false); + } + switch (cat2->opc) { case OPC_ABSNEG_F: case OPC_ABSNEG_S: @@ -421,9 +433,19 @@ static void print_instr_cat2(instr_t *instr) break; default: printf(", "); - print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r, - cat2->src2_c, cat2->src2_im, cat2->src2_neg, - cat2->src2_abs, cat2->src2_rel); + if (cat2->c2.src2_c) { + print_reg_src((reg_t)(cat2->c2.src2), cat2->full, cat2->src2_r, + cat2->c2.src2_c, cat2->src2_im, cat2->src2_neg, + cat2->src2_abs, false); + } else if (cat2->rel2.src2_rel) { + print_reg_src((reg_t)(cat2->rel2.src2), cat2->full, cat2->src2_r, + cat2->rel2.src2_c, cat2->src2_im, cat2->src2_neg, + cat2->src2_abs, cat2->rel2.src2_rel); + } else { + print_reg_src((reg_t)(cat2->src2), cat2->full, cat2->src2_r, + false, cat2->src2_im, cat2->src2_neg, + cat2->src2_abs, false); + } break; } } @@ -450,17 +472,37 @@ static void print_instr_cat3(instr_t *instr) printf(" "); print_reg_dst((reg_t)(cat3->dst), full ^ cat3->dst_half, false); printf(", "); - print_reg_src((reg_t)(cat3->src1), full, - cat3->src1_r, cat3->src1_c, false, cat3->src1_neg, - false, cat3->src1_rel); + if (cat3->c1.src1_c) { + print_reg_src((reg_t)(cat3->c1.src1), full, + cat3->src1_r, cat3->c1.src1_c, false, cat3->src1_neg, + false, false); + } else if (cat3->rel1.src1_rel) { + print_reg_src((reg_t)(cat3->rel1.src1), full, + cat3->src1_r, cat3->rel1.src1_c, false, cat3->src1_neg, + false, cat3->rel1.src1_rel); + } else { + print_reg_src((reg_t)(cat3->src1), full, + cat3->src1_r, false, false, cat3->src1_neg, + false, false); + } printf(", "); print_reg_src((reg_t)cat3->src2, full, cat3->src2_r, cat3->src2_c, false, cat3->src2_neg, false, false); printf(", "); - print_reg_src((reg_t)(cat3->src3), full, - cat3->src3_r, cat3->src3_c, false, cat3->src3_neg, - false, cat3->src3_rel); + if (cat3->c2.src3_c) { + print_reg_src((reg_t)(cat3->c2.src3), full, + cat3->src3_r, cat3->c2.src3_c, false, cat3->src3_neg, + false, false); + } else if (cat3->rel2.src3_rel) { + print_reg_src((reg_t)(cat3->rel2.src3), full, + cat3->src3_r, cat3->rel2.src3_c, false, cat3->src3_neg, + false, cat3->rel2.src3_rel); + } else { + print_reg_src((reg_t)(cat3->src3), full, + cat3->src3_r, false, false, cat3->src3_neg, + false, false); + } } static void print_instr_cat4(instr_t *instr) @@ -470,9 +512,20 @@ static void print_instr_cat4(instr_t *instr) printf(" "); print_reg_dst((reg_t)(cat4->dst), cat4->full ^ cat4->dst_half, false); printf(", "); - print_reg_src((reg_t)(cat4->src), cat4->full, - cat4->src_r, cat4->src_c, cat4->src_im, - cat4->src_neg, cat4->src_abs, cat4->src_rel); + + if (cat4->c.src_c) { + print_reg_src((reg_t)(cat4->c.src), cat4->full, + cat4->src_r, cat4->c.src_c, cat4->src_im, + cat4->src_neg, cat4->src_abs, false); + } else if (cat4->rel.src_rel) { + print_reg_src((reg_t)(cat4->rel.src), cat4->full, + cat4->src_r, cat4->rel.src_c, cat4->src_im, + cat4->src_neg, cat4->src_abs, cat4->rel.src_rel); + } else { + print_reg_src((reg_t)(cat4->src), cat4->full, + cat4->src_r, false, cat4->src_im, + cat4->src_neg, cat4->src_abs, false); + } if ((debug & PRINT_VERBOSE) && (cat4->dummy1|cat4->dummy2)) printf("\t{4: %x,%x}", cat4->dummy1, cat4->dummy2); diff --git a/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h b/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h index 464a7e9d757..1085ddf8c12 100644 --- a/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h +++ b/src/gallium/drivers/freedreno/a3xx/instr-a3xx.h @@ -232,13 +232,16 @@ typedef union PACKED { /* normal gpr or const src register: */ struct PACKED { uint32_t comp : 2; - uint32_t num : 9; + uint32_t num : 10; }; /* for immediate val: */ int32_t iim_val : 11; /* to make compiler happy: */ uint32_t dummy32; + uint32_t dummy10 : 10; uint32_t dummy11 : 11; + uint32_t dummy12 : 12; + uint32_t dummy13 : 13; uint32_t dummy8 : 8; } reg_t; @@ -276,12 +279,16 @@ typedef struct PACKED { /* for normal src register: */ struct PACKED { uint32_t src : 11; + /* at least low bit of pad must be zero or it will + * look like a address relative src + */ uint32_t pad : 21; }; /* for address relative: */ struct PACKED { int32_t off : 10; - uint32_t must_be_3 : 2; + uint32_t src_rel_c : 1; + uint32_t src_rel : 1; uint32_t unknown : 20; }; /* for immediate: */ @@ -294,7 +301,7 @@ typedef struct PACKED { uint32_t repeat : 3; uint32_t src_r : 1; uint32_t ss : 1; - uint32_t src_rel : 1; + uint32_t ul : 1; uint32_t dst_type : 3; uint32_t dst_rel : 1; uint32_t src_type : 3; @@ -310,19 +317,49 @@ typedef struct PACKED { typedef struct PACKED { /* dword0: */ - uint32_t src1 : 11; - uint32_t src1_rel : 1; /* relative address */ - uint32_t src1_c : 1; /* const */ - uint32_t src1_im : 1; /* immediate */ - uint32_t src1_neg : 1; /* negate */ - uint32_t src1_abs : 1; /* absolute value */ - - uint32_t src2 : 11; - uint32_t src2_rel : 1; /* relative address */ - uint32_t src2_c : 1; /* const */ - uint32_t src2_im : 1; /* immediate */ - uint32_t src2_neg : 1; /* negate */ - uint32_t src2_abs : 1; /* absolute value */ + union PACKED { + struct PACKED { + uint32_t src1 : 11; + uint32_t must_be_zero1: 2; + uint32_t src1_im : 1; /* immediate */ + uint32_t src1_neg : 1; /* negate */ + uint32_t src1_abs : 1; /* absolute value */ + }; + struct PACKED { + uint32_t src1 : 10; + uint32_t src1_c : 1; /* relative-const */ + uint32_t src1_rel : 1; /* relative address */ + uint32_t must_be_zero : 1; + uint32_t dummy : 3; + } rel1; + struct PACKED { + uint32_t src1 : 12; + uint32_t src1_c : 1; /* const */ + uint32_t dummy : 3; + } c1; + }; + + union PACKED { + struct PACKED { + uint32_t src2 : 11; + uint32_t must_be_zero2: 2; + uint32_t src2_im : 1; /* immediate */ + uint32_t src2_neg : 1; /* negate */ + uint32_t src2_abs : 1; /* absolute value */ + }; + struct PACKED { + uint32_t src2 : 10; + uint32_t src2_c : 1; /* relative-const */ + uint32_t src2_rel : 1; /* relative address */ + uint32_t must_be_zero : 1; + uint32_t dummy : 3; + } rel2; + struct PACKED { + uint32_t src2 : 12; + uint32_t src2_c : 1; /* const */ + uint32_t dummy : 3; + } c2; + }; /* dword1: */ uint32_t dst : 8; @@ -343,18 +380,49 @@ typedef struct PACKED { typedef struct PACKED { /* dword0: */ - uint32_t src1 : 11; - uint32_t src1_rel : 1; - uint32_t src1_c : 1; - uint32_t src2_c : 1; - uint32_t src1_neg : 1; - uint32_t src2_r : 1; - uint32_t src3 : 11; - uint32_t src3_rel : 1; - uint32_t src3_c : 1; - uint32_t src3_r : 1; - uint32_t src2_neg : 1; - uint32_t src3_neg : 1; + union PACKED { + struct PACKED { + uint32_t src1 : 11; + uint32_t must_be_zero1: 2; + uint32_t src2_c : 1; + uint32_t src1_neg : 1; + uint32_t src2_r : 1; + }; + struct PACKED { + uint32_t src1 : 10; + uint32_t src1_c : 1; + uint32_t src1_rel : 1; + uint32_t must_be_zero : 1; + uint32_t dummy : 3; + } rel1; + struct PACKED { + uint32_t src1 : 12; + uint32_t src1_c : 1; + uint32_t dummy : 3; + } c1; + }; + + union PACKED { + struct PACKED { + uint32_t src3 : 11; + uint32_t must_be_zero2: 2; + uint32_t src3_r : 1; + uint32_t src2_neg : 1; + uint32_t src3_neg : 1; + }; + struct PACKED { + uint32_t src3 : 10; + uint32_t src3_c : 1; + uint32_t src3_rel : 1; + uint32_t must_be_zero : 1; + uint32_t dummy : 3; + } rel2; + struct PACKED { + uint32_t src3 : 12; + uint32_t src3_c : 1; + uint32_t dummy : 3; + } c2; + }; /* dword1: */ uint32_t dst : 8; @@ -372,12 +440,27 @@ typedef struct PACKED { typedef struct PACKED { /* dword0: */ - uint32_t src : 11; - uint32_t src_rel : 1; - uint32_t src_c : 1; - uint32_t src_im : 1; - uint32_t src_neg : 1; - uint32_t src_abs : 1; + union PACKED { + struct PACKED { + uint32_t src : 11; + uint32_t must_be_zero1: 2; + uint32_t src_im : 1; /* immediate */ + uint32_t src_neg : 1; /* negate */ + uint32_t src_abs : 1; /* absolute value */ + }; + struct PACKED { + uint32_t src : 10; + uint32_t src_c : 1; /* relative-const */ + uint32_t src_rel : 1; /* relative address */ + uint32_t must_be_zero : 1; + uint32_t dummy : 3; + } rel; + struct PACKED { + uint32_t src : 12; + uint32_t src_c : 1; /* const */ + uint32_t dummy : 3; + } c; + }; uint32_t dummy1 : 16; /* seem to be ignored */ /* dword1: */ diff --git a/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c b/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c index 76e8b113ac1..238ce3452ff 100644 --- a/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c +++ b/src/gallium/drivers/freedreno/a3xx/ir-a3xx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Rob Clark <[email protected]> + * Copyright (c) 2012 Rob Clark <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -132,11 +132,12 @@ static int emit_cat1(struct ir3_instruction *instr, void *ptr, } else if (src->flags & IR3_REG_RELATIV) { cat1->off = src->offset; cat1->src_rel = 1; - cat1->must_be_3 = 3; + cat1->src_rel_c = !!(src->flags & IR3_REG_CONST); } else { cat1->src = reg(src, info, instr->repeat, - IR3_REG_IMMED | IR3_REG_RELATIV | - IR3_REG_R | IR3_REG_CONST | IR3_REG_HALF); + IR3_REG_IMMED | IR3_REG_R | + IR3_REG_CONST | IR3_REG_HALF); + cat1->src_c = !!(src->flags & IR3_REG_CONST); } cat1->dst = reg(dst, info, instr->repeat, @@ -145,10 +146,10 @@ static int emit_cat1(struct ir3_instruction *instr, void *ptr, cat1->repeat = instr->repeat; cat1->src_r = !!(src->flags & IR3_REG_R); cat1->ss = !!(instr->flags & IR3_INSTR_SS); + cat1->ul = !!(instr->flags & IR3_INSTR_UL); cat1->dst_type = instr->cat1.dst_type; cat1->dst_rel = !!(dst->flags & IR3_REG_RELATIV); cat1->src_type = instr->cat1.src_type; - cat1->src_c = !!(src->flags & IR3_REG_CONST); cat1->even = !!(dst->flags & IR3_REG_EVEN); cat1->pos_inf = !!(dst->flags & IR3_REG_POS_INF); cat1->jmp_tgt = !!(instr->flags & IR3_INSTR_JP); @@ -168,11 +169,25 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr, iassert((instr->regs_count == 2) || (instr->regs_count == 3)); - cat2->src1 = reg(src1, info, instr->repeat, - IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED | - IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF); - cat2->src1_rel = !!(src1->flags & IR3_REG_RELATIV); - cat2->src1_c = !!(src1->flags & IR3_REG_CONST); + if (src1->flags & IR3_REG_RELATIV) { + iassert(src1->num < (1 << 10)); + cat2->rel1.src1 = reg(src1, info, instr->repeat, + IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE | + IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF); + cat2->rel1.src1_c = !!(src1->flags & IR3_REG_CONST); + cat2->rel1.src1_rel = 1; + } else if (src1->flags & IR3_REG_CONST) { + iassert(src1->num < (1 << 12)); + cat2->c1.src1 = reg(src1, info, instr->repeat, + IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + cat2->c1.src1_c = 1; + } else { + iassert(src1->num < (1 << 11)); + cat2->src1 = reg(src1, info, instr->repeat, + IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + } cat2->src1_im = !!(src1->flags & IR3_REG_IMMED); cat2->src1_neg = !!(src1->flags & IR3_REG_NEGATE); cat2->src1_abs = !!(src1->flags & IR3_REG_ABS); @@ -181,11 +196,27 @@ static int emit_cat2(struct ir3_instruction *instr, void *ptr, if (src2) { iassert((src2->flags & IR3_REG_IMMED) || !((src1->flags ^ src2->flags) & IR3_REG_HALF)); - cat2->src2 = reg(src2, info, instr->repeat, - IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED | - IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF); - cat2->src2_rel = !!(src2->flags & IR3_REG_RELATIV); - cat2->src2_c = !!(src2->flags & IR3_REG_CONST); + + if (src2->flags & IR3_REG_RELATIV) { + iassert(src2->num < (1 << 10)); + cat2->rel2.src2 = reg(src2, info, instr->repeat, + IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE | + IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF); + cat2->rel2.src2_c = !!(src2->flags & IR3_REG_CONST); + cat2->rel2.src2_rel = 1; + } else if (src2->flags & IR3_REG_CONST) { + iassert(src2->num < (1 << 12)); + cat2->c2.src2 = reg(src2, info, instr->repeat, + IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + cat2->c2.src2_c = 1; + } else { + iassert(src2->num < (1 << 11)); + cat2->src2 = reg(src2, info, instr->repeat, + IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + } + cat2->src2_im = !!(src2->flags & IR3_REG_IMMED); cat2->src2_neg = !!(src2->flags & IR3_REG_NEGATE); cat2->src2_abs = !!(src2->flags & IR3_REG_ABS); @@ -239,11 +270,25 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr, iassert(!((src2->flags ^ src_flags) & IR3_REG_HALF)); iassert(!((src3->flags ^ src_flags) & IR3_REG_HALF)); - cat3->src1 = reg(src1, info, instr->repeat, - IR3_REG_RELATIV | IR3_REG_CONST | - IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF); - cat3->src1_rel = !!(src1->flags & IR3_REG_RELATIV); - cat3->src1_c = !!(src1->flags & IR3_REG_CONST); + if (src1->flags & IR3_REG_RELATIV) { + iassert(src1->num < (1 << 10)); + cat3->rel1.src1 = reg(src1, info, instr->repeat, + IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE | + IR3_REG_R | IR3_REG_HALF); + cat3->rel1.src1_c = !!(src1->flags & IR3_REG_CONST); + cat3->rel1.src1_rel = 1; + } else if (src1->flags & IR3_REG_CONST) { + iassert(src1->num < (1 << 12)); + cat3->c1.src1 = reg(src1, info, instr->repeat, + IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_R | + IR3_REG_HALF); + cat3->c1.src1_c = 1; + } else { + iassert(src1->num < (1 << 11)); + cat3->src1 = reg(src1, info, instr->repeat, + IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF); + } + cat3->src1_neg = !!(src1->flags & IR3_REG_NEGATE); cat3->src1_r = !!(src1->flags & IR3_REG_R); @@ -254,11 +299,26 @@ static int emit_cat3(struct ir3_instruction *instr, void *ptr, cat3->src2_neg = !!(src2->flags & IR3_REG_NEGATE); cat3->src2_r = !!(src2->flags & IR3_REG_R); - cat3->src3 = reg(src3, info, instr->repeat, - IR3_REG_RELATIV | IR3_REG_CONST | - IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF); - cat3->src3_rel = !!(src3->flags & IR3_REG_RELATIV); - cat3->src3_c = !!(src3->flags & IR3_REG_CONST); + + if (src3->flags & IR3_REG_RELATIV) { + iassert(src3->num < (1 << 10)); + cat3->rel2.src3 = reg(src3, info, instr->repeat, + IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE | + IR3_REG_R | IR3_REG_HALF); + cat3->rel2.src3_c = !!(src3->flags & IR3_REG_CONST); + cat3->rel2.src3_rel = 1; + } else if (src3->flags & IR3_REG_CONST) { + iassert(src3->num < (1 << 12)); + cat3->c2.src3 = reg(src3, info, instr->repeat, + IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_R | + IR3_REG_HALF); + cat3->c2.src3_c = 1; + } else { + iassert(src3->num < (1 << 11)); + cat3->src3 = reg(src3, info, instr->repeat, + IR3_REG_NEGATE | IR3_REG_R | IR3_REG_HALF); + } + cat3->src3_neg = !!(src3->flags & IR3_REG_NEGATE); cat3->src3_r = !!(src3->flags & IR3_REG_R); @@ -284,12 +344,26 @@ static int emit_cat4(struct ir3_instruction *instr, void *ptr, iassert(instr->regs_count == 2); - cat4->src = reg(src, info, instr->repeat, - IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_IMMED | - IR3_REG_NEGATE | IR3_REG_ABS | IR3_REG_R | - IR3_REG_HALF); - cat4->src_rel = !!(src->flags & IR3_REG_RELATIV); - cat4->src_c = !!(src->flags & IR3_REG_CONST); + if (src->flags & IR3_REG_RELATIV) { + iassert(src->num < (1 << 10)); + cat4->rel.src = reg(src, info, instr->repeat, + IR3_REG_RELATIV | IR3_REG_CONST | IR3_REG_NEGATE | + IR3_REG_ABS | IR3_REG_R | IR3_REG_HALF); + cat4->rel.src_c = !!(src->flags & IR3_REG_CONST); + cat4->rel.src_rel = 1; + } else if (src->flags & IR3_REG_CONST) { + iassert(src->num < (1 << 12)); + cat4->c.src = reg(src, info, instr->repeat, + IR3_REG_CONST | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + cat4->c.src_c = 1; + } else { + iassert(src->num < (1 << 11)); + cat4->src = reg(src, info, instr->repeat, + IR3_REG_IMMED | IR3_REG_NEGATE | IR3_REG_ABS | + IR3_REG_R | IR3_REG_HALF); + } + cat4->src_im = !!(src->flags & IR3_REG_IMMED); cat4->src_neg = !!(src->flags & IR3_REG_NEGATE); cat4->src_abs = !!(src->flags & IR3_REG_ABS); diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index a038a779029..2be242af191 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -267,6 +267,8 @@ static int fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum pipe_shader_cap param) { + struct fd_screen *screen = fd_screen(pscreen); + switch(shader) { case PIPE_SHADER_FRAGMENT: @@ -293,13 +295,13 @@ fd_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, case PIPE_SHADER_CAP_MAX_INPUTS: return 32; case PIPE_SHADER_CAP_MAX_TEMPS: - return 256; /* Max native temporaries. */ + return 64; /* Max native temporaries. */ case PIPE_SHADER_CAP_MAX_ADDRS: - /* XXX Isn't this equal to TEMPS? */ return 1; /* Max native address registers */ case PIPE_SHADER_CAP_MAX_CONSTS: + return (screen->gpu_id >= 300) ? 1024 : 64; case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: - return 64; + return 1; case PIPE_SHADER_CAP_MAX_PREDS: return 0; /* nothing uses this */ case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: |