From 9bd15aef865352b9234fedae76617fc51c71e6d5 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 25 Jul 2011 16:06:45 -0600 Subject: [PATCH] svga: implement texture swizzling This exposes the GL_EXT_texture_swizzle extension and allows the various depth texture modes to be implemented properly. This, plus a follow-on texture/shadow change fixes quite a few piglit GLSL shadow sampler test failures. --- src/gallium/drivers/svga/svga_screen.c | 2 + src/gallium/drivers/svga/svga_state_fs.c | 5 + src/gallium/drivers/svga/svga_tgsi.h | 4 + src/gallium/drivers/svga/svga_tgsi_insn.c | 126 ++++++++++++++++++++-- 4 files changed, 128 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 3a1ac9e1d93..87b48dea173 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -148,6 +148,8 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_cap param) return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; + case PIPE_CAP_TEXTURE_SWIZZLE: + return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: { diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index 5b96750bbf1..349aa275f18 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -167,6 +167,11 @@ static int make_fs_key( const struct svga_context *svga, key->tex[i].unnormalized = TRUE; ++key->num_unnormalized_coords; } + + key->tex[i].swizzle_r = svga->curr.sampler_views[i]->swizzle_r; + key->tex[i].swizzle_g = svga->curr.sampler_views[i]->swizzle_g; + key->tex[i].swizzle_b = svga->curr.sampler_views[i]->swizzle_b; + key->tex[i].swizzle_a = svga->curr.sampler_views[i]->swizzle_a; } } key->num_textures = svga->curr.num_sampler_views; diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h index bd63bf5c264..214e113aaaa 100644 --- a/src/gallium/drivers/svga/svga_tgsi.h +++ b/src/gallium/drivers/svga/svga_tgsi.h @@ -60,6 +60,10 @@ struct svga_fs_compile_key unsigned width_height_idx:7; unsigned texture_target:8; unsigned sprite_texgen:1; + unsigned swizzle_r:3; + unsigned swizzle_g:3; + unsigned swizzle_b:3; + unsigned swizzle_a:3; } tex[PIPE_MAX_SAMPLERS]; }; diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index 05531a15eb5..b93c0cbab90 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -25,6 +25,7 @@ #include "pipe/p_shader_tokens.h" +#include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_parse.h" #include "util/u_memory.h" #include "util/u_math.h" @@ -1524,6 +1525,73 @@ static boolean emit_tex4(struct svga_shader_emitter *emit, } +/** + * Emit texture swizzle code. + */ +static boolean emit_tex_swizzle( struct svga_shader_emitter *emit, + SVGA3dShaderDestToken dst, + struct src_register src, + unsigned swizzle_x, + unsigned swizzle_y, + unsigned swizzle_z, + unsigned swizzle_w) +{ + const unsigned swizzleIn[4] = {swizzle_x, swizzle_y, swizzle_z, swizzle_w}; + unsigned srcSwizzle[4]; + unsigned srcWritemask = 0x0, zeroWritemask = 0x0, oneWritemask = 0x0; + int i; + + /* build writemasks and srcSwizzle terms */ + for (i = 0; i < 4; i++) { + if (swizzleIn[i] == PIPE_SWIZZLE_ZERO) { + srcSwizzle[i] = TGSI_SWIZZLE_X + i; + zeroWritemask |= (1 << i); + } + else if (swizzleIn[i] == PIPE_SWIZZLE_ONE) { + srcSwizzle[i] = TGSI_SWIZZLE_X + i; + oneWritemask |= (1 << i); + } + else { + srcSwizzle[i] = swizzleIn[i]; + srcWritemask |= (1 << i); + } + } + + /* write x/y/z/w comps */ + if (dst.mask & srcWritemask) { + if (!submit_op1(emit, + inst_token(SVGA3DOP_MOV), + writemask(dst, srcWritemask), + swizzle(src, + srcSwizzle[0], + srcSwizzle[1], + srcSwizzle[2], + srcSwizzle[3]))) + return FALSE; + } + + /* write 0 comps */ + if (dst.mask & zeroWritemask) { + if (!submit_op1(emit, + inst_token(SVGA3DOP_MOV), + writemask(dst, zeroWritemask), + scalar(get_zero_immediate(emit), TGSI_SWIZZLE_X))) + return FALSE; + } + + /* write 1 comps */ + if (dst.mask & oneWritemask) { + if (!submit_op1(emit, + inst_token(SVGA3DOP_MOV), + writemask(dst, oneWritemask), + scalar(get_zero_immediate(emit), TGSI_SWIZZLE_W))) + return FALSE; + } + + return TRUE; +} + + static boolean emit_tex(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn ) { @@ -1535,16 +1603,23 @@ static boolean emit_tex(struct svga_shader_emitter *emit, translate_src_register( emit, &insn->Src[1] ); SVGA3dShaderDestToken tex_result; + const unsigned unit = src1.base.num; /* check for shadow samplers */ - boolean compare = (emit->key.fkey.tex[src1.base.num].compare_mode == + boolean compare = (emit->key.fkey.tex[unit].compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE); + /* texture swizzle */ + boolean swizzle = (emit->key.fkey.tex[unit].swizzle_r != PIPE_SWIZZLE_RED || + emit->key.fkey.tex[unit].swizzle_g != PIPE_SWIZZLE_GREEN || + emit->key.fkey.tex[unit].swizzle_b != PIPE_SWIZZLE_BLUE || + emit->key.fkey.tex[unit].swizzle_a != PIPE_SWIZZLE_ALPHA); - /* If doing compare processing, need to put this value into a - * temporary so it can be used as a source later on. + /* If doing compare processing or tex swizzle, need to put fetched color into + * a temporary so it can be used as a source later on. */ if (compare || + swizzle || (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW) ) { tex_result = get_temp( emit ); } @@ -1570,8 +1645,18 @@ static boolean emit_tex(struct svga_shader_emitter *emit, if (compare) { + SVGA3dShaderDestToken dst2; + + if (swizzle) + dst2 = tex_result; + else + dst2 = dst; + if (dst.mask & TGSI_WRITEMASK_XYZ) { SVGA3dShaderDestToken src0_zdivw = get_temp( emit ); + /* When sampling a depth texture, the result of the comparison is in + * the Y component. + */ struct src_register tex_src_x = scalar(src(tex_result), TGSI_SWIZZLE_Y); /* Divide texcoord R by Q */ @@ -1588,8 +1673,8 @@ static boolean emit_tex(struct svga_shader_emitter *emit, if (!emit_select( emit, - emit->key.fkey.tex[src1.base.num].compare_func, - writemask( dst, TGSI_WRITEMASK_XYZ ), + emit->key.fkey.tex[unit].compare_func, + writemask( dst2, TGSI_WRITEMASK_XYZ ), scalar(src(src0_zdivw), TGSI_SWIZZLE_X), tex_src_x)) return FALSE; @@ -1600,15 +1685,29 @@ static boolean emit_tex(struct svga_shader_emitter *emit, scalar( get_zero_immediate( emit ), TGSI_SWIZZLE_W ); if (!submit_op1( emit, inst_token( SVGA3DOP_MOV ), - writemask( dst, TGSI_WRITEMASK_W ), + writemask( dst2, TGSI_WRITEMASK_W ), one )) return FALSE; } + } - return TRUE; + if (swizzle) { + /* swizzle from tex_result to dst */ + emit_tex_swizzle(emit, + dst, src(tex_result), + emit->key.fkey.tex[unit].swizzle_r, + emit->key.fkey.tex[unit].swizzle_g, + emit->key.fkey.tex[unit].swizzle_b, + emit->key.fkey.tex[unit].swizzle_a); } - else if (!emit->use_sm30 && dst.mask != TGSI_WRITEMASK_XYZW) - { + + if (!emit->use_sm30 && + dst.mask != TGSI_WRITEMASK_XYZW && + !compare && + !swizzle) { + /* pre SM3.0 a TEX instruction can't have a writemask. Do it as a + * separate step here. + */ if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), dst, src(tex_result) )) return FALSE; } @@ -2934,6 +3033,15 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) if (emit->inverted_texcoords) return TRUE; + + /* look for any PIPE_SWIZZLE_ZERO/ONE terms */ + for (i = 0; i < emit->key.fkey.num_textures; i++) { + if (emit->key.fkey.tex[i].swizzle_r > PIPE_SWIZZLE_ALPHA || + emit->key.fkey.tex[i].swizzle_g > PIPE_SWIZZLE_ALPHA || + emit->key.fkey.tex[i].swizzle_b > PIPE_SWIZZLE_ALPHA || + emit->key.fkey.tex[i].swizzle_a > PIPE_SWIZZLE_ALPHA) + return TRUE; + } } if (emit->unit == PIPE_SHADER_VERTEX) { -- 2.30.2