X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_simple_shaders.c;h=983307ead731956bc29a397120f0b49c86769c98;hb=dffeaa55dd1155d7a1e8feb5ecfc54fff688fcd8;hp=76950a1a9cf12ee6b272494f58cc93737bfbc110;hpb=2c3f95d6aaab38cd66dd3dee1b089d5c91928eea;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index 76950a1a9cf..983307ead73 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -41,6 +41,7 @@ #include "util/u_simple_shaders.h" #include "util/u_debug.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_strings.h" #include "tgsi/tgsi_ureg.h" @@ -58,28 +59,28 @@ void * util_make_vertex_passthrough_shader(struct pipe_context *pipe, uint num_attribs, - const uint *semantic_names, + const enum tgsi_semantic *semantic_names, const uint *semantic_indexes, bool window_space) { return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, semantic_names, semantic_indexes, - window_space, NULL); + window_space, false, NULL); } void * util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, uint num_attribs, - const uint *semantic_names, + const enum tgsi_semantic *semantic_names, const uint *semantic_indexes, - bool window_space, + bool window_space, bool layered, const struct pipe_stream_output_info *so) { struct ureg_program *ureg; uint i; - ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + ureg = ureg_create( PIPE_SHADER_VERTEX ); if (!ureg) return NULL; @@ -99,6 +100,15 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, ureg_MOV( ureg, dst, src ); } + if (layered) { + struct ureg_src instance_id = + ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0); + struct ureg_dst layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); + + ureg_MOV(ureg, ureg_writemask(layer, TGSI_WRITEMASK_X), + ureg_scalar(instance_id, TGSI_SWIZZLE_X)); + } + ureg_END( ureg ); return ureg_create_shader_with_so_and_destroy( ureg, pipe, so ); @@ -107,27 +117,13 @@ util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe) { - static const char text[] = - "VERT\n" - "DCL IN[0]\n" - "DCL IN[1]\n" - "DCL SV[0], INSTANCEID\n" - "DCL OUT[0], POSITION\n" - "DCL OUT[1], GENERIC[0]\n" - "DCL OUT[2], LAYER\n" + const enum tgsi_semantic semantic_names[] = {TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC}; + const unsigned semantic_indices[] = {0, 0}; - "MOV OUT[0], IN[0]\n" - "MOV OUT[1], IN[1]\n" - "MOV OUT[2], SV[0]\n" - "END\n"; - struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; - - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { - assert(0); - return NULL; - } - return pipe->create_vs_state(pipe, &state); + return util_make_vertex_passthrough_shader_with_so(pipe, 2, semantic_names, + semantic_indices, false, + true, NULL); } /** @@ -149,12 +145,13 @@ void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe) "MOV OUT[2].x, SV[0].xxxx\n" "END\n"; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } + pipe_shader_state_from_tgsi(&state, tokens); return pipe->create_vs_state(pipe, &state); } @@ -192,42 +189,120 @@ void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe) "EMIT IMM[0].xxxx\n" "END\n"; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } + pipe_shader_state_from_tgsi(&state, tokens); return pipe->create_gs_state(pipe, &state); } +static void +ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out, + struct ureg_src coord, struct ureg_src sampler, + enum tgsi_texture_type tex_target, + bool load_level_zero, bool use_txf) +{ + if (use_txf) { + struct ureg_dst temp = ureg_DECL_temporary(ureg); + + ureg_F2I(ureg, temp, coord); + + if (load_level_zero) + ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler); + else + ureg_TXF(ureg, out, tex_target, ureg_src(temp), sampler); + } else { + if (load_level_zero) + ureg_TEX_LZ(ureg, out, tex_target, coord, sampler); + else + ureg_TEX(ureg, out, tex_target, coord, sampler); + } +} + +/** + * Make simple fragment texture shader, with xrbias->float conversion: + * IMM {1023/510, -384/510, 0, 1} + * TEX TEMP[0], IN[0], SAMP[0], 2D; + * MAD TEMP[0].xyz TEMP[0], IMM[0].xxxx, IMM[0].yyyy + * MOV OUT[0], TEMP[0] + * END; + * + * \param tex_target one of PIPE_TEXTURE_x + */ +void * +util_make_fragment_tex_shader_xrbias(struct pipe_context *pipe, + enum tgsi_texture_type tex_target) +{ + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src coord; + struct ureg_dst temp; + struct ureg_dst out; + struct ureg_src imm; + enum tgsi_return_type stype = TGSI_RETURN_TYPE_FLOAT; + + ureg = ureg_create(PIPE_SHADER_FRAGMENT); + if (!ureg) + return NULL; + + imm = ureg_imm4f(ureg, 1023.0f/510.0f, -384.0f/510.0f, 0.0f, 1.0f); + sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, stype, stype, stype, stype); + coord = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + temp = ureg_DECL_temporary(ureg); + + ureg_TEX(ureg, temp, tex_target, coord, sampler); + ureg_MAD(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZ), + ureg_src(temp), + ureg_scalar(imm, TGSI_SWIZZLE_X), + ureg_scalar(imm, TGSI_SWIZZLE_Y)); + ureg_MOV(ureg, out, ureg_src(temp)); + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + + /** * Make simple fragment texture shader: * IMM {0,0,0,1} // (if writemask != 0xf) - * MOV OUT[0], IMM[0] // (if writemask != 0xf) - * TEX OUT[0].writemask, IN[0], SAMP[0], 2D; + * MOV TEMP[0], IMM[0] // (if writemask != 0xf) + * TEX TEMP[0].writemask, IN[0], SAMP[0], 2D; + * .. optional SINT <-> UINT clamping .. + * MOV OUT[0], TEMP[0] * END; * - * \param tex_target one of PIPE_TEXTURE_x + * \param tex_target one of TGSI_TEXTURE_x * \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE * \param writemask mask of TGSI_WRITEMASK_x */ void * util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, - unsigned tex_target, - unsigned interp_mode, + enum tgsi_texture_type tex_target, + enum tgsi_interpolate_mode interp_mode, unsigned writemask, - enum tgsi_return_type stype) + enum tgsi_return_type stype, + enum tgsi_return_type dtype, + bool load_level_zero, + bool use_txf) { struct ureg_program *ureg; struct ureg_src sampler; struct ureg_src tex; + struct ureg_dst temp; struct ureg_dst out; + assert((stype == TGSI_RETURN_TYPE_FLOAT) == (dtype == TGSI_RETURN_TYPE_FLOAT)); assert(interp_mode == TGSI_INTERPOLATE_LINEAR || interp_mode == TGSI_INTERPOLATE_PERSPECTIVE); - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + ureg = ureg_create( PIPE_SHADER_FRAGMENT ); if (!ureg) return NULL; @@ -243,20 +318,36 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, TGSI_SEMANTIC_COLOR, 0 ); + temp = ureg_DECL_temporary(ureg); + if (writemask != TGSI_WRITEMASK_XYZW) { struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); - ureg_MOV( ureg, out, imm ); + ureg_MOV(ureg, temp, imm); } if (tex_target == TGSI_TEXTURE_BUFFER) ureg_TXF(ureg, - ureg_writemask(out, writemask), + ureg_writemask(temp, writemask), tex_target, tex, sampler); else - ureg_TEX(ureg, - ureg_writemask(out, writemask), - tex_target, tex, sampler); + ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler, + tex_target, load_level_zero, use_txf); + + if (stype != dtype) { + if (stype == TGSI_RETURN_TYPE_SINT) { + assert(dtype == TGSI_RETURN_TYPE_UINT); + + ureg_IMAX(ureg, temp, ureg_src(temp), ureg_imm1i(ureg, 0)); + } else { + assert(stype == TGSI_RETURN_TYPE_UINT); + assert(dtype == TGSI_RETURN_TYPE_SINT); + + ureg_UMIN(ureg, temp, ureg_src(temp), ureg_imm1u(ureg, (1u << 31) - 1)); + } + } + + ureg_MOV(ureg, out, ureg_src(temp)); ureg_END( ureg ); @@ -267,70 +358,23 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, /** * Make a simple fragment shader that sets the output color to a color * taken from a texture. - * \param tex_target one of PIPE_TEXTURE_x + * \param tex_target one of TGSI_TEXTURE_x */ void * -util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target, - unsigned interp_mode, - enum tgsi_return_type stype) +util_make_fragment_tex_shader(struct pipe_context *pipe, + enum tgsi_texture_type tex_target, + enum tgsi_interpolate_mode interp_mode, + enum tgsi_return_type stype, + enum tgsi_return_type dtype, + bool load_level_zero, + bool use_txf) { return util_make_fragment_tex_shader_writemask( pipe, tex_target, interp_mode, TGSI_WRITEMASK_XYZW, - stype ); -} - - -/** - * Make a simple fragment texture shader which reads an X component from - * a texture and writes it as depth. - */ -void * -util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, - unsigned tex_target, - unsigned interp_mode) -{ - struct ureg_program *ureg; - struct ureg_src sampler; - struct ureg_src tex; - struct ureg_dst out, depth; - struct ureg_src imm; - - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (!ureg) - return NULL; - - sampler = ureg_DECL_sampler( ureg, 0 ); - - ureg_DECL_sampler_view(ureg, 0, tex_target, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT); - - tex = ureg_DECL_fs_input( ureg, - TGSI_SEMANTIC_GENERIC, 0, - interp_mode ); - - out = ureg_DECL_output( ureg, - TGSI_SEMANTIC_COLOR, - 0 ); - - depth = ureg_DECL_output( ureg, - TGSI_SEMANTIC_POSITION, - 0 ); - - imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); - - ureg_MOV( ureg, out, imm ); - - ureg_TEX( ureg, - ureg_writemask(depth, TGSI_WRITEMASK_Z), - tex_target, tex, sampler ); - ureg_END( ureg ); - - return ureg_create_shader_and_destroy( ureg, pipe ); + stype, dtype, load_level_zero, + use_txf); } @@ -339,114 +383,57 @@ util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe, * and writes it as depth and stencil, respectively. */ void * -util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe, - unsigned tex_target, - unsigned interp_mode) -{ - struct ureg_program *ureg; - struct ureg_src depth_sampler, stencil_sampler; - struct ureg_src tex; - struct ureg_dst out, depth, stencil; - struct ureg_src imm; - - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (!ureg) - return NULL; - - depth_sampler = ureg_DECL_sampler( ureg, 0 ); - ureg_DECL_sampler_view(ureg, 0, tex_target, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT, - TGSI_RETURN_TYPE_FLOAT); - stencil_sampler = ureg_DECL_sampler( ureg, 1 ); - ureg_DECL_sampler_view(ureg, 0, tex_target, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT); - - tex = ureg_DECL_fs_input( ureg, - TGSI_SEMANTIC_GENERIC, 0, - interp_mode ); - - out = ureg_DECL_output( ureg, - TGSI_SEMANTIC_COLOR, - 0 ); - - depth = ureg_DECL_output( ureg, - TGSI_SEMANTIC_POSITION, - 0 ); - - stencil = ureg_DECL_output( ureg, - TGSI_SEMANTIC_STENCIL, - 0 ); - - imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); - - ureg_MOV( ureg, out, imm ); - - ureg_TEX( ureg, - ureg_writemask(depth, TGSI_WRITEMASK_Z), - tex_target, tex, depth_sampler ); - ureg_TEX( ureg, - ureg_writemask(stencil, TGSI_WRITEMASK_Y), - tex_target, tex, stencil_sampler ); - ureg_END( ureg ); - - return ureg_create_shader_and_destroy( ureg, pipe ); -} - - -/** - * Make a simple fragment texture shader which reads a texture and writes it - * as stencil. - */ -void * -util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe, - unsigned tex_target, - unsigned interp_mode) +util_make_fs_blit_zs(struct pipe_context *pipe, unsigned zs_mask, + enum tgsi_texture_type tex_target, + bool load_level_zero, bool use_txf) { struct ureg_program *ureg; - struct ureg_src stencil_sampler; - struct ureg_src tex; - struct ureg_dst out, stencil; - struct ureg_src imm; + struct ureg_src depth_sampler, stencil_sampler, coord; + struct ureg_dst depth, stencil, tmp; - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + ureg = ureg_create(PIPE_SHADER_FRAGMENT); if (!ureg) return NULL; - stencil_sampler = ureg_DECL_sampler( ureg, 0 ); + coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + tmp = ureg_DECL_temporary(ureg); - ureg_DECL_sampler_view(ureg, 0, tex_target, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT, - TGSI_RETURN_TYPE_UINT); + if (zs_mask & PIPE_MASK_Z) { + depth_sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT); - tex = ureg_DECL_fs_input( ureg, - TGSI_SEMANTIC_GENERIC, 0, - interp_mode ); + ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord, + depth_sampler, tex_target, load_level_zero, use_txf); - out = ureg_DECL_output( ureg, - TGSI_SEMANTIC_COLOR, - 0 ); + depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Z), + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); + } - stencil = ureg_DECL_output( ureg, - TGSI_SEMANTIC_STENCIL, - 0 ); + if (zs_mask & PIPE_MASK_S) { + stencil_sampler = ureg_DECL_sampler(ureg, zs_mask & PIPE_MASK_Z ? 1 : 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT); - imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); + ureg_load_tex(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), coord, + stencil_sampler, tex_target, load_level_zero, use_txf); - ureg_MOV( ureg, out, imm ); + stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0); + ureg_MOV(ureg, ureg_writemask(stencil, TGSI_WRITEMASK_Y), + ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X)); + } - ureg_TEX( ureg, - ureg_writemask(stencil, TGSI_WRITEMASK_Y), - tex_target, tex, stencil_sampler ); - ureg_END( ureg ); + ureg_END(ureg); - return ureg_create_shader_and_destroy( ureg, pipe ); + return ureg_create_shader_and_destroy(ureg, pipe); } @@ -471,17 +458,18 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe, char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; sprintf(text, shader_templ, write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "", tgsi_semantic_names[input_semantic], tgsi_interpolate_names[input_interpolate]); - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } + pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif @@ -493,7 +481,7 @@ util_make_fragment_passthrough_shader(struct pipe_context *pipe, void * util_make_empty_fragment_shader(struct pipe_context *pipe) { - struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + struct ureg_program *ureg = ureg_create(PIPE_SHADER_FRAGMENT); if (!ureg) return NULL; @@ -517,7 +505,7 @@ util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, assert(num_cbufs <= PIPE_MAX_COLOR_BUFS); - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + ureg = ureg_create( PIPE_SHADER_FRAGMENT ); if (!ureg) return NULL; @@ -538,10 +526,12 @@ util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, static void * util_make_fs_blit_msaa_gen(struct pipe_context *pipe, - unsigned tgsi_tex, + enum tgsi_texture_type tgsi_tex, const char *samp_type, const char *output_semantic, - const char *output_mask) + const char *output_mask, + const char *conversion_decl, + const char *conversion) { static const char shader_templ[] = "FRAG\n" @@ -550,27 +540,31 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe, "DCL SVIEW[0], %s, %s\n" "DCL OUT[0], %s\n" "DCL TEMP[0]\n" + "%s" "F2U TEMP[0], IN[0]\n" - "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n" + "TXF TEMP[0], TEMP[0], SAMP[0], %s\n" + "%s" + "MOV OUT[0]%s, TEMP[0]\n" "END\n"; const char *type = tgsi_texture_names[tgsi_tex]; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); - sprintf(text, shader_templ, type, samp_type, - output_semantic, output_mask, type); + snprintf(text, sizeof(text), shader_templ, type, samp_type, + output_semantic, conversion_decl, type, conversion, output_mask); - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { puts(text); assert(0); return NULL; } + pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif @@ -586,20 +580,36 @@ util_make_fs_blit_msaa_gen(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_color(struct pipe_context *pipe, - unsigned tgsi_tex, - enum tgsi_return_type stype) + enum tgsi_texture_type tgsi_tex, + enum tgsi_return_type stype, + enum tgsi_return_type dtype) { const char *samp_type; + const char *conversion_decl = ""; + const char *conversion = ""; - if (stype == TGSI_RETURN_TYPE_UINT) + if (stype == TGSI_RETURN_TYPE_UINT) { samp_type = "UINT"; - else if (stype == TGSI_RETURN_TYPE_SINT) + + if (dtype == TGSI_RETURN_TYPE_SINT) { + conversion_decl = "IMM[0] UINT32 {2147483647, 0, 0, 0}\n"; + conversion = "UMIN TEMP[0], TEMP[0], IMM[0].xxxx\n"; + } + } else if (stype == TGSI_RETURN_TYPE_SINT) { samp_type = "SINT"; - else + + if (dtype == TGSI_RETURN_TYPE_UINT) { + conversion_decl = "IMM[0] INT32 {0, 0, 0, 0}\n"; + conversion = "IMAX TEMP[0], TEMP[0], IMM[0].xxxx\n"; + } + } else { + assert(dtype == TGSI_RETURN_TYPE_FLOAT); samp_type = "FLOAT"; + } return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type, - "COLOR[0]", ""); + "COLOR[0]", "", conversion_decl, + conversion); } @@ -610,10 +620,10 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_depth(struct pipe_context *pipe, - unsigned tgsi_tex) + enum tgsi_texture_type tgsi_tex) { return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT", - "POSITION", ".z"); + "POSITION", ".z", "", ""); } @@ -624,10 +634,10 @@ util_make_fs_blit_msaa_depth(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, - unsigned tgsi_tex) + enum tgsi_texture_type tgsi_tex) { return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT", - "STENCIL", ".y"); + "STENCIL", ".y", "", ""); } @@ -640,7 +650,7 @@ util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, - unsigned tgsi_tex) + enum tgsi_texture_type tgsi_tex) { static const char shader_templ[] = "FRAG\n" @@ -659,17 +669,18 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, const char *type = tgsi_texture_names[tgsi_tex]; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; - struct pipe_shader_state state = {tokens}; + struct pipe_shader_state state; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); sprintf(text, shader_templ, type, type, type); - if (!tgsi_text_translate(text, tokens, Elements(tokens))) { + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } + pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif @@ -680,15 +691,15 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, void * util_make_fs_msaa_resolve(struct pipe_context *pipe, - unsigned tgsi_tex, unsigned nr_samples, + enum tgsi_texture_type tgsi_tex, unsigned nr_samples, enum tgsi_return_type stype) { struct ureg_program *ureg; struct ureg_src sampler, coord; struct ureg_dst out, tmp_sum, tmp_coord, tmp; - int i; + unsigned i; - ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + ureg = ureg_create(PIPE_SHADER_FRAGMENT); if (!ureg) return NULL; @@ -740,16 +751,17 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, void * util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, - unsigned tgsi_tex, unsigned nr_samples, + enum tgsi_texture_type tgsi_tex, + unsigned nr_samples, enum tgsi_return_type stype) { struct ureg_program *ureg; struct ureg_src sampler, coord; struct ureg_dst out, tmp, top, bottom; struct ureg_dst tmp_coord[4], tmp_sum[4]; - int i, c; + unsigned i, c; - ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + ureg = ureg_create(PIPE_SHADER_FRAGMENT); if (!ureg) return NULL; @@ -848,7 +860,7 @@ util_make_geometry_passthrough_shader(struct pipe_context *pipe, unsigned i; - ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY); + ureg = ureg_create(PIPE_SHADER_GEOMETRY); if (!ureg) return NULL; @@ -875,7 +887,7 @@ util_make_geometry_passthrough_shader(struct pipe_context *pipe, } /* EMIT IMM[0] */ - ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1); + ureg_insn(ureg, TGSI_OPCODE_EMIT, NULL, 0, &imm, 1, 0); /* END */ ureg_END(ureg); @@ -883,3 +895,164 @@ util_make_geometry_passthrough_shader(struct pipe_context *pipe, return ureg_create_shader_and_destroy(ureg, pipe); } +/** + * Blit from color to ZS or from ZS to color in a manner that is equivalent + * to memcpy. + * + * Color is either R32_UINT (for Z24S8 / S8Z24) or R32G32_UINT (Z32_S8X24). + * + * Depth and stencil samplers are used to load depth and stencil, + * and they are packed and the result is written to a color output. + * OR + * A color sampler is used to load a color value, which is unpacked and + * written to depth and stencil shader outputs. + */ +void * +util_make_fs_pack_color_zs(struct pipe_context *pipe, + enum tgsi_texture_type tex_target, + enum pipe_format zs_format, + bool dst_is_color) +{ + struct ureg_program *ureg; + struct ureg_src depth_sampler, stencil_sampler, color_sampler, coord; + struct ureg_dst out, depth, depth_x, stencil, out_depth, out_stencil, color; + + assert(zs_format == PIPE_FORMAT_Z24_UNORM_S8_UINT || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT || /* color is R32G32_UINT */ + zs_format == PIPE_FORMAT_Z24X8_UNORM || /* color is R32_UINT */ + zs_format == PIPE_FORMAT_X8Z24_UNORM); /* color is R32_UINT */ + + bool has_stencil = zs_format != PIPE_FORMAT_Z24X8_UNORM && + zs_format != PIPE_FORMAT_X8Z24_UNORM; + bool is_z24 = zs_format != PIPE_FORMAT_Z32_FLOAT_S8X24_UINT; + bool z24_is_high = zs_format == PIPE_FORMAT_S8_UINT_Z24_UNORM || + zs_format == PIPE_FORMAT_X8Z24_UNORM; + + ureg = ureg_create(PIPE_SHADER_FRAGMENT); + if (!ureg) + return NULL; + + coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_LINEAR); + + if (dst_is_color) { + /* Load depth. */ + depth_sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT); + + depth = ureg_DECL_temporary(ureg); + depth_x = ureg_writemask(depth, TGSI_WRITEMASK_X); + ureg_load_tex(ureg, depth_x, coord, depth_sampler, tex_target, true, true); + + /* Pack to Z24. */ + if (is_z24) { + double imm = 0xffffff; + struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2); + struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg), + TGSI_WRITEMASK_XY); + + ureg_F2D(ureg, tmp_xy, ureg_src(depth)); + ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64); + ureg_D2U(ureg, depth_x, ureg_src(tmp_xy)); + + if (z24_is_high) + ureg_SHL(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 8)); + else + ureg_AND(ureg, depth_x, ureg_src(depth), ureg_imm1u(ureg, 0xffffff)); + } + + if (has_stencil) { + /* Load stencil. */ + stencil_sampler = ureg_DECL_sampler(ureg, 1); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT); + + stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + ureg_load_tex(ureg, stencil, coord, stencil_sampler, tex_target, + true, true); + + /* Pack stencil into depth. */ + if (is_z24) { + if (!z24_is_high) + ureg_SHL(ureg, stencil, ureg_src(stencil), ureg_imm1u(ureg, 24)); + + ureg_OR(ureg, depth_x, ureg_src(depth), ureg_src(stencil)); + } + } + + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + + if (is_z24) { + ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_X), ureg_src(depth)); + } else { + /* Z32_S8X24 */ + ureg_MOV(ureg, ureg_writemask(depth, TGSI_WRITEMASK_Y), + ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X)); + ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_XY), ureg_src(depth)); + } + } else { + color_sampler = ureg_DECL_sampler(ureg, 0); + ureg_DECL_sampler_view(ureg, 0, tex_target, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT, + TGSI_RETURN_TYPE_UINT); + + color = ureg_DECL_temporary(ureg); + ureg_load_tex(ureg, color, coord, color_sampler, tex_target, true, true); + + depth = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + stencil = ureg_writemask(ureg_DECL_temporary(ureg), TGSI_WRITEMASK_X); + + if (is_z24) { + double imm = 1.0 / 0xffffff; + struct ureg_src imm_f64 = ureg_DECL_immediate_f64(ureg, &imm, 2); + struct ureg_dst tmp_xy = ureg_writemask(ureg_DECL_temporary(ureg), + TGSI_WRITEMASK_XY); + + ureg_UBFE(ureg, depth, ureg_src(color), + ureg_imm1u(ureg, z24_is_high ? 8 : 0), + ureg_imm1u(ureg, 24)); + ureg_U2D(ureg, tmp_xy, ureg_src(depth)); + ureg_DMUL(ureg, tmp_xy, ureg_src(tmp_xy), imm_f64); + ureg_D2F(ureg, depth, ureg_src(tmp_xy)); + } else { + /* depth = color.x; (Z32_S8X24) */ + ureg_MOV(ureg, depth, ureg_src(color)); + } + + out_depth = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + ureg_MOV(ureg, ureg_writemask(out_depth, TGSI_WRITEMASK_Z), + ureg_scalar(ureg_src(depth), TGSI_SWIZZLE_X)); + + if (has_stencil) { + if (is_z24) { + ureg_UBFE(ureg, stencil, ureg_src(color), + ureg_imm1u(ureg, z24_is_high ? 0 : 24), + ureg_imm1u(ureg, 8)); + } else { + /* stencil = color.y[0:7]; (Z32_S8X24) */ + ureg_UBFE(ureg, stencil, + ureg_scalar(ureg_src(color), TGSI_SWIZZLE_Y), + ureg_imm1u(ureg, 0), + ureg_imm1u(ureg, 8)); + } + + out_stencil = ureg_DECL_output(ureg, TGSI_SEMANTIC_STENCIL, 0); + ureg_MOV(ureg, ureg_writemask(out_stencil, TGSI_WRITEMASK_Y), + ureg_scalar(ureg_src(stencil), TGSI_SWIZZLE_X)); + } + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +}