#include "sid.h"
#include "si_pipe.h"
-#include "../radeon/r600_cs.h"
+#include "radeon/r600_cs.h"
#include "util/u_format.h"
-static unsigned si_array_mode(unsigned mode)
-{
- switch (mode) {
- case RADEON_SURF_MODE_LINEAR_ALIGNED:
- return V_009910_ARRAY_LINEAR_ALIGNED;
- case RADEON_SURF_MODE_1D:
- return V_009910_ARRAY_1D_TILED_THIN1;
- case RADEON_SURF_MODE_2D:
- return V_009910_ARRAY_2D_TILED_THIN1;
- default:
- case RADEON_SURF_MODE_LINEAR:
- return V_009910_ARRAY_LINEAR_GENERAL;
- }
-}
-
static uint32_t si_micro_tile_mode(struct si_screen *sscreen, unsigned tile_mode)
{
if (sscreen->b.info.si_tile_mode_array_valid) {
uint64_t src_offset,
uint64_t size)
{
- struct radeon_winsys_cs *cs = ctx->b.rings.dma.cs;
+ struct radeon_winsys_cs *cs = ctx->b.dma.cs;
unsigned i, ncopy, csize, max_csize, sub_cmd, shift;
struct r600_resource *rdst = (struct r600_resource*)dst;
struct r600_resource *rsrc = (struct r600_resource*)src;
util_range_add(&rdst->valid_buffer_range, dst_offset,
dst_offset + size);
- dst_offset += r600_resource_va(&ctx->screen->b.b, dst);
- src_offset += r600_resource_va(&ctx->screen->b.b, src);
+ dst_offset += rdst->gpu_address;
+ src_offset += rsrc->gpu_address;
/* see if we use dword or byte copy */
if (!(dst_offset % 4) && !(src_offset % 4) && !(size % 4)) {
r600_need_dma_space(&ctx->b, ncopy * 5);
- r600_context_bo_reloc(&ctx->b, &ctx->b.rings.dma, rsrc, RADEON_USAGE_READ,
- RADEON_PRIO_MIN);
- r600_context_bo_reloc(&ctx->b, &ctx->b.rings.dma, rdst, RADEON_USAGE_WRITE,
- RADEON_PRIO_MIN);
+ radeon_add_to_buffer_list(&ctx->b, &ctx->b.dma, rsrc, RADEON_USAGE_READ,
+ RADEON_PRIO_SDMA_BUFFER);
+ radeon_add_to_buffer_list(&ctx->b, &ctx->b.dma, rdst, RADEON_USAGE_WRITE,
+ RADEON_PRIO_SDMA_BUFFER);
for (i = 0; i < ncopy; i++) {
csize = size < max_csize ? size : max_csize;
cs->buf[cs->cdw++] = SI_DMA_PACKET(SI_DMA_PACKET_COPY, sub_cmd, csize);
- cs->buf[cs->cdw++] = dst_offset & 0xffffffff;
- cs->buf[cs->cdw++] = src_offset & 0xffffffff;
+ cs->buf[cs->cdw++] = dst_offset;
+ cs->buf[cs->cdw++] = src_offset;
cs->buf[cs->cdw++] = (dst_offset >> 32UL) & 0xff;
cs->buf[cs->cdw++] = (src_offset >> 32UL) & 0xff;
dst_offset += csize << shift;
unsigned pitch,
unsigned bpp)
{
- struct radeon_winsys_cs *cs = ctx->b.rings.dma.cs;
+ struct radeon_winsys_cs *cs = ctx->b.dma.cs;
struct si_screen *sscreen = ctx->screen;
struct r600_texture *rsrc = (struct r600_texture*)src;
struct r600_texture *rdst = (struct r600_texture*)dst;
+ struct r600_texture *rlinear, *rtiled;
+ unsigned linear_lvl, tiled_lvl;
unsigned array_mode, lbpp, pitch_tile_max, slice_tile_max, size;
- unsigned ncopy, height, cheight, detile, i, x, y, z, src_mode, dst_mode;
+ unsigned ncopy, height, cheight, detile, i, src_mode, dst_mode;
+ unsigned linear_x, linear_y, linear_z, tiled_x, tiled_y, tiled_z;
unsigned sub_cmd, bank_h, bank_w, mt_aspect, nbanks, tile_split, mt;
uint64_t base, addr;
unsigned pipe_config, tile_mode_index;
dst_mode = dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : dst_mode;
assert(dst_mode != src_mode);
- y = 0;
sub_cmd = SI_DMA_COPY_TILED;
lbpp = util_logbase2(bpp);
pitch_tile_max = ((pitch / bpp) / 8) - 1;
- if (dst_mode == RADEON_SURF_MODE_LINEAR) {
- /* T2L */
- array_mode = si_array_mode(src_mode);
- slice_tile_max = (rsrc->surface.level[src_level].nblk_x * rsrc->surface.level[src_level].nblk_y) / (8*8);
- slice_tile_max = slice_tile_max ? slice_tile_max - 1 : 0;
- /* linear height must be the same as the slice tile max height, it's ok even
- * if the linear destination/source have smaller heigh as the size of the
- * dma packet will be using the copy_height which is always smaller or equal
- * to the linear height
- */
- height = rsrc->surface.level[src_level].npix_y;
- detile = 1;
- x = src_x;
- y = src_y;
- z = src_z;
- base = rsrc->surface.level[src_level].offset;
- addr = rdst->surface.level[dst_level].offset;
- addr += rdst->surface.level[dst_level].slice_size * dst_z;
- addr += dst_y * pitch + dst_x * bpp;
- bank_h = cik_bank_wh(rsrc->surface.bankh);
- bank_w = cik_bank_wh(rsrc->surface.bankw);
- mt_aspect = cik_macro_tile_aspect(rsrc->surface.mtilea);
- tile_split = cik_tile_split(rsrc->surface.tile_split);
- tile_mode_index = si_tile_mode_index(rsrc, src_level,
- util_format_has_stencil(util_format_description(src->format)));
- nbanks = si_num_banks(sscreen, rsrc->surface.bpe, rsrc->surface.tile_split,
- tile_mode_index);
- base += r600_resource_va(&ctx->screen->b.b, src);
- addr += r600_resource_va(&ctx->screen->b.b, dst);
- } else {
- /* L2T */
- array_mode = si_array_mode(dst_mode);
- slice_tile_max = (rdst->surface.level[dst_level].nblk_x * rdst->surface.level[dst_level].nblk_y) / (8*8);
- slice_tile_max = slice_tile_max ? slice_tile_max - 1 : 0;
- /* linear height must be the same as the slice tile max height, it's ok even
- * if the linear destination/source have smaller heigh as the size of the
- * dma packet will be using the copy_height which is always smaller or equal
- * to the linear height
- */
- height = rdst->surface.level[dst_level].npix_y;
- detile = 0;
- x = dst_x;
- y = dst_y;
- z = dst_z;
- base = rdst->surface.level[dst_level].offset;
- addr = rsrc->surface.level[src_level].offset;
- addr += rsrc->surface.level[src_level].slice_size * src_z;
- addr += src_y * pitch + src_x * bpp;
- bank_h = cik_bank_wh(rdst->surface.bankh);
- bank_w = cik_bank_wh(rdst->surface.bankw);
- mt_aspect = cik_macro_tile_aspect(rdst->surface.mtilea);
- tile_split = cik_tile_split(rdst->surface.tile_split);
- tile_mode_index = si_tile_mode_index(rdst, dst_level,
- util_format_has_stencil(util_format_description(dst->format)));
- nbanks = si_num_banks(sscreen, rdst->surface.bpe, rdst->surface.tile_split,
- tile_mode_index);
- base += r600_resource_va(&ctx->screen->b.b, dst);
- addr += r600_resource_va(&ctx->screen->b.b, src);
- }
+ detile = dst_mode == RADEON_SURF_MODE_LINEAR;
+ rlinear = detile ? rdst : rsrc;
+ rtiled = detile ? rsrc : rdst;
+ linear_lvl = detile ? dst_level : src_level;
+ tiled_lvl = detile ? src_level : dst_level;
+ linear_x = detile ? dst_x : src_x;
+ linear_y = detile ? dst_y : src_y;
+ linear_z = detile ? dst_z : src_z;
+ tiled_x = detile ? src_x : dst_x;
+ tiled_y = detile ? src_y : dst_y;
+ tiled_z = detile ? src_z : dst_z;
+
+ assert(!util_format_is_depth_and_stencil(rtiled->resource.b.b.format));
+
+ array_mode = si_array_mode(rtiled->surface.level[tiled_lvl].mode);
+ slice_tile_max = (rtiled->surface.level[tiled_lvl].nblk_x *
+ rtiled->surface.level[tiled_lvl].nblk_y) / (8*8) - 1;
+ /* linear height must be the same as the slice tile max height, it's ok even
+ * if the linear destination/source have smaller heigh as the size of the
+ * dma packet will be using the copy_height which is always smaller or equal
+ * to the linear height
+ */
+ height = rtiled->surface.level[tiled_lvl].nblk_y;
+ base = rtiled->surface.level[tiled_lvl].offset;
+ addr = rlinear->surface.level[linear_lvl].offset;
+ addr += rlinear->surface.level[linear_lvl].slice_size * linear_z;
+ addr += linear_y * pitch + linear_x * bpp;
+ bank_h = cik_bank_wh(rtiled->surface.bankh);
+ bank_w = cik_bank_wh(rtiled->surface.bankw);
+ mt_aspect = cik_macro_tile_aspect(rtiled->surface.mtilea);
+ tile_split = cik_tile_split(rtiled->surface.tile_split);
+ tile_mode_index = si_tile_mode_index(rtiled, tiled_lvl, false);
+ nbanks = si_num_banks(sscreen, rtiled);
+ base += rtiled->resource.gpu_address;
+ addr += rlinear->resource.gpu_address;
pipe_config = cik_db_pipe_config(sscreen, tile_mode_index);
mt = si_micro_tile_mode(sscreen, tile_mode_index);
ncopy = (size / SI_DMA_COPY_MAX_SIZE_DW) + !!(size % SI_DMA_COPY_MAX_SIZE_DW);
r600_need_dma_space(&ctx->b, ncopy * 9);
- r600_context_bo_reloc(&ctx->b, &ctx->b.rings.dma, &rsrc->resource,
- RADEON_USAGE_READ, RADEON_PRIO_MIN);
- r600_context_bo_reloc(&ctx->b, &ctx->b.rings.dma, &rdst->resource,
- RADEON_USAGE_WRITE, RADEON_PRIO_MIN);
+ 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);
for (i = 0; i < ncopy; i++) {
cheight = copy_height;
(bank_w << 18) | (mt_aspect << 16);
cs->buf[cs->cdw++] = (pitch_tile_max << 0) | ((height - 1) << 16);
cs->buf[cs->cdw++] = (slice_tile_max << 0) | (pipe_config << 26);
- cs->buf[cs->cdw++] = (x << 0) | (z << 18);
- cs->buf[cs->cdw++] = (y << 0) | (tile_split << 21) | (nbanks << 25) | (mt << 27);
+ cs->buf[cs->cdw++] = (tiled_x << 0) | (tiled_z << 18);
+ cs->buf[cs->cdw++] = (tiled_y << 0) | (tile_split << 21) | (nbanks << 25) | (mt << 27);
cs->buf[cs->cdw++] = addr & 0xfffffffc;
cs->buf[cs->cdw++] = (addr >> 32UL) & 0xff;
copy_height -= cheight;
addr += cheight * pitch;
- y += cheight;
+ tiled_y += cheight;
}
}
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, bpp, dst_mode, src_mode, copy_height;
+ unsigned dst_pitch, src_pitch, bpp, dst_mode, src_mode;
unsigned src_w, dst_w;
unsigned src_x, src_y;
unsigned dst_x = dstx, dst_y = dsty, dst_z = dstz;
- if (sctx->b.rings.dma.cs == NULL) {
- goto fallback;
- }
-
- /* TODO: Implement DMA copy for CIK */
- if (sctx->b.chip_class >= CIK) {
+ if (sctx->b.dma.cs == NULL) {
goto fallback;
}
return;
}
+ /* XXX: Using the asynchronous DMA engine for multi-dimensional
+ * operations seems to cause random GPU lockups for various people.
+ * While the root cause for this might need to be fixed in the kernel,
+ * let's disable it for now.
+ *
+ * Before re-enabling this, please make sure you can hit all newly
+ * enabled paths in your testing, preferably with both piglit and real
+ * world apps, and get in touch with people on the bug reports below
+ * for stability testing.
+ *
+ * https://bugs.freedesktop.org/show_bug.cgi?id=85647
+ * https://bugs.freedesktop.org/show_bug.cgi?id=83500
+ */
+ goto fallback;
+
if (src->format != dst->format || src_box->depth > 1 ||
- rdst->dirty_level_mask != 0) {
+ (rdst->dirty_level_mask | rdst->stencil_dirty_level_mask) & (1 << dst_level) ||
+ rdst->cmask.size || rdst->fmask.size ||
+ rsrc->cmask.size || rsrc->fmask.size ||
+ rdst->dcc_buffer || rsrc->dcc_buffer) {
goto fallback;
}
- if (rsrc->dirty_level_mask) {
+ if (rsrc->dirty_level_mask & (1 << src_level)) {
ctx->flush_resource(ctx, src);
}
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;
- 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;
src_mode = src_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : src_mode;
dst_mode = dst_mode == RADEON_SURF_MODE_LINEAR_ALIGNED ? RADEON_SURF_MODE_LINEAR : dst_mode;
- if (src_pitch != dst_pitch || src_box->x || dst_x || src_w != dst_w) {
+ if (src_pitch != dst_pitch || src_box->x || dst_x || src_w != dst_w ||
+ src_box->width != src_w ||
+ src_box->height != rsrc->surface.level[src_level].npix_y ||
+ src_box->height != rdst->surface.level[dst_level].npix_y ||
+ rsrc->surface.level[src_level].nblk_y !=
+ rdst->surface.level[dst_level].nblk_y) {
/* FIXME si can do partial blit */
goto fallback;
}
/* the x test here are currently useless (because we don't support partial blit)
* but keep them around so we don't forget about those
*/
- if ((src_pitch % 8) || (src_box->x % 8) || (dst_x % 8) || (src_box->y % 8) || (dst_y % 8)) {
+ if ((src_pitch % 8) || (src_box->x % 8) || (dst_x % 8) ||
+ (src_box->y % 8) || (dst_y % 8) || (src_box->height % 8)) {
goto fallback;
}
dst_offset += rdst->surface.level[dst_level].slice_size * dst_z;
dst_offset += dst_y * dst_pitch + dst_x * bpp;
si_dma_copy_buffer(sctx, dst, src, dst_offset, src_offset,
- src_box->height * src_pitch);
+ rsrc->surface.level[src_level].slice_size);
} else {
si_dma_copy_tile(sctx, dst, dst_level, dst_x, dst_y, dst_z,
src, src_level, src_x, src_y, src_box->z,
- copy_height, dst_pitch, bpp);
+ src_box->height / rsrc->surface.blk_h,
+ dst_pitch, bpp);
}
return;
fallback:
- ctx->resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
- src, src_level, src_box);
+ si_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
+ src, src_level, src_box);
}