radeonsi: use hw MSAA resolve for non-trivial resolves
authorMarek Olšák <marek.olsak@amd.com>
Sun, 5 Jun 2016 14:42:26 +0000 (16:42 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 6 Jun 2016 20:50:55 +0000 (22:50 +0200)
This improves MSAA resolve performance.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeonsi/si_blit.c

index 3748a59177973443b92da056441f70860f4fe9ab..0d18730951d71245606bb18604b02943bb67643f 100644 (file)
@@ -855,8 +855,18 @@ static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
        struct r600_texture *dst = (struct r600_texture*)info->dst.resource;
        unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level);
        unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level);
-       enum pipe_format format = info->dst.format;
+       enum pipe_format format = info->src.format;
        unsigned sample_mask = ~0;
+       struct pipe_resource *tmp, templ;
+       struct pipe_blit_info blit;
+
+       /* Check basic requirements for hw resolve. */
+       if (!(info->src.resource->nr_samples > 1 &&
+             info->dst.resource->nr_samples <= 1 &&
+             !util_format_is_pure_integer(format) &&
+             !util_format_is_depth_or_stencil(format) &&
+             util_max_layer(info->src.resource, 0) == 0))
+               return false;
 
        /* Hardware MSAA resolve doesn't work if SPI format = NORM16_ABGR and
         * the format is R16G16. Use R16A16, which does work.
@@ -866,16 +876,12 @@ static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
        if (format == PIPE_FORMAT_R16G16_SNORM)
                format = PIPE_FORMAT_R16A16_SNORM;
 
-       if (info->src.resource->nr_samples > 1 &&
-           info->dst.resource->nr_samples <= 1 &&
-           util_max_layer(info->src.resource, 0) == 0 &&
-           util_max_layer(info->dst.resource, info->dst.level) == 0 &&
-           util_is_format_compatible(util_format_description(info->src.format),
-                                     util_format_description(info->dst.format)) &&
-           !util_format_is_pure_integer(format) &&
-           !util_format_is_depth_or_stencil(format) &&
+       /* Check the remaining requirements for hw resolve. */
+       if (util_max_layer(info->dst.resource, info->dst.level) == 0 &&
            !info->scissor_enable &&
            (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA &&
+           util_is_format_compatible(util_format_description(info->src.format),
+                                     util_format_description(info->dst.format)) &&
            dst_width == info->src.resource->width0 &&
            dst_height == info->src.resource->height0 &&
            info->dst.box.x == 0 &&
@@ -903,7 +909,45 @@ static bool do_hardware_msaa_resolve(struct pipe_context *ctx,
                si_blitter_end(ctx);
                return true;
        }
-       return false;
+
+       /* Shader-based resolve is VERY SLOW. Instead, resolve into
+        * a temporary texture and blit.
+        */
+       memset(&templ, 0, sizeof(templ));
+       templ.target = PIPE_TEXTURE_2D;
+       templ.format = info->src.resource->format;
+       templ.width0 = info->src.resource->width0;
+       templ.height0 = info->src.resource->height0;
+       templ.depth0 = 1;
+       templ.array_size = 1;
+       templ.usage = PIPE_USAGE_DEFAULT;
+       templ.flags = R600_RESOURCE_FLAG_FORCE_TILING;
+
+       tmp = ctx->screen->resource_create(ctx->screen, &templ);
+       if (!tmp)
+               return false;
+
+       /* resolve */
+       si_blitter_begin(ctx, SI_COLOR_RESOLVE |
+                        (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND));
+       util_blitter_custom_resolve_color(sctx->blitter, tmp, 0, 0,
+                                         info->src.resource, info->src.box.z,
+                                         sample_mask, sctx->custom_blend_resolve,
+                                         format);
+       si_blitter_end(ctx);
+
+       /* blit */
+       blit = *info;
+       blit.src.resource = tmp;
+       blit.src.box.z = 0;
+
+       si_blitter_begin(ctx, SI_BLIT |
+                        (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND));
+       util_blitter_blit(sctx->blitter, &blit);
+       si_blitter_end(ctx);
+
+       pipe_resource_reference(&tmp, NULL);
+       return true;
 }
 
 static void si_blit(struct pipe_context *ctx,