diff options
Diffstat (limited to 'src/gallium/drivers/radeonsi')
-rw-r--r-- | src/gallium/drivers/radeonsi/cik_sdma.c | 217 |
1 files changed, 2 insertions, 215 deletions
diff --git a/src/gallium/drivers/radeonsi/cik_sdma.c b/src/gallium/drivers/radeonsi/cik_sdma.c index a8caf04909f..ec3446a5b5f 100644 --- a/src/gallium/drivers/radeonsi/cik_sdma.c +++ b/src/gallium/drivers/radeonsi/cik_sdma.c @@ -89,110 +89,6 @@ static void cik_sdma_copy_buffer(struct si_context *ctx, cik_sdma_do_copy_buffer(ctx, dst, src, dst_offset, src_offset, size); } -static void cik_sdma_copy_tile(struct si_context *ctx, - struct pipe_resource *dst, - unsigned dst_level, - struct pipe_resource *src, - unsigned src_level, - unsigned y, - unsigned copy_height, - unsigned y_align, - unsigned pitch, - unsigned bpe) -{ - struct radeon_winsys_cs *cs = ctx->b.dma.cs; - struct r600_texture *rsrc = (struct r600_texture*)src; - struct r600_texture *rdst = (struct r600_texture*)dst; - unsigned dst_mode = rdst->surface.level[dst_level].mode; - unsigned src_mode = rsrc->surface.level[src_level].mode; - bool detile = dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED; - struct r600_texture *rlinear = detile ? rdst : rsrc; - struct r600_texture *rtiled = detile ? rsrc : rdst; - unsigned linear_lvl = detile ? dst_level : src_level; - unsigned tiled_lvl = detile ? src_level : dst_level; - struct radeon_info *info = &ctx->screen->b.info; - unsigned index = rtiled->surface.tiling_index[tiled_lvl]; - unsigned macro_index = rtiled->surface.macro_tile_index; - unsigned tile_mode = info->si_tile_mode_array[index]; - unsigned macro_mode = info->cik_macrotile_mode_array[macro_index]; - unsigned array_mode, lbpe, pitch_tile_max, slice_tile_max, size; - unsigned ncopy, height, cheight, i; - unsigned sub_op, bank_h, bank_w, mt_aspect, nbanks, tile_split, mt; - uint64_t base, addr; - unsigned pipe_config; - - assert(dst_mode != src_mode); - assert(src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED || dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED); - - sub_op = CIK_SDMA_COPY_SUB_OPCODE_TILED; - lbpe = util_logbase2(bpe); - pitch_tile_max = ((pitch / bpe) / 8) - 1; - - assert(!util_format_is_depth_and_stencil(rtiled->resource.b.b.format)); - - array_mode = G_009910_ARRAY_MODE(tile_mode); - slice_tile_max = (rtiled->surface.level[tiled_lvl].nblk_x * - rtiled->surface.level[tiled_lvl].nblk_y) / (8*8) - 1; - height = rlinear->surface.level[linear_lvl].nblk_y; - base = rtiled->surface.level[tiled_lvl].offset; - addr = rlinear->surface.level[linear_lvl].offset; - bank_h = G_009990_BANK_HEIGHT(macro_mode); - bank_w = G_009990_BANK_WIDTH(macro_mode); - mt_aspect = G_009990_MACRO_TILE_ASPECT(macro_mode); - /* Non-depth modes don't have TILE_SPLIT set. */ - tile_split = util_logbase2(rtiled->surface.tile_split >> 6); - nbanks = G_009990_NUM_BANKS(macro_mode); - base += rtiled->resource.gpu_address; - addr += rlinear->resource.gpu_address; - - pipe_config = G_009910_PIPE_CONFIG(tile_mode); - mt = G_009910_MICRO_TILE_MODE_NEW(tile_mode); - - size = (copy_height * pitch) / 4; - cheight = copy_height; - if (((cheight * pitch) / 4) > CIK_SDMA_COPY_MAX_SIZE) { - cheight = (CIK_SDMA_COPY_MAX_SIZE * 4) / pitch; - cheight &= ~(y_align - 1); - } - ncopy = (copy_height + cheight - 1) / cheight; - r600_need_dma_space(&ctx->b, ncopy * 12); - - radeon_add_to_buffer_list(&ctx->b, &ctx->b.dma, &rsrc->resource, - RADEON_USAGE_READ, RADEON_PRIO_SDMA_TEXTURE); - radeon_add_to_buffer_list(&ctx->b, &ctx->b.dma, &rdst->resource, - RADEON_USAGE_WRITE, RADEON_PRIO_SDMA_TEXTURE); - - copy_height = size * 4 / pitch; - for (i = 0; i < ncopy; i++) { - cheight = copy_height; - if (((cheight * pitch) / 4) > CIK_SDMA_COPY_MAX_SIZE) { - cheight = (CIK_SDMA_COPY_MAX_SIZE * 4) / pitch; - cheight &= ~(y_align - 1); - } - size = (cheight * pitch) / 4; - - cs->buf[cs->cdw++] = CIK_SDMA_PACKET(CIK_SDMA_OPCODE_COPY, - sub_op, detile << 15); - cs->buf[cs->cdw++] = base; - cs->buf[cs->cdw++] = base >> 32; - cs->buf[cs->cdw++] = ((height - 1) << 16) | pitch_tile_max; - cs->buf[cs->cdw++] = slice_tile_max; - cs->buf[cs->cdw++] = (pipe_config << 26) | (mt_aspect << 24) | - (nbanks << 21) | (bank_h << 18) | (bank_w << 15) | - (tile_split << 11) | (mt << 8) | (array_mode << 3) | - lbpe; - cs->buf[cs->cdw++] = y << 16; /* | x */ - cs->buf[cs->cdw++] = 0; /* z */ - cs->buf[cs->cdw++] = addr & 0xfffffffc; - cs->buf[cs->cdw++] = addr >> 32; - cs->buf[cs->cdw++] = (pitch / bpe) - 1; - cs->buf[cs->cdw++] = size; - - copy_height -= cheight; - y += cheight; - } -} - static void cik_sdma_copy(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dst_level, @@ -202,124 +98,15 @@ static void cik_sdma_copy(struct pipe_context *ctx, const struct pipe_box *src_box) { struct si_context *sctx = (struct si_context *)ctx; - struct r600_texture *rsrc = (struct r600_texture*)src; - struct r600_texture *rdst = (struct r600_texture*)dst; - unsigned dst_pitch, src_pitch, bpe, dst_mode, src_mode; - unsigned src_w, dst_w; - unsigned src_x, src_y; - unsigned copy_height, y_align; - unsigned dst_x = dstx, dst_y = dsty, dst_z = dstz; - if (sctx->b.dma.cs == NULL) { + if (!sctx->b.dma.cs) goto fallback; - } if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { - cik_sdma_copy_buffer(sctx, dst, src, dst_x, src_box->x, src_box->width); + cik_sdma_copy_buffer(sctx, dst, src, dstx, src_box->x, src_box->width); return; } - /* Before re-enabling this, please make sure you can hit all newly - * enabled paths in your testing, preferably with both piglit (in - * particular the streaming-texture-leak test) and real world apps - * (e.g. the UE4 Elemental demo). - */ - goto fallback; - - if (!r600_prepare_for_dma_blit(&sctx->b, rdst, dst_level, dstx, dsty, - dstz, rsrc, src_level, src_box)) - goto fallback; - - src_x = util_format_get_nblocksx(src->format, src_box->x); - dst_x = util_format_get_nblocksx(src->format, dst_x); - src_y = util_format_get_nblocksy(src->format, src_box->y); - dst_y = util_format_get_nblocksy(src->format, dst_y); - - dst_pitch = rdst->surface.level[dst_level].pitch_bytes; - src_pitch = rsrc->surface.level[src_level].pitch_bytes; - src_w = rsrc->surface.level[src_level].npix_x; - dst_w = rdst->surface.level[dst_level].npix_x; - - if (src_pitch != dst_pitch || src_box->x || dst_x || src_w != dst_w || - src_box->width != src_w || - rsrc->surface.level[src_level].nblk_y != - rdst->surface.level[dst_level].nblk_y) { - /* FIXME CIK can do partial blit */ - goto fallback; - } - - bpe = rdst->surface.bpe; - copy_height = src_box->height / rsrc->surface.blk_h; - dst_mode = rdst->surface.level[dst_level].mode; - src_mode = rsrc->surface.level[src_level].mode; - - /* Dimensions must be aligned to (macro)tiles */ - switch (src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? dst_mode : src_mode) { - case RADEON_SURF_MODE_1D: - if ((src_x % 8) || (src_y % 8) || (dst_x % 8) || (dst_y % 8) || - (copy_height % 8)) - goto fallback; - y_align = 8; - break; - case RADEON_SURF_MODE_2D: { - unsigned mtilew, mtileh; - struct radeon_info *info = &sctx->screen->b.info; - unsigned macro_index = rsrc->surface.macro_tile_index; - unsigned macro_mode = info->cik_macrotile_mode_array[macro_index]; - unsigned num_banks = 2 << G_009990_NUM_BANKS(macro_mode); - - mtilew = (8 * rsrc->surface.bankw * - sctx->screen->b.info.num_tile_pipes) * - rsrc->surface.mtilea; - assert(!(mtilew & (mtilew - 1))); - mtileh = (8 * rsrc->surface.bankh * num_banks) / - rsrc->surface.mtilea; - assert(!(mtileh & (mtileh - 1))); - - if ((src_x & (mtilew - 1)) || (src_y & (mtileh - 1)) || - (dst_x & (mtilew - 1)) || (dst_y & (mtileh - 1)) || - (copy_height & (mtileh - 1))) - goto fallback; - - y_align = mtileh; - break; - } - default: - y_align = 1; - } - - if (src_mode == dst_mode) { - uint64_t dst_offset, src_offset; - unsigned src_h, dst_h; - - src_h = rsrc->surface.level[src_level].npix_y; - dst_h = rdst->surface.level[dst_level].npix_y; - - if (src_box->depth > 1 && - (src_y || dst_y || src_h != dst_h || src_box->height != src_h)) - goto fallback; - - /* simple dma blit would do NOTE code here assume : - * dst_pitch == src_pitch - */ - src_offset= rsrc->surface.level[src_level].offset; - src_offset += rsrc->surface.level[src_level].slice_size * src_box->z; - src_offset += src_y * src_pitch + src_x * bpe; - dst_offset = rdst->surface.level[dst_level].offset; - dst_offset += rdst->surface.level[dst_level].slice_size * dst_z; - dst_offset += dst_y * dst_pitch + dst_x * bpe; - cik_sdma_do_copy_buffer(sctx, dst, src, dst_offset, src_offset, - src_box->depth * - rsrc->surface.level[src_level].slice_size); - } else { - if (dst_y != src_y || src_box->depth > 1 || src_box->z || dst_z) - goto fallback; - - cik_sdma_copy_tile(sctx, dst, dst_level, src, src_level, - src_y, copy_height, y_align, dst_pitch, bpe); - } - return; - fallback: si_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); |