diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2011-10-04 20:13:30 +0200 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-10-05 10:17:22 +0100 |
commit | e2fa3a76839ada0d788549607263a036aa654243 (patch) | |
tree | 24883fcf9f80483aed537661a49ed389d0dff671 /drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |
parent | e93daed8e2fd5ce3dc98efe9938426127a534ccc (diff) |
vmwgfx: Fix up query processing
Previously, query results could be placed in any buffer object, but since
we didn't allow pinned buffer objects, query results could be written when
that buffer was evicted, corrupting data in other buffers.
Now, require that buffers holding query results are no more than two pages
large, and allow one single pinned such buffer. When the command submission
code encounters query result structures in other buffers, the queries in the
pinned buffer will be finished using a query barrier for the last hardware
context using the buffer. Also if the command submission code detects
that a new hardware context is used for queries, all queries of the previous
hardware context is also flushed. Currently we use waiting for a no-op
occlusion query as a query barrier for a specific context.
The query buffer is also flushed and unpinned on context destructions,
master drops and before scanout bo placement.
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index d7ed33e732a..62d6377b8ee 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -505,3 +505,60 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) out_err: return ret; } + +/** + * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo. + * + * @dev_priv: The device private structure. + * @cid: The hardware context id used for the query. + * + * This function is used to emit a dummy occlusion query with + * no primitives rendered between query begin and query end. + * It's used to provide a query barrier, in order to know that when + * this query is finished, all preceding queries are also finished. + * + * A Query results structure should have been initialized at the start + * of the dev_priv->dummy_query_bo buffer object. And that buffer object + * must also be either reserved or pinned when this function is called. + * + * Returns -ENOMEM on failure to reserve fifo space. + */ +int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv, + uint32_t cid) +{ + /* + * A query wait without a preceding query end will + * actually finish all queries for this cid + * without writing to the query result structure. + */ + + struct ttm_buffer_object *bo = dev_priv->dummy_query_bo; + struct { + SVGA3dCmdHeader header; + SVGA3dCmdWaitForQuery body; + } *cmd; + + cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); + + if (unlikely(cmd == NULL)) { + DRM_ERROR("Out of fifo space for dummy query.\n"); + return -ENOMEM; + } + + cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY; + cmd->header.size = sizeof(cmd->body); + cmd->body.cid = cid; + cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION; + + if (bo->mem.mem_type == TTM_PL_VRAM) { + cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER; + cmd->body.guestResult.offset = bo->offset; + } else { + cmd->body.guestResult.gmrId = bo->mem.start; + cmd->body.guestResult.offset = 0; + } + + vmw_fifo_commit(dev_priv, sizeof(*cmd)); + + return 0; +} |