* Chia-I Wu <olv@lunarg.com>
*/
-#include "util/u_blitter.h"
-#include "util/u_clear.h"
-#include "util/u_pack_color.h"
#include "util/u_surface.h"
-#include "intel_reg.h"
+#include "ilo_blitter.h"
#include "ilo_context.h"
-#include "ilo_cp.h"
-#include "ilo_resource.h"
-#include "ilo_screen.h"
#include "ilo_blit.h"
-static bool
-blitter_xy_color_blt(struct pipe_context *pipe,
- struct pipe_resource *r,
- int16_t x1, int16_t y1,
- int16_t x2, int16_t y2,
- uint32_t color)
+static void
+ilo_resource_copy_region(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ unsigned dst_level,
+ unsigned dstx, unsigned dsty, unsigned dstz,
+ struct pipe_resource *src,
+ unsigned src_level,
+ const struct pipe_box *src_box)
{
- const int cmd_len = 6;
struct ilo_context *ilo = ilo_context(pipe);
- struct ilo_resource *res = ilo_resource(r);
- uint32_t cmd, br13;
- int cpp, stride;
- struct intel_bo *bo_check[2];
-
- /* how to support Y-tiling? */
- if (res->tiling == INTEL_TILING_Y)
- return false;
-
- /* nothing to clear */
- if (x1 >= x2 || y1 >= y2)
- return true;
-
- cmd = XY_COLOR_BLT_CMD | (cmd_len - 2);
- br13 = 0xf0 << 16;
-
- cpp = util_format_get_blocksize(res->base.format);
- switch (cpp) {
- case 4:
- cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
- br13 |= BR13_8888;
- break;
- case 2:
- br13 |= BR13_565;
- break;
- case 1:
- br13 |= BR13_8;
- break;
- default:
- return false;
- break;
- }
-
- stride = res->bo_stride;
- if (res->tiling != INTEL_TILING_NONE) {
- assert(res->tiling == INTEL_TILING_X);
-
- cmd |= XY_DST_TILED;
- /* in dwords */
- stride /= 4;
- }
- /* make room if necessary */
- bo_check[0] = ilo->cp->bo;
- bo_check[1] = res->bo;
- if (ilo->winsys->check_aperture_space(ilo->winsys, bo_check, 2))
- ilo_cp_flush(ilo->cp);
-
- ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT);
-
- ilo_cp_begin(ilo->cp, cmd_len);
- ilo_cp_write(ilo->cp, cmd);
- ilo_cp_write(ilo->cp, br13 | stride);
- ilo_cp_write(ilo->cp, (y1 << 16) | x1);
- ilo_cp_write(ilo->cp, (y2 << 16) | x2);
- ilo_cp_write_bo(ilo->cp, 0, res->bo,
- INTEL_DOMAIN_RENDER,
- INTEL_DOMAIN_RENDER);
- ilo_cp_write(ilo->cp, color);
- ilo_cp_end(ilo->cp);
-
- return true;
-}
-
-enum ilo_blitter_op {
- ILO_BLITTER_CLEAR,
- ILO_BLITTER_CLEAR_SURFACE,
- ILO_BLITTER_BLIT,
-};
+ if (ilo_blitter_blt_copy_resource(ilo->blitter,
+ dst, dst_level, dstx, dsty, dstz,
+ src, src_level, src_box))
+ return;
-static void
-ilo_blitter_begin(struct ilo_context *ilo, enum ilo_blitter_op op)
-{
- /* as documented in util/u_blitter.h */
- util_blitter_save_vertex_buffer_slot(ilo->blitter,
- ilo->vertex_buffers.buffers);
- util_blitter_save_vertex_elements(ilo->blitter, ilo->vertex_elements);
- util_blitter_save_vertex_shader(ilo->blitter, ilo->vs);
- util_blitter_save_geometry_shader(ilo->blitter, ilo->gs);
- util_blitter_save_so_targets(ilo->blitter,
- ilo->stream_output_targets.num_targets,
- ilo->stream_output_targets.targets);
-
- util_blitter_save_fragment_shader(ilo->blitter, ilo->fs);
- util_blitter_save_depth_stencil_alpha(ilo->blitter,
- ilo->depth_stencil_alpha);
- util_blitter_save_blend(ilo->blitter, ilo->blend);
-
- /* undocumented? */
- util_blitter_save_viewport(ilo->blitter, &ilo->viewport);
- util_blitter_save_stencil_ref(ilo->blitter, &ilo->stencil_ref);
- util_blitter_save_sample_mask(ilo->blitter, ilo->sample_mask);
-
- switch (op) {
- case ILO_BLITTER_CLEAR:
- util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
- break;
- case ILO_BLITTER_CLEAR_SURFACE:
- util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
- break;
- case ILO_BLITTER_BLIT:
- util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
- util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
-
- util_blitter_save_fragment_sampler_states(ilo->blitter,
- ilo->samplers[PIPE_SHADER_FRAGMENT].num_samplers,
- (void **) ilo->samplers[PIPE_SHADER_FRAGMENT].samplers);
-
- util_blitter_save_fragment_sampler_views(ilo->blitter,
- ilo->sampler_views[PIPE_SHADER_FRAGMENT].num_views,
- ilo->sampler_views[PIPE_SHADER_FRAGMENT].views);
-
- /* disable render condition? */
- break;
- default:
- break;
- }
-}
+ if (ilo_blitter_pipe_copy_resource(ilo->blitter,
+ dst, dst_level, dstx, dsty, dstz,
+ src, src_level, src_box))
+ return;
-static void
-ilo_blitter_end(struct ilo_context *ilo)
-{
+ util_resource_copy_region(&ilo->base, dst, dst_level,
+ dstx, dsty, dstz, src, src_level, src_box);
}
static void
{
struct ilo_context *ilo = ilo_context(pipe);
- /* TODO we should pause/resume some queries */
- ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR);
+ if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && ilo->fb.state.zsbuf) {
+ if (ilo_blitter_rectlist_clear_zs(ilo->blitter, ilo->fb.state.zsbuf,
+ buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil))
+ buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
- util_blitter_clear(ilo->blitter,
- ilo->framebuffer.width, ilo->framebuffer.height,
- ilo->framebuffer.nr_cbufs, buffers,
- (ilo->framebuffer.nr_cbufs) ? ilo->framebuffer.cbufs[0]->format :
- PIPE_FORMAT_NONE,
- color, depth, stencil);
+ if (!buffers)
+ return;
+ }
- ilo_blitter_end(ilo);
+ ilo_blitter_pipe_clear_fb(ilo->blitter, buffers, color, depth, stencil);
}
static void
unsigned width, unsigned height)
{
struct ilo_context *ilo = ilo_context(pipe);
- union util_color packed;
if (!width || !height || dstx >= dst->width || dsty >= dst->height)
return;
if (dsty + height > dst->height)
height = dst->height - dsty;
- util_pack_color(color->f, dst->format, &packed);
-
- /* try HW blit first */
- if (blitter_xy_color_blt(pipe, dst->texture,
- dstx, dsty,
- dstx + width, dsty + height,
- packed.ui))
+ if (ilo_blitter_blt_clear_rt(ilo->blitter,
+ dst, color, dstx, dsty, width, height))
return;
- ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
- util_blitter_clear_render_target(ilo->blitter,
+ ilo_blitter_pipe_clear_rt(ilo->blitter,
dst, color, dstx, dsty, width, height);
- ilo_blitter_end(ilo);
}
static void
{
struct ilo_context *ilo = ilo_context(pipe);
- /*
- * The PRM claims that HW blit supports Y-tiling since GEN6, but it does
- * not tell us how to program it. Since depth buffers are always Y-tiled,
- * HW blit will not work.
- */
- ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
- util_blitter_clear_depth_stencil(ilo->blitter,
+ if (!width || !height || dstx >= dst->width || dsty >= dst->height)
+ return;
+
+ if (dstx + width > dst->width)
+ width = dst->width - dstx;
+ if (dsty + height > dst->height)
+ height = dst->height - dsty;
+
+ if (ilo_blitter_blt_clear_zs(ilo->blitter,
+ dst, clear_flags, depth, stencil, dstx, dsty, width, height))
+ return;
+
+ ilo_blitter_pipe_clear_zs(ilo->blitter,
dst, clear_flags, depth, stencil, dstx, dsty, width, height);
- ilo_blitter_end(ilo);
}
static void
ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
{
struct ilo_context *ilo = ilo_context(pipe);
- struct pipe_blit_info skip_stencil;
- if (util_try_blit_via_copy_region(pipe, info))
- return;
+ ilo_blitter_pipe_blit(ilo->blitter, info);
+}
- if (!util_blitter_is_blit_supported(ilo->blitter, info)) {
- /* try without stencil */
- if (info->mask & PIPE_MASK_S) {
- skip_stencil = *info;
- skip_stencil.mask = info->mask & ~PIPE_MASK_S;
+static void
+ilo_flush_resource(struct pipe_context *pipe, struct pipe_resource *res)
+{
+ struct ilo_context *ilo = ilo_context(pipe);
+ const unsigned flags = ILO_TEXTURE_CPU_READ |
+ ILO_TEXTURE_BLT_READ |
+ ILO_TEXTURE_RENDER_READ;
- if (util_blitter_is_blit_supported(ilo->blitter, &skip_stencil))
- info = &skip_stencil;
- }
+ ilo_blit_resolve_resource(ilo, res, flags);
+}
- if (info == &skip_stencil) {
- ilo_warn("ignore stencil buffer blitting\n");
+void
+ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo,
+ struct pipe_resource *res, unsigned level,
+ unsigned first_slice, unsigned num_slices,
+ unsigned resolve_flags)
+{
+ struct ilo_texture *tex = ilo_texture(res);
+ const unsigned any_reader =
+ ILO_TEXTURE_RENDER_READ |
+ ILO_TEXTURE_BLT_READ |
+ ILO_TEXTURE_CPU_READ;
+ const unsigned other_writers =
+ ILO_TEXTURE_BLT_WRITE |
+ ILO_TEXTURE_CPU_WRITE;
+ unsigned i;
+
+ assert(tex->base.target != PIPE_BUFFER &&
+ ilo_texture_can_enable_hiz(tex, level, first_slice, num_slices));
+
+ if (resolve_flags & ILO_TEXTURE_RENDER_WRITE) {
+ /*
+ * When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader. We
+ * need to perform a HiZ Buffer Resolve in case the resource was
+ * previously written by another writer, unless this is a clear.
+ *
+ * When slices have different clear values, we perform a Depth Buffer
+ * Resolve on all slices not sharing the clear value of the first slice.
+ * After resolving, those slices do not use 3DSTATE_CLEAR_PARAMS and can
+ * be made to have the same clear value as the first slice does. This
+ * way,
+ *
+ * - 3DSTATE_CLEAR_PARAMS can be set to the clear value of any slice
+ * - we will not resolve unnecessarily next time this function is
+ * called
+ *
+ * Since slice clear value is the value the slice is cleared to when
+ * ILO_TEXTURE_CLEAR is set, the bit needs to be unset.
+ */
+ assert(!(resolve_flags & (other_writers | any_reader)));
+
+ if (!(resolve_flags & ILO_TEXTURE_CLEAR)) {
+ bool set_clear_value = false;
+ uint32_t first_clear_value;
+
+ for (i = 0; i < num_slices; i++) {
+ const struct ilo_texture_slice *slice =
+ ilo_texture_get_slice(tex, level, first_slice + i);
+
+ if (slice->flags & other_writers) {
+ ilo_blitter_rectlist_resolve_hiz(ilo->blitter,
+ res, level, first_slice + i);
+ }
+ else if (i == 0) {
+ first_clear_value = slice->clear_value;
+ }
+ else if (slice->clear_value != first_clear_value &&
+ (slice->flags & ILO_TEXTURE_RENDER_WRITE)) {
+ ilo_blitter_rectlist_resolve_z(ilo->blitter,
+ res, level, first_slice + i);
+ set_clear_value = true;
+ }
+ }
+
+ if (set_clear_value) {
+ /* ILO_TEXTURE_CLEAR will be cleared later */
+ ilo_texture_set_slice_clear_value(tex, level,
+ first_slice, num_slices, first_clear_value);
+ }
}
- else {
- ilo_warn("failed to blit with the generic blitter\n");
- return;
+ }
+ else if ((resolve_flags & any_reader) ||
+ ((resolve_flags & other_writers) &&
+ !(resolve_flags & ILO_TEXTURE_CLEAR))) {
+ /*
+ * When there is at least a reader or writer, we need to perform a
+ * Depth Buffer Resolve in case the resource was previously written
+ * by ILO_TEXTURE_RENDER_WRITE.
+ */
+ for (i = 0; i < num_slices; i++) {
+ const struct ilo_texture_slice *slice =
+ ilo_texture_get_slice(tex, level, first_slice + i);
+
+ if (slice->flags & ILO_TEXTURE_RENDER_WRITE) {
+ ilo_blitter_rectlist_resolve_z(ilo->blitter,
+ &tex->base, level, first_slice + i);
+ }
}
}
-
- ilo_blitter_begin(ilo, ILO_BLITTER_BLIT);
- util_blitter_blit(ilo->blitter, info);
- ilo_blitter_end(ilo);
}
/**
void
ilo_init_blit_functions(struct ilo_context *ilo)
{
- ilo->base.resource_copy_region = util_resource_copy_region;
+ ilo->base.resource_copy_region = ilo_resource_copy_region;
ilo->base.blit = ilo_blit;
+ ilo->base.flush_resource = ilo_flush_resource;
ilo->base.clear = ilo_clear;
ilo->base.clear_render_target = ilo_clear_render_target;