From be5d8bd07886157fe524b8715509cd03ade2fda9 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 08:21:43 -0600 Subject: gallium: initial PPC/Altivec codegen --- src/gallium/auxiliary/rtasm/rtasm_ppc.c | 365 ++++++++++++++++++++++++++++++++ src/gallium/auxiliary/rtasm/rtasm_ppc.h | 181 ++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 src/gallium/auxiliary/rtasm/rtasm_ppc.c create mode 100644 src/gallium/auxiliary/rtasm/rtasm_ppc.h (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc.c b/src/gallium/auxiliary/rtasm/rtasm_ppc.c new file mode 100644 index 00000000000..534a23568d5 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc.c @@ -0,0 +1,365 @@ +/************************************************************************** + * + * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * PPC code generation. + * \author Brian Paul + */ + + +#include "util/u_memory.h" +#include "pipe/p_debug.h" +#include "rtasm_ppc.h" + + +void +ppc_init_func(struct ppc_function *p, unsigned max_inst) +{ + p->store = align_malloc(max_inst * PPC_INST_SIZE, 16); + p->num_inst = 0; + p->max_inst = max_inst; + p->vec_used = ~0; +} + + +void +ppc_release_func(struct ppc_function *p) +{ + assert(p->num_inst <= p->max_inst); + if (p->store != NULL) { + align_free(p->store); + } + p->store = NULL; +} + + +/** + * Alloate a vector register. + * \return register index or -1 if none left. + */ +int +ppc_allocate_vec_register(struct ppc_function *p, int reg) +{ + unsigned i; + for (i = 0; i < PPC_NUM_VEC_REGS; i++) { + const uint64_t mask = 1 << i; + if ((p->vec_used & mask) != 0) { + p->vec_used &= ~mask; + return i; + } + } + + return -1; +} + + +/** + * Mark the given vector register as "unallocated". + */ +void +ppc_release_vec_register(struct ppc_function *p, int reg) +{ + assert(reg < PPC_NUM_VEC_REGS); + assert((p->vec_used & (1 << reg)) == 0); + + p->vec_used |= (1 << reg); +} + + + +union vx_inst { + uint32_t bits; + struct { + unsigned op:6; + unsigned vD:5; + unsigned vA:5; + unsigned vB:5; + unsigned op2:11; + } inst; +}; + +union vxr_inst { + uint32_t bits; + struct { + unsigned op:6; + unsigned vD:5; + unsigned vA:5; + unsigned vB:5; + unsigned rC:1; + unsigned op2:10; + } inst; +}; + +union va_inst { + uint32_t bits; + struct { + unsigned op:6; + unsigned vD:5; + unsigned vA:5; + unsigned vB:5; + unsigned vC:5; + unsigned op2:6; + } inst; +}; + + +static inline void +emit_vx(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB) +{ + union vx_inst inst; + inst.inst.op = 4; + inst.inst.vD = vD; + inst.inst.vA = vA; + inst.inst.vB = vB; + inst.inst.op2 = op2; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); +}; + +static inline void +emit_vxr(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB) +{ + union vxr_inst inst; + inst.inst.op = 4; + inst.inst.vD = vD; + inst.inst.vA = vA; + inst.inst.vB = vB; + inst.inst.rC = 0; + inst.inst.op2 = op2; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); +}; + +static inline void +emit_va(struct ppc_function *p, uint op2, uint vD, uint vA, uint vB, uint vC) +{ + union va_inst inst; + inst.inst.op = 4; + inst.inst.vD = vD; + inst.inst.vA = vA; + inst.inst.vB = vB; + inst.inst.vC = vC; + inst.inst.op2 = op2; + p->store[p->num_inst++] = inst.bits; + assert(p->num_inst <= p->max_inst); +}; + + + +/** + ** float vector arithmetic + **/ + +/** vector float add */ +void +ppc_vaddfp(struct ppc_function *p,uint vD, uint vA, uint vB) +{ + emit_vx(p, 10, vD, vA, vB); +} + +/** vector float substract */ +void +ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 74, vD, vA, vB); +} + +/** vector float min */ +void +ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1098, vD, vA, vB); +} + +/** vector float max */ +void +ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1034, vD, vA, vB); +} + +/** vector float mult add */ +void +ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC) +{ + emit_va(p, 46, vD, vA, vB, vC); +} + +/** vector float compare greater than */ +void +ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vxr(p, 710, vD, vA, vB); +} + +/** vector float compare greater than or equal to */ +void +ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vxr(p, 454, vD, vA, vB); +} + +/** vector float compare equal */ +void +ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vxr(p, 198, vD, vA, vB); +} + +/** vector float 2^x */ +void +ppc_vexptefp(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 394, vD, 0, vB); +} + +/** vector float log2(x) */ +void +ppc_vlogefp(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 458, vD, 0, vB); +} + +/** vector float reciprocol */ +void +ppc_vrefp(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 266, vD, 0, vB); +} + +/** vector float reciprocol sqrt estimate */ +void +ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 330, vD, 0, vB); +} + +/** vector float round to negative infinity */ +void +ppc_vrfim(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 714, vD, 0, vB); +} + +/** vector float round to positive infinity */ +void +ppc_vrfip(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 650, vD, 0, vB); +} + +/** vector float round to nearest int */ +void +ppc_vrfin(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 522, vD, 0, vB); +} + +/** vector float round to int toward zero */ +void +ppc_vrfiz(struct ppc_function *p, uint vD, uint vB) +{ + emit_vx(p, 586, vD, 0, vB); +} + + + +/** + ** bitwise operations + **/ + + +/** vector and */ +void +ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1028, vD, vA, vB); +} + +/** vector and complement */ +void +ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1092, vD, vA, vB); +} + +/** vector or */ +void +ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1156, vD, vA, vB); +} + +/** vector nor */ +void +ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1284, vD, vA, vB); +} + +/** vector xor */ +void +ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB) +{ + emit_vx(p, 1220, vD, vA, vB); +} + + +/** + ** Vector shuffle / select / splat / etc + **/ + +/** vector permute */ +void +ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC) +{ + emit_va(p, 43, vD, vA, vB, vC); +} + +/** vector select */ +void +ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC) +{ + emit_va(p, 42, vD, vA, vB, vC); +} + +/** vector splat byte */ +void +ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm) +{ + emit_vx(p, 42, vD, imm, vB); +} + +/** vector splat half word */ +void +ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm) +{ + emit_vx(p, 588, vD, imm, vB); +} + +/** vector splat word */ +void +ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm) +{ + emit_vx(p, 652, vD, imm, vB); +} diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc.h b/src/gallium/auxiliary/rtasm/rtasm_ppc.h new file mode 100644 index 00000000000..ed14e943df6 --- /dev/null +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc.h @@ -0,0 +1,181 @@ +/************************************************************************** + * + * Copyright (C) 2008 Tungsten Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * PPC code generation. + * \author Brian Paul + */ + + +#ifndef RTASM_PPC_H +#define RTASM_PPC_H + + +#include "pipe/p_compiler.h" + + +#define PPC_INST_SIZE 4 /**< 4 bytes / instruction */ + +#define PPC_NUM_VEC_REGS 32 + + +struct ppc_function +{ + uint32_t *store; /**< instruction buffer */ + uint num_inst; + uint max_inst; + uint32_t vec_used; /** used/free vector registers bitmask */ + uint32_t reg_used; /** used/free general-purpose registers bitmask */ +}; + + + +extern void ppc_init_func(struct ppc_function *p, unsigned max_inst); +extern void ppc_release_func(struct ppc_function *p); + +extern int ppc_allocate_vec_register(struct ppc_function *p, int reg); +extern void ppc_release_vec_register(struct ppc_function *p, int reg); + + +/** + ** float vector arithmetic + **/ + +/** vector float add */ +extern void +ppc_vaddfp(struct ppc_function *p,uint vD, uint vA, uint vB); + +/** vector float substract */ +extern void +ppc_vsubfp(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float min */ +extern void +ppc_vminfp(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float max */ +extern void +ppc_vmaxfp(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float mult add */ +extern void +ppc_vmaddfp(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC); + +/** vector float compare greater than */ +extern void +ppc_vcmpgtfpx(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float compare greater than or equal to */ +extern void +ppc_vcmpgefpx(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float compare equal */ +extern void +ppc_vcmpeqfpx(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector float 2^x */ +extern void +ppc_vexptefp(struct ppc_function *p, uint vD, uint vB); + +/** vector float log2(x) */ +extern void +ppc_vlogefp(struct ppc_function *p, uint vD, uint vB); + +/** vector float reciprocol */ +extern void +ppc_vrefp(struct ppc_function *p, uint vD, uint vB); + +/** vector float reciprocol sqrt estimate */ +extern void +ppc_vrsqrtefp(struct ppc_function *p, uint vD, uint vB); + +/** vector float round to negative infinity */ +extern void +ppc_vrfim(struct ppc_function *p, uint vD, uint vB); + +/** vector float round to positive infinity */ +extern void +ppc_vrfip(struct ppc_function *p, uint vD, uint vB); + +/** vector float round to nearest int */ +extern void +ppc_vrfin(struct ppc_function *p, uint vD, uint vB); + +/** vector float round to int toward zero */ +extern void +ppc_vrfiz(struct ppc_function *p, uint vD, uint vB); + + + +/** + ** bitwise operations + **/ + + +/** vector and */ +extern void +ppc_vand(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector and complement */ +extern void +ppc_vandc(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector or */ +extern void +ppc_vor(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector nor */ +extern void +ppc_vnor(struct ppc_function *p, uint vD, uint vA, uint vB); + +/** vector xor */ +extern void +ppc_vxor(struct ppc_function *p, uint vD, uint vA, uint vB); + + +/** + ** Vector shuffle / select / splat / etc + **/ + +/** vector permute */ +extern void +ppc_vperm(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC); + +/** vector select */ +extern void +ppc_vsel(struct ppc_function *p, uint vD, uint vA, uint vB, uint vC); + +/** vector splat byte */ +extern void +ppc_vspltb(struct ppc_function *p, uint vD, uint vB, uint imm); + +/** vector splat half word */ +extern void +ppc_vsplthw(struct ppc_function *p, uint vD, uint vB, uint imm); + +/** vector splat word */ +extern void +ppc_vspltw(struct ppc_function *p, uint vD, uint vB, uint imm); + + +#endif /* RTASM_PPC_H */ -- cgit v1.2.3 From b71f4150c8be662d777da22ed0554663a9d1c84d Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 08:22:15 -0600 Subject: gallium: minor optimization to spe_load_int() --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index a04cc6c4ff7..62e3adb357c 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -505,7 +505,8 @@ spe_load_int(struct spe_function *p, unsigned rT, int i) } else { spe_ilhu(p, rT, i >> 16); - spe_iohl(p, rT, i & 0xffff); + if (i & 0xffff) + spe_iohl(p, rT, i & 0xffff); } } -- cgit v1.2.3 From 50f78fcc2e3da24fa6dc076f0985355b3f64e9fd Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 11:01:31 -0600 Subject: gallium: silence warning --- src/gallium/auxiliary/tgsi/tgsi_exec.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index df002939c6b..1a5294eabc3 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -1674,6 +1674,7 @@ exec_declaration( break; default: + eval = NULL; assert( 0 ); } -- cgit v1.2.3 From 31d2e5b954ece02070555b51c06ee427cf951b1f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 11:02:18 -0600 Subject: gallium: use new compare32() function to fix warnings about type punning and aliasing --- src/gallium/auxiliary/tgsi/tgsi_build.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index 74614d36884..38fcaf88293 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -793,10 +793,14 @@ tgsi_default_instruction_ext_nv( void ) return instruction_ext_nv; } -union token_u32 + +/** test for inequality of 32-bit values pointed to by a and b */ +static INLINE boolean +compare32(const void *a, const void *b) { - unsigned u32; -}; + return *((uint32_t *) a) != *((uint32_t *) b); +} + unsigned tgsi_compare_instruction_ext_nv( @@ -805,7 +809,7 @@ tgsi_compare_instruction_ext_nv( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_instruction_ext_nv @@ -864,7 +868,7 @@ tgsi_compare_instruction_ext_label( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_instruction_ext_label @@ -905,7 +909,7 @@ tgsi_compare_instruction_ext_texture( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_instruction_ext_texture @@ -1027,7 +1031,7 @@ tgsi_compare_src_register_ext_swz( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_src_register_ext_swz @@ -1095,7 +1099,7 @@ tgsi_compare_src_register_ext_mod( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_src_register_ext_mod @@ -1241,7 +1245,7 @@ tgsi_compare_dst_register_ext_concode( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_dst_register_ext_concode @@ -1299,7 +1303,7 @@ tgsi_compare_dst_register_ext_modulate( { a.Padding = b.Padding = 0; a.Extended = b.Extended = 0; - return ((union token_u32 *) &a)->u32 != ((union token_u32 *) &b)->u32; + return compare32(&a, &b); } struct tgsi_dst_register_ext_modulate -- cgit v1.2.3 From bd34b8a4febb7aadec0545250fd8b6b06ad774e8 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 11:40:31 -0600 Subject: gallium: use copy_token() function to avoid type punning/aliasing problems This fixes parsing errors seen with optimized builds on PPC (which led to crashes). The memcpy() is heavy-handed, but works. A lighter uint assignment could be used on x86... --- src/gallium/auxiliary/tgsi/tgsi_parse.c | 54 ++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 21 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 3757486ba9b..2cd56e413a5 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -88,16 +88,33 @@ tgsi_parse_end_of_tokens( 1 + ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize; } + +/** + * This function is used to avoid and work-around type punning/aliasing + * warnings. The warnings seem harmless on x86 but on PPC they cause + * real failures. + */ +static INLINE void +copy_token(void *dst, const void *src) +{ + memcpy(dst, src, 4); +} + + +/** + * Get next 4-byte token, return it at address specified by 'token' + */ static void next_token( struct tgsi_parse_context *ctx, void *token ) { assert( !tgsi_parse_end_of_tokens( ctx ) ); - - *(struct tgsi_token *) token = ctx->Tokens[ctx->Position++]; + copy_token(token, &ctx->Tokens[ctx->Position]); + ctx->Position++; } + void tgsi_parse_token( struct tgsi_parse_context *ctx ) @@ -116,7 +133,7 @@ tgsi_parse_token( struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration; *decl = tgsi_default_full_declaration(); - decl->Declaration = *(struct tgsi_declaration *) &token; + copy_token(&decl->Declaration, &token); next_token( ctx, &decl->DeclarationRange ); @@ -132,8 +149,7 @@ tgsi_parse_token( struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate; *imm = tgsi_default_full_immediate(); - imm->Immediate = *(struct tgsi_immediate *) &token; - + copy_token(&imm->Immediate, &token); assert( !imm->Immediate.Extended ); switch (imm->Immediate.DataType) { @@ -158,8 +174,7 @@ tgsi_parse_token( unsigned extended; *inst = tgsi_default_full_instruction(); - inst->Instruction = *(struct tgsi_instruction *) &token; - + copy_token(&inst->Instruction, &token); extended = inst->Instruction.Extended; while( extended ) { @@ -169,18 +184,15 @@ tgsi_parse_token( switch( token.Type ) { case TGSI_INSTRUCTION_EXT_TYPE_NV: - inst->InstructionExtNv = - *(struct tgsi_instruction_ext_nv *) &token; + copy_token(&inst->InstructionExtNv, &token); break; case TGSI_INSTRUCTION_EXT_TYPE_LABEL: - inst->InstructionExtLabel = - *(struct tgsi_instruction_ext_label *) &token; + copy_token(&inst->InstructionExtLabel, &token); break; case TGSI_INSTRUCTION_EXT_TYPE_TEXTURE: - inst->InstructionExtTexture = - *(struct tgsi_instruction_ext_texture *) &token; + copy_token(&inst->InstructionExtTexture, &token); break; default: @@ -212,13 +224,13 @@ tgsi_parse_token( switch( token.Type ) { case TGSI_DST_REGISTER_EXT_TYPE_CONDCODE: - inst->FullDstRegisters[i].DstRegisterExtConcode = - *(struct tgsi_dst_register_ext_concode *) &token; + copy_token(&inst->FullDstRegisters[i].DstRegisterExtConcode, + &token); break; case TGSI_DST_REGISTER_EXT_TYPE_MODULATE: - inst->FullDstRegisters[i].DstRegisterExtModulate = - *(struct tgsi_dst_register_ext_modulate *) &token; + copy_token(&inst->FullDstRegisters[i].DstRegisterExtModulate, + &token); break; default: @@ -245,13 +257,13 @@ tgsi_parse_token( switch( token.Type ) { case TGSI_SRC_REGISTER_EXT_TYPE_SWZ: - inst->FullSrcRegisters[i].SrcRegisterExtSwz = - *(struct tgsi_src_register_ext_swz *) &token; + copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtSwz, + &token); break; case TGSI_SRC_REGISTER_EXT_TYPE_MOD: - inst->FullSrcRegisters[i].SrcRegisterExtMod = - *(struct tgsi_src_register_ext_mod *) &token; + copy_token(&inst->FullSrcRegisters[i].SrcRegisterExtMod, + &token); break; default: -- cgit v1.2.3 From 9defef29c59c580da1f6312f737822cd2efc9e28 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 11:42:33 -0600 Subject: gallium: avoid redundant tgsi_exec_machine_bind_shader() calls on draw exec path tgsi_exec_machine_bind_shader() isn't cheap so avoiding unecessary calls is a big win. A similar change should be done for softpipe's fragment exec path but extra care needs to be taken with the texture sampler state/params. --- src/gallium/auxiliary/draw/draw_vs_exec.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 44563803f90..8041705b9ca 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -46,6 +46,7 @@ struct exec_vertex_shader { struct draw_vertex_shader base; struct tgsi_exec_machine *machine; + struct tgsi_token *machine_tokens; }; static struct exec_vertex_shader *exec_vertex_shader( struct draw_vertex_shader *vs ) @@ -62,12 +63,16 @@ vs_exec_prepare( struct draw_vertex_shader *shader, { struct exec_vertex_shader *evs = exec_vertex_shader(shader); - /* specify the vertex program to interpret/execute */ - tgsi_exec_machine_bind_shader(evs->machine, - shader->state.tokens, - PIPE_MAX_SAMPLERS, - NULL /*samplers*/ ); - + /* Specify the vertex program to interpret/execute. + * Avoid rebinding when possible. + */ + if (evs->machine_tokens != shader->state.tokens) { + tgsi_exec_machine_bind_shader(evs->machine, + shader->state.tokens, + PIPE_MAX_SAMPLERS, + NULL /*samplers*/ ); + evs->machine_tokens = shader->state.tokens; + } } -- cgit v1.2.3 From 31a112cad4d2e515bc668b58abd4e402b4362c70 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 21:08:01 -0600 Subject: gallium: added spe_splat_word() --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 25 +++++++++++++++++++++++++ src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 4 ++++ 2 files changed, 29 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 62e3adb357c..89f8e24ce6a 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -540,4 +540,29 @@ spe_zero(struct spe_function *p, unsigned rT) } +void +spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) +{ + assert(word >= 0); + assert(word <= 3); + + if (word == 0) { + int tmp1 = rT; + spe_ila(p, tmp1, 66051); + spe_shufb(p, rT, rA, rA, tmp1); + } + else { + /* XXX review this, we may not need the rotqbyi instruction */ + int tmp1 = rT; + int tmp2 = spe_allocate_available_register(p); + + spe_ila(p, tmp1, 66051); + spe_rotqbyi(p, tmp2, rA, 4 * word); + spe_shufb(p, rT, tmp2, tmp2, tmp1); + + spe_release_register(p, tmp2); + } +} + + #endif /* GALLIUM_CELL */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index d95e5aace34..7a3ab9ace52 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -308,6 +308,10 @@ spe_move(struct spe_function *p, unsigned rT, unsigned rA); extern void spe_zero(struct spe_function *p, unsigned rT); +/** rT = splat(rA, word) */ +extern void +spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word); + /* Floating-point instructions */ -- cgit v1.2.3 From 8b5013d232bf6846717fac093465e8a39064e0b6 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 12 Sep 2008 21:52:47 -0600 Subject: gallium: added print/dump code to SPE code emitter --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 128 ++++++++++++++++++++++------ src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 10 +++ 2 files changed, 113 insertions(+), 25 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 89f8e24ce6a..8718be9dedb 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -27,12 +27,16 @@ * Real-time assembly generation interface for Cell B.E. SPEs. * * \author Ian Romanick + * \author Brian Paul */ + +#include #include "pipe/p_compiler.h" #include "util/u_memory.h" #include "rtasm_ppc_spe.h" + #ifdef GALLIUM_CELL /** * SPE instruction types @@ -143,8 +147,25 @@ union spe_inst_RI18 { /*@}*/ +static void +indent(const struct spe_function *p) +{ + int i; + for (i = 0; i < p->indent; i++) { + putchar(' '); + } +} + + +static const char * +rem_prefix(const char *longname) +{ + return longname + 4; +} + + static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, unsigned rB) + unsigned rA, unsigned rB, const char *name) { union spe_inst_RR inst; inst.inst.op = op; @@ -153,11 +174,15 @@ static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB); + } } static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, unsigned rB, unsigned rC) + unsigned rA, unsigned rB, unsigned rC, const char *name) { union spe_inst_RRR inst; inst.inst.op = op; @@ -167,11 +192,15 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rC = rC; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, r%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB, rB); + } } static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm) + unsigned rA, int imm, const char *name) { union spe_inst_RI7 inst; inst.inst.op = op; @@ -180,12 +209,16 @@ static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + } } static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm) + unsigned rA, int imm, const char *name) { union spe_inst_RI8 inst; inst.inst.op = op; @@ -194,12 +227,16 @@ static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + } } static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, - unsigned rA, int imm) + unsigned rA, int imm, const char *name) { union spe_inst_RI10 inst; inst.inst.op = op; @@ -208,11 +245,15 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + } } static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, - int imm) + int imm, const char *name) { union spe_inst_RI16 inst; inst.inst.op = op; @@ -220,11 +261,15 @@ static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, 0x%x\n", rem_prefix(name), rT, imm); + } } static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, - int imm) + int imm, const char *name) { union spe_inst_RI18 inst; inst.inst.op = op; @@ -232,6 +277,10 @@ static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, inst.inst.rT = rT; p->store[p->num_inst++] = inst.bits; assert(p->num_inst <= p->max_inst); + if (p->print) { + indent(p); + printf("%s\tr%d, 0x%x\n", rem_prefix(name), rT, imm); + } } @@ -240,61 +289,61 @@ static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, #define EMIT_(_name, _op) \ void _name (struct spe_function *p, unsigned rT) \ { \ - emit_RR(p, _op, rT, 0, 0); \ + emit_RR(p, _op, rT, 0, 0, __FUNCTION__); \ } #define EMIT_R(_name, _op) \ void _name (struct spe_function *p, unsigned rT, unsigned rA) \ { \ - emit_RR(p, _op, rT, rA, 0); \ + emit_RR(p, _op, rT, rA, 0, __FUNCTION__); \ } #define EMIT_RR(_name, _op) \ void _name (struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) \ { \ - emit_RR(p, _op, rT, rA, rB); \ + emit_RR(p, _op, rT, rA, rB, __FUNCTION__); \ } #define EMIT_RRR(_name, _op) \ void _name (struct spe_function *p, unsigned rT, unsigned rA, unsigned rB, unsigned rC) \ { \ - emit_RRR(p, _op, rT, rA, rB, rC); \ + emit_RRR(p, _op, rT, rA, rB, rC, __FUNCTION__); \ } #define EMIT_RI7(_name, _op) \ void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ { \ - emit_RI7(p, _op, rT, rA, imm); \ + emit_RI7(p, _op, rT, rA, imm, __FUNCTION__); \ } #define EMIT_RI8(_name, _op, bias) \ void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ { \ - emit_RI8(p, _op, rT, rA, bias - imm); \ + emit_RI8(p, _op, rT, rA, bias - imm, __FUNCTION__); \ } #define EMIT_RI10(_name, _op) \ void _name (struct spe_function *p, unsigned rT, unsigned rA, int imm) \ { \ - emit_RI10(p, _op, rT, rA, imm); \ + emit_RI10(p, _op, rT, rA, imm, __FUNCTION__); \ } #define EMIT_RI16(_name, _op) \ void _name (struct spe_function *p, unsigned rT, int imm) \ { \ - emit_RI16(p, _op, rT, imm); \ + emit_RI16(p, _op, rT, imm, __FUNCTION__); \ } #define EMIT_RI18(_name, _op) \ void _name (struct spe_function *p, unsigned rT, int imm) \ { \ - emit_RI18(p, _op, rT, imm); \ + emit_RI18(p, _op, rT, imm, __FUNCTION__); \ } #define EMIT_I16(_name, _op) \ void _name (struct spe_function *p, int imm) \ { \ - emit_RI16(p, _op, 0, imm); \ + emit_RI16(p, _op, 0, imm, __FUNCTION__); \ } #include "rtasm_ppc_spe.h" @@ -314,6 +363,9 @@ void spe_init_func(struct spe_function *p, unsigned code_size) */ p->regs[0] = ~7; p->regs[1] = (1U << (80 - 64)) - 1; + + p->print = false; + p->indent = 0; } @@ -382,6 +434,32 @@ void spe_release_register(struct spe_function *p, int reg) } +void +spe_print_code(struct spe_function *p, boolean enable) +{ + p->print = enable; +} + + +void +spe_indent(struct spe_function *p, int spaces) +{ + p->indent += spaces; +} + + +extern void +spe_comment(struct spe_function *p, int rel_indent, const char *s) +{ + if (p->print) { + p->indent += rel_indent; + indent(p); + p->indent -= rel_indent; + printf("%s\n", s); + } +} + + /** * For branch instructions: * \param d if 1, disable interupts if branch is taken @@ -392,51 +470,51 @@ void spe_release_register(struct spe_function *p, int reg) /** Branch Indirect to address in rA */ void spe_bi(struct spe_function *p, unsigned rA, int d, int e) { - emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x1a8, 0, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Interupt Return */ void spe_iret(struct spe_function *p, unsigned rA, int d, int e) { - emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x1aa, 0, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect and set link on external data */ void spe_bisled(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x1ab, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect and set link. Save PC in rT, jump to rA. */ void spe_bisl(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x1a9, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if zero word. If rT.word[0]==0, jump to rA. */ void spe_biz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x128, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if non-zero word. If rT.word[0]!=0, jump to rA. */ void spe_binz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x129, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if zero halfword. If rT.halfword[1]==0, jump to rA. */ void spe_bihz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x12a, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } /** Branch indirect if non-zero halfword. If rT.halfword[1]!=0, jump to rA. */ void spe_bihnz(struct spe_function *p, unsigned rT, unsigned rA, int d, int e) { - emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4)); + emit_RI7(p, 0x12b, rT, rA, (d << 5) | (e << 4), __FUNCTION__); } diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 7a3ab9ace52..25790452325 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -28,6 +28,7 @@ * For details, see /opt/cell/sdk/docs/arch/SPU_ISA_v1.2_27Jan2007_pub.pdf * * \author Ian Romanick + * \author Brian Paul */ #ifndef RTASM_PPC_SPE_H @@ -63,8 +64,12 @@ struct spe_function * spe_release_register */ uint64_t regs[SPE_NUM_REGS / 64]; + + boolean print; /**< print/dump instructions as they're emitted? */ + int indent; /**< number of spaces to indent */ }; + extern void spe_init_func(struct spe_function *p, unsigned code_size); extern void spe_release_func(struct spe_function *p); @@ -72,6 +77,11 @@ extern int spe_allocate_available_register(struct spe_function *p); extern int spe_allocate_register(struct spe_function *p, int reg); extern void spe_release_register(struct spe_function *p, int reg); +extern void spe_print_code(struct spe_function *p, boolean enable); +extern void spe_indent(struct spe_function *p, int spaces); +extern void spe_comment(struct spe_function *p, int rel_indent, const char *s); + + #endif /* RTASM_PPC_SPE_H */ #ifndef EMIT_ -- cgit v1.2.3 From 809e81c0b424839cb742ff2502b1010c0258b368 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 13 Sep 2008 15:21:58 -0600 Subject: gallium: add another value check to util_fast_pow() Fixes glitches seen in morph3d demo. --- src/gallium/auxiliary/util/u_math.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 9b4ca393714..0b10622ee75 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -272,8 +272,10 @@ util_fast_log2(float val) static INLINE float util_fast_pow(float x, float y) { - /* XXX this test may need adjustment */ - if (y >= 3.0 && -0.02f <= x && x <= 0.02f) + /* XXX these tests may need adjustment */ + if (y >= 3.0f && (-0.02f <= x && x <= 0.02f)) + return 0.0f; + if (y >= 50.0f && (-0.9f <= x && x <= 0.9f)) return 0.0f; return util_fast_exp2(util_fast_log2(x) * y); } -- cgit v1.2.3 From 75c19eb5a1caf0c36e04270174579d0d7fec9ccb Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 13 Sep 2008 15:20:31 -0600 Subject: gallium: add another value check to util_fast_pow() Fixes glitches seen in morph3d demo. --- src/gallium/auxiliary/util/u_math.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 9b4ca393714..0b10622ee75 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -272,8 +272,10 @@ util_fast_log2(float val) static INLINE float util_fast_pow(float x, float y) { - /* XXX this test may need adjustment */ - if (y >= 3.0 && -0.02f <= x && x <= 0.02f) + /* XXX these tests may need adjustment */ + if (y >= 3.0f && (-0.02f <= x && x <= 0.02f)) + return 0.0f; + if (y >= 50.0f && (-0.9f <= x && x <= 0.9f)) return 0.0f; return util_fast_exp2(util_fast_log2(x) * y); } -- cgit v1.2.3 From e852232ebf256d1587ae0d456c366553749fd275 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Sun, 14 Sep 2008 19:04:53 +0200 Subject: draw: Silence compiler warnings on Windows. --- src/gallium/auxiliary/draw/draw_vs_exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 8041705b9ca..79a19d6be2b 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -46,7 +46,7 @@ struct exec_vertex_shader { struct draw_vertex_shader base; struct tgsi_exec_machine *machine; - struct tgsi_token *machine_tokens; + const struct tgsi_token *machine_tokens; }; static struct exec_vertex_shader *exec_vertex_shader( struct draw_vertex_shader *vs ) -- cgit v1.2.3 From 367774a62aa0627c5589e91ab7b411634113c815 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Mon, 15 Sep 2008 11:56:21 -0600 Subject: Fixed emit_RRR --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 8718be9dedb..74cd4176e7b 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -194,7 +194,7 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB, rB); + printf("%s\tr%d, r%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB, rC); } } -- cgit v1.2.3 From ae3373441dd4548702f23fe44bd04830e4902241 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 15 Sep 2008 15:10:02 -0600 Subject: gallium: emit SPU instructions in assembler-compatible syntax --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 74cd4176e7b..870ae802c52 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -176,7 +176,7 @@ static void emit_RR(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB); + printf("%s\t$%d, $%d, $%d\n", rem_prefix(name), rT, rA, rB); } } @@ -194,7 +194,7 @@ static void emit_RRR(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, r%d, r%d\n", rem_prefix(name), rT, rA, rB, rC); + printf("%s\t$%d, $%d, $%d, $%d\n", rem_prefix(name), rT, rA, rB, rC); } } @@ -211,7 +211,7 @@ static void emit_RI7(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + printf("%s\t$%d, $%d, 0x%x\n", rem_prefix(name), rT, rA, imm); } } @@ -229,7 +229,7 @@ static void emit_RI8(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + printf("%s\t$%d, $%d, 0x%x\n", rem_prefix(name), rT, rA, imm); } } @@ -247,7 +247,11 @@ static void emit_RI10(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, r%d, 0x%x\n", rem_prefix(name), rT, rA, imm); + if (strcmp(name, "spe_lqd") == 0 || + strcmp(name, "spe_stqd") == 0) + printf("%s\t$%d, 0x%x($%d)\n", rem_prefix(name), rT, imm, rA); + else + printf("%s\t$%d, $%d, 0x%x\n", rem_prefix(name), rT, rA, imm); } } @@ -263,7 +267,7 @@ static void emit_RI16(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, 0x%x\n", rem_prefix(name), rT, imm); + printf("%s\t$%d, 0x%x\n", rem_prefix(name), rT, imm); } } @@ -279,7 +283,7 @@ static void emit_RI18(struct spe_function *p, unsigned op, unsigned rT, assert(p->num_inst <= p->max_inst); if (p->print) { indent(p); - printf("%s\tr%d, 0x%x\n", rem_prefix(name), rT, imm); + printf("%s\t$%d, 0x%x\n", rem_prefix(name), rT, imm); } } @@ -455,7 +459,7 @@ spe_comment(struct spe_function *p, int rel_indent, const char *s) p->indent += rel_indent; indent(p); p->indent -= rel_indent; - printf("%s\n", s); + printf("# %s\n", s); } } -- cgit v1.2.3 From ad16ecbbe4fe8c1bcb18ed8fbbd672c68a0b17fa Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 16 Sep 2008 16:16:54 +0200 Subject: tgsi: Make tgsi_sanity.c compile with make --- src/gallium/auxiliary/tgsi/Makefile | 1 + src/gallium/auxiliary/tgsi/tgsi_sanity.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile index 806a2bd4c52..c5d2082087c 100644 --- a/src/gallium/auxiliary/tgsi/Makefile +++ b/src/gallium/auxiliary/tgsi/Makefile @@ -4,6 +4,7 @@ include $(TOP)/configs/current LIBNAME = tgsi C_SOURCES = \ + tgsi_sanity.c \ tgsi_build.c \ tgsi_dump.c \ tgsi_exec.c \ diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index c6590272969..20b32477be3 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -152,6 +152,12 @@ check_register_usage( { if (!check_file_name( ctx, file )) return FALSE; + + if (index < 0 || index > MAX_REGISTERS) { + report_error( ctx, "%s[%i]: Invalid index %s", file_names[file], index, name ); + return FALSE; + } + if (indirect_access) { if (!is_any_register_declared( ctx, file )) report_error( ctx, "%s: Undeclared %s register", file_names[file], name ); -- cgit v1.2.3 From 8cdab20c9a0d8794d5d85dbeef478b982ce39506 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 16 Sep 2008 12:52:19 -0600 Subject: gallium: fix info entries for KIL, KILP KIL takes 1 src register. KILP uses no registers (uses cond codes). --- src/gallium/auxiliary/tgsi/tgsi_info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index a4899cd4c2d..68c7a6b7f58 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -69,7 +69,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 1, 1, 0, 0, "COS" }, { 1, 1, 0, 0, "DDX" }, { 1, 1, 0, 0, "DDY" }, - { 0, 1, 0, 0, "KILP" }, + { 0, 0, 0, 0, "KILP" }, { 1, 1, 0, 0, "PK2H" }, { 1, 1, 0, 0, "PK2US" }, { 1, 1, 0, 0, "PK4B" }, @@ -146,7 +146,7 @@ static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { 0, 1, 0, 0, "CALLNZ" }, { 0, 1, 0, 0, "IFC" }, { 0, 1, 0, 0, "BREAKC" }, - { 0, 0, 0, 0, "KIL" }, + { 0, 1, 0, 0, "KIL" }, { 0, 0, 0, 0, "END" }, { 1, 1, 0, 0, "SWZ" } }; -- cgit v1.2.3 From f10e7f0d288530a31a7ed3bc976a537fe640ce69 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 17 Sep 2008 09:47:51 -0600 Subject: gallium: fix lack of surface reference counting in cso_set/save/restore_framebuffer() Fixes asst problems with FBO / render to texture. --- src/gallium/auxiliary/cso_cache/cso_context.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index f22ba40824d..b1ccfc0374a 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -765,12 +765,30 @@ void cso_restore_vertex_shader(struct cso_context *ctx) } +/** + * Copy framebuffer state from src to dst with refcounting of surfaces. + */ +static void +copy_framebuffer_state(struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src) +{ + uint i; + + dst->width = src->width; + dst->height = src->height; + dst->num_cbufs = src->num_cbufs; + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]); + } + pipe_surface_reference(&dst->zsbuf, src->zsbuf); +} + enum pipe_error cso_set_framebuffer(struct cso_context *ctx, const struct pipe_framebuffer_state *fb) { if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { - ctx->fb = *fb; + copy_framebuffer_state(&ctx->fb, fb); ctx->pipe->set_framebuffer_state(ctx->pipe, fb); } return PIPE_OK; @@ -778,13 +796,13 @@ enum pipe_error cso_set_framebuffer(struct cso_context *ctx, void cso_save_framebuffer(struct cso_context *ctx) { - ctx->fb_saved = ctx->fb; + copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); } void cso_restore_framebuffer(struct cso_context *ctx) { if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { - ctx->fb = ctx->fb_saved; + copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); } } -- cgit v1.2.3 From e6a120fefea44078b3a8d4292d83671e6c41357f Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 17 Sep 2008 13:14:57 -0600 Subject: gallium: fix tgsi sanity checker with respect to END. Subroutine code may be found after the END instruction so it's not always the last instruction. At least check for presence of exactly one END instruction though. --- src/gallium/auxiliary/tgsi/tgsi_sanity.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index 20b32477be3..11659247c0c 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -180,12 +180,10 @@ iter_instruction( const struct tgsi_opcode_info *info; uint i; - /* There must be no other instructions after END. - */ - if (ctx->index_of_END != ~0) { - report_error( ctx, "Unexpected instruction after END" ); - } - else if (inst->Instruction.Opcode == TGSI_OPCODE_END) { + if (inst->Instruction.Opcode == TGSI_OPCODE_END) { + if (ctx->index_of_END != ~0) { + report_error( ctx, "Too many END instructions" ); + } ctx->index_of_END = ctx->num_instructions; } @@ -307,10 +305,10 @@ epilog( struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter; uint file; - /* There must be an END instruction at the end. + /* There must be an END instruction somewhere. */ - if (ctx->index_of_END == ~0 || ctx->index_of_END != ctx->num_instructions - 1) { - report_error( ctx, "Expected END at end of instruction sequence" ); + if (ctx->index_of_END == ~0) { + report_error( ctx, "Missing END instruction" ); } /* Check if all declared registers were used. -- cgit v1.2.3 From a06d38a74e865a0373a7314aad26b25c27ef8c57 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 17 Sep 2008 16:51:53 -0600 Subject: gallium: fix wide point / point coord semantic info (generic, not fog) --- src/gallium/auxiliary/draw/draw_pipe_wide_point.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index 4f1326053df..e1af9e56a24 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -222,8 +222,8 @@ static void widepoint_first_point( struct draw_stage *stage, /* find fragment shader PointCoord/Fog input */ wide->point_coord_fs_input = 0; /* XXX fix this! */ - /* setup extra vp output */ - draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_FOG; + /* setup extra vp output (point coord implemented as a texcoord) */ + draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; draw->extra_vp_outputs.semantic_index = 0; draw->extra_vp_outputs.slot = draw->vs.num_vs_outputs; } -- cgit v1.2.3 From 1672e8e05996d48e51a1998bd7e9b08b78e012f5 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 18 Sep 2008 11:10:09 +0900 Subject: pipebuffer: New callback to flush all temporary-held buffers. Used mostly to aid debugging memory issues or to clean up resources when the drivers are long lived. --- .../auxiliary/pipebuffer/pb_buffer_malloc.c | 14 +++++++++--- src/gallium/auxiliary/pipebuffer/pb_bufmgr.h | 14 ++++++++---- src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c | 16 +++++++++++++ src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 11 ++++++--- src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c | 11 +++++++++ .../auxiliary/pipebuffer/pb_bufmgr_fenced.c | 14 ++++++++++++ src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c | 10 ++++++++- src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c | 8 +++++++ src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c | 26 ++++++++++++++++++++++ 9 files changed, 113 insertions(+), 11 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 20fc87b39d2..1bf22a2ec09 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -129,7 +129,7 @@ pb_malloc_buffer_create(size_t size, static struct pb_buffer * -pb_malloc_buffer_create_buffer(struct pb_manager *mgr, +pb_malloc_bufmgr_create_buffer(struct pb_manager *mgr, size_t size, const struct pb_desc *desc) { @@ -137,6 +137,13 @@ pb_malloc_buffer_create_buffer(struct pb_manager *mgr, } +static void +pb_malloc_bufmgr_flush(struct pb_manager *mgr) +{ + /* No-op */ +} + + static void pb_malloc_bufmgr_destroy(struct pb_manager *mgr) { @@ -146,8 +153,9 @@ pb_malloc_bufmgr_destroy(struct pb_manager *mgr) static struct pb_manager pb_malloc_bufmgr = { - pb_malloc_buffer_create_buffer, - pb_malloc_bufmgr_destroy + pb_malloc_bufmgr_destroy, + pb_malloc_bufmgr_create_buffer, + pb_malloc_bufmgr_flush }; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h index 32867029ee7..cafbee045ae 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr.h @@ -69,13 +69,22 @@ struct pipe_winsys; */ struct pb_manager { + void + (*destroy)( struct pb_manager *mgr ); + struct pb_buffer * (*create_buffer)( struct pb_manager *mgr, size_t size, const struct pb_desc *desc); + /** + * Flush all temporary-held buffers. + * + * Used mostly to aid debugging memory issues or to clean up resources when + * the drivers are long lived. + */ void - (*destroy)( struct pb_manager *mgr ); + (*flush)( struct pb_manager *mgr ); }; @@ -153,9 +162,6 @@ struct pb_manager * pb_cache_manager_create(struct pb_manager *provider, unsigned usecs); -void -pb_cache_flush(struct pb_manager *mgr); - /** * Fenced buffer manager. diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c index 2afaeafa1a1..c956924cc76 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_alt.c @@ -75,6 +75,21 @@ pb_alt_manager_create_buffer(struct pb_manager *_mgr, } +static void +pb_alt_manager_flush(struct pb_manager *_mgr) +{ + struct pb_alt_manager *mgr = pb_alt_manager(_mgr); + + assert(mgr->provider1->flush); + if(mgr->provider1->flush) + mgr->provider1->flush(mgr->provider1); + + assert(mgr->provider2->flush); + if(mgr->provider2->flush) + mgr->provider2->flush(mgr->provider2); +} + + static void pb_alt_manager_destroy(struct pb_manager *mgr) { @@ -97,6 +112,7 @@ pb_alt_manager_create(struct pb_manager *provider1, mgr->base.destroy = pb_alt_manager_destroy; mgr->base.create_buffer = pb_alt_manager_create_buffer; + mgr->base.flush = pb_alt_manager_flush; mgr->provider1 = provider1; mgr->provider2 = provider2; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 1ec422fb19e..8f118874ec3 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -306,8 +306,8 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr, } -void -pb_cache_flush(struct pb_manager *_mgr) +static void +pb_cache_manager_flush(struct pb_manager *_mgr) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); struct list_head *curr, *next; @@ -323,13 +323,17 @@ pb_cache_flush(struct pb_manager *_mgr) next = curr->next; } pipe_mutex_unlock(mgr->mutex); + + assert(mgr->provider->flush); + if(mgr->provider->flush) + mgr->provider->flush(mgr->provider); } static void pb_cache_manager_destroy(struct pb_manager *mgr) { - pb_cache_flush(mgr); + pb_cache_manager_flush(mgr); FREE(mgr); } @@ -349,6 +353,7 @@ pb_cache_manager_create(struct pb_manager *provider, mgr->base.destroy = pb_cache_manager_destroy; mgr->base.create_buffer = pb_cache_manager_create_buffer; + mgr->base.flush = pb_cache_manager_flush; mgr->provider = provider; mgr->usecs = usecs; LIST_INITHEAD(&mgr->delayed); diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c index 5f1ed3e5a8a..1675e6e1822 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_debug.c @@ -313,6 +313,16 @@ pb_debug_manager_create_buffer(struct pb_manager *_mgr, } +static void +pb_debug_manager_flush(struct pb_manager *_mgr) +{ + struct pb_debug_manager *mgr = pb_debug_manager(_mgr); + assert(mgr->provider->flush); + if(mgr->provider->flush) + mgr->provider->flush(mgr->provider); +} + + static void pb_debug_manager_destroy(struct pb_manager *_mgr) { @@ -336,6 +346,7 @@ pb_debug_manager_create(struct pb_manager *provider, size_t band_size) mgr->base.destroy = pb_debug_manager_destroy; mgr->base.create_buffer = pb_debug_manager_create_buffer; + mgr->base.flush = pb_debug_manager_flush; mgr->provider = provider; mgr->band_size = band_size; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c index 8fc63ce648c..633ee70a75b 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_fenced.c @@ -94,6 +94,19 @@ fenced_bufmgr_create_buffer(struct pb_manager *mgr, } +static void +fenced_bufmgr_flush(struct pb_manager *mgr) +{ + struct fenced_pb_manager *fenced_mgr = fenced_pb_manager(mgr); + + fenced_buffer_list_check_free(fenced_mgr->fenced_list, TRUE); + + assert(fenced_mgr->provider->flush); + if(fenced_mgr->provider->flush) + fenced_mgr->provider->flush(fenced_mgr->provider); +} + + static void fenced_bufmgr_destroy(struct pb_manager *mgr) { @@ -123,6 +136,7 @@ fenced_bufmgr_create(struct pb_manager *provider, fenced_mgr->base.destroy = fenced_bufmgr_destroy; fenced_mgr->base.create_buffer = fenced_bufmgr_create_buffer; + fenced_mgr->base.flush = fenced_bufmgr_flush; fenced_mgr->provider = provider; fenced_mgr->fenced_list = fenced_buffer_list_create(winsys); diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c index e8c7f8e1f82..fe80ca30eea 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_mm.c @@ -199,6 +199,13 @@ mm_bufmgr_create_buffer(struct pb_manager *mgr, } +static void +mm_bufmgr_flush(struct pb_manager *mgr) +{ + /* No-op */ +} + + static void mm_bufmgr_destroy(struct pb_manager *mgr) { @@ -230,8 +237,9 @@ mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, if (!mm) return NULL; - mm->base.create_buffer = mm_bufmgr_create_buffer; mm->base.destroy = mm_bufmgr_destroy; + mm->base.create_buffer = mm_bufmgr_create_buffer; + mm->base.flush = mm_bufmgr_flush; mm->size = size; mm->align2 = align2; /* 64-byte alignment */ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c index 3ef72c5bbb3..61ac291ed77 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_pool.c @@ -202,6 +202,13 @@ pool_bufmgr_create_buffer(struct pb_manager *mgr, } +static void +pool_bufmgr_flush(struct pb_manager *mgr) +{ + /* No-op */ +} + + static void pool_bufmgr_destroy(struct pb_manager *mgr) { @@ -238,6 +245,7 @@ pool_bufmgr_create(struct pb_manager *provider, pool->base.destroy = pool_bufmgr_destroy; pool->base.create_buffer = pool_bufmgr_create_buffer; + pool->base.flush = pool_bufmgr_flush; LIST_INITHEAD(&pool->free); diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 8698c4cff62..2a801549202 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -406,6 +406,17 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, } +static void +pb_slab_manager_flush(struct pb_manager *_mgr) +{ + struct pb_slab_manager *mgr = pb_slab_manager(_mgr); + + assert(mgr->provider->flush); + if(mgr->provider->flush) + mgr->provider->flush(mgr->provider); +} + + static void pb_slab_manager_destroy(struct pb_manager *_mgr) { @@ -430,6 +441,7 @@ pb_slab_manager_create(struct pb_manager *provider, mgr->base.destroy = pb_slab_manager_destroy; mgr->base.create_buffer = pb_slab_manager_create_buffer; + mgr->base.flush = pb_slab_manager_flush; mgr->provider = provider; mgr->bufSize = bufSize; @@ -465,6 +477,19 @@ pb_slab_range_manager_create_buffer(struct pb_manager *_mgr, } +static void +pb_slab_range_manager_flush(struct pb_manager *_mgr) +{ + struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr); + + /* Individual slabs don't hold any temporary buffers so no need to call them */ + + assert(mgr->provider->flush); + if(mgr->provider->flush) + mgr->provider->flush(mgr->provider); +} + + static void pb_slab_range_manager_destroy(struct pb_manager *_mgr) { @@ -499,6 +524,7 @@ pb_slab_range_manager_create(struct pb_manager *provider, mgr->base.destroy = pb_slab_range_manager_destroy; mgr->base.create_buffer = pb_slab_range_manager_create_buffer; + mgr->base.flush = pb_slab_range_manager_flush; mgr->provider = provider; mgr->minBufSize = minBufSize; -- cgit v1.2.3 From f8bba34d4e12ef4c620cac881a4b697a1e668377 Mon Sep 17 00:00:00 2001 From: Robert Ellison Date: Thu, 18 Sep 2008 01:29:41 -0600 Subject: CELL: finish fragment ops blending (except for unusual D3D modes) - Added new "macro" functions spe_float_min() and spe_float_max() to rtasm_ppc_spe.{ch}. These emit instructions that cause the minimum or maximum of each element in a vector of floats to be saved in the destination register. - Major changes to cell_gen_fragment.c to implement all the blending modes (except for the mysterious D3D-based PIPE_BLENDFACTOR_SRC1_COLOR, PIPE_BLENDFACTOR_SRC1_ALPHA, PIPE_BLENDFACTOR_INV_SRC1_COLOR, and PIPE_BLENDFACTOR_INV_SRC1_ALPHA). - Some revamping of code in cell_gen_fragment.c: use the new spe_float_min() and spe_float_max() functions (instead of expanding these calculations inline via macros); create and use an inline utility function for handling "optional" register allocation (for the {1,1,1,1} vector, and the blend color vectors) instead of expanding with macros; use the Float Multiply and Subtract (fnms) instruction to simplify and optimize many blending calculations. --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 41 +- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 8 + src/gallium/drivers/cell/ppu/cell_gen_fragment.c | 546 ++++++++++++++--------- 3 files changed, 377 insertions(+), 218 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 870ae802c52..12e0826fb9b 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -384,7 +384,7 @@ void spe_release_func(struct spe_function *p) /** - * Alloate a SPE register. + * Allocate a SPE register. * \return register index or -1 if none left. */ int spe_allocate_available_register(struct spe_function *p) @@ -646,5 +646,44 @@ spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) } } +/* For each 32-bit float element of rA and rB, choose the smaller of the + * two, compositing them into the rT register. + * + * The Float Compare Greater Than (fcgt) instruction will put 1s into + * compare_reg where rA > rB, and 0s where rA <= rB. + * + * Then the Select Bits (selb) instruction will take bits from rA where + * compare_reg is 0, and from rB where compare_reg is 1; i.e., from rA + * where rA <= rB and from rB where rB > rA, which is exactly the + * "min" operation. + * + * The compare_reg could in many cases be the same as rT, unless + * rT == rA || rt == rB. But since this is common in constructions + * like "x = min(x, a)", we always allocate a new register to be safe. + */ +void +spe_float_min(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned int rB) +{ + unsigned int compare_reg = spe_allocate_available_register(p); + spe_fcgt(p, compare_reg, rA, rB); + spe_selb(p, rT, rA, rB, compare_reg); + spe_release_register(p, compare_reg); +} + +/* For each 32-bit float element of rA and rB, choose the greater of the + * two, compositing them into the rT register. + * + * The logic is similar to that of spe_float_min() above; the only + * difference is that the registers on spe_selb() have been reversed, + * so that the larger of the two is selected instead of the smaller. + */ +void +spe_float_max(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned int rB) +{ + unsigned int compare_reg = spe_allocate_available_register(p); + spe_fcgt(p, compare_reg, rA, rB); + spe_selb(p, rT, rB, rA, compare_reg); + spe_release_register(p, compare_reg); +} #endif /* GALLIUM_CELL */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 25790452325..4ef05ea27d1 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -322,6 +322,14 @@ spe_zero(struct spe_function *p, unsigned rT); extern void spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word); +/** rT = float min(rA, rB) */ +extern void +spe_float_min(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB); + +/** rT = float max(rA, rB) */ +extern void +spe_float_max(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB); + /* Floating-point instructions */ diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 2c80dd712e6..9d25e820ad9 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -229,35 +229,26 @@ gen_alpha_test(const struct pipe_depth_stencil_alpha_state *dsa, spe_release_register(f, amask_reg); } -/* This is a convenient and oft-used sequence. It chooses - * the smaller of each element of reg1 and reg2, and combines them - * into the result register, as follows: - * - * The Float Compare Greater Than (fcgt) instruction will put - * 1s into compare_reg where reg1 > reg2, and 0s where reg1 <= reg2. - * - * Then the Select Bits (selb) instruction will take bits from - * reg1 where compare_reg is 0, and from reg2 where compare_reg is - * 1. Ergo, result_reg will have the bits from reg1 where reg1 <= reg2, - * and the bits from reg2 where reg1 > reg2, which is exactly the - * MIN operation. +/* This pair of functions is used inline to allocate and deallocate + * optional constant registers. Once a constant is discovered to be + * needed, we will likely need it again, so we don't want to deallocate + * it and have to allocate and load it again unnecessarily. */ -#define FLOAT_VECTOR_MIN(f, result_reg, reg1, reg2) {\ - int compare_reg = spe_allocate_available_register(f); \ - spe_fcgt(f, compare_reg, reg1, reg2); \ - spe_selb(f, result_reg, reg1, reg2, compare_reg); \ - spe_release_register(f, compare_reg); \ +static inline void +setup_const_register(struct spe_function *f, boolean *is_already_set, unsigned int *r, float value) +{ + if (*is_already_set) return; + *r = spe_allocate_available_register(f); + spe_load_float(f, *r, value); + *is_already_set = true; } -/* The FLOAT_VECTOR_MAX sequence is similar to the FLOAT_VECTOR_MIN - * sequence above, except that the registers specified when selecting - * bits are reversed. - */ -#define FLOAT_VECTOR_MAX(f, result_reg, reg1, reg2) {\ - int compare_reg = spe_allocate_available_register(f); \ - spe_fcgt(f, compare_reg, reg1, reg2); \ - spe_selb(f, result_reg, reg2, reg1, compare_reg); \ - spe_release_register(f, compare_reg); \ +static inline void +release_const_register(struct spe_function *f, boolean *is_already_set, unsigned int r) +{ + if (!*is_already_set) return; + spe_release_register(f, r); + *is_already_set = false; } /** @@ -294,51 +285,15 @@ gen_blend(const struct pipe_blend_state *blend, int tmp_reg = spe_allocate_available_register(f); - /* These values might or might not eventually get put into - * registers. We avoid allocating them and setting them until - * they're actually needed; then we avoid setting them more than - * once, and release them at the end of code generation. + /* Optional constant registers we might or might not end up using; + * if we do use them, make sure we only allocate them once by + * keeping a flag on each one. */ - boolean one_reg_set = false; - int one_reg; -#define SET_ONE_REG_IF_UNSET(f) if (!one_reg_set) {\ - one_reg = spe_allocate_available_register(f); \ - spe_load_float(f, one_reg, 1.0f); \ - one_reg_set = true; \ -} -#define RELEASE_ONE_REG_IF_USED(f) if (one_reg_set) {\ - spe_release_register(f, one_reg); \ -} - - boolean const_color_set = false; - int constR_reg, constG_reg, constB_reg; -#define SET_CONST_COLOR_IF_UNSET(f, blend_color) if (!const_color_set) {\ - constR_reg = spe_allocate_available_register(f); \ - constG_reg = spe_allocate_available_register(f); \ - constG_reg = spe_allocate_available_register(f); \ - spe_load_float(f, constR_reg, blend_color->color[0]); \ - spe_load_float(f, constG_reg, blend_color->color[1]); \ - spe_load_float(f, constB_reg, blend_color->color[2]); \ - const_color_set = true;\ -} -#define RELEASE_CONST_COLOR_IF_USED(f) if (const_color_set) {\ - spe_release_register(f, constR_reg); \ - spe_release_register(f, constG_reg); \ - spe_release_register(f, constB_reg); \ -} - - boolean const_alpha_set = false; - int constA_reg; -#define SET_CONST_ALPHA_IF_UNSET(f, blend_color) if (!const_alpha_set) {\ - constA_reg = spe_allocate_available_register(f); \ - spe_load_float(f, constA_reg, blend_color->color[3]); \ - const_alpha_set = true; \ -} -#define RELEASE_CONST_ALPHA_IF_USED(f) if (const_alpha_set) {\ - spe_release_register(f, constA_reg); \ -} - - /* Real code starts here */ + boolean one_reg_set = false; + unsigned int one_reg; + boolean constR_reg_set = false, constG_reg_set = false, + constB_reg_set = false, constA_reg_set = false; + unsigned int constR_reg, constG_reg, constB_reg, constA_reg; ASSERT(blend->blend_enable); @@ -419,10 +374,11 @@ gen_blend(const struct pipe_blend_state *blend, spe_release_register(f, mask_reg); } - /* * Compute Src RGB terms. We're actually looking for the value - * of (the appropriate RGB factors) * (the incoming source RGB color). + * of (the appropriate RGB factors) * (the incoming source RGB color), + * because in some cases (like PIPE_BLENDFACTOR_ONE and + * PIPE_BLENDFACTOR_ZERO) we can avoid doing unnecessary math. */ switch (blend->rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: @@ -450,18 +406,13 @@ gen_blend(const struct pipe_blend_state *blend, spe_fm(f, term1B_reg, fragB_reg, fragA_reg); break; case PIPE_BLENDFACTOR_INV_SRC_COLOR: - /* factors = (1-R,1-G,1-B), so term = (R*(1-R), G*(1-G), B*(1-B)) */ - /* we'll need the optional constant {1,1,1,1} register */ - SET_ONE_REG_IF_UNSET(f) - /* tmp = 1 - R */ - spe_fs(f, tmp_reg, one_reg, fragR_reg); - /* term = R * tmp */ - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - /* repeat for G and B */ - spe_fs(f, tmp_reg, one_reg, fragG_reg); - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fs(f, tmp_reg, one_reg, fragB_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + /* factors = (1-R,1-G,1-B), so term = (R*(1-R), G*(1-G), B*(1-B)) + * or in other words term = (R-R*R, G-G*G, B-B*B) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term1R_reg, fragR_reg, fragR_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, fragG_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, fragB_reg, fragB_reg); break; case PIPE_BLENDFACTOR_DST_COLOR: /* factors = (Rfb,Gfb,Bfb), so term = (R*Rfb, G*Gfb, B*Bfb) */ @@ -470,30 +421,22 @@ gen_blend(const struct pipe_blend_state *blend, spe_fm(f, term1B_reg, fragB_reg, fbB_reg); break; case PIPE_BLENDFACTOR_INV_DST_COLOR: - /* factors = (1-Rfb,1-Gfb,1-Bfb), so term = (R*(1-Rfb),G*(1-Gfb),B*(1-Bfb)) */ - /* we'll need the optional constant {1,1,1,1} register */ - SET_ONE_REG_IF_UNSET(f) - /* tmp = 1 - Rfb */ - spe_fs(f, tmp_reg, one_reg, fbR_reg); - /* term = R * tmp */ - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - /* repeat for G and B */ - spe_fs(f, tmp_reg, one_reg, fbG_reg); - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fs(f, tmp_reg, one_reg, fbB_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + /* factors = (1-Rfb,1-Gfb,1-Bfb), so term = (R*(1-Rfb),G*(1-Gfb),B*(1-Bfb)) + * or term = (R-R*Rfb, G-G*Gfb, B-B*Bfb) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term1R_reg, fragR_reg, fbR_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, fbG_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, fbB_reg, fragB_reg); break; case PIPE_BLENDFACTOR_INV_SRC_ALPHA: - /* factors = (1-A,1-A,1-A), so term = (R*(1-A),G*(1-A),B*(1-A)) */ - /* we'll need the optional constant {1,1,1,1} register */ - SET_ONE_REG_IF_UNSET(f) - /* tmp = 1 - A */ - spe_fs(f, tmp_reg, one_reg, fragA_reg); - /* term = R * tmp */ - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - /* repeat for G and B with the same (1-A) factor */ - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + /* factors = (1-A,1-A,1-A), so term = (R*(1-A),G*(1-A),B*(1-A)) + * or term = (R-R*A,G-G*A,B-B*A) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term1R_reg, fragR_reg, fragA_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, fragA_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, fragA_reg, fragB_reg); break; case PIPE_BLENDFACTOR_DST_ALPHA: /* factors = (Afb, Afb, Afb), so term = (R*Afb, G*Afb, B*Afb) */ @@ -502,19 +445,19 @@ gen_blend(const struct pipe_blend_state *blend, spe_fm(f, term1B_reg, fragB_reg, fbA_reg); break; case PIPE_BLENDFACTOR_INV_DST_ALPHA: - /* factors = (1-Afb, 1-Afb, 1-Afb), so term = (R*(1-Afb),G*(1-Afb),B*(1-Afb)) */ - /* we'll need the optional constant {1,1,1,1} register */ - SET_ONE_REG_IF_UNSET(f) - /* tmp = 1 - A */ - spe_fs(f, tmp_reg, one_reg, fbA_reg); - /* term = R * tmp, G*tmp, and B*tmp */ - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + /* factors = (1-Afb, 1-Afb, 1-Afb), so term = (R*(1-Afb),G*(1-Afb),B*(1-Afb)) + * or term = (R-R*Afb,G-G*Afb,b-B*Afb) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term1R_reg, fragR_reg, fbA_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, fbA_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, fbA_reg, fragB_reg); break; case PIPE_BLENDFACTOR_CONST_COLOR: - /* We'll need the optional blend color registers */ - SET_CONST_COLOR_IF_UNSET(f,blend_color) + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); /* now, factor = (Rc,Gc,Bc), so term = (R*Rc,G*Gc,B*Bc) */ spe_fm(f, term1R_reg, fragR_reg, constR_reg); spe_fm(f, term1G_reg, fragG_reg, constG_reg); @@ -522,55 +465,61 @@ gen_blend(const struct pipe_blend_state *blend, break; case PIPE_BLENDFACTOR_CONST_ALPHA: /* we'll need the optional constant alpha register */ - SET_CONST_ALPHA_IF_UNSET(f, blend_color) + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); /* factor = (Ac,Ac,Ac), so term = (R*Ac,G*Ac,B*Ac) */ spe_fm(f, term1R_reg, fragR_reg, constA_reg); spe_fm(f, term1G_reg, fragG_reg, constA_reg); spe_fm(f, term1B_reg, fragB_reg, constA_reg); break; case PIPE_BLENDFACTOR_INV_CONST_COLOR: - /* We need both the optional {1,1,1,1} register, and the optional - * constant color registers + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + /* factor = (1-Rc,1-Gc,1-Bc), so term = (R*(1-Rc),G*(1-Gc),B*(1-Bc)) + * or term = (R-R*Rc, G-G*Gc, B-B*Bc) + * fnms(a,b,c,d) computes a = d - b*c */ - SET_ONE_REG_IF_UNSET(f) - SET_CONST_COLOR_IF_UNSET(f, blend_color) - /* factor = (1-Rc,1-Gc,1-Bc), so term = (R*(1-Rc),G*(1-Gc),B*(1-Bc)) */ - spe_fs(f, tmp_reg, one_reg, constR_reg); - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - spe_fs(f, tmp_reg, one_reg, constG_reg); - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fs(f, tmp_reg, one_reg, constB_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + spe_fnms(f, term1R_reg, fragR_reg, constR_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, constG_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, constB_reg, fragB_reg); break; case PIPE_BLENDFACTOR_INV_CONST_ALPHA: - /* We need the optional {1,1,1,1} register and the optional - * constant alpha register + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + /* factor = (1-Ac,1-Ac,1-Ac), so term = (R*(1-Ac),G*(1-Ac),B*(1-Ac)) + * or term = (R-R*Ac,G-G*Ac,B-B*Ac) + * fnms(a,b,c,d) computes a = d - b*c */ - SET_ONE_REG_IF_UNSET(f) - SET_CONST_ALPHA_IF_UNSET(f, blend_color) - /* factor = (1-Ac,1-Ac,1-Ac), so term = (R*(1-Ac),G*(1-Ac),B*(1-Ac)) */ - spe_fs(f, tmp_reg, one_reg, constA_reg); - spe_fm(f, term1R_reg, fragR_reg, tmp_reg); - spe_fm(f, term1G_reg, fragG_reg, tmp_reg); - spe_fm(f, term1B_reg, fragB_reg, tmp_reg); + spe_fnms(f, term1R_reg, fragR_reg, constA_reg, fragR_reg); + spe_fnms(f, term1G_reg, fragG_reg, constA_reg, fragG_reg); + spe_fnms(f, term1B_reg, fragB_reg, constA_reg, fragB_reg); break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* We'll need the optional {1,1,1,1} register */ - SET_ONE_REG_IF_UNSET(f) + setup_const_register(f, &one_reg_set, &one_reg, 1.0f); /* factor = (min(A,1-Afb),min(A,1-Afb),min(A,1-Afb)), so * term = (R*min(A,1-Afb), G*min(A,1-Afb), B*min(A,1-Afb)) + * We could expand the term (as a*min(b,c) == min(a*b,a*c) + * as long as a is positive), but then we'd have to do three + * spe_float_min() functions instead of one, so this is simpler. */ /* tmp = 1 - Afb */ spe_fs(f, tmp_reg, one_reg, fbA_reg); /* tmp = min(A,tmp) */ - FLOAT_VECTOR_MIN(f, tmp_reg, fragA_reg, tmp_reg) + spe_float_min(f, tmp_reg, fragA_reg, tmp_reg); /* term = R*tmp */ spe_fm(f, term1R_reg, fragR_reg, tmp_reg); spe_fm(f, term1G_reg, fragG_reg, tmp_reg); spe_fm(f, term1B_reg, fragB_reg, tmp_reg); break; - /* non-OpenGL cases? */ + /* These are special D3D cases involving a second color output + * from the fragment shader. I'm not sure we can support them + * yet... XXX + */ case PIPE_BLENDFACTOR_SRC1_COLOR: case PIPE_BLENDFACTOR_SRC1_ALPHA: case PIPE_BLENDFACTOR_INV_SRC1_COLOR: @@ -581,132 +530,293 @@ gen_blend(const struct pipe_blend_state *blend, } /* - * Compute Src Alpha term + * Compute Src Alpha term. Like the above, we're looking for + * the full term A*factor, not just the factor itself, because + * in many cases we can avoid doing unnecessary multiplies. */ switch (blend->alpha_src_factor) { + case PIPE_BLENDFACTOR_ZERO: + /* factor = 0, so term = 0 */ + spe_load_float(f, term1A_reg, 0.0f); + break; + + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* fall through */ case PIPE_BLENDFACTOR_ONE: + /* factor = 1, so term = A */ spe_move(f, term1A_reg, fragA_reg); break; + case PIPE_BLENDFACTOR_SRC_COLOR: + /* factor = A, so term = A*A */ spe_fm(f, term1A_reg, fragA_reg, fragA_reg); break; case PIPE_BLENDFACTOR_SRC_ALPHA: spe_fm(f, term1A_reg, fragA_reg, fragA_reg); break; - /* XXX more cases */ + + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + /* factor = 1-A, so term = A*(1-A) = A-A*A */ + /* fnms(a,b,c,d) computes a = d - b*c */ + spe_fnms(f, term1A_reg, fragA_reg, fragA_reg, fragA_reg); + break; + + case PIPE_BLENDFACTOR_DST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_DST_COLOR: + /* factor = Afb, so term = A*Afb */ + spe_fm(f, term1A_reg, fragA_reg, fbA_reg); + break; + + case PIPE_BLENDFACTOR_INV_DST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_DST_COLOR: + /* factor = 1-Afb, so term = A*(1-Afb) = A - A*Afb */ + /* fnms(a,b,c,d) computes a = d - b*c */ + spe_fnms(f, term1A_reg, fragA_reg, fbA_reg, fragA_reg); + break; + + case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_CONST_COLOR: + /* We need the optional constA_reg register */ + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + /* factor = Ac, so term = A*Ac */ + spe_fm(f, term1A_reg, fragA_reg, constA_reg); + break; + + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + /* We need the optional constA_reg register */ + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + /* factor = 1-Ac, so term = A*(1-Ac) = A-A*Ac */ + /* fnms(a,b,c,d) computes a = d - b*c */ + spe_fnms(f, term1A_reg, fragA_reg, constA_reg, fragA_reg); + break; + + /* These are special D3D cases involving a second color output + * from the fragment shader. I'm not sure we can support them + * yet... XXX + */ + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: default: ASSERT(0); } /* - * Compute Dest RGB terms + * Compute Dest RGB term. Like the above, we're looking for + * the full term (Rfb,Gfb,Bfb)*(factor), not just the factor itself, because + * in many cases we can avoid doing unnecessary multiplies. */ switch (blend->rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: + /* factors = (1,1,1), so term = (Rfb,Gfb,Bfb) */ spe_move(f, term2R_reg, fbR_reg); spe_move(f, term2G_reg, fbG_reg); spe_move(f, term2B_reg, fbB_reg); break; case PIPE_BLENDFACTOR_ZERO: - spe_zero(f, term2R_reg); - spe_zero(f, term2G_reg); - spe_zero(f, term2B_reg); + /* factor s= (0,0,0), so term = (0,0,0) */ + spe_load_float(f, term2R_reg, 0.0f); + spe_load_float(f, term2G_reg, 0.0f); + spe_load_float(f, term2B_reg, 0.0f); break; case PIPE_BLENDFACTOR_SRC_COLOR: + /* factors = (R,G,B), so term = (R*Rfb, G*Gfb, B*Bfb) */ spe_fm(f, term2R_reg, fbR_reg, fragR_reg); spe_fm(f, term2G_reg, fbG_reg, fragG_reg); spe_fm(f, term2B_reg, fbB_reg, fragB_reg); break; + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + /* factors = (1-R,1-G,1-B), so term = (Rfb*(1-R), Gfb*(1-G), Bfb*(1-B)) + * or in other words term = (Rfb-Rfb*R, Gfb-Gfb*G, Bfb-Bfb*B) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term2R_reg, fragR_reg, fbR_reg, fbR_reg); + spe_fnms(f, term2G_reg, fragG_reg, fbG_reg, fbG_reg); + spe_fnms(f, term2B_reg, fragB_reg, fbB_reg, fbB_reg); + break; case PIPE_BLENDFACTOR_SRC_ALPHA: + /* factors = (A,A,A), so term = (Rfb*A, Gfb*A, Bfb*A) */ spe_fm(f, term2R_reg, fbR_reg, fragA_reg); spe_fm(f, term2G_reg, fbG_reg, fragA_reg); spe_fm(f, term2B_reg, fbB_reg, fragA_reg); break; case PIPE_BLENDFACTOR_INV_SRC_ALPHA: -#if 0 - /* one = {1.0, 1.0, 1.0, 1.0} */ - if (!one_reg_set) { - one_reg = spe_allocate_available_register(f); - spe_load_float(f, one_reg, 1.0f); - one_reg_set = true; - } - /* tmp = one - fragA */ - spe_fs(f, tmp_reg, one_reg, fragA_reg); - /* term = fb * tmp */ - spe_fm(f, term2R_reg, fbR_reg, tmp_reg); - spe_fm(f, term2G_reg, fbG_reg, tmp_reg); - spe_fm(f, term2B_reg, fbB_reg, tmp_reg); -#else - /* Compute: term2x = fbx * (1.0 - fragA) - * Which is: term2x = fbx - fbx * fragA - * Use fnms t,a,b,c which computes t=c-a*b - */ + /* factors = (1-A,1-A,1-A) so term = (Rfb-Rfb*A,Gfb-Gfb*A,Bfb-Bfb*A) */ + /* fnms(a,b,c,d) computes a = d - b*c */ spe_fnms(f, term2R_reg, fbR_reg, fragA_reg, fbR_reg); spe_fnms(f, term2G_reg, fbG_reg, fragA_reg, fbG_reg); spe_fnms(f, term2B_reg, fbB_reg, fragA_reg, fbB_reg); -#endif break; - /* XXX more cases */ - // GL_ONE_MINUS_SRC_COLOR - // GL_DST_COLOR - // GL_ONE_MINUS_DST_COLOR - // GL_DST_ALPHA - // GL_CONSTANT_COLOR - // GL_ONE_MINUS_CONSTANT_COLOR - // GL_CONSTANT_ALPHA - // GL_ONE_MINUS_CONSTANT_ALPHA + case PIPE_BLENDFACTOR_DST_COLOR: + /* factors = (Rfb,Gfb,Bfb), so term = (Rfb*Rfb, Gfb*Gfb, Bfb*Bfb) */ + spe_fm(f, term2R_reg, fbR_reg, fbR_reg); + spe_fm(f, term2G_reg, fbG_reg, fbG_reg); + spe_fm(f, term2B_reg, fbB_reg, fbB_reg); + break; + case PIPE_BLENDFACTOR_INV_DST_COLOR: + /* factors = (1-Rfb,1-Gfb,1-Bfb), so term = (Rfb*(1-Rfb),Gfb*(1-Gfb),Bfb*(1-Bfb)) + * or term = (Rfb-Rfb*Rfb, Gfb-Gfb*Gfb, Bfb-Bfb*Bfb) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term2R_reg, fbR_reg, fbR_reg, fbR_reg); + spe_fnms(f, term2G_reg, fbG_reg, fbG_reg, fbG_reg); + spe_fnms(f, term2B_reg, fbB_reg, fbB_reg, fbB_reg); + break; + + case PIPE_BLENDFACTOR_DST_ALPHA: + /* factors = (Afb, Afb, Afb), so term = (Rfb*Afb, Gfb*Afb, Bfb*Afb) */ + spe_fm(f, term2R_reg, fbR_reg, fbA_reg); + spe_fm(f, term2G_reg, fbG_reg, fbA_reg); + spe_fm(f, term2B_reg, fbB_reg, fbA_reg); + break; + case PIPE_BLENDFACTOR_INV_DST_ALPHA: + /* factors = (1-Afb, 1-Afb, 1-Afb), so term = (Rfb*(1-Afb),Gfb*(1-Afb),Bfb*(1-Afb)) + * or term = (Rfb-Rfb*Afb,Gfb-Gfb*Afb,Bfb-Bfb*Afb) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term2R_reg, fbR_reg, fbA_reg, fbR_reg); + spe_fnms(f, term2G_reg, fbG_reg, fbA_reg, fbG_reg); + spe_fnms(f, term2B_reg, fbB_reg, fbA_reg, fbB_reg); + break; + case PIPE_BLENDFACTOR_CONST_COLOR: + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + /* now, factor = (Rc,Gc,Bc), so term = (Rfb*Rc,Gfb*Gc,Bfb*Bc) */ + spe_fm(f, term2R_reg, fbR_reg, constR_reg); + spe_fm(f, term2G_reg, fbG_reg, constG_reg); + spe_fm(f, term2B_reg, fbB_reg, constB_reg); + break; + case PIPE_BLENDFACTOR_CONST_ALPHA: + /* we'll need the optional constant alpha register */ + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + /* factor = (Ac,Ac,Ac), so term = (Rfb*Ac,Gfb*Ac,Bfb*Ac) */ + spe_fm(f, term2R_reg, fbR_reg, constA_reg); + spe_fm(f, term2G_reg, fbG_reg, constA_reg); + spe_fm(f, term2B_reg, fbB_reg, constA_reg); + break; + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + /* factor = (1-Rc,1-Gc,1-Bc), so term = (Rfb*(1-Rc),Gfb*(1-Gc),Bfb*(1-Bc)) + * or term = (Rfb-Rfb*Rc, Gfb-Gfb*Gc, Bfb-Bfb*Bc) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term2R_reg, fbR_reg, constR_reg, fbR_reg); + spe_fnms(f, term2G_reg, fbG_reg, constG_reg, fbG_reg); + spe_fnms(f, term2B_reg, fbB_reg, constB_reg, fbB_reg); + break; + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: + /* We need the optional constant color registers */ + setup_const_register(f, &constR_reg_set, &constR_reg, blend_color->color[0]); + setup_const_register(f, &constG_reg_set, &constG_reg, blend_color->color[1]); + setup_const_register(f, &constB_reg_set, &constB_reg, blend_color->color[2]); + /* factor = (1-Ac,1-Ac,1-Ac), so term = (Rfb*(1-Ac),Gfb*(1-Ac),Bfb*(1-Ac)) + * or term = (Rfb-Rfb*Ac,Gfb-Gfb*Ac,Bfb-Bfb*Ac) + * fnms(a,b,c,d) computes a = d - b*c + */ + spe_fnms(f, term2R_reg, fbR_reg, constA_reg, fbR_reg); + spe_fnms(f, term2G_reg, fbG_reg, constA_reg, fbG_reg); + spe_fnms(f, term2B_reg, fbB_reg, constA_reg, fbB_reg); + break; + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* not supported for dest RGB */ + ASSERT(0); + break; + + /* These are special D3D cases involving a second color output + * from the fragment shader. I'm not sure we can support them + * yet... XXX + */ + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: + default: ASSERT(0); } /* - * Compute Dest Alpha term + * Compute Dest Alpha term. Like the above, we're looking for + * the full term Afb*factor, not just the factor itself, because + * in many cases we can avoid doing unnecessary multiplies. */ switch (blend->alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: + /* factor = 1, so term = Afb */ spe_move(f, term2A_reg, fbA_reg); break; case PIPE_BLENDFACTOR_ZERO: - spe_zero(f, term2A_reg); + /* factor = 0, so term = 0 */ + spe_load_float(f, term2A_reg, 0.0f); break; - case PIPE_BLENDFACTOR_SRC_ALPHA: + + case PIPE_BLENDFACTOR_SRC_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_SRC_COLOR: + /* factor = A, so term = Afb*A */ spe_fm(f, term2A_reg, fbA_reg, fragA_reg); break; - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: -#if 0 - /* one = {1.0, 1.0, 1.0, 1.0} */ - if (!one_reg_set) { - one_reg = spe_allocate_available_register(f); - spe_load_float(f, one_reg, 1.0f); - one_reg_set = true; - } - /* tmp = one - fragA */ - spe_fs(f, tmp_reg, one_reg, fragA_reg); - /* termA = fbA * tmp */ - spe_fm(f, term2A_reg, fbA_reg, tmp_reg); -#else - /* Compute: term2A = fbA * (1.0 - fragA) - * Which is: term2A = fbA - fbA * fragA - * Use fnms t,a,b,c which computes t=c-a*b - */ + + case PIPE_BLENDFACTOR_INV_SRC_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_SRC_COLOR: + /* factor = 1-A, so term = Afb*(1-A) = Afb-Afb*A */ + /* fnms(a,b,c,d) computes a = d - b*c */ spe_fnms(f, term2A_reg, fbA_reg, fragA_reg, fbA_reg); -#endif break; - /* XXX more cases */ - // GL_ONE_MINUS_SRC_COLOR - // GL_DST_COLOR - // GL_ONE_MINUS_DST_COLOR - // GL_DST_ALPHA - // GL_CONSTANT_COLOR - // GL_ONE_MINUS_CONSTANT_COLOR - // GL_CONSTANT_ALPHA - // GL_ONE_MINUS_CONSTANT_ALPHA + + case PIPE_BLENDFACTOR_DST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_DST_COLOR: + /* factor = Afb, so term = Afb*Afb */ + spe_fm(f, term2A_reg, fbA_reg, fbA_reg); + break; + + case PIPE_BLENDFACTOR_INV_DST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_DST_COLOR: + /* factor = 1-Afb, so term = Afb*(1-Afb) = Afb - Afb*Afb */ + /* fnms(a,b,c,d) computes a = d - b*c */ + spe_fnms(f, term2A_reg, fbA_reg, fbA_reg, fbA_reg); + break; + + case PIPE_BLENDFACTOR_CONST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_CONST_COLOR: + /* We need the optional constA_reg register */ + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + /* factor = Ac, so term = Afb*Ac */ + spe_fm(f, term2A_reg, fbA_reg, constA_reg); + break; + + case PIPE_BLENDFACTOR_INV_CONST_ALPHA: /* fall through */ + case PIPE_BLENDFACTOR_INV_CONST_COLOR: + /* We need the optional constA_reg register */ + setup_const_register(f, &constA_reg_set, &constA_reg, blend_color->color[3]); + /* factor = 1-Ac, so term = Afb*(1-Ac) = Afb-Afb*Ac */ + /* fnms(a,b,c,d) computes a = d - b*c */ + spe_fnms(f, term2A_reg, fbA_reg, constA_reg, fbA_reg); + break; + + case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* not supported for dest alpha */ + ASSERT(0); + break; + + /* These are special D3D cases involving a second color output + * from the fragment shader. I'm not sure we can support them + * yet... XXX + */ + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: + case PIPE_BLENDFACTOR_INV_SRC1_COLOR: + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: default: ASSERT(0); } /* - * Combine Src/Dest RGB terms + * Combine Src/Dest RGB terms as per the blend equation. */ switch (blend->rgb_func) { case PIPE_BLEND_ADD: @@ -725,14 +835,14 @@ gen_blend(const struct pipe_blend_state *blend, spe_fs(f, fragB_reg, term2B_reg, term1B_reg); break; case PIPE_BLEND_MIN: - FLOAT_VECTOR_MIN(f, fragR_reg, term1R_reg, term2R_reg) - FLOAT_VECTOR_MIN(f, fragG_reg, term1G_reg, term2G_reg) - FLOAT_VECTOR_MIN(f, fragB_reg, term1B_reg, term2B_reg) + spe_float_min(f, fragR_reg, term1R_reg, term2R_reg); + spe_float_min(f, fragG_reg, term1G_reg, term2G_reg); + spe_float_min(f, fragB_reg, term1B_reg, term2B_reg); break; case PIPE_BLEND_MAX: - FLOAT_VECTOR_MAX(f, fragR_reg, term1R_reg, term2R_reg) - FLOAT_VECTOR_MAX(f, fragG_reg, term1G_reg, term2G_reg) - FLOAT_VECTOR_MAX(f, fragB_reg, term1B_reg, term2B_reg) + spe_float_max(f, fragR_reg, term1R_reg, term2R_reg); + spe_float_max(f, fragG_reg, term1G_reg, term2G_reg); + spe_float_max(f, fragB_reg, term1B_reg, term2B_reg); break; default: ASSERT(0); @@ -752,10 +862,10 @@ gen_blend(const struct pipe_blend_state *blend, spe_fs(f, fragA_reg, term2A_reg, term1A_reg); break; case PIPE_BLEND_MIN: - FLOAT_VECTOR_MIN(f, fragA_reg, term1A_reg, term2A_reg) + spe_float_min(f, fragA_reg, term1A_reg, term2A_reg); break; case PIPE_BLEND_MAX: - FLOAT_VECTOR_MAX(f, fragA_reg, term1A_reg, term2A_reg) + spe_float_max(f, fragA_reg, term1A_reg, term2A_reg); break; default: ASSERT(0); @@ -779,9 +889,11 @@ gen_blend(const struct pipe_blend_state *blend, spe_release_register(f, tmp_reg); /* Free any optional registers that actually got used */ - RELEASE_ONE_REG_IF_USED(f) - RELEASE_CONST_COLOR_IF_USED(f) - RELEASE_CONST_ALPHA_IF_USED(f) + release_const_register(f, &one_reg_set, one_reg); + release_const_register(f, &constR_reg_set, constR_reg); + release_const_register(f, &constG_reg_set, constG_reg); + release_const_register(f, &constB_reg_set, constB_reg); + release_const_register(f, &constA_reg_set, constA_reg); } -- cgit v1.2.3 From 5e1ef85dc430a4439cd60b66262eab9062dd5f4f Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 18 Sep 2008 14:48:45 +0200 Subject: tgsi: Make tgsi dumps look more like mesa shader dumps. --- src/gallium/auxiliary/tgsi/tgsi_dump.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index afc8ffa553c..3177f549523 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -68,6 +68,7 @@ dump_enum( #define CHR(C) ctx->printf( ctx, "%c", C ) #define UIX(I) ctx->printf( ctx, "0x%x", I ) #define UID(I) ctx->printf( ctx, "%u", I ) +#define INSTID(I) ctx->printf( ctx, "% 3u", I ) #define SID(I) ctx->printf( ctx, "%d", I ) #define FLT(F) ctx->printf( ctx, "%10.4f", F ) #define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) ) @@ -315,8 +316,8 @@ iter_instruction( uint i; boolean first_reg = TRUE; - UID( instno ); - CHR( ':' ); + INSTID( instno ); + TXT( ": " ); TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic ); switch (inst->Instruction.Saturate) { -- cgit v1.2.3 From f68d2a0febca38bc7b31f9ab9718e944935b48bc Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 18 Sep 2008 08:10:34 -0600 Subject: gallium: fix surface object memory leak in cso module --- src/gallium/auxiliary/cso_cache/cso_context.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index b1ccfc0374a..68508f24de4 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -80,6 +80,10 @@ struct cso_context { }; +static void +free_framebuffer_state(struct pipe_framebuffer_state *fb); + + static boolean delete_blend_state(struct cso_context *ctx, void *state) { struct cso_blend *cso = (struct cso_blend *)state; @@ -252,6 +256,9 @@ void cso_release_all( struct cso_context *ctx ) pipe_texture_reference(&ctx->textures_saved[i], NULL); } + free_framebuffer_state(&ctx->fb); + free_framebuffer_state(&ctx->fb_saved); + if (ctx->cache) { cso_cache_delete( ctx->cache ); ctx->cache = NULL; @@ -784,6 +791,18 @@ copy_framebuffer_state(struct pipe_framebuffer_state *dst, } +static void +free_framebuffer_state(struct pipe_framebuffer_state *fb) +{ + uint i; + + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { + pipe_surface_reference(&fb->cbufs[i], NULL); + } + pipe_surface_reference(&fb->zsbuf, NULL); +} + + enum pipe_error cso_set_framebuffer(struct cso_context *ctx, const struct pipe_framebuffer_state *fb) { @@ -804,6 +823,7 @@ void cso_restore_framebuffer(struct cso_context *ctx) if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); + free_framebuffer_state(&ctx->fb_saved); } } -- cgit v1.2.3 From 451888ee8f9d9749a2d52351374a14525c07ef2b Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 18 Sep 2008 22:24:45 +0900 Subject: util: Add missing p_debug.h include. --- src/gallium/auxiliary/util/u_math.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 0b10622ee75..196aeb28fa4 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -40,6 +40,7 @@ #include "pipe/p_compiler.h" +#include "pipe/p_debug.h" #ifdef __cplusplus -- cgit v1.2.3 From eb5c288df48fa818ecb2bbd71f263ec68ebbef8a Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 18 Sep 2008 23:00:18 +0900 Subject: util: A few more memory debugging checks. --- src/gallium/auxiliary/util/p_debug_mem.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c index ed18c6540ea..9511479cbbe 100644 --- a/src/gallium/auxiliary/util/p_debug_mem.c +++ b/src/gallium/auxiliary/util/p_debug_mem.c @@ -122,8 +122,12 @@ debug_malloc(const char *file, unsigned line, const char *function, struct debug_memory_footer *ftr; hdr = real_malloc(sizeof(*hdr) + size + sizeof(*ftr)); - if(!hdr) + if(!hdr) { + debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n", + file, line, function, + (long unsigned)size); return NULL; + } hdr->no = last_no++; hdr->file = file; @@ -219,8 +223,12 @@ debug_realloc(const char *file, unsigned line, const char *function, /* alloc new */ new_hdr = real_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr)); - if(!new_hdr) + if(!new_hdr) { + debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n", + file, line, function, + (long unsigned)new_size); return NULL; + } new_hdr->no = old_hdr->no; new_hdr->file = old_hdr->file; new_hdr->line = old_hdr->line; @@ -261,8 +269,19 @@ debug_memory_end(unsigned long start_no) for (; entry != &list; entry = entry->prev) { struct debug_memory_header *hdr; void *ptr; + struct debug_memory_footer *ftr; + hdr = LIST_ENTRY(struct debug_memory_header, entry, head); ptr = data_from_header(hdr); + ftr = footer_from_header(hdr); + + if(hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: bad or corrupted memory %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } + if((start_no <= hdr->no && hdr->no < last_no) || (last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) { debug_printf("%s:%u:%s: %u bytes at %p not freed\n", @@ -270,7 +289,15 @@ debug_memory_end(unsigned long start_no) hdr->size, ptr); total_size += hdr->size; } + + if(ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, + ptr); + debug_assert(0); + } } + if(total_size) { debug_printf("Total of %u KB of system memory apparently leaked\n", (total_size + 1023)/1024); -- cgit v1.2.3 From 0b8e19ffc51c29543796d4f1e3243e97d8c32671 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 18 Sep 2008 16:28:16 +0200 Subject: tgsi: Build tgsi_text with make --- src/gallium/auxiliary/tgsi/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile index c5d2082087c..c7155a93168 100644 --- a/src/gallium/auxiliary/tgsi/Makefile +++ b/src/gallium/auxiliary/tgsi/Makefile @@ -13,6 +13,7 @@ C_SOURCES = \ tgsi_parse.c \ tgsi_scan.c \ tgsi_sse2.c \ + tgsi_text.c \ tgsi_transform.c \ tgsi_util.c -- cgit v1.2.3 From a57fbe53dcb54694da9c9b4be1533c9d800079d2 Mon Sep 17 00:00:00 2001 From: Robert Ellison Date: Fri, 19 Sep 2008 01:55:00 -0600 Subject: CELL: add codegen for logic op, color mask - rtasm_ppc_spe.c, rtasm_ppc_spe.h: added a new macro function "spe_load_uint" for loading and splatting unsigned integers in a register; it will use "ila" for values 18 bits or less, "ilh" for word values that are symmetric across halfwords, "ilhu" for values that have zeroes in their bottom halfwords, or "ilhu" followed by "iohl" for general 32-bit values. Of the 15 color masks of interest, 4 are 18 bits or less, 2 are symmetric across halfwords, 3 are zero in the bottom halfword, and 6 require two instructions to load. - cell_gen_fragment.c: added full codegen for logic op and color mask. --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 23 +++- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 4 + src/gallium/drivers/cell/ppu/cell_gen_fragment.c | 143 ++++++++++++++++++++++- 3 files changed, 163 insertions(+), 7 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 12e0826fb9b..f60bfba3f51 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -592,11 +592,32 @@ spe_load_int(struct spe_function *p, unsigned rT, int i) } } +void spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui) +{ + /* If the whole value is in the lower 18 bits, use ila, which + * doesn't sign-extend. Otherwise, if the two halfwords of + * the constant are identical, use ilh. Otherwise, we have + * to use ilhu followed by iohl. + */ + if ((ui & 0xfffc0000) == ui) { + spe_ila(p, rT, ui); + } + else if ((ui >> 16) == (ui & 0xffff)) { + spe_ilh(p, rT, ui & 0xffff); + } + else { + spe_ilhu(p, rT, ui >> 16); + if (ui & 0xffff) + spe_iohl(p, rT, ui & 0xffff); + } +} + void spe_splat(struct spe_function *p, unsigned rT, unsigned rA) { - spe_ila(p, rT, 66051); + /* Duplicate bytes 0, 1, 2, and 3 across the whole register */ + spe_ila(p, rT, 0x00010203); spe_shufb(p, rT, rA, rA, rT); } diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 4ef05ea27d1..09400b3fb2a 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -302,6 +302,10 @@ spe_load_float(struct spe_function *p, unsigned rT, float x); extern void spe_load_int(struct spe_function *p, unsigned rT, int i); +/** Load/splat immediate unsigned int into rT. */ +extern void +spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui); + /** Replicate word 0 of rA across rT. */ extern void spe_splat(struct spe_function *p, unsigned rT, unsigned rA); diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 9d25e820ad9..899d8423b24 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -902,8 +902,69 @@ gen_logicop(const struct pipe_blend_state *blend, struct spe_function *f, int fragRGBA_reg, int fbRGBA_reg) { - /* XXX to-do */ - /* operate on 32-bit packed pixels, not float colors */ + /* We've got four 32-bit RGBA packed pixels in each of + * fragRGBA_reg and fbRGBA_reg, not sets of floating-point + * reds, greens, blues, and alphas. + * */ + ASSERT(blend->logicop_enable); + + switch(blend->logicop_func) { + case PIPE_LOGICOP_CLEAR: /* 0 */ + spe_zero(f, fragRGBA_reg); + break; + case PIPE_LOGICOP_NOR: /* ~(s | d) */ + spe_nor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_AND_INVERTED: /* ~s & d */ + /* andc R, A, B computes R = A & ~B */ + spe_andc(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg); + break; + case PIPE_LOGICOP_COPY_INVERTED: /* ~s */ + spe_complement(f, fragRGBA_reg); + break; + case PIPE_LOGICOP_AND_REVERSE: /* s & ~d */ + /* andc R, A, B computes R = A & ~B */ + spe_andc(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_INVERT: /* ~d */ + /* Note that (A nor A) == ~(A|A) == ~A */ + spe_nor(f, fragRGBA_reg, fbRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_XOR: /* s ^ d */ + spe_xor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_NAND: /* ~(s & d) */ + spe_nand(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_AND: /* s & d */ + spe_and(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_EQUIV: /* ~(s ^ d) */ + spe_xor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + spe_complement(f, fragRGBA_reg); + break; + case PIPE_LOGICOP_NOOP: /* d */ + spe_move(f, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_OR_INVERTED: /* ~s | d */ + /* orc R, A, B computes R = A | ~B */ + spe_orc(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg); + break; + case PIPE_LOGICOP_COPY: /* s */ + break; + case PIPE_LOGICOP_OR_REVERSE: /* s | ~d */ + /* orc R, A, B computes R = A | ~B */ + spe_orc(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_OR: /* s | d */ + spe_or(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); + break; + case PIPE_LOGICOP_SET: /* 1 */ + spe_load_int(f, fragRGBA_reg, 0xffffffff); + break; + default: + ASSERT(0); + } } @@ -912,11 +973,81 @@ gen_colormask(uint colormask, struct spe_function *f, int fragRGBA_reg, int fbRGBA_reg) { - /* XXX to-do */ - /* operate on 32-bit packed pixels, not float colors */ -} + /* We've got four 32-bit RGBA packed pixels in each of + * fragRGBA_reg and fbRGBA_reg, not sets of floating-point + * reds, greens, blues, and alphas. + * */ + + /* The color mask operation can prevent any set of color + * components in the incoming fragment from being written to the frame + * buffer; we do this by replacing the masked components of the + * fragment with the frame buffer values. + * + * There are only 16 possibilities, with a unique mask for + * each of the possibilities. (Technically, there are only 15 + * possibilities, since we shouldn't be called for the one mask + * that does nothing, but the complete implementation is here + * anyway to avoid confusion.) + * + * We implement this via a constant static array which we'll index + * into to get the correct mask. + * + * We're dependent on the mask values being low-order bits, + * with particular values for each bit; so we start with a + * few assertions, which will fail if any of the values were + * to change. + */ + ASSERT(PIPE_MASK_R == 0x1); + ASSERT(PIPE_MASK_G == 0x2); + ASSERT(PIPE_MASK_B == 0x4); + ASSERT(PIPE_MASK_A == 0x8); + /* Here's the list of all possible colormasks, indexed by the + * value of the combined mask specifier. + */ + static const unsigned int colormasks[16] = { + 0x00000000, /* 0: all colors masked */ + 0xff000000, /* 1: PIPE_MASK_R */ + 0x00ff0000, /* 2: PIPE_MASK_G */ + 0xffff0000, /* 3: PIPE_MASK_R | PIPE_MASK_G */ + 0x0000ff00, /* 4: PIPE_MASK_B */ + 0xff00ff00, /* 5: PIPE_MASK_R | PIPE_MASK_B */ + 0x00ffff00, /* 6: PIPE_MASK_G | PIPE_MASK_B */ + 0xffffff00, /* 7: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B */ + 0x000000ff, /* 8: PIPE_MASK_A */ + 0xff0000ff, /* 9: PIPE_MASK_R | PIPE_MASK_A */ + 0x00ff00ff, /* 10: PIPE_MASK_G | PIPE_MASK_A */ + 0xffff00ff, /* 11: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_A */ + 0x0000ffff, /* 12: PIPE_MASK_B | PIPE_MASK_A */ + 0xff00ffff, /* 13: PIPE_MASK_R | PIPE_MASK_B | PIPE_MASK_A */ + 0x00ffffff, /* 14: PIPE_MASK_G | PIPE_MASK_B | PIPE_MASK_A */ + 0xffffffff /* 15: PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B | PIPE_MASK_A */ + }; + + /* Get a temporary register to hold the mask */ + int colormask_reg = spe_allocate_available_register(f); + + /* Look up the desired mask directly and load it into the mask register. + * This will load the same mask into each of the four words in the + * mask register. + */ + spe_load_uint(f, colormask_reg, colormasks[colormask]); + + /* Use the mask register to select between the fragment color + * values and the frame buffer color values. Wherever the + * mask has a 0 bit, the current frame buffer color should override + * the fragment color. Wherever the mask has a 1 bit, the + * fragment color should persevere. The Select Bits (selb rt, rA, rB, rM) + * instruction will select bits from its first operand rA wherever the + * the mask bits rM are 0, and from its second operand rB wherever the + * mask bits rM are 1. That means that the frame buffer color is the + * first operand, and the fragment color the second. + */ + spe_selb(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg, colormask_reg); + /* Release the temporary register and we're done */ + spe_release_register(f, colormask_reg); +} /** * Generate code to pack a quad of float colors into a four 32-bit integers. @@ -1223,7 +1354,7 @@ cell_gen_fragment_function(struct cell_context *cell, struct spe_function *f) gen_logicop(blend, f, rgba_reg, fbRGBA_reg); } - if (blend->colormask != 0xf) { + if (blend->colormask != PIPE_MASK_RGBA) { gen_colormask(blend->colormask, f, rgba_reg, fbRGBA_reg); } -- cgit v1.2.3 From dda5c0c611d55449a7079c9efeaccc417552c5db Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 19 Sep 2008 23:25:29 +0900 Subject: util: Use OpenGL rasterization rules in blits and mipmap generation. --- src/gallium/auxiliary/util/u_blit.c | 1 + src/gallium/auxiliary/util/u_gen_mipmap.c | 1 + 2 files changed, 2 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 9adf72944e6..d28201ac8dc 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -104,6 +104,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; ctx->rasterizer.bypass_clipping = 1; /*ctx->rasterizer.bypass_vs = 1;*/ + ctx->rasterizer.gl_rasterization_rules = 1; /* samplers */ memset(&ctx->sampler, 0, sizeof(ctx->sampler)); diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index b19a649bbcd..9d305ad763a 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -725,6 +725,7 @@ util_create_gen_mipmap(struct pipe_context *pipe, ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; ctx->rasterizer.bypass_clipping = 1; /*ctx->rasterizer.bypass_vs = 1;*/ + ctx->rasterizer.gl_rasterization_rules = 1; /* sampler state */ memset(&ctx->sampler, 0, sizeof(ctx->sampler)); -- cgit v1.2.3 From 0838b702750d85b0284a97be211fa379e9f8d8d8 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 19 Sep 2008 09:36:29 -0600 Subject: cell: change spe_complement() to take a src and dst reg, like other instructions --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 14 ++++++++------ src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 4 ++-- src/gallium/drivers/cell/ppu/cell_gen_fp.c | 4 ++-- src/gallium/drivers/cell/ppu/cell_gen_fragment.c | 4 ++-- 4 files changed, 14 insertions(+), 12 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index f60bfba3f51..85280f680a4 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -623,9 +623,9 @@ spe_splat(struct spe_function *p, unsigned rT, unsigned rA) void -spe_complement(struct spe_function *p, unsigned rT) +spe_complement(struct spe_function *p, unsigned rT, unsigned rA) { - spe_nor(p, rT, rT, rT); + spe_nor(p, rT, rA, rA); } @@ -667,7 +667,8 @@ spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) } } -/* For each 32-bit float element of rA and rB, choose the smaller of the +/** + * For each 32-bit float element of rA and rB, choose the smaller of the * two, compositing them into the rT register. * * The Float Compare Greater Than (fcgt) instruction will put 1s into @@ -683,7 +684,7 @@ spe_splat_word(struct spe_function *p, unsigned rT, unsigned rA, int word) * like "x = min(x, a)", we always allocate a new register to be safe. */ void -spe_float_min(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned int rB) +spe_float_min(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) { unsigned int compare_reg = spe_allocate_available_register(p); spe_fcgt(p, compare_reg, rA, rB); @@ -691,7 +692,8 @@ spe_float_min(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned spe_release_register(p, compare_reg); } -/* For each 32-bit float element of rA and rB, choose the greater of the +/** + * For each 32-bit float element of rA and rB, choose the greater of the * two, compositing them into the rT register. * * The logic is similar to that of spe_float_min() above; the only @@ -699,7 +701,7 @@ spe_float_min(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned * so that the larger of the two is selected instead of the smaller. */ void -spe_float_max(struct spe_function *p, unsigned int rT, unsigned int rA, unsigned int rB) +spe_float_max(struct spe_function *p, unsigned rT, unsigned rA, unsigned rB) { unsigned int compare_reg = spe_allocate_available_register(p); spe_fcgt(p, compare_reg, rA, rB); diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 09400b3fb2a..8a0d70fdac5 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -310,9 +310,9 @@ spe_load_uint(struct spe_function *p, unsigned rT, unsigned int ui); extern void spe_splat(struct spe_function *p, unsigned rT, unsigned rA); -/** Complement/invert all bits in rT. */ +/** rT = complement_all_bits(rA). */ extern void -spe_complement(struct spe_function *p, unsigned rT); +spe_complement(struct spe_function *p, unsigned rT, unsigned rA); /** rT = rA. */ extern void diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fp.c b/src/gallium/drivers/cell/ppu/cell_gen_fp.c index 6f2b89c695c..d835aae2552 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fp.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.c @@ -924,7 +924,7 @@ emit_IF(struct codegen *gen, const struct tgsi_full_instruction *inst) /* tmp = (s1_reg == 0) */ spe_ceqi(gen->f, tmp_reg, s1_reg, 0); /* tmp = !tmp */ - spe_complement(gen->f, tmp_reg); + spe_complement(gen->f, tmp_reg, tmp_reg); /* exec_mask = exec_mask & tmp */ spe_and(gen->f, exec_reg, exec_reg, tmp_reg); @@ -944,7 +944,7 @@ emit_ELSE(struct codegen *gen, const struct tgsi_full_instruction *inst) spe_comment(gen->f, -4, "ELSE:"); /* exec_mask = !exec_mask */ - spe_complement(gen->f, exec_reg); + spe_complement(gen->f, exec_reg, exec_reg); return true; } diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 899d8423b24..06a9fa102f9 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -920,7 +920,7 @@ gen_logicop(const struct pipe_blend_state *blend, spe_andc(f, fragRGBA_reg, fbRGBA_reg, fragRGBA_reg); break; case PIPE_LOGICOP_COPY_INVERTED: /* ~s */ - spe_complement(f, fragRGBA_reg); + spe_complement(f, fragRGBA_reg, fragRGBA_reg); break; case PIPE_LOGICOP_AND_REVERSE: /* s & ~d */ /* andc R, A, B computes R = A & ~B */ @@ -941,7 +941,7 @@ gen_logicop(const struct pipe_blend_state *blend, break; case PIPE_LOGICOP_EQUIV: /* ~(s ^ d) */ spe_xor(f, fragRGBA_reg, fragRGBA_reg, fbRGBA_reg); - spe_complement(f, fragRGBA_reg); + spe_complement(f, fragRGBA_reg, fragRGBA_reg); break; case PIPE_LOGICOP_NOOP: /* d */ spe_move(f, fragRGBA_reg, fbRGBA_reg); -- cgit v1.2.3 From 7af5f944e5709920623c766bc572f8d587709270 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 19 Sep 2008 17:45:51 -0600 Subject: gallium: added spe_code_size() --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 7 +++++++ src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 85280f680a4..1c3e21b4c03 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -383,6 +383,13 @@ void spe_release_func(struct spe_function *p) } +/** Return current code size in bytes. */ +unsigned spe_code_size(const struct spe_function *p) +{ + return p->num_inst * SPE_INST_SIZE; +} + + /** * Allocate a SPE register. * \return register index or -1 if none left. diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 8a0d70fdac5..4165a971a2f 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -72,6 +72,7 @@ struct spe_function extern void spe_init_func(struct spe_function *p, unsigned code_size); extern void spe_release_func(struct spe_function *p); +extern unsigned spe_code_size(const struct spe_function *p); extern int spe_allocate_available_register(struct spe_function *p); extern int spe_allocate_register(struct spe_function *p, int reg); -- cgit v1.2.3 From 99cdfc997b9da10fee57cf1048a55354e1ee4244 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 19 Sep 2008 17:55:54 -0600 Subject: cell: use different opcodes for spe_move() depending on even/odd address --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c index 1c3e21b4c03..491141f1908 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.c @@ -639,7 +639,13 @@ spe_complement(struct spe_function *p, unsigned rT, unsigned rA) void spe_move(struct spe_function *p, unsigned rT, unsigned rA) { - spe_ori(p, rT, rA, 0); + /* Use different instructions depending on the instruction address + * to take advantage of the dual pipelines. + */ + if (p->num_inst & 1) + spe_shlqbyi(p, rT, rA, 0); /* odd pipe */ + else + spe_ori(p, rT, rA, 0); /* even pipe */ } -- cgit v1.2.3 From 6901d6ef24224c27e20c3e864d035db1552aeeb8 Mon Sep 17 00:00:00 2001 From: Robert Ellison Date: Tue, 23 Sep 2008 10:09:36 -0600 Subject: CELL: improve legibility of CELL_DEBUG environment variable output --- src/gallium/auxiliary/util/p_debug.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index b6cff281e6d..3ed8bdfdf33 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -306,6 +306,13 @@ debug_get_flags_option(const char *name, str = _debug_get_option(name); if(!str) result = dfault; + else if (!util_strcmp(str, "help")) { + result = dfault; + while (flags->name) { + debug_printf("%s: help for %s: %s [0x%lx]\n", __FUNCTION__, name, flags->name, flags->value); + flags++; + } + } else { result = 0; while( flags->name ) { @@ -315,7 +322,12 @@ debug_get_flags_option(const char *name, } } - debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result); + if (str) { + debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str); + } + else { + debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result); + } return result; } -- cgit v1.2.3 From 4fe186f8dc4fc7eeab3b1069c886458cfc2e517c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 24 Sep 2008 20:42:57 +0100 Subject: add cso_hash_contains() function --- src/gallium/auxiliary/cso_cache/cso_hash.c | 6 ++++++ src/gallium/auxiliary/cso_cache/cso_hash.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/cso_cache/cso_hash.c b/src/gallium/auxiliary/cso_cache/cso_hash.c index 7f0044c5a7f..4e7664f9bf0 100644 --- a/src/gallium/auxiliary/cso_cache/cso_hash.c +++ b/src/gallium/auxiliary/cso_cache/cso_hash.c @@ -431,3 +431,9 @@ struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter --hash->data.d->size; return ret; } + +boolean cso_hash_contains(struct cso_hash *hash, unsigned key) +{ + struct cso_node **node = cso_hash_find_node(hash, key); + return (*node != hash->data.e); +} diff --git a/src/gallium/auxiliary/cso_cache/cso_hash.h b/src/gallium/auxiliary/cso_cache/cso_hash.h index 85f3e276c6a..5891c325fa5 100644 --- a/src/gallium/auxiliary/cso_cache/cso_hash.h +++ b/src/gallium/auxiliary/cso_cache/cso_hash.h @@ -44,6 +44,7 @@ #ifndef CSO_HASH_H #define CSO_HASH_H +#include "pipe/p_compiler.h" #ifdef __cplusplus extern "C" { @@ -95,6 +96,11 @@ struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash); */ struct cso_hash_iter cso_hash_find(struct cso_hash *hash, unsigned key); +/** + * Returns true if a value with the given key exists in the hash + */ +boolean cso_hash_contains(struct cso_hash *hash, unsigned key); + int cso_hash_iter_is_null(struct cso_hash_iter iter); unsigned cso_hash_iter_key(struct cso_hash_iter iter); -- cgit v1.2.3 From 9f3e37de17a5636625f0275ca639fdc25ef1e95b Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 23 Sep 2008 16:40:49 +0900 Subject: util: Update fast_log2 article url. --- src/gallium/auxiliary/util/u_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index 196aeb28fa4..084655e6ddc 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -254,7 +254,7 @@ util_fast_exp2(float x) /** - * Based on code from http://www.flipcode.com/totd/ + * Based on code from http://www.flipcode.com/archives/Fast_log_Function.shtml */ static INLINE float util_fast_log2(float val) -- cgit v1.2.3 From 938e12c1caee7e34fcc6630f17f422ebdd824ec3 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 26 Sep 2008 17:06:22 -0600 Subject: gallium: SPU register comments --- src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h index 4165a971a2f..61c7edeb604 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h +++ b/src/gallium/auxiliary/rtasm/rtasm_ppc_spe.h @@ -40,10 +40,10 @@ /** number of general-purpose SIMD registers */ #define SPE_NUM_REGS 128 -/** Return Address register */ +/** Return Address register (aka $lr / Link Register) */ #define SPE_REG_RA 0 -/** Stack Pointer register */ +/** Stack Pointer register (aka $sp) */ #define SPE_REG_SP 1 -- cgit v1.2.3 From 6607f2cf19d083a979716a341e6e175aef7d6830 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 29 Sep 2008 19:09:39 +0900 Subject: rtasm: Implement immediate group 1 instructions. Fix SIB emition. --- src/gallium/auxiliary/rtasm/rtasm_x86sse.c | 66 +++++++++++++++++++++++++----- src/gallium/auxiliary/rtasm/rtasm_x86sse.h | 11 ++--- 2 files changed, 62 insertions(+), 15 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index 6d4c081e04e..3bba9dcc076 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -240,7 +240,8 @@ static void emit_modrm( struct x86_function *p, /* Oh-oh we've stumbled into the SIB thing. */ if (regmem.file == file_REG32 && - regmem.idx == reg_SP) { + regmem.idx == reg_SP && + regmem.mod != mod_REG) { emit_1ub(p, 0x24); /* simplistic! */ } @@ -435,25 +436,70 @@ void x86_call( struct x86_function *p, struct x86_reg reg) } -/* michal: - * Temporary. As I need immediate operands, and dont want to mess with the codegen, - * I load the immediate into general purpose register and use it. - */ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ) { DUMP_RI( dst, imm ); + assert(dst.file == file_REG32); assert(dst.mod == mod_REG); emit_1ub(p, 0xb8 + dst.idx); emit_1i(p, imm); } -void x86_add_reg_imm8( struct x86_function *p, struct x86_reg dst, ubyte imm ) +/** + * Immediate group 1 instructions. + */ +static INLINE void +x86_group1_imm( struct x86_function *p, + unsigned op, struct x86_reg dst, int imm ) { - DUMP_RI( dst, imm ); + assert(dst.file == file_REG32); assert(dst.mod == mod_REG); - emit_1ub(p, 0x80); - emit_modrm_noreg(p, 0, dst); - emit_1ub(p, imm); + if(-0x80 <= imm && imm < 0x80) { + emit_1ub(p, 0x83); + emit_modrm_noreg(p, op, dst); + emit_1b(p, (char)imm); + } + else { + emit_1ub(p, 0x81); + emit_modrm_noreg(p, op, dst); + emit_1i(p, imm); + } +} + +void x86_add_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 0, dst, imm); +} + +void x86_or_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 1, dst, imm); +} + +void x86_and_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 4, dst, imm); +} + +void x86_sub_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 5, dst, imm); +} + +void x86_xor_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 6, dst, imm); +} + +void x86_cmp_imm( struct x86_function *p, struct x86_reg dst, int imm ) +{ + DUMP_RI( dst, imm ); + x86_group1_imm(p, 7, dst, imm); } diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h index af94577aaba..510aa1b0dec 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h @@ -152,12 +152,13 @@ void x86_jmp( struct x86_function *p, int label ); /* void x86_call( struct x86_function *p, void (*label)() ); */ void x86_call( struct x86_function *p, struct x86_reg reg); -/* michal: - * Temporary. As I need immediate operands, and dont want to mess with the codegen, - * I load the immediate into general purpose register and use it. - */ void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm ); -void x86_add_reg_imm8( struct x86_function *p, struct x86_reg dst, ubyte imm ); +void x86_add_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_or_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_and_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_sub_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_xor_imm( struct x86_function *p, struct x86_reg dst, int imm ); +void x86_cmp_imm( struct x86_function *p, struct x86_reg dst, int imm ); /* Macro for sse_shufps() and sse2_pshufd(): -- cgit v1.2.3 From 906336cd7ce5ff1cf9d10fb21375b9c0bcd5fe57 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 30 Sep 2008 01:07:09 +0900 Subject: util: Header for SSE2 intrinsics portability. --- src/gallium/auxiliary/util/u_sse.h | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/gallium/auxiliary/util/u_sse.h (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/util/u_sse.h b/src/gallium/auxiliary/util/u_sse.h new file mode 100644 index 00000000000..0c8356cd057 --- /dev/null +++ b/src/gallium/auxiliary/util/u_sse.h @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SSE intrinsics portability header. + * + * Although the SSE intrinsics are support by all modern x86 and x86-64 + * compilers, there are some intrisincs missing in some implementations + * (especially older MSVC versions). This header abstracts that away. + */ + +#ifndef U_SSE_H_ +#define U_SSE_H_ + +#include +#include + + +/* MSVC before VC8 does not support the _mm_castxxx_yyy */ +#if defined(_MSC_VER) && _MSC_VER < 1500 + +union __declspec(align(16)) m128_types { + __m128 m128; + __m128i m128i; + __m128d m128d; +}; + +static __inline __m128 +_mm_castsi128_ps(__m128i a) +{ + union m128_types u; + u.m128i = a; + return u.m128; +} + +static __inline __m128i +_mm_castps_si128(__m128 a) +{ + union m128_types u; + u.m128 = a; + return u.m128i; +} + +#endif + + +#endif /* U_SSE_H_ */ -- cgit v1.2.3 From 5dc8e67078be8b8c42a809311debd275ac7d64a7 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 30 Sep 2008 01:12:52 +0900 Subject: tgsi: SSE2 optimized exp2, log2 and pow implementations. Special care must be taken when calling compiler generated SSE2 functions from the runtime generated SSE2: saving the xmm registers, and notify gcc the stack is not 16byte aligned. It would be more efficient to keep the stack pointer 16byte aligned, but too hairy, and not consistent in all x86 architectures. This has been tested in linux x86 and windows x86 userspace. Not tested on x86-64 because it is broken for other reasons (even without this change). --- src/gallium/auxiliary/tgsi/tgsi_sse2.c | 287 ++++++++++++++++++++++++--------- 1 file changed, 211 insertions(+), 76 deletions(-) (limited to 'src/gallium/auxiliary') diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 4681b29f52b..4fdad3a5c78 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -28,6 +28,7 @@ #include "pipe/p_debug.h" #include "pipe/p_shader_tokens.h" #include "util/u_math.h" +#include "util/u_sse.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi_exec.h" @@ -480,10 +481,31 @@ emit_coef_dady( * Function call helpers. */ +/** + * NOTE: In gcc, if the destination uses the SSE intrinsics, then it must be + * defined with __attribute__((force_align_arg_pointer)), as we do not guarantee + * that the stack pointer is 16 byte aligned, as expected. + */ static void -emit_push_gp( - struct x86_function *func ) +emit_func_call_dst( + struct x86_function *func, + unsigned xmm_save, + unsigned xmm_dst, + void (PIPE_CDECL *code)() ) { + struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); + unsigned i, n, xmm; + unsigned xmm_mask; + + /* Bitmask of the xmm registers to save */ + xmm_mask = (1 << xmm_save) - 1; + xmm_mask &= ~(1 << xmm_dst); + + sse_movaps( + func, + get_temp( TEMP_R0, 0 ), + make_xmm( xmm_dst ) ); + x86_push( func, x86_make_reg( file_REG32, reg_AX) ); @@ -493,12 +515,49 @@ emit_push_gp( x86_push( func, x86_make_reg( file_REG32, reg_DX) ); -} + + for(i = 0, n = 0; i < 8; ++i) + if(xmm_mask & (1 << i)) + ++n; + + x86_sub_imm( + func, + x86_make_reg( file_REG32, reg_SP ), + n*16); + + for(i = 0, n = 0; i < 8; ++i) + if(xmm_mask & (1 << i)) { + sse_movups( + func, + x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ), + make_xmm( xmm ) ); + ++n; + } + + x86_lea( + func, + ecx, + get_temp( TEMP_R0, 0 ) ); + + x86_push( func, ecx ); + x86_mov_reg_imm( func, ecx, (unsigned long) code ); + x86_call( func, ecx ); + x86_pop(func, ecx ); + + for(i = 0, n = 0; i < 8; ++i) + if(xmm_mask & (1 << i)) { + sse_movups( + func, + make_xmm( xmm ), + x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ) ); + ++n; + } + + x86_add_imm( + func, + x86_make_reg( file_REG32, reg_SP ), + n*16); -static void -x86_pop_gp( - struct x86_function *func ) -{ /* Restore GP registers in a reverse order. */ x86_pop( @@ -510,39 +569,6 @@ x86_pop_gp( x86_pop( func, x86_make_reg( file_REG32, reg_AX) ); -} - -static void -emit_func_call_dst( - struct x86_function *func, - unsigned xmm_dst, - void (PIPE_CDECL *code)() ) -{ - sse_movaps( - func, - get_temp( TEMP_R0, 0 ), - make_xmm( xmm_dst ) ); - - emit_push_gp( - func ); - - { - struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); - - x86_lea( - func, - ecx, - get_temp( TEMP_R0, 0 ) ); - - x86_push( func, ecx ); - x86_mov_reg_imm( func, ecx, (unsigned long) code ); - x86_call( func, ecx ); - x86_pop(func, ecx ); - } - - - x86_pop_gp( - func ); sse_movaps( func, @@ -553,6 +579,7 @@ emit_func_call_dst( static void emit_func_call_dst_src( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst, unsigned xmm_src, void (PIPE_CDECL *code)() ) @@ -564,10 +591,111 @@ emit_func_call_dst_src( emit_func_call_dst( func, + xmm_save, xmm_dst, code ); } +/* + * Fast SSE2 implementation of special math functions. + */ + +#define POLY0(x, c0) _mm_set1_ps(c0) +#define POLY1(x, c0, c1) _mm_add_ps(_mm_mul_ps(POLY0(x, c1), x), _mm_set1_ps(c0)) +#define POLY2(x, c0, c1, c2) _mm_add_ps(_mm_mul_ps(POLY1(x, c1, c2), x), _mm_set1_ps(c0)) +#define POLY3(x, c0, c1, c2, c3) _mm_add_ps(_mm_mul_ps(POLY2(x, c1, c2, c3), x), _mm_set1_ps(c0)) +#define POLY4(x, c0, c1, c2, c3, c4) _mm_add_ps(_mm_mul_ps(POLY3(x, c1, c2, c3, c4), x), _mm_set1_ps(c0)) +#define POLY5(x, c0, c1, c2, c3, c4, c5) _mm_add_ps(_mm_mul_ps(POLY4(x, c1, c2, c3, c4, c5), x), _mm_set1_ps(c0)) + +#define EXP_POLY_DEGREE 3 +#define LOG_POLY_DEGREE 5 + +/** + * See http://www.devmaster.net/forums/showthread.php?p=43580 + */ +static INLINE __m128 +exp2f4(__m128 x) +{ + __m128i ipart; + __m128 fpart, expipart, expfpart; + + x = _mm_min_ps(x, _mm_set1_ps( 129.00000f)); + x = _mm_max_ps(x, _mm_set1_ps(-126.99999f)); + + /* ipart = int(x - 0.5) */ + ipart = _mm_cvtps_epi32(_mm_sub_ps(x, _mm_set1_ps(0.5f))); + + /* fpart = x - ipart */ + fpart = _mm_sub_ps(x, _mm_cvtepi32_ps(ipart)); + + /* expipart = (float) (1 << ipart) */ + expipart = _mm_castsi128_ps(_mm_slli_epi32(_mm_add_epi32(ipart, _mm_set1_epi32(127)), 23)); + + /* minimax polynomial fit of 2**x, in range [-0.5, 0.5[ */ +#if EXP_POLY_DEGREE == 5 + expfpart = POLY5(fpart, 9.9999994e-1f, 6.9315308e-1f, 2.4015361e-1f, 5.5826318e-2f, 8.9893397e-3f, 1.8775767e-3f); +#elif EXP_POLY_DEGREE == 4 + expfpart = POLY4(fpart, 1.0000026f, 6.9300383e-1f, 2.4144275e-1f, 5.2011464e-2f, 1.3534167e-2f); +#elif EXP_POLY_DEGREE == 3 + expfpart = POLY3(fpart, 9.9992520e-1f, 6.9583356e-1f, 2.2606716e-1f, 7.8024521e-2f); +#elif EXP_POLY_DEGREE == 2 + expfpart = POLY2(fpart, 1.0017247f, 6.5763628e-1f, 3.3718944e-1f); +#else +#error +#endif + + return _mm_mul_ps(expipart, expfpart); +} + +/** + * See http://www.devmaster.net/forums/showthread.php?p=43580 + */ +static INLINE __m128 +log2f4(__m128 x) +{ + __m128i expmask = _mm_set1_epi32(0x7f800000); + __m128i mantmask = _mm_set1_epi32(0x007fffff); + __m128 one = _mm_set1_ps(1.0f); + + __m128i i = _mm_castps_si128(x); + + /* exp = (float) exponent(x) */ + __m128 exp = _mm_cvtepi32_ps(_mm_sub_epi32(_mm_srli_epi32(_mm_and_si128(i, expmask), 23), _mm_set1_epi32(127))); + + /* mant = (float) mantissa(x) */ + __m128 mant = _mm_or_ps(_mm_castsi128_ps(_mm_and_si128(i, mantmask)), one); + + __m128 logmant; + + /* Minimax polynomial fit of log2(x)/(x - 1), for x in range [1, 2[ + * These coefficients can be generate with + * http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html + */ +#if LOG_POLY_DEGREE == 6 + logmant = POLY5(mant, 3.11578814719469302614f, -3.32419399085241980044f, 2.59883907202499966007f, -1.23152682416275988241f, 0.318212422185251071475f, -0.0344359067839062357313f); +#elif LOG_POLY_DEGREE == 5 + logmant = POLY4(mant, 2.8882704548164776201f, -2.52074962577807006663f, 1.48116647521213171641f, -0.465725644288844778798f, 0.0596515482674574969533f); +#elif LOG_POLY_DEGREE == 4 + logmant = POLY3(mant, 2.61761038894603480148f, -1.75647175389045657003f, 0.688243882994381274313f, -0.107254423828329604454f); +#elif LOG_POLY_DEGREE == 3 + logmant = POLY2(mant, 2.28330284476918490682f, -1.04913055217340124191f, 0.204446009836232697516f); +#else +#error +#endif + + /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/ + logmant = _mm_mul_ps(logmant, _mm_sub_ps(mant, one)); + + return _mm_add_ps(logmant, exp); +} + +static INLINE __m128 +powf4(__m128 x, __m128 y) +{ + return exp2f4(_mm_mul_ps(log2f4(x), y)); +} + + /** * Low-level instruction translators. */ @@ -610,38 +738,35 @@ cos4f( static void emit_cos( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst ) { emit_func_call_dst( func, + xmm_save, xmm_dst, cos4f ); } static void PIPE_CDECL +#if defined(PIPE_CC_GCC) +__attribute__((force_align_arg_pointer)) +#endif ex24f( float *store ) { -#if FAST_MATH - store[0] = util_fast_exp2( store[0] ); - store[1] = util_fast_exp2( store[1] ); - store[2] = util_fast_exp2( store[2] ); - store[3] = util_fast_exp2( store[3] ); -#else - store[0] = powf( 2.0f, store[0] ); - store[1] = powf( 2.0f, store[1] ); - store[2] = powf( 2.0f, store[2] ); - store[3] = powf( 2.0f, store[3] ); -#endif + _mm_store_ps(&store[0], exp2f4( _mm_load_ps(&store[0]) )); } static void emit_ex2( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst ) { emit_func_call_dst( func, + xmm_save, xmm_dst, ex24f ); } @@ -670,10 +795,12 @@ flr4f( static void emit_flr( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst ) { emit_func_call_dst( func, + xmm_save, xmm_dst, flr4f ); } @@ -691,31 +818,35 @@ frc4f( static void emit_frc( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst ) { emit_func_call_dst( func, + xmm_save, xmm_dst, frc4f ); } static void PIPE_CDECL +#if defined(PIPE_CC_GCC) +__attribute__((force_align_arg_pointer)) +#endif lg24f( float *store ) { - store[0] = util_fast_log2( store[0] ); - store[1] = util_fast_log2( store[1] ); - store[2] = util_fast_log2( store[2] ); - store[3] = util_fast_log2( store[3] ); + _mm_store_ps(&store[0], log2f4( _mm_load_ps(&store[0]) )); } static void emit_lg2( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst ) { emit_func_call_dst( func, + xmm_save, xmm_dst, lg24f ); } @@ -757,14 +888,14 @@ emit_neg( } static void PIPE_CDECL +#if defined(PIPE_CC_GCC) +__attribute__((force_align_arg_pointer)) +#endif pow4f( float *store ) { -#if FAST_MATH - store[0] = util_fast_pow( store[0], store[4] ); - store[1] = util_fast_pow( store[1], store[5] ); - store[2] = util_fast_pow( store[2], store[6] ); - store[3] = util_fast_pow( store[3], store[7] ); +#if 1 + _mm_store_ps(&store[0], powf4( _mm_load_ps(&store[0]), _mm_load_ps(&store[4]) )); #else store[0] = powf( store[0], store[4] ); store[1] = powf( store[1], store[5] ); @@ -776,11 +907,13 @@ pow4f( static void emit_pow( struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst, unsigned xmm_src ) { emit_func_call_dst_src( func, + xmm_save, xmm_dst, xmm_src, pow4f ); @@ -873,10 +1006,12 @@ sin4f( static void emit_sin (struct x86_function *func, + unsigned xmm_save, unsigned xmm_dst) { emit_func_call_dst( func, + xmm_save, xmm_dst, sin4f ); } @@ -1296,7 +1431,7 @@ emit_instruction( get_temp( TGSI_EXEC_TEMP_MINUS_128_I, TGSI_EXEC_TEMP_MINUS_128_C ) ); - emit_pow( func, 1, 2 ); + emit_pow( func, 3, 1, 2 ); FETCH( func, *inst, 0, 0, CHAN_X ); sse_xorps( func, @@ -1342,11 +1477,11 @@ emit_instruction( if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) { emit_MOV( func, 1, 0 ); - emit_flr( func, 1 ); + emit_flr( func, 2, 1 ); /* dst.x = ex2(floor(src.x)) */ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X )) { emit_MOV( func, 2, 1 ); - emit_ex2( func, 2 ); + emit_ex2( func, 3, 2 ); STORE( func, *inst, 2, 0, CHAN_X ); } /* dst.y = src.x - floor(src.x) */ @@ -1358,7 +1493,7 @@ emit_instruction( } /* dst.z = ex2(src.x) */ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) { - emit_ex2( func, 0 ); + emit_ex2( func, 3, 0 ); STORE( func, *inst, 0, 0, CHAN_Z ); } } @@ -1376,21 +1511,21 @@ emit_instruction( FETCH( func, *inst, 0, 0, CHAN_X ); emit_abs( func, 0 ); emit_MOV( func, 1, 0 ); - emit_lg2( func, 1 ); + emit_lg2( func, 2, 1 ); /* dst.z = lg2(abs(src.x)) */ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z )) { STORE( func, *inst, 1, 0, CHAN_Z ); } if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) { - emit_flr( func, 1 ); + emit_flr( func, 2, 1 ); /* dst.x = floor(lg2(abs(src.x))) */ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X )) { STORE( func, *inst, 1, 0, CHAN_X ); } /* dst.x = abs(src)/ex2(floor(lg2(abs(src.x)))) */ if (IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y )) { - emit_ex2( func, 1 ); + emit_ex2( func, 2, 1 ); emit_rcp( func, 1, 1 ); emit_mul( func, 0, 1 ); STORE( func, *inst, 0, 0, CHAN_Y ); @@ -1580,7 +1715,7 @@ emit_instruction( /* TGSI_OPCODE_FRC */ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); - emit_frc( func, 0 ); + emit_frc( func, 0, 0 ); STORE( func, *inst, 0, 0, chan_index ); } break; @@ -1593,7 +1728,7 @@ emit_instruction( /* TGSI_OPCODE_FLR */ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); - emit_flr( func, 0 ); + emit_flr( func, 0, 0 ); STORE( func, *inst, 0, 0, chan_index ); } break; @@ -1605,7 +1740,7 @@ emit_instruction( case TGSI_OPCODE_EXPBASE2: /* TGSI_OPCODE_EX2 */ FETCH( func, *inst, 0, 0, CHAN_X ); - emit_ex2( func, 0 ); + emit_ex2( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -1614,7 +1749,7 @@ emit_instruction( case TGSI_OPCODE_LOGBASE2: /* TGSI_OPCODE_LG2 */ FETCH( func, *inst, 0, 0, CHAN_X ); - emit_lg2( func, 0 ); + emit_lg2( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -1624,7 +1759,7 @@ emit_instruction( /* TGSI_OPCODE_POW */ FETCH( func, *inst, 0, 0, CHAN_X ); FETCH( func, *inst, 1, 1, CHAN_X ); - emit_pow( func, 0, 1 ); + emit_pow( func, 0, 0, 1 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -1715,7 +1850,7 @@ emit_instruction( case TGSI_OPCODE_COS: FETCH( func, *inst, 0, 0, CHAN_X ); - emit_cos( func, 0 ); + emit_cos( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -1774,7 +1909,7 @@ emit_instruction( case TGSI_OPCODE_SIN: FETCH( func, *inst, 0, 0, CHAN_X ); - emit_sin( func, 0 ); + emit_sin( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -1868,12 +2003,12 @@ emit_instruction( case TGSI_OPCODE_SCS: IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) { FETCH( func, *inst, 0, 0, CHAN_X ); - emit_cos( func, 0 ); + emit_cos( func, 0, 0 ); STORE( func, *inst, 0, 0, CHAN_X ); } IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) { FETCH( func, *inst, 0, 0, CHAN_X ); - emit_sin( func, 0 ); + emit_sin( func, 0, 0 ); STORE( func, *inst, 0, 0, CHAN_Y ); } IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) { -- cgit v1.2.3