diff options
Diffstat (limited to 'src/gallium/auxiliary/util/u_simple_shaders.c')
-rw-r--r-- | src/gallium/auxiliary/util/u_simple_shaders.c | 603 |
1 files changed, 368 insertions, 235 deletions
diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index aaaa0434804..9ecb041bdd9 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -58,9 +58,9 @@ */ void * util_make_vertex_passthrough_shader(struct pipe_context *pipe, - uint num_attribs, + unsigned num_attribs, const enum tgsi_semantic *semantic_names, - const uint *semantic_indexes, + const unsigned *semantic_indexes, bool window_space) { return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs, @@ -71,21 +71,21 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, void * util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe, - uint num_attribs, + unsigned num_attribs, const enum tgsi_semantic *semantic_names, - const uint *semantic_indexes, + const unsigned *semantic_indexes, bool window_space, bool layered, const struct pipe_stream_output_info *so) { struct ureg_program *ureg; - uint i; + unsigned i; ureg = ureg_create( PIPE_SHADER_VERTEX ); if (!ureg) return NULL; if (window_space) - ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE); + ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, true); for (i = 0; i < num_attribs; i++) { struct ureg_src src; @@ -208,7 +208,21 @@ ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out, if (use_txf) { struct ureg_dst temp = ureg_DECL_temporary(ureg); - ureg_F2I(ureg, temp, coord); + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + * u_blitter only uses this when the coordinates are in bounds, + * so no clamping is needed and we can use trunc instead of floor. trunc + * with f2i will get optimized out in NIR where f2i has round-to-zero + * behaviour already. + */ + unsigned wrmask = tex_target == TGSI_TEXTURE_1D || + tex_target == TGSI_TEXTURE_1D_ARRAY ? TGSI_WRITEMASK_X : + tex_target == TGSI_TEXTURE_3D ? TGSI_WRITEMASK_XYZ : + TGSI_WRITEMASK_XY; + + ureg_MOV(ureg, temp, coord); + ureg_TRUNC(ureg, ureg_writemask(temp, wrmask), ureg_src(temp)); + ureg_F2I(ureg, temp, ureg_src(temp)); if (load_level_zero) ureg_TXF_LZ(ureg, out, tex_target, ureg_src(temp), sampler); @@ -223,74 +237,21 @@ ureg_load_tex(struct ureg_program *ureg, struct ureg_dst out, } /** - * 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 TEMP[0], IMM[0] // (if writemask != 0xf) - * TEX TEMP[0].writemask, IN[0], SAMP[0], 2D; + * TEX TEMP[0], IN[0], SAMP[0], 2D; * .. optional SINT <-> UINT clamping .. * MOV OUT[0], TEMP[0] * END; * * \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, - enum tgsi_texture_type tex_target, - enum tgsi_interpolate_mode interp_mode, - unsigned writemask, - enum tgsi_return_type stype, - enum tgsi_return_type dtype, - bool load_level_zero, - bool use_txf) +util_make_fragment_tex_shader(struct pipe_context *pipe, + enum tgsi_texture_type tex_target, + 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; @@ -299,8 +260,6 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 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( PIPE_SHADER_FRAGMENT ); if (!ureg) @@ -312,7 +271,7 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, tex = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_GENERIC, 0, - interp_mode ); + TGSI_INTERPOLATE_LINEAR ); out = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, @@ -320,18 +279,12 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, temp = ureg_DECL_temporary(ureg); - if (writemask != TGSI_WRITEMASK_XYZW) { - struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 ); - - ureg_MOV(ureg, temp, imm); - } - if (tex_target == TGSI_TEXTURE_BUFFER) ureg_TXF(ureg, - ureg_writemask(temp, writemask), + ureg_writemask(temp, TGSI_WRITEMASK_XYZW), tex_target, tex, sampler); else - ureg_load_tex(ureg, ureg_writemask(temp, writemask), tex, sampler, + ureg_load_tex(ureg, ureg_writemask(temp, TGSI_WRITEMASK_XYZW), tex, sampler, tex_target, load_level_zero, use_txf); if (stype != dtype) { @@ -354,30 +307,6 @@ util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, return ureg_create_shader_and_destroy( ureg, pipe ); } - -/** - * Make a simple fragment shader that sets the output color to a color - * taken from a texture. - * \param tex_target one of TGSI_TEXTURE_x - */ -void * -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, dtype, load_level_zero, - use_txf); -} - - /** * Make a simple fragment texture shader which reads the texture unit 0 and 1 * and writes it as depth and stencil, respectively. @@ -445,7 +374,7 @@ void * util_make_fragment_passthrough_shader(struct pipe_context *pipe, int input_semantic, int input_interpolate, - boolean write_all_cbufs) + bool write_all_cbufs) { static const char shader_templ[] = "FRAG\n" @@ -527,37 +456,90 @@ util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs, static void * util_make_fs_blit_msaa_gen(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex, + bool sample_shading, bool has_txq, const char *samp_type, const char *output_semantic, const char *output_mask, - const char *conversion_decl, const char *conversion) { - static const char shader_templ[] = - "FRAG\n" - "DCL IN[0], GENERIC[0], LINEAR\n" - "DCL SAMP[0]\n" - "DCL SVIEW[0], %s, %s\n" - "DCL OUT[0], %s\n" - "DCL TEMP[0]\n" - "%s" - - "F2U TEMP[0], IN[0]\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]; + char text[1000]; struct tgsi_token tokens[1000]; struct pipe_shader_state state = {0}; - assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || - tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); - - snprintf(text, sizeof(text), shader_templ, type, samp_type, - output_semantic, conversion_decl, type, conversion, output_mask); + if (has_txq) { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL SVIEW[0], %s, %s\n" + "DCL OUT[0], %s\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 2147483647, 0}\n" + "%s" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Clamp to edge for the upper bound. */ + "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n" + "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */ + "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n" + /* Texel fetch. */ + "%s" + "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]; + + assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || + tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); + + snprintf(text, sizeof(text), shader_templ, type, samp_type, + output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "", + type, sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "", + type, conversion, output_mask); + } else { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL SVIEW[0], %s, %s\n" + "DCL OUT[0], %s\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 2147483647, 0}\n" + "%s" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp + * to dim - 1 because TXQ is unsupported. + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Texel fetch. */ + "%s" + "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]; + + assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || + tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); + + snprintf(text, sizeof(text), shader_templ, type, samp_type, + output_semantic, sample_shading ? "DCL SV[0], SAMPLEID\n" : "", + sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "", + type, conversion, output_mask); + } if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { puts(text); @@ -582,24 +564,22 @@ void * util_make_fs_blit_msaa_color(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex, enum tgsi_return_type stype, - enum tgsi_return_type dtype) + enum tgsi_return_type dtype, + bool sample_shading, bool has_txq) { const char *samp_type; - const char *conversion_decl = ""; const char *conversion = ""; if (stype == TGSI_RETURN_TYPE_UINT) { samp_type = "UINT"; 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"; + conversion = "UMIN TEMP[0], TEMP[0], IMM[0].zzzz\n"; } } else if (stype == TGSI_RETURN_TYPE_SINT) { samp_type = "SINT"; 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 { @@ -607,9 +587,8 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe, samp_type = "FLOAT"; } - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, samp_type, - "COLOR[0]", "", conversion_decl, - conversion); + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq, + samp_type, "COLOR[0]", "", conversion); } @@ -620,10 +599,12 @@ util_make_fs_blit_msaa_color(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_depth(struct pipe_context *pipe, - enum tgsi_texture_type tgsi_tex) + enum tgsi_texture_type tgsi_tex, + bool sample_shading, bool has_txq) { - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "FLOAT", - "POSITION", ".z", "", ""); + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq, + "FLOAT", "POSITION", ".z", + "MOV TEMP[0].z, TEMP[0].xxxx\n"); } @@ -634,10 +615,12 @@ util_make_fs_blit_msaa_depth(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, - enum tgsi_texture_type tgsi_tex) + enum tgsi_texture_type tgsi_tex, + bool sample_shading, bool has_txq) { - return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, "UINT", - "STENCIL", ".y", "", ""); + return util_make_fs_blit_msaa_gen(pipe, tgsi_tex, sample_shading, has_txq, + "UINT", "STENCIL", ".y", + "MOV TEMP[0].y, TEMP[0].xxxx\n"); } @@ -650,32 +633,83 @@ util_make_fs_blit_msaa_stencil(struct pipe_context *pipe, */ void * util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, - enum tgsi_texture_type tgsi_tex) + enum tgsi_texture_type tgsi_tex, + bool sample_shading, bool has_txq) { - static const char shader_templ[] = - "FRAG\n" - "DCL IN[0], GENERIC[0], LINEAR\n" - "DCL SAMP[0..1]\n" - "DCL SVIEW[0], %s, FLOAT\n" - "DCL SVIEW[1], %s, UINT\n" - "DCL OUT[0], POSITION\n" - "DCL OUT[1], STENCIL\n" - "DCL TEMP[0]\n" - - "F2U TEMP[0], IN[0]\n" - "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" - "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" - "END\n"; - const char *type = tgsi_texture_names[tgsi_tex]; - char text[sizeof(shader_templ)+100]; + char text[1000]; struct tgsi_token tokens[1000]; struct pipe_shader_state state = {0}; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); - sprintf(text, shader_templ, type, type, type, type); + if (has_txq) { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0..1]\n" + "DCL SVIEW[0], %s, FLOAT\n" + "DCL SVIEW[1], %s, UINT\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], STENCIL\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 0, 0}\n" + "%s" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Clamp to edge for the upper bound. */ + "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n" + "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */ + "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n" + /* Texel fetch. */ + "%s" + "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" + "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" + "END\n"; + + sprintf(text, shader_templ, type, type, + sample_shading ? "DCL SV[0], SAMPLEID\n" : "", type, + sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "", + type, type); + } else { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0..1]\n" + "DCL SVIEW[0], %s, FLOAT\n" + "DCL SVIEW[1], %s, UINT\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], STENCIL\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 0, 0}\n" + "%s" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). Don't clamp + * to dim - 1 because TXQ is unsupported. + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Texel fetch. */ + "%s" + "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" + "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" + "END\n"; + + sprintf(text, shader_templ, type, type, + sample_shading ? "DCL SV[0], SAMPLEID\n" : "", + sample_shading ? "MOV TEMP[0].w, SV[0].xxxx\n" : "", + type, type); + } if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); @@ -693,7 +727,7 @@ util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, void * util_make_fs_msaa_resolve(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex, unsigned nr_samples, - enum tgsi_return_type stype) + bool has_txq) { struct ureg_program *ureg; struct ureg_src sampler, coord; @@ -706,7 +740,9 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, /* Declarations. */ sampler = ureg_DECL_sampler(ureg, 0); - ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype); + ureg_DECL_sampler_view(ureg, 0, tgsi_tex, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR); out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); @@ -716,7 +752,25 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, /* Instructions. */ ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0)); - ureg_F2U(ureg, tmp_coord, coord); + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + */ + ureg_MOV(ureg, tmp_coord, coord); + ureg_FLR(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY), + ureg_src(tmp_coord)); + ureg_F2I(ureg, tmp_coord, ureg_src(tmp_coord)); + ureg_IMAX(ureg, tmp_coord, ureg_src(tmp_coord), ureg_imm1i(ureg, 0)); + + /* Clamp to edge for the upper bound. */ + if (has_txq) { + ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex, + ureg_imm1u(ureg, 0), sampler); + ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), + ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */ + ureg_IMIN(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_XY), + ureg_src(tmp_coord), ureg_src(tmp)); + } for (i = 0; i < nr_samples; i++) { /* Read one sample. */ @@ -724,26 +778,13 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, ureg_imm1u(ureg, i)); ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler); - if (stype == TGSI_RETURN_TYPE_UINT) - ureg_U2F(ureg, tmp, ureg_src(tmp)); - else if (stype == TGSI_RETURN_TYPE_SINT) - ureg_I2F(ureg, tmp, ureg_src(tmp)); - /* Add it to the sum.*/ ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp)); } /* Calculate the average and return. */ - ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum), + ureg_MUL(ureg, out, ureg_src(tmp_sum), ureg_imm1f(ureg, 1.0 / nr_samples)); - - if (stype == TGSI_RETURN_TYPE_UINT) - ureg_F2U(ureg, out, ureg_src(tmp_sum)); - else if (stype == TGSI_RETURN_TYPE_SINT) - ureg_F2I(ureg, out, ureg_src(tmp_sum)); - else - ureg_MOV(ureg, out, ureg_src(tmp_sum)); - ureg_END(ureg); return ureg_create_shader_and_destroy(ureg, pipe); @@ -753,13 +794,12 @@ util_make_fs_msaa_resolve(struct pipe_context *pipe, void * util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex, - unsigned nr_samples, - enum tgsi_return_type stype) + unsigned nr_samples, bool has_txq) { 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]; + struct ureg_dst tmp_coord[4], tmp_sum[4], weights; unsigned i, c; ureg = ureg_create(PIPE_SHADER_FRAGMENT); @@ -768,7 +808,9 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, /* Declarations. */ sampler = ureg_DECL_sampler(ureg, 0); - ureg_DECL_sampler_view(ureg, 0, tgsi_tex, stype, stype, stype, stype); + ureg_DECL_sampler_view(ureg, 0, tgsi_tex, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT, + TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT); coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_LINEAR); out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); @@ -778,21 +820,62 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, tmp_coord[c] = ureg_DECL_temporary(ureg); tmp = ureg_DECL_temporary(ureg); top = ureg_DECL_temporary(ureg); + weights = ureg_DECL_temporary(ureg); bottom = ureg_DECL_temporary(ureg); /* Instructions. */ for (c = 0; c < 4; c++) ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0)); - /* Get 4 texture coordinates for the bilinear filter. */ - ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */ - ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]), - ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */ - ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]), - ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */ + /* Bilinear filtering starts with subtracting 0.5 from unnormalized + * coordinates. + */ + ureg_MOV(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_ZW), coord); + ureg_ADD(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), coord, + ureg_imm2f(ureg, -0.5, -0.5)); + + /* Get the filter weights. */ + ureg_FRC(ureg, ureg_writemask(weights, TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[0])); + + /* Convert to integer by flooring to get the top-left coordinates. */ + ureg_FLR(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[0])); + ureg_F2I(ureg, tmp_coord[0], ureg_src(tmp_coord[0])); + + /* Get the bottom-right coordinates. */ ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]), ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */ + /* Clamp to edge. */ + if (has_txq) { + ureg_TXQ(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), tgsi_tex, + ureg_imm1u(ureg, 0), sampler); + ureg_UADD(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), + ureg_imm2i(ureg, -1, -1)); /* width - 1, height - 1 */ + + ureg_IMIN(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[0]), ureg_src(tmp)); + ureg_IMIN(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[3]), ureg_src(tmp)); + } + + ureg_IMAX(ureg, ureg_writemask(tmp_coord[0], TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[0]), ureg_imm2i(ureg, 0, 0)); + ureg_IMAX(ureg, ureg_writemask(tmp_coord[3], TGSI_WRITEMASK_XY), + ureg_src(tmp_coord[3]), ureg_imm2i(ureg, 0, 0)); + + /* Get the remaining top-right and bottom-left coordinates. */ + ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_X), + ureg_src(tmp_coord[3])); + ureg_MOV(ureg, ureg_writemask(tmp_coord[1], TGSI_WRITEMASK_YZW), + ureg_src(tmp_coord[0])); /* top-right */ + + ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_Y), + ureg_src(tmp_coord[3])); + ureg_MOV(ureg, ureg_writemask(tmp_coord[2], TGSI_WRITEMASK_XZW), + ureg_src(tmp_coord[0])); /* bottom-left */ + for (i = 0; i < nr_samples; i++) { for (c = 0; c < 4; c++) { /* Read one sample. */ @@ -800,11 +883,6 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, ureg_imm1u(ureg, i)); ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler); - if (stype == TGSI_RETURN_TYPE_UINT) - ureg_U2F(ureg, tmp, ureg_src(tmp)); - else if (stype == TGSI_RETURN_TYPE_SINT) - ureg_I2F(ureg, tmp, ureg_src(tmp)); - /* Add it to the sum.*/ ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp)); } @@ -816,31 +894,20 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, ureg_imm1f(ureg, 1.0 / nr_samples)); /* Take the 4 average values and apply a standard bilinear filter. */ - ureg_FRC(ureg, tmp, coord); - ureg_LRP(ureg, top, - ureg_scalar(ureg_src(tmp), 0), + ureg_scalar(ureg_src(weights), 0), ureg_src(tmp_sum[1]), ureg_src(tmp_sum[0])); ureg_LRP(ureg, bottom, - ureg_scalar(ureg_src(tmp), 0), + ureg_scalar(ureg_src(weights), 0), ureg_src(tmp_sum[3]), ureg_src(tmp_sum[2])); - ureg_LRP(ureg, tmp, - ureg_scalar(ureg_src(tmp), 1), + ureg_LRP(ureg, out, + ureg_scalar(ureg_src(weights), 1), ureg_src(bottom), ureg_src(top)); - - /* Convert to the texture format and return. */ - if (stype == TGSI_RETURN_TYPE_UINT) - ureg_F2U(ureg, out, ureg_src(tmp)); - else if (stype == TGSI_RETURN_TYPE_SINT) - ureg_F2I(ureg, out, ureg_src(tmp)); - else - ureg_MOV(ureg, out, ureg_src(tmp)); - ureg_END(ureg); return ureg_create_shader_and_destroy(ureg, pipe); @@ -848,9 +915,9 @@ util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe, void * util_make_geometry_passthrough_shader(struct pipe_context *pipe, - uint num_attribs, - const ubyte *semantic_names, - const ubyte *semantic_indexes) + unsigned num_attribs, + const uint8_t *semantic_names, + const uint8_t *semantic_indexes) { static const unsigned zero[4] = {0, 0, 0, 0}; @@ -865,8 +932,8 @@ util_make_geometry_passthrough_shader(struct pipe_context *pipe, if (!ureg) return NULL; - ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_POINTS); - ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_POINTS); + ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, MESA_PRIM_POINTS); + ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, MESA_PRIM_POINTS); ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 1); ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, 1); imm = ureg_DECL_immediate_uint(ureg, zero, 4); @@ -1067,12 +1134,12 @@ util_make_fs_pack_color_zs(struct pipe_context *pipe, */ void * util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe, - uint num_vs_outputs, - uint num_tes_inputs, - const ubyte *vs_semantic_names, - const ubyte *vs_semantic_indexes, - const ubyte *tes_semantic_names, - const ubyte *tes_semantic_indexes, + unsigned num_vs_outputs, + unsigned num_tes_inputs, + const uint8_t *vs_semantic_names, + const uint8_t *vs_semantic_indexes, + const uint8_t *tes_semantic_names, + const uint8_t *tes_semantic_indexes, const unsigned vertices_per_patch) { unsigned i, j; @@ -1167,33 +1234,99 @@ util_make_tess_ctrl_passthrough_shader(struct pipe_context *pipe, } void * -util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src) +util_make_fs_stencil_blit(struct pipe_context *pipe, bool msaa_src, bool has_txq) { - static const char shader_templ[] = + char text[1000]; + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = { 0 }; + enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA : + TGSI_TEXTURE_2D; + + if (has_txq) { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL SVIEW[0], %s, UINT\n" + "DCL CONST[0][0]\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 0, 0}\n" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Clamp to edge for the upper bound. */ + "TXQ TEMP[1].xy, IMM[0].xxxx, SAMP[0], %s\n" + "UADD TEMP[1].xy, TEMP[1], IMM[0].yyyy\n" /* width - 1, height - 1 */ + "IMIN TEMP[0].xy, TEMP[0], TEMP[1]\n" + /* Texel fetch. */ + "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n" + "AND TEMP[0].x, TEMP[0], CONST[0][0]\n" + "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n" + "U2F TEMP[0].x, TEMP[0]\n" + "KILL_IF -TEMP[0].xxxx\n" + "END\n"; + + sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex], + tgsi_texture_names[tgsi_tex], tgsi_texture_names[tgsi_tex]); + } else { + static const char shader_templ[] = + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL SVIEW[0], %s, UINT\n" + "DCL CONST[0][0]\n" + "DCL TEMP[0..1]\n" + "IMM[0] INT32 {0, -1, 0, 0}\n" + + /* Nearest filtering floors and then converts to integer, and then + * applies clamp to edge as clamp(coord, 0, dim - 1). + */ + "MOV TEMP[0], IN[0]\n" + "FLR TEMP[0].xy, TEMP[0]\n" + "F2I TEMP[0], TEMP[0]\n" + "IMAX TEMP[0].xy, TEMP[0], IMM[0].xxxx\n" + /* Texel fetch. */ + "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n" + "AND TEMP[0].x, TEMP[0], CONST[0][0]\n" + "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n" + "U2F TEMP[0].x, TEMP[0]\n" + "KILL_IF -TEMP[0].xxxx\n" + "END\n"; + + sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex], + tgsi_texture_names[tgsi_tex]); + } + + if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { + assert(0); + return NULL; + } + + pipe_shader_state_from_tgsi(&state, tokens); + + return pipe->create_fs_state(pipe, &state); +} + +void * +util_make_fs_clear_all_cbufs(struct pipe_context *pipe) +{ + static const char text[] = "FRAG\n" - "DCL IN[0], GENERIC[0], LINEAR\n" - "DCL SAMP[0]\n" - "DCL SVIEW[0], 2D, UINT\n" + "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" + "DCL OUT[0], COLOR[0]\n" "DCL CONST[0][0]\n" - "DCL TEMP[0]\n" - - "F2U TEMP[0], IN[0]\n" - "TXF_LZ TEMP[0].x, TEMP[0], SAMP[0], %s\n" - "AND TEMP[0].x, TEMP[0], CONST[0][0]\n" - "USNE TEMP[0].x, TEMP[0], CONST[0][0]\n" - "U2F TEMP[0].x, TEMP[0]\n" - "KILL_IF -TEMP[0].xxxx\n" + + "MOV OUT[0], CONST[0][0]\n" "END\n"; - char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; struct pipe_shader_state state = { 0 }; - enum tgsi_texture_type tgsi_tex = msaa_src ? TGSI_TEXTURE_2D_MSAA : - TGSI_TEXTURE_2D; - - sprintf(text, shader_templ, tgsi_texture_names[tgsi_tex]); - if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; |