Re: [Mesa-dev] [PATCH] r600g: Use new kernel interface to wait for fences

2012-02-01 Thread Simon Farnsworth
On Tuesday 31 January 2012, Michel Dänzer mic...@daenzer.net wrote:
 On Die, 2012-01-31 at 17:02 +, Simon Farnsworth wrote: 
  Instead of busywaiting for the GPU to finish a fence, use the new kernel
  interface to wait for fence completion.
  
  If the new kernel interface is unavailable, fall back to busywaiting.
  
  if (timeout != PIPE_TIMEOUT_INFINITE 
  os_time_get() - start_time = timeout) {
  return FALSE;
 
 Maybe add something like
 
 if (rscreen-fences.data[rfence-index])
 return TRUE;
 
 before the timeout check? Otherwise there may be a false negative if the
 fence signalled just before the timeout.

I'll fix this - I think I'd prefer to use a ternary operator in the return.

  diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
  b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
  index 143dcf9..487fc58 100644
  --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
  +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
  @@ -892,4 +922,9 @@ void radeon_bomgr_init_functions(struct 
  radeon_drm_winsys *ws)
   ws-base.buffer_from_handle = radeon_winsys_bo_from_handle;
   ws-base.buffer_get_handle = radeon_winsys_bo_get_handle;
   ws-base.buffer_get_virtual_address = radeon_winsys_bo_va;
  +if (ws-info.drm_major  2 ||
  +(ws-info.drm_major == 2  ws-info.drm_minor = 15))
  +ws-base.buffer_wait_fence = radeon_winsys_bo_wait_fence;
  +else
  +ws-base.buffer_wait_fence = radeon_winsys_bo_wait_fence_nokernel;
   }

 We have no idea what kind of API a hypothetical major version  2 might
 have, so I think it's better to only check for (ws-info.drm_minor =
 15) here.

I'll make that change as well and respin.
-- 
Simon Farnsworth
Software Engineer
ONELAN Limited
http://www.onelan.com/


signature.asc
Description: This is a digitally signed message part.
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev


[Mesa-dev] [PATCH] r600g: Use new kernel interface to wait for fences

2012-01-31 Thread Simon Farnsworth
Instead of busywaiting for the GPU to finish a fence, use the new kernel
interface to wait for fence completion.

If the new kernel interface is unavailable, fall back to busywaiting.

Signed-off-by: Simon Farnsworth simon.farnswo...@onelan.co.uk
---
This builds on top of the kernel interface I add in Message-Id:
1328029169-12729-1-git-send-email-simon.farnswo...@onelan.co.uk and
depends on libdrm's copy of radeon_drm.h being synced with the changes made
in that patch.

As with the kernel patch, I'm working atop Jerome's 2D tiling work, so this
may not apply to any current tree. I'm happy to rebase against another tree
on request, though.

 src/gallium/drivers/r600/r600_hw_context.c|2 +-
 src/gallium/drivers/r600/r600_pipe.c  |   12 +++-
 src/gallium/winsys/radeon/drm/radeon_drm_bo.c |   35 +
 src/gallium/winsys/radeon/drm/radeon_winsys.h |   16 +++
 4 files changed, 56 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_hw_context.c 
b/src/gallium/drivers/r600/r600_hw_context.c
index 8eb8e6d..35a57a7 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -1618,7 +1618,7 @@ void r600_context_emit_fence(struct r600_context *ctx, 
struct r600_resource *fen
ctx-pm4[ctx-pm4_cdwords++] = 
EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
ctx-pm4[ctx-pm4_cdwords++] = va  0xUL;   /* ADDRESS_LO */
/* DATA_SEL | INT_EN | ADDRESS_HI */
-   ctx-pm4[ctx-pm4_cdwords++] = (1  29) | (0  24) | ((va  32UL)  
0xFF);
+   ctx-pm4[ctx-pm4_cdwords++] = (1  29) | (2  24) | ((va  32UL)  
0xFF);
ctx-pm4[ctx-pm4_cdwords++] = value;   /* DATA_LO */
ctx-pm4[ctx-pm4_cdwords++] = 0;   /* DATA_HI */
ctx-pm4[ctx-pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0);
diff --git a/src/gallium/drivers/r600/r600_pipe.c 
b/src/gallium/drivers/r600/r600_pipe.c
index c38fbc5..12c5bf5 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -595,7 +595,6 @@ static boolean r600_fence_finish(struct pipe_screen 
*pscreen,
struct r600_screen *rscreen = (struct r600_screen *)pscreen;
struct r600_fence *rfence = (struct r600_fence*)fence;
int64_t start_time = 0;
-   unsigned spins = 0;
 
if (timeout != PIPE_TIMEOUT_INFINITE) {
start_time = os_time_get();
@@ -605,13 +604,10 @@ static boolean r600_fence_finish(struct pipe_screen 
*pscreen,
}
 
while (rscreen-fences.data[rfence-index] == 0) {
-   if (++spins % 256)
-   continue;
-#ifdef PIPE_OS_UNIX
-   sched_yield();
-#else
-   os_time_sleep(10);
-#endif
+   rscreen-ws-buffer_wait_fence(rscreen-fences.bo-buf,
+  rfence-index  2,
+  0,
+  timeout);
if (timeout != PIPE_TIMEOUT_INFINITE 
os_time_get() - start_time = timeout) {
return FALSE;
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c 
b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index 143dcf9..487fc58 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -879,6 +879,36 @@ static uint64_t radeon_winsys_bo_va(struct pb_buffer 
*buffer)
 return bo-va;
 }
 
+/* No kernel support for doing this faster - just spin */
+static void radeon_winsys_bo_wait_fence_nokernel(struct pb_buffer *buf,
+unsigned offset,
+uint32_t value,
+uint64_t timeout)
+{
+#ifdef PIPE_OS_UNIX
+sched_yield();
+#else
+os_time_sleep(10);
+#endif
+}
+
+static void radeon_winsys_bo_wait_fence(struct pb_buffer *_buf,
+   unsigned offset,
+   uint32_t value,
+   uint64_t timeout)
+{
+struct radeon_bo *bo = get_radeon_bo(_buf);
+struct drm_radeon_gem_wait_user_fence args;
+memset(args, 0, sizeof(args));
+args.handle = bo-handle;
+args.ring = RADEON_CS_RING_GFX;
+args.offset = offset;
+args.value = value;
+args.timeout_usec = timeout;
+while (drmCommandWrite(bo-rws-fd, DRM_RADEON_GEM_WAIT_USER_FENCE,
+   args, sizeof(args)) == -EBUSY);
+}
+
 void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
 {
 ws-base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
@@ -892,4 +922,9 @@ void radeon_bomgr_init_functions(struct radeon_drm_winsys 
*ws)
 ws-base.buffer_from_handle = radeon_winsys_bo_from_handle;
 ws-base.buffer_get_handle = radeon_winsys_bo_get_handle;