static void si_msaa_color_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_screen *screen = ctx->screen; struct pipe_resource *tmp, templ; struct pipe_blit_info blit; unsigned sample_mask = ~0; assert(info->src.level == 0); assert(info->src.box.depth == 1); assert(info->dst.box.depth == 1); if (is_simple_msaa_resolve(info)) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, int_to_norm_format(info->dst.format)); r600_blitter_end(ctx); return; } /* resolve into a temporary texture, then blit */ 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.last_level = 0; templ.nr_samples = 0; templ.usage = PIPE_USAGE_STATIC; templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; templ.flags = R600_RESOURCE_FLAG_FORCE_TILING; /* dst must not have a linear layout */ tmp = screen->resource_create(screen, &templ); /* resolve */ r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, tmp, 0, 0, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, int_to_norm_format(tmp->format)); r600_blitter_end(ctx); /* blit */ blit = *info; blit.src.resource = tmp; blit.src.box.z = 0; r600_blitter_begin(ctx, R600_BLIT); util_blitter_blit(rctx->blitter, &blit); r600_blitter_end(ctx); pipe_resource_reference(&tmp, NULL); }
static void r600_color_resolve(struct pipe_context *ctx, const struct pipe_resolve_info *info) { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_screen *screen = ctx->screen; struct pipe_resource *tmp, templ; struct pipe_box box; unsigned sample_mask = rctx->chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.res->nr_samples)) - 1); assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA); if (is_simple_resolve(info)) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, info->dst.res, info->dst.level, info->dst.layer, info->src.res, info->src.layer, sample_mask, rctx->custom_blend_resolve); r600_blitter_end(ctx); return; } /* resolve into a temporary texture, then blit */ templ.target = PIPE_TEXTURE_2D; templ.format = info->src.res->format; templ.width0 = info->src.res->width0; templ.height0 = info->src.res->height0; templ.depth0 = 1; templ.array_size = 1; templ.last_level = 0; templ.nr_samples = 0; templ.usage = PIPE_USAGE_STATIC; templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; templ.flags = 0; tmp = screen->resource_create(screen, &templ); /* XXX use scissor, so that only the needed part of the resource is resolved */ r600_blitter_begin(ctx, R600_COLOR_RESOLVE); util_blitter_custom_resolve_color(rctx->blitter, tmp, 0, 0, info->src.res, info->src.layer, sample_mask, rctx->custom_blend_resolve); r600_blitter_end(ctx); /* this is correct for upside-down blits too */ u_box_2d(info->src.x0, info->src.y0, info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &box); r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_copy_texture(rctx->blitter, info->dst.res, info->dst.level, ~0, info->dst.x0, info->dst.y0, info->dst.layer, tmp, 0, 0, &box); r600_blitter_end(ctx); pipe_resource_reference(&tmp, NULL); }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct si_context *sctx = (struct si_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 = int_to_norm_format(info->dst.format); unsigned sample_mask = ~0; /* Hardware MSAA resolve doesn't work if SPI format = NORM16_ABGR and * the format is R16G16. Use R16A16, which does work. */ if (format == PIPE_FORMAT_R16G16_UNORM) format = PIPE_FORMAT_R16A16_UNORM; 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) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && !(dst->surface.flags & RADEON_SURF_SCANOUT) && (!dst->cmask.size || !dst->dirty_level_mask) && /* dst cannot be fast-cleared */ !dst->dcc_offset) { si_blitter_begin(ctx, SI_COLOR_RESOLVE | (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(sctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, sctx->custom_blend_resolve, format); si_blitter_end(ctx); return true; } return false; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_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 = int_to_norm_format(info->dst.format); unsigned sample_mask = rctx->b.chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); 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 && info->dst.format == info->src.format && !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && (!dst->cmask.size || !dst->dirty_level_mask) /* dst cannot be fast-cleared */) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(rctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, format); r600_blitter_end(ctx); return true; } return false; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct si_context *sctx = (struct si_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 = int_to_norm_format(info->dst.format); unsigned sample_mask = ~0; 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 && info->dst.format == info->src.format && !util_format_is_pure_integer(format) && !util_format_is_depth_or_stencil(format) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && !(dst->surface.flags & RADEON_SURF_SCANOUT)) { si_blitter_begin(ctx, SI_COLOR_RESOLVE); util_blitter_custom_resolve_color(sctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, sctx->custom_blend_resolve, format); si_blitter_end(ctx); return true; } return false; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_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->src.format; unsigned sample_mask = rctx->b.chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); 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; /* Check the remaining requirements for hw resolve. */ if (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)) && !info->scissor_enable && (info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && (!dst->cmask.size || !dst->dirty_level_mask) /* dst cannot be fast-cleared */) { r600_blitter_begin(ctx, R600_COLOR_RESOLVE | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(rctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, format); r600_blitter_end(ctx); return true; } /* 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 */ r600_blitter_begin(ctx, R600_COLOR_RESOLVE | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(rctx->blitter, tmp, 0, 0, info->src.resource, info->src.box.z, sample_mask, rctx->custom_blend_resolve, format); r600_blitter_end(ctx); /* blit */ blit = *info; blit.src.resource = tmp; blit.src.box.z = 0; r600_blitter_begin(ctx, R600_BLIT | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_blit(rctx->blitter, &blit); r600_blitter_end(ctx); pipe_resource_reference(&tmp, NULL); return true; }
static bool do_hardware_msaa_resolve(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct si_context *sctx = (struct si_context*)ctx; struct r600_texture *src = (struct r600_texture*)info->src.resource; 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->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. */ if (format == PIPE_FORMAT_R16G16_UNORM) format = PIPE_FORMAT_R16A16_UNORM; if (format == PIPE_FORMAT_R16G16_SNORM) format = PIPE_FORMAT_R16A16_SNORM; /* 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 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->dst.box.depth == 1 && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && info->src.box.depth == 1 && dst->surface.level[info->dst.level].mode >= RADEON_SURF_MODE_1D && (!dst->cmask.size || !dst->dirty_level_mask)) { /* dst cannot be fast-cleared */ /* Check the last constraint. */ if (src->surface.micro_tile_mode != dst->surface.micro_tile_mode) { /* The next fast clear will switch to this mode to * get direct hw resolve next time if the mode is * different now. */ src->last_msaa_resolve_target_micro_mode = dst->surface.micro_tile_mode; goto resolve_to_temp; } /* Resolving into a surface with DCC is unsupported. Since * it's being overwritten anyway, clear it to uncompressed. * This is still the fastest codepath even with this clear. */ if (dst->dcc_offset && dst->surface.level[info->dst.level].dcc_enabled) { vi_dcc_clear_level(&sctx->b, dst, info->dst.level, 0xFFFFFFFF); dst->dirty_level_mask &= ~(1 << info->dst.level); } /* Resolve directly from src to dst. */ si_blitter_begin(ctx, SI_COLOR_RESOLVE | (info->render_condition_enable ? 0 : SI_DISABLE_RENDER_COND)); util_blitter_custom_resolve_color(sctx->blitter, info->dst.resource, info->dst.level, info->dst.box.z, info->src.resource, info->src.box.z, sample_mask, sctx->custom_blend_resolve, format); si_blitter_end(ctx); return true; } resolve_to_temp: /* 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 | R600_RESOURCE_FLAG_DISABLE_DCC; /* The src and dst microtile modes must be the same. */ if (src->surface.micro_tile_mode == V_009910_ADDR_SURF_DISPLAY_MICRO_TILING) templ.bind = PIPE_BIND_SCANOUT; else templ.bind = 0; tmp = ctx->screen->resource_create(ctx->screen, &templ); if (!tmp) return false; assert(src->surface.micro_tile_mode == ((struct r600_texture*)tmp)->surface.micro_tile_mode); /* 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; }