[Mesa-dev] [PATCH 5/5] gallium/u_blitter: use 2D_ARRAY for cubemap blits if possible
Marek Olšák
maraeo at gmail.com
Tue May 30 22:46:47 UTC 2017
From: Marek Olšák <marek.olsak at amd.com>
so that we can use TXF.
The cubemap blit pixel shader code size: 148 -> 92 bytes
---
src/gallium/auxiliary/util/u_blitter.c | 52 ++++++++++++++++++++++------------
src/gallium/auxiliary/util/u_blitter.h | 3 +-
src/gallium/drivers/r300/r300_blit.c | 2 +-
src/gallium/drivers/r600/r600_blit.c | 2 +-
src/gallium/drivers/radeonsi/si_blit.c | 2 +-
5 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index b4f393e..c38534d 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -131,20 +131,21 @@ struct blitter_context_priv
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 cube_as_2darray;
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,
@@ -200,20 +201,22 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
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;
+ ctx->cube_as_2darray = pipe->screen->get_param(pipe->screen,
+ PIPE_CAP_SAMPLER_VIEW_TARGET);
/* 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;
@@ -762,25 +765,24 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
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, bool uses_txf,
float out[4])
{
- struct pipe_resource *tex = src->texture;
unsigned level = src->u.tex.first_level;
boolean normalized = !uses_txf &&
- tex->target != PIPE_TEXTURE_RECT &&
- tex->nr_samples <= 1;
+ src->target != PIPE_TEXTURE_RECT &&
+ src->texture->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;
out[2] = (float) x2;
@@ -811,34 +813,34 @@ static void blitter_set_texcoords(struct blitter_context_priv *ctx,
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, uses_txf,
coord);
- if (src->texture->target == PIPE_TEXTURE_CUBE ||
- src->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
+ if (src->target == PIPE_TEXTURE_CUBE ||
+ src->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) {
+ switch (src->target) {
case PIPE_TEXTURE_3D:
{
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*/
}
@@ -1451,26 +1453,36 @@ util_blitter_get_next_surface_layer(struct pipe_context *pipe,
memset(&dst_templ, 0, sizeof(dst_templ));
dst_templ.format = surf->format;
dst_templ.u.tex.level = surf->u.tex.level;
dst_templ.u.tex.first_layer = surf->u.tex.first_layer + 1;
dst_templ.u.tex.last_layer = surf->u.tex.last_layer + 1;
return pipe->create_surface(pipe, surf->texture, &dst_templ);
}
-void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
+void util_blitter_default_src_texture(struct blitter_context *blitter,
+ struct pipe_sampler_view *src_templ,
struct pipe_resource *src,
unsigned srclevel)
{
+ struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+
memset(src_templ, 0, sizeof(*src_templ));
- src_templ->target = src->target;
+
+ if (ctx->cube_as_2darray &&
+ (src->target == PIPE_TEXTURE_CUBE ||
+ src->target == PIPE_TEXTURE_CUBE_ARRAY))
+ src_templ->target = PIPE_TEXTURE_2D_ARRAY;
+ else
+ src_templ->target = src->target;
+
src_templ->format = util_format_linear(src->format);
src_templ->u.tex.first_level = srclevel;
src_templ->u.tex.last_level = srclevel;
src_templ->u.tex.first_layer = 0;
src_templ->u.tex.last_layer =
src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
: src->array_size - 1;
src_templ->swizzle_r = PIPE_SWIZZLE_X;
src_templ->swizzle_g = PIPE_SWIZZLE_Y;
src_templ->swizzle_b = PIPE_SWIZZLE_Z;
@@ -1575,21 +1587,21 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
assert(src->target < PIPE_MAX_TEXTURE_TYPES);
u_box_3d(dstx, dsty, dstz, abs(srcbox->width), abs(srcbox->height),
abs(srcbox->depth), &dstbox);
/* Initialize the surface. */
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
dst_view = pipe->create_surface(pipe, dst, &dst_templ);
/* Initialize the sampler view. */
- util_blitter_default_src_texture(&src_templ, src, src_level);
+ util_blitter_default_src_texture(blitter, &src_templ, src, src_level);
src_view = pipe->create_sampler_view(pipe, src, &src_templ);
/* Copy. */
util_blitter_blit_generic(blitter, dst_view, &dstbox,
src_view, srcbox, src->width0, src->height0,
PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
FALSE);
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
@@ -1601,21 +1613,21 @@ static void do_blits(struct blitter_context_priv *ctx,
struct pipe_sampler_view *src,
unsigned src_width0,
unsigned src_height0,
const struct pipe_box *srcbox,
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;
+ enum pipe_texture_target src_target = src->target;
struct pipe_framebuffer_state fb_state = {0};
/* Initialize framebuffer state. */
fb_state.width = dst->width;
fb_state.height = dst->height;
fb_state.nr_cbufs = is_zsbuf ? 0 : 1;
blitter_set_dst_dimensions(ctx, fb_state.width, fb_state.height);
if ((src_target == PIPE_TEXTURE_1D ||
@@ -1731,21 +1743,21 @@ void util_blitter_blit_generic(struct blitter_context *blitter,
const struct pipe_box *dstbox,
struct pipe_sampler_view *src,
const struct pipe_box *srcbox,
unsigned src_width0, unsigned src_height0,
unsigned mask, unsigned filter,
const struct pipe_scissor_state *scissor,
boolean alpha_blend)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
- enum pipe_texture_target src_target = src->texture->target;
+ enum pipe_texture_target src_target = src->target;
unsigned src_samples = src->texture->nr_samples;
unsigned dst_samples = dst->texture->nr_samples;
boolean has_depth, has_stencil, has_color;
boolean blit_stencil, blit_depth, blit_color;
void *sampler_state;
const struct util_format_description *src_desc =
util_format_description(src->format);
const struct util_format_description *dst_desc =
util_format_description(dst->format);
@@ -1935,21 +1947,21 @@ util_blitter_blit(struct blitter_context *blitter,
struct pipe_surface *dst_view, dst_templ;
struct pipe_sampler_view src_templ, *src_view;
/* Initialize the surface. */
util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,
info->dst.box.z);
dst_templ.format = info->dst.format;
dst_view = pipe->create_surface(pipe, dst, &dst_templ);
/* Initialize the sampler view. */
- util_blitter_default_src_texture(&src_templ, src, info->src.level);
+ util_blitter_default_src_texture(blitter, &src_templ, src, info->src.level);
src_templ.format = info->src.format;
src_view = pipe->create_sampler_view(pipe, src, &src_templ);
/* Copy. */
util_blitter_blit_generic(blitter, dst_view, &info->dst.box,
src_view, &info->src.box, src->width0, src->height0,
info->mask, info->filter,
info->scissor_enable ? &info->scissor : NULL,
info->alpha_blend);
@@ -1965,87 +1977,91 @@ void util_blitter_generate_mipmap(struct blitter_context *blitter,
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_surface dst_templ, *dst_view;
struct pipe_sampler_view src_templ, *src_view;
boolean is_depth;
void *sampler_state;
const struct util_format_description *desc =
util_format_description(format);
unsigned src_level;
+ unsigned target = tex->target;
+
+ if (ctx->cube_as_2darray &&
+ (target == PIPE_TEXTURE_CUBE || target == PIPE_TEXTURE_CUBE_ARRAY))
+ target = PIPE_TEXTURE_2D_ARRAY;
assert(tex->nr_samples <= 1);
assert(!util_format_has_stencil(desc));
is_depth = desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS;
/* 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);
/* 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,
- false));
+ blitter_get_fs_texfetch_depth(ctx, 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,
+ blitter_get_fs_texfetch_col(ctx, tex->format, tex->format, target,
1, 1, PIPE_TEX_FILTER_LINEAR, false));
}
- if (tex->target == PIPE_TEXTURE_RECT) {
+ if (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);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
blitter_set_common_draw_rect_state(ctx, FALSE, FALSE);
for (src_level = base_level; src_level < last_level; src_level++) {
struct pipe_box dstbox = {0}, srcbox = {0};
unsigned dst_level = src_level + 1;
dstbox.width = u_minify(tex->width0, dst_level);
dstbox.height = u_minify(tex->height0, dst_level);
srcbox.width = u_minify(tex->width0, src_level);
srcbox.height = u_minify(tex->height0, src_level);
- if (tex->target == PIPE_TEXTURE_3D) {
+ if (target == PIPE_TEXTURE_3D) {
dstbox.depth = util_max_layer(tex, dst_level) + 1;
srcbox.depth = util_max_layer(tex, src_level) + 1;
} else {
dstbox.z = srcbox.z = first_layer;
dstbox.depth = srcbox.depth = last_layer - first_layer + 1;
}
/* Initialize the surface. */
util_blitter_default_dst_texture(&dst_templ, tex, dst_level,
first_layer);
dst_templ.format = format;
dst_view = pipe->create_surface(pipe, tex, &dst_templ);
/* Initialize the sampler view. */
- util_blitter_default_src_texture(&src_templ, tex, src_level);
+ util_blitter_default_src_texture(blitter, &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, false);
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
index fd4fe7a..912af83 100644
--- a/src/gallium/auxiliary/util/u_blitter.h
+++ b/src/gallium/auxiliary/util/u_blitter.h
@@ -261,21 +261,22 @@ void util_blitter_generate_mipmap(struct blitter_context *blitter,
*/
void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
struct pipe_resource *dst,
unsigned dstlevel,
unsigned dstz);
/**
* Helper function to initialize a view for copy_texture_view.
* The parameters must match copy_texture_view.
*/
-void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
+void util_blitter_default_src_texture(struct blitter_context *blitter,
+ struct pipe_sampler_view *src_templ,
struct pipe_resource *src,
unsigned srclevel);
/**
* Copy data from one buffer to another using the Stream Output functionality.
* 4-byte alignment is required, otherwise software fallback is used.
*/
void util_blitter_copy_buffer(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dstx,
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 434cf38..8fda727 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -560,21 +560,21 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
/* Can't read MSAA textures. */
if (src->nr_samples > 1 || dst->nr_samples > 1) {
return;
}
/* The code below changes the texture format so that the copy can be done
* on hardware. E.g. depth-stencil surfaces are copied as RGBA
* colorbuffers. */
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
- util_blitter_default_src_texture(&src_templ, src, src_level);
+ util_blitter_default_src_texture(r300->blitter, &src_templ, src, src_level);
layout = util_format_description(dst_templ.format)->layout;
/* Handle non-renderable plain formats. */
if (layout == UTIL_FORMAT_LAYOUT_PLAIN &&
(!screen->is_format_supported(screen, src_templ.format, src->target,
src->nr_samples,
PIPE_BIND_SAMPLER_VIEW) ||
!screen->is_format_supported(screen, dst_templ.format, dst->target,
dst->nr_samples,
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index c52492e..80aa9c0 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -640,21 +640,21 @@ void r600_resource_copy_region(struct pipe_context *ctx,
}
dst_width = u_minify(dst->width0, dst_level);
dst_height = u_minify(dst->height0, dst_level);
src_width0 = src->width0;
src_height0 = src->height0;
src_widthFL = u_minify(src->width0, src_level);
src_heightFL = u_minify(src->height0, src_level);
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
- util_blitter_default_src_texture(&src_templ, src, src_level);
+ util_blitter_default_src_texture(rctx->blitter, &src_templ, src, src_level);
if (util_format_is_compressed(src->format) ||
util_format_is_compressed(dst->format)) {
unsigned blocksize = util_format_get_blocksize(src->format);
if (blocksize == 8)
src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */
else
src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */
dst_templ.format = src_templ.format;
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 998288d..f5d9048 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -868,21 +868,21 @@ void si_resource_copy_region(struct pipe_context *ctx,
src_box->z, src_box->z + src_box->depth - 1);
dst_width = u_minify(dst->width0, dst_level);
dst_height = u_minify(dst->height0, dst_level);
dst_width0 = dst->width0;
dst_height0 = dst->height0;
src_width0 = src->width0;
src_height0 = src->height0;
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
- util_blitter_default_src_texture(&src_templ, src, src_level);
+ util_blitter_default_src_texture(sctx->blitter, &src_templ, src, src_level);
if (util_format_is_compressed(src->format) ||
util_format_is_compressed(dst->format)) {
unsigned blocksize = rsrc->surface.bpe;
if (blocksize == 8)
src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */
else
src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */
dst_templ.format = src_templ.format;
--
2.7.4
More information about the mesa-dev
mailing list