From: Marek Olšák <marek.ol...@amd.com> This fixes piglit: arb_texture_view-rendering-r32ui
TEX (image_sample) flushes denorms to 0 with FP32 textures on GCN, but such a texture can contain integer data written using an integer render view. If we do a transfer blit with TEX, denorms are flushed to 0. Luckily, TXF (image_load) doesn't do that. TXF also doesn't need to load the sampler state, so blit shaders don't have to do s_load_dwordx4. TXF doesn't do CLAMP_TO_EDGE, so it can only be used if the src box is in bounds, or if we clamp manually (this commit doesn't). --- src/gallium/auxiliary/util/u_blitter.c | 292 +++++++++++++++++++++------------ 1 file changed, 190 insertions(+), 102 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 21f0686..b4f393e 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -69,30 +69,34 @@ struct blitter_context_priv /* Vertex shaders. */ void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/ void *vs_pos_only[4]; /**< Vertex shader which passes pos to the output.*/ void *vs_layered; /**< Vertex shader which sets LAYER = INSTANCEID. */ /* Fragment shaders. */ void *fs_empty; void *fs_write_one_cbuf; void *fs_write_all_cbufs; - /* FS which outputs a color from a texture. - * The first index indicates the texture type / destination type, - * the second index is the PIPE_TEXTURE_* to be sampled. */ - void *fs_texfetch_col[5][PIPE_MAX_TEXTURE_TYPES]; + /* FS which outputs a color from a texture where + * the 1st index indicates the texture type / destination type, + * the 2nd index is the PIPE_TEXTURE_* to be sampled, + * the 3rd index is 0 = use TEX, 1 = use TXF. + */ + void *fs_texfetch_col[5][PIPE_MAX_TEXTURE_TYPES][2]; - /* FS which outputs a depth from a texture, - where the index is PIPE_TEXTURE_* to be sampled. */ - void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; - void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES]; - void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES]; + /* FS which outputs a depth from a texture, where + * the 1st index is the PIPE_TEXTURE_* to be sampled, + * the 2nd index is 0 = use TEX, 1 = use TXF. + */ + void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES][2]; + void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES][2]; + void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES][2]; /* FS which outputs one sample from a multisample texture. */ void *fs_texfetch_col_msaa[5][PIPE_MAX_TEXTURE_TYPES]; void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES]; void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES]; void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES]; /* FS which outputs an average of all samples. */ void *fs_resolve[PIPE_MAX_TEXTURE_TYPES][NUM_RESOLVE_FRAG_SHADERS][2]; @@ -126,20 +130,21 @@ struct blitter_context_priv unsigned dst_width; unsigned dst_height; boolean has_geometry_shader; boolean has_tessellation; boolean has_layered; boolean has_stream_out; boolean has_stencil_export; boolean has_texture_multisample; boolean has_tex_lz; + boolean has_txf; boolean cached_all_shaders; /* The Draw module overrides these functions. * Always create the blitter before Draw. */ void (*bind_fs_state)(struct pipe_context *, void *); void (*delete_fs_state)(struct pipe_context *, void *); }; static struct pipe_surface * util_blitter_get_next_surface_layer(struct pipe_context *pipe, @@ -193,20 +198,22 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->has_stencil_export = pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT); ctx->has_texture_multisample = pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE); ctx->has_tex_lz = pipe->screen->get_param(pipe->screen, PIPE_CAP_TGSI_TEX_TXF_LZ); + ctx->has_txf = pipe->screen->get_param(pipe->screen, + PIPE_CAP_GLSL_FEATURE_LEVEL) > 130; /* blend state objects */ memset(&blend, 0, sizeof(blend)); for (i = 0; i <= PIPE_MASK_RGBA; i++) { for (j = 0; j < 2; j++) { memset(&blend.rt[0], 0, sizeof(blend.rt[0])); blend.rt[0].colormask = i; if (j) { blend.rt[0].blend_enable = 1; @@ -446,32 +453,36 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_vs_state(pipe, ctx->vs_layered); pipe->delete_vertex_elements_state(pipe, ctx->velem_state); for (i = 0; i < 4; i++) { if (ctx->velem_state_readbuf[i]) { pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]); } } for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { for (unsigned type = 0; type < ARRAY_SIZE(ctx->fs_texfetch_col); ++type) { - if (ctx->fs_texfetch_col[type][i]) - ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[type][i]); + for (unsigned inst = 0; inst < 2; inst++) { + if (ctx->fs_texfetch_col[type][i][inst]) + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[type][i][inst]); + } if (ctx->fs_texfetch_col_msaa[type][i]) ctx->delete_fs_state(pipe, ctx->fs_texfetch_col_msaa[type][i]); } - if (ctx->fs_texfetch_depth[i]) - ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); - if (ctx->fs_texfetch_depthstencil[i]) - ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); - if (ctx->fs_texfetch_stencil[i]) - ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); + for (unsigned inst = 0; inst < 2; inst++) { + if (ctx->fs_texfetch_depth[i][inst]) + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i][inst]); + if (ctx->fs_texfetch_depthstencil[i][inst]) + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i][inst]); + if (ctx->fs_texfetch_stencil[i][inst]) + ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i][inst]); + } if (ctx->fs_texfetch_depth_msaa[i]) ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth_msaa[i]); if (ctx->fs_texfetch_depthstencil_msaa[i]) ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil_msaa[i]); if (ctx->fs_texfetch_stencil_msaa[i]) ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil_msaa[i]); for (j = 0; j< ARRAY_SIZE(ctx->fs_resolve[i]); j++) for (f = 0; f < 2; f++) @@ -748,26 +759,27 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx, ctx->vertices[i][1][0] = 0; ctx->vertices[i][1][1] = 0; ctx->vertices[i][1][2] = 0; ctx->vertices[i][1][3] = 0; } } } static void get_texcoords(struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, - int x1, int y1, int x2, int y2, + int x1, int y1, int x2, int y2, bool uses_txf, float out[4]) { struct pipe_resource *tex = src->texture; unsigned level = src->u.tex.first_level; - boolean normalized = tex->target != PIPE_TEXTURE_RECT && + boolean normalized = !uses_txf && + tex->target != PIPE_TEXTURE_RECT && tex->nr_samples <= 1; if (normalized) { out[0] = x1 / (float)u_minify(src_width0, level); out[1] = y1 / (float)u_minify(src_height0, level); out[2] = x2 / (float)u_minify(src_width0, level); out[3] = y2 / (float)u_minify(src_height0, level); } else { out[0] = (float) x1; out[1] = (float) y1; @@ -789,46 +801,51 @@ static void set_texcoords_in_vertices(const float coord[4], out[1] = coord[3]; /*t2.t*/ out += stride; out[0] = coord[0]; /*t3.s*/ out[1] = coord[3]; /*t3.t*/ } static void blitter_set_texcoords(struct blitter_context_priv *ctx, struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, float layer, unsigned sample, - int x1, int y1, int x2, int y2) + int x1, int y1, int x2, int y2, + bool uses_txf) { unsigned i; float coord[4]; float face_coord[4][2]; - get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord); + get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, uses_txf, + coord); if (src->texture->target == PIPE_TEXTURE_CUBE || src->texture->target == PIPE_TEXTURE_CUBE_ARRAY) { set_texcoords_in_vertices(coord, &face_coord[0][0], 2); util_map_texcoords2d_onto_cubemap((unsigned)layer % 6, /* pointer, stride in floats */ &face_coord[0][0], 2, &ctx->vertices[0][1][0], 8, FALSE); } else { set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); } /* Set the layer. */ switch (src->texture->target) { case PIPE_TEXTURE_3D: { - float r = layer / (float)u_minify(src->texture->depth0, - src->u.tex.first_level); + float r = layer; + + if (!uses_txf) + r /= u_minify(src->texture->depth0, src->u.tex.first_level); + for (i = 0; i < 4; i++) ctx->vertices[i][1][2] = r; /*r*/ } break; case PIPE_TEXTURE_1D_ARRAY: for (i = 0; i < 4; i++) ctx->vertices[i][1][1] = (float) layer; /*t*/ break; @@ -860,21 +877,22 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, ctx->dst_width = width; ctx->dst_height = height; } static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, enum pipe_format src_format, enum pipe_format dst_format, enum pipe_texture_target target, unsigned src_nr_samples, unsigned dst_nr_samples, - unsigned filter) + unsigned filter, + bool use_txf) { struct pipe_context *pipe = ctx->base.pipe; unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, src_nr_samples); enum tgsi_return_type stype; enum tgsi_return_type dtype; unsigned type; assert(target < PIPE_MAX_TEXTURE_TYPES); if (util_format_is_pure_uint(src_format)) { @@ -942,236 +960,267 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, /* Create the fragment shader on-demand. */ if (!*shader) { assert(!ctx->cached_all_shaders); *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex, stype, dtype); } } return *shader; } else { - void **shader = &ctx->fs_texfetch_col[type][target]; + void **shader; + + if (use_txf) + shader = &ctx->fs_texfetch_col[type][target][1]; + else + shader = &ctx->fs_texfetch_col[type][target][0]; /* Create the fragment shader on-demand. */ if (!*shader) { assert(!ctx->cached_all_shaders); *shader = util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR, stype, dtype, - ctx->has_tex_lz, false); + ctx->has_tex_lz, use_txf); } return *shader; } } static inline void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, enum pipe_texture_target target, - unsigned nr_samples) + unsigned nr_samples, + bool use_txf) { struct pipe_context *pipe = ctx->base.pipe; assert(target < PIPE_MAX_TEXTURE_TYPES); if (nr_samples > 1) { void **shader = &ctx->fs_texfetch_depth_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples); *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex); } return *shader; } else { - void **shader = &ctx->fs_texfetch_depth[target]; + void **shader; + + if (use_txf) + shader = &ctx->fs_texfetch_depth[target][1]; + else + shader = &ctx->fs_texfetch_depth[target][0]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR, - ctx->has_tex_lz, false); + ctx->has_tex_lz, use_txf); } return *shader; } } static inline void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, enum pipe_texture_target target, - unsigned nr_samples) + unsigned nr_samples, + bool use_txf) { struct pipe_context *pipe = ctx->base.pipe; assert(target < PIPE_MAX_TEXTURE_TYPES); if (nr_samples > 1) { void **shader = &ctx->fs_texfetch_depthstencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples); *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex); } return *shader; } else { - void **shader = &ctx->fs_texfetch_depthstencil[target]; + void **shader; + + if (use_txf) + shader = &ctx->fs_texfetch_depthstencil[target][1]; + else + shader = &ctx->fs_texfetch_depthstencil[target][0]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR, ctx->has_tex_lz, - false); + use_txf); } return *shader; } } static inline void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, enum pipe_texture_target target, - unsigned nr_samples) + unsigned nr_samples, + bool use_txf) { struct pipe_context *pipe = ctx->base.pipe; assert(target < PIPE_MAX_TEXTURE_TYPES); if (nr_samples > 1) { void **shader = &ctx->fs_texfetch_stencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, nr_samples); *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex); } return *shader; } else { - void **shader = &ctx->fs_texfetch_stencil[target]; + void **shader; + + if (use_txf) + shader = &ctx->fs_texfetch_stencil[target][1]; + else + shader = &ctx->fs_texfetch_stencil[target][0]; /* Create the fragment shader on-demand. */ if (!*shader) { unsigned tgsi_tex; assert(!ctx->cached_all_shaders); tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR, - ctx->has_tex_lz, false); + ctx->has_tex_lz, use_txf); } return *shader; } } /** * Generate and save all fragment shaders that we will ever need for * blitting. Drivers which use the 'draw' fallbacks will typically use * this to make sure we generate/use shaders that don't go through the * draw module's wrapper functions. */ void util_blitter_cache_all_shaders(struct blitter_context *blitter) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = blitter->pipe; struct pipe_screen *screen = pipe->screen; - unsigned samples, j, f, target, max_samples; + unsigned samples, j, f, target, max_samples, use_txf; boolean has_arraytex, has_cubearraytex; max_samples = ctx->has_texture_multisample ? 2 : 1; has_arraytex = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0; has_cubearraytex = screen->get_param(screen, PIPE_CAP_CUBE_MAP_ARRAY) != 0; /* It only matters if i <= 1 or > 1. */ for (samples = 1; samples <= max_samples; samples++) { for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) { - if (!has_arraytex && - (target == PIPE_TEXTURE_1D_ARRAY || - target == PIPE_TEXTURE_2D_ARRAY)) { - continue; - } - if (!has_cubearraytex && - (target == PIPE_TEXTURE_CUBE_ARRAY)) - continue; - - if (samples > 1 && - (target != PIPE_TEXTURE_2D && - target != PIPE_TEXTURE_2D_ARRAY)) - continue; + for (use_txf = 0; use_txf <= ctx->has_txf; use_txf++) { + if (!has_arraytex && + (target == PIPE_TEXTURE_1D_ARRAY || + target == PIPE_TEXTURE_2D_ARRAY)) { + continue; + } + if (!has_cubearraytex && + (target == PIPE_TEXTURE_CUBE_ARRAY)) + continue; - /* If samples == 1, the shaders read one texel. If samples >= 1, - * they read one sample. - */ - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, - PIPE_FORMAT_R32_FLOAT, target, - samples, samples, 0); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, - PIPE_FORMAT_R32_UINT, target, - samples, samples, 0); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, - PIPE_FORMAT_R32_SINT, target, - samples, samples, 0); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, - PIPE_FORMAT_R32_SINT, target, - samples, samples, 0); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, - PIPE_FORMAT_R32_UINT, target, - samples, samples, 0); - blitter_get_fs_texfetch_depth(ctx, target, samples); - if (ctx->has_stencil_export) { - blitter_get_fs_texfetch_depthstencil(ctx, target, samples); - blitter_get_fs_texfetch_stencil(ctx, target, samples); - } + if (samples > 1 && + (target != PIPE_TEXTURE_2D && + target != PIPE_TEXTURE_2D_ARRAY)) + continue; - if (samples == 1) - continue; + if (samples > 1 && use_txf) + continue; /* TXF is the only option, use_txf has no effect */ + + /* If samples == 1, the shaders read one texel. If samples >= 1, + * they read one sample. + */ + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R32_FLOAT, target, + samples, samples, 0, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32_UINT, target, + samples, samples, 0, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32_SINT, target, + samples, samples, 0, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, + PIPE_FORMAT_R32_SINT, target, + samples, samples, 0, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, + PIPE_FORMAT_R32_UINT, target, + samples, samples, 0, use_txf); + blitter_get_fs_texfetch_depth(ctx, target, samples, use_txf); + if (ctx->has_stencil_export) { + blitter_get_fs_texfetch_depthstencil(ctx, target, samples, use_txf); + blitter_get_fs_texfetch_stencil(ctx, target, samples, use_txf); + } - /* MSAA resolve shaders. */ - for (j = 2; j < 32; j++) { - if (!screen->is_format_supported(screen, PIPE_FORMAT_R32_FLOAT, - target, j, - PIPE_BIND_SAMPLER_VIEW)) { + if (samples == 1) continue; - } - for (f = 0; f < 2; f++) { - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, - PIPE_FORMAT_R32_FLOAT, target, - j, 1, f); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, - PIPE_FORMAT_R32_UINT, target, - j, 1, f); - blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, - PIPE_FORMAT_R32_SINT, target, - j, 1, f); + /* MSAA resolve shaders. */ + for (j = 2; j < 32; j++) { + if (!screen->is_format_supported(screen, PIPE_FORMAT_R32_FLOAT, + target, j, + PIPE_BIND_SAMPLER_VIEW)) { + continue; + } + + for (f = 0; f < 2; f++) { + if (f != PIPE_TEX_FILTER_NEAREST && use_txf) + continue; + + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R32_FLOAT, target, + j, 1, f, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32_UINT, target, + j, 1, f, use_txf); + blitter_get_fs_texfetch_col(ctx, PIPE_FORMAT_R32_SINT, + PIPE_FORMAT_R32_SINT, target, + j, 1, f, use_txf); + } } } } } ctx->fs_empty = util_make_empty_fragment_shader(pipe); ctx->fs_write_one_cbuf = util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC, TGSI_INTERPOLATE_CONSTANT, FALSE); @@ -1546,21 +1595,22 @@ void util_blitter_copy_texture(struct blitter_context *blitter, pipe_sampler_view_reference(&src_view, NULL); } static void do_blits(struct blitter_context_priv *ctx, struct pipe_surface *dst, const struct pipe_box *dstbox, struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, const struct pipe_box *srcbox, - bool is_zsbuf) + bool is_zsbuf, + bool uses_txf) { struct pipe_context *pipe = ctx->base.pipe; unsigned src_samples = src->texture->nr_samples; unsigned dst_samples = dst->texture->nr_samples; enum pipe_texture_target src_target = src->texture->target; struct pipe_framebuffer_state fb_state = {0}; /* Initialize framebuffer state. */ fb_state.width = dst->width; fb_state.height = dst->height; @@ -1574,21 +1624,22 @@ static void do_blits(struct blitter_context_priv *ctx, src_samples <= 1) { /* Draw the quad with the draw_rectangle callback. */ /* Set texture coordinates. - use a pipe color union * for interface purposes. * XXX pipe_color_union is a wrong name since we use that to set * texture coordinates too. */ union pipe_color_union coord; get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y, - srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f); + srcbox->x+srcbox->width, srcbox->y+srcbox->height, + uses_txf, coord.f); /* Set framebuffer state. */ if (is_zsbuf) { fb_state.zsbuf = dst; } else { fb_state.cbufs[0] = dst; } pipe->set_framebuffer_state(pipe, &fb_state); /* Draw. */ @@ -1637,33 +1688,33 @@ static void do_blits(struct blitter_context_priv *ctx, if (src_samples == dst_samples && dst_samples > 1) { /* MSAA copy. */ unsigned i, max_sample = dst_samples - 1; for (i = 0; i <= max_sample; i++) { pipe->set_sample_mask(pipe, 1 << i); blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z + src_z, i, srcbox->x, srcbox->y, srcbox->x + srcbox->width, - srcbox->y + srcbox->height); + srcbox->y + srcbox->height, uses_txf); blitter_draw(ctx, dstbox->x, dstbox->y, dstbox->x + dstbox->width, dstbox->y + dstbox->height, 0, 1); } } else { /* Normal copy, MSAA upsampling, or MSAA resolve. */ pipe->set_sample_mask(pipe, ~0); blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z + src_z, 0, srcbox->x, srcbox->y, srcbox->x + srcbox->width, - srcbox->y + srcbox->height); + srcbox->y + srcbox->height, uses_txf); blitter_draw(ctx, dstbox->x, dstbox->y, dstbox->x + dstbox->width, dstbox->y + dstbox->height, 0, 1); } /* Get the next surface or (if this is the last iteration) * just unreference the last one. */ old = dst; if (dst_z < dstbox->depth-1) { dst = ctx->base.get_next_surface_layer(ctx->base.pipe, dst); @@ -1713,59 +1764,95 @@ void util_blitter_blit_generic(struct blitter_context *blitter, if (!blit_stencil && !blit_depth && !blit_color) { return; } if (blit_stencil || (dstbox->width == abs(srcbox->width) && dstbox->height == abs(srcbox->height))) { filter = PIPE_TEX_FILTER_NEAREST; } + bool use_txf = false; + + if (ctx->has_txf && + filter == PIPE_TEX_FILTER_NEAREST && + src->target != PIPE_TEXTURE_CUBE && + src->target != PIPE_TEXTURE_CUBE_ARRAY) { + int src_width = u_minify(src_width0, src->u.tex.first_level); + int src_height = u_minify(src_height0, src->u.tex.first_level); + int src_depth = src->u.tex.last_layer + 1; + struct pipe_box box = *srcbox; + + /* Eliminate negative width/height/depth. */ + if (box.width < 0) { + box.x += box.width; + box.width *= -1; + } + if (box.height < 0) { + box.y += box.height; + box.height *= -1; + } + if (box.depth < 0) { + box.z += box.depth; + box.depth *= -1; + } + + /* See if srcbox is in bounds. TXF doesn't clamp the coordinates. */ + use_txf = + box.x >= 0 && box.x < src_width && + box.y >= 0 && box.y < src_height && + box.z >= 0 && box.z < src_depth && + box.x + box.width > 0 && box.x + box.width <= src_width && + box.y + box.height > 0 && box.y + box.height <= src_height && + box.z + box.depth > 0 && box.z + box.depth <= src_depth; + } + /* Check whether the states are properly saved. */ util_blitter_set_running_flag(blitter); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_textures(ctx); blitter_check_saved_fb_state(ctx); blitter_disable_render_cond(ctx); if (blit_depth || blit_stencil) { pipe->bind_blend_state(pipe, ctx->blend[0][0]); if (blit_depth && blit_stencil) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_depthstencil(ctx, src_target, - src_samples)); + src_samples, use_txf)); } else if (blit_depth) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_depth(ctx, src_target, - src_samples)); + src_samples, use_txf)); } else { /* is_stencil */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_stencil(ctx, src_target, - src_samples)); + src_samples, use_txf)); } } else { unsigned colormask = mask & PIPE_MASK_RGBA; pipe->bind_blend_state(pipe, ctx->blend[colormask][alpha_blend]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_col(ctx, src->format, dst->format, src_target, - src_samples, dst_samples, filter)); + src_samples, dst_samples, filter, + use_txf)); } /* Set the linear filter only for scaled color non-MSAA blits. */ if (filter == PIPE_TEX_FILTER_LINEAR) { if (src_target == PIPE_TEXTURE_RECT) { sampler_state = ctx->sampler_state_rect_linear; } else { sampler_state = ctx->sampler_state_linear; } } else { @@ -1817,21 +1904,21 @@ void util_blitter_blit_generic(struct blitter_context *blitter, } pipe->bind_vertex_elements_state(pipe, ctx->velem_state); if (scissor) { pipe->set_scissor_states(pipe, 0, 1, scissor); } blitter_set_common_draw_rect_state(ctx, scissor != NULL, FALSE); do_blits(ctx, dst, dstbox, src, src_width0, src_height0, - srcbox, blit_depth || blit_stencil); + srcbox, blit_depth || blit_stencil, use_txf); util_blitter_restore_vertex_states(blitter); util_blitter_restore_fragment_states(blitter); util_blitter_restore_textures(blitter); util_blitter_restore_fb_state(blitter); if (scissor) { pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor); } util_blitter_restore_render_cond(blitter); util_blitter_unset_running_flag(blitter); @@ -1898,27 +1985,28 @@ void util_blitter_generate_mipmap(struct blitter_context *blitter, blitter_check_saved_textures(ctx); blitter_check_saved_fb_state(ctx); blitter_disable_render_cond(ctx); /* Set states. */ if (is_depth) { pipe->bind_blend_state(pipe, ctx->blend[0][0]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); ctx->bind_fs_state(pipe, - blitter_get_fs_texfetch_depth(ctx, tex->target, 1)); + blitter_get_fs_texfetch_depth(ctx, tex->target, 1, + false)); } else { pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_col(ctx, tex->format, tex->format, tex->target, - 1, 1, PIPE_TEX_FILTER_LINEAR)); + 1, 1, PIPE_TEX_FILTER_LINEAR, false)); } if (tex->target == PIPE_TEXTURE_RECT) { sampler_state = ctx->sampler_state_rect_linear; } else { sampler_state = ctx->sampler_state_linear; } pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state); @@ -1950,21 +2038,21 @@ void util_blitter_generate_mipmap(struct blitter_context *blitter, dst_view = pipe->create_surface(pipe, tex, &dst_templ); /* Initialize the sampler view. */ util_blitter_default_src_texture(&src_templ, tex, src_level); src_templ.format = format; src_view = pipe->create_sampler_view(pipe, tex, &src_templ); pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &src_view); do_blits(ctx, dst_view, &dstbox, src_view, tex->width0, tex->height0, - &srcbox, is_depth); + &srcbox, is_depth, false); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); } util_blitter_restore_vertex_states(blitter); util_blitter_restore_fragment_states(blitter); util_blitter_restore_textures(blitter); util_blitter_restore_fb_state(blitter); util_blitter_restore_render_cond(blitter); -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev