[Mesa-dev] [PATCH 4/5] gallium/u_blitter: use TXF if possible
Marek Olšák
maraeo at gmail.com
Tue May 30 22:46:46 UTC 2017
From: Marek Olšák <marek.olsak at 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
More information about the mesa-dev
mailing list