[Nouveau] Interrupt setting

Younes Manton younes.m at gmail.com
Sat Mar 13 09:36:20 PST 2010


On Sat, Mar 13, 2010 at 11:47 AM, Shinpei KATO
<shinpei at il.is.s.u-tokyo.ac.jp> wrote:
> Just one more thing.
> If two commands, (1) simple DMA data copies and (2) fencing, are executed in
> this order, it is possible to have the fence value written before completing DMA
> data copies, since DMA and GPU are independent, isn't is?

No, the fence value will be written after the DMA completes. There is
no independent DMA controller on the GPU, all memory copies are done
by the GPU and are no different than the drawing commands.

Here is a quick example, I copied them from
src/gallium/drivers/nouveau/nv04_surface_2d.c and edited them slightly
in case you want to look at it yourself:

/* Set up a 2D blit operation to copy an image with dimensions w,h
from src_bo at sx,sy to dst_bo at dx,dy */
MARK_RING (chan, 12, 4);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, src_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING  (chan, format);
OUT_RING  (chan, (dst_pitch << 16) | src_pitch);
OUT_RELOCl(chan, src_bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, blit, 0x0300, 3);
OUT_RING  (chan, (sy << 16) | sx);
OUT_RING  (chan, (dy << 16) | dx);
OUT_RING  (chan, ( h << 16) |  w);

/* Set up a general memory-to-memory operation to copy w*h*blocksize
bytes from src_bo + src_offset to dst_bo + dst_offset */
MARK_RING (chan, 3 + ((h / 2047) + 1) * 9, 2 + ((h / 2047) + 1) * 2);
BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
OUT_RELOCo(chan, src_bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(chan, src_bo, src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART
| NOUVEAU_BO_RD);
OUT_RELOCl(chan, dst_bo, dst_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART
| NOUVEAU_BO_WR);
OUT_RING  (chan, src_pitch);
OUT_RING  (chan, dst_pitch);
OUT_RING  (chan, w * util_format_get_blocksize(src->texture->format));
OUT_RING  (chan, h);
OUT_RING  (chan, 0x0101);
OUT_RING  (chan, 0);

/* Set up a fill operation to fill a rectangle in dst_bo with
coordinates dx,dy,w,h with some solid color */
MARK_RING (chan, 16, 4);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCo(chan, dst_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING  (chan, cs2d_format);
OUT_RING  (chan, (dst_pitch << 16) | dst_pitch);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING  (chan, gdirect_format);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
OUT_RING  (chan, value);
BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
OUT_RING  (chan, (dx << 16) | dy);
OUT_RING  (chan, ( w << 16) |  h);

/* Tell the GPU to execute all of the commands in the pushbuffer */
/* This will cause the kernel to emit a fence with some value X after
the last command in the pushbuffer */
FIRE_RING(chan)

while (nvchan_rd32(chan, 0x48) != X)
{
     /* wait... */
}

/* At this point we are guaranteed that all 3 operations are complete
because the GPU will only write X into the register after it has seen
the fence command created by FIRE_RING() and it will only see that
command after it has seen and executed all other commands. */


More information about the Nouveau mailing list