Mesa (master): r300: add occlusion queries support

Maciej Cencora osiris at kemper.freedesktop.org
Sun Aug 16 00:13:50 UTC 2009


Module: Mesa
Branch: master
Commit: 0d0f01e2e0b37ed5152614ceeff34da8e46b5e37
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0d0f01e2e0b37ed5152614ceeff34da8e46b5e37

Author: Maciej Cencora <m.cencora at gmail.com>
Date:   Thu Jun 11 16:13:23 2009 +0200

r300: add occlusion queries support

TODO:
- use proper interface for checking if bo is idle when it's available
- disable ZTOP only when needed
- make it work under KMS

---

 src/mesa/drivers/dri/r300/Makefile        |    1 +
 src/mesa/drivers/dri/r300/r300_context.c  |    8 +
 src/mesa/drivers/dri/r300/r300_context.h  |   17 ++
 src/mesa/drivers/dri/r300/r300_draw.c     |    7 +-
 src/mesa/drivers/dri/r300/r300_queryobj.c |  229 +++++++++++++++++++++++++++++
 src/mesa/drivers/dri/r300/r300_queryobj.h |   34 +++++
 src/mesa/drivers/dri/r300/r300_reg.h      |   12 ++
 src/mesa/drivers/dri/r300/r300_render.c   |    1 +
 8 files changed, 308 insertions(+), 1 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile
index 2390d18..77b3d16 100644
--- a/src/mesa/drivers/dri/r300/Makefile
+++ b/src/mesa/drivers/dri/r300/Makefile
@@ -54,6 +54,7 @@ DRIVER_SOURCES = \
 		 r300_shader.c \
 		 r300_emit.c \
 		 r300_swtcl.c \
+		 r300_queryobj.c \
 		 $(RADEON_COMMON_SOURCES) \
 		 $(EGL_SOURCES) \
 		 $(CS_SOURCES)
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 1baae8f..d37a37c 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -74,6 +74,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "xmlpool.h"		/* for symbolic values of enum-type options */
 
 #define need_GL_VERSION_2_0
+#define need_GL_ARB_occlusion_query
 #define need_GL_ARB_point_parameters
 #define need_GL_ARB_vertex_program
 #define need_GL_EXT_blend_equation_separate
@@ -310,6 +311,11 @@ static void r300InitConstValues(GLcontext *ctx, radeonScreenPtr screen)
 		ctx->Const.FragmentProgram.MaxNativeTexIndirections = R300_PFS_MAX_TEX_INDIRECT;
 		ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0;
 	}
+
+	if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530)
+		r300->num_z_pipes = 2;
+	else
+		r300->num_z_pipes = r300->radeon.radeonScreen->num_gb_pipes;
 }
 
 static void r300ParseOptions(r300ContextPtr r300, radeonScreenPtr screen)
@@ -439,6 +445,8 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 
 	r300InitGLExtensions(ctx);
 
+	make_empty_list(&r300->query.not_flushed_head);
+
 	return GL_TRUE;
 }
 
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index d620417..3ba3426 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -505,6 +505,16 @@ struct r300_index_buffer {
 	GLuint count;
 };
 
+struct r300_query_object {
+	struct gl_query_object Base;
+	struct radeon_bo *bo;
+	int curr_offset;
+	GLboolean emitted_begin;
+
+	/* Double linked list of not flushed query objects */
+	struct r300_query_object *prev, *next;
+};
+
 /**
  * \brief R300 context structure.
  */
@@ -539,6 +549,13 @@ struct r300_context {
 	uint32_t fallback;
 
 	DECLARE_RENDERINPUTS(render_inputs_bitset);
+
+	struct {
+		struct r300_query_object *current;
+		struct r300_query_object not_flushed_head;
+	} query;
+
+	int num_z_pipes;
 };
 
 #define R300_CONTEXT(ctx)		((r300ContextPtr)(ctx->DriverCtx))
diff --git a/src/mesa/drivers/dri/r300/r300_draw.c b/src/mesa/drivers/dri/r300/r300_draw.c
index d6ebdcb..fb416a0 100644
--- a/src/mesa/drivers/dri/r300/r300_draw.c
+++ b/src/mesa/drivers/dri/r300/r300_draw.c
@@ -36,6 +36,7 @@
 #include "r300_context.h"
 #include "r300_emit.h"
 #include "r300_render.h"
+#include "r300_queryobj.h"
 #include "r300_state.h"
 #include "r300_tex.h"
 
@@ -507,7 +508,7 @@ static void r300SetVertexFormat(GLcontext *ctx, const struct gl_client_array *ar
 				radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs, r300->vbuf.attribs[i].bo, RADEON_GEM_DOMAIN_GTT, 0);
 			}
 		}
-		
+
 		r300->radeon.tcl.aos_count = vbuf->num_attribs;
 		ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs, r300->radeon.dma.current, RADEON_GEM_DOMAIN_GTT, 0);
 		if (ret)
@@ -581,12 +582,16 @@ static GLboolean r300TryDrawPrims(GLcontext *ctx,
 	r300EmitCacheFlush(r300);
 	radeonEmitState(&r300->radeon);
 
+	r300EmitQueryBegin(ctx);
+
 	for (i = 0; i < nr_prims; ++i) {
 		r300RunRenderPrimitive(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode);
 	}
 
 	r300EmitCacheFlush(r300);
 
+	r300EmitQueryEnd(ctx);
+
 	r300FreeData(ctx);
 
 	return GL_TRUE;
diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.c b/src/mesa/drivers/dri/r300/r300_queryobj.c
new file mode 100644
index 0000000..830a9ed
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_queryobj.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright © 2008-2009 Maciej Cencora <m.cencora at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Maciej Cencora <m.cencora at gmail.com>
+ *
+ */
+
+#include "r300_queryobj.h"
+#include "r300_emit.h"
+
+#include "main/imports.h"
+#include "main/simple_list.h"
+
+#define PAGE_SIZE 4096
+
+static void r300QueryGetResult(GLcontext *ctx, struct gl_query_object *q)
+{
+	struct r300_query_object *query = (struct r300_query_object *)q;
+	uint32_t *result;
+	int i;
+
+	radeon_bo_map(query->bo, GL_FALSE);
+
+	result = query->bo->ptr;
+
+	query->Base.Result = 0;
+	for (i = 0; i < query->curr_offset/sizeof(uint32_t); ++i) {
+		query->Base.Result += result[i];
+	}
+
+	radeon_bo_unmap(query->bo);
+}
+
+static struct gl_query_object * r300NewQueryObject(GLcontext *ctx, GLuint id)
+{
+	struct r300_query_object *query;
+
+	query = _mesa_calloc(sizeof(struct r300_query_object));
+
+	query->Base.Id = id;
+	query->Base.Result = 0;
+	query->Base.Active = GL_FALSE;
+	query->Base.Ready = GL_TRUE;
+
+	return &query->Base;
+}
+
+static void r300DeleteQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+	struct r300_query_object *query = (struct r300_query_object *)q;
+
+	if (query->bo) {
+		radeon_bo_unref(query->bo);
+	}
+
+	_mesa_free(query);
+}
+
+static void r300BeginQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+	r300ContextPtr r300 = R300_CONTEXT(ctx);
+	struct r300_query_object *query = (struct r300_query_object *)q;
+
+	assert(r300->query.current == NULL);
+
+	if (!query->bo) {
+		query->bo = radeon_bo_open(r300->radeon.radeonScreen->bom, 0, PAGE_SIZE, PAGE_SIZE, RADEON_GEM_DOMAIN_GTT, 0);
+	}
+	query->curr_offset = 0;
+
+	r300->query.current = query;
+	insert_at_tail(&r300->query.not_flushed_head, query);
+}
+
+static void r300EndQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+	r300ContextPtr r300 = R300_CONTEXT(ctx);
+
+	r300EmitQueryEnd(ctx);
+
+	r300->query.current = NULL;
+}
+
+static void r300WaitQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+	r300ContextPtr r300 = R300_CONTEXT(ctx);
+	struct r300_query_object *tmp, *query = (struct r300_query_object *)q;
+
+	/* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
+	{
+		GLboolean found = GL_FALSE;
+		foreach(tmp, &r300->query.not_flushed_head) {
+			if (tmp == query) {
+				found = GL_TRUE;
+				break;
+			}
+		}
+
+		if (found)
+			ctx->Driver.Flush(ctx);
+	}
+
+	r300QueryGetResult(ctx, q);
+
+	query->Base.Ready = GL_TRUE;
+}
+
+
+/**
+ * TODO:
+ * should check if bo is idle, bo there's no interface to do it
+ * just wait for result now
+ */
+static void r300CheckQuery(GLcontext *ctx, struct gl_query_object *q)
+{
+	r300WaitQuery(ctx, q);
+}
+
+void r300EmitQueryBegin(GLcontext *ctx)
+{
+	r300ContextPtr r300 = R300_CONTEXT(ctx);
+	struct r300_query_object *query = r300->query.current;
+	BATCH_LOCALS(&r300->radeon);
+
+	if (!query || query->emitted_begin)
+		return;
+
+	if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+		BEGIN_BATCH_NO_AUTOSTATE(4);
+		OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+		OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0);
+		END_BATCH();
+	} else {
+		BEGIN_BATCH_NO_AUTOSTATE(4);
+		OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
+		OUT_BATCH_REGVAL(R300_ZB_ZPASS_DATA, 0);
+		END_BATCH();
+	}
+
+	query->emitted_begin = GL_TRUE;
+}
+
+void r300EmitQueryEnd(GLcontext *ctx)
+{
+	r300ContextPtr r300 = R300_CONTEXT(ctx);
+	struct r300_query_object *query = r300->query.current;
+	BATCH_LOCALS(&r300->radeon);
+
+	if (!query || !query->emitted_begin)
+		return;
+
+	radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
+								  query->bo,
+								  0, RADEON_GEM_DOMAIN_GTT);
+
+	if (r300->radeon.radeonScreen->chip_family == CHIP_FAMILY_RV530) {
+		BEGIN_BATCH_NO_AUTOSTATE(14);
+		OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0);
+		OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+		OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+		OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1);
+		OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+		OUT_BATCH_RELOC(0, query->bo, query->curr_offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+		OUT_BATCH_REGVAL(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL);
+		END_BATCH();
+	} else {
+		BEGIN_BATCH_NO_AUTOSTATE(3 * 2 *r300->num_z_pipes + 2);
+		switch (r300->num_z_pipes) {
+			case 4:
+				OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+				OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+				OUT_BATCH_RELOC(0, query->bo, query->curr_offset+3*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+			case 3:
+				OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_2);
+				OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+				OUT_BATCH_RELOC(0, query->bo, query->curr_offset+2*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+			case 2:
+				if (r300->radeon.radeonScreen->chip_family <= CHIP_FAMILY_RV380) {
+					OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_3);
+				} else {
+					OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_1);
+				}
+				OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+				OUT_BATCH_RELOC(0, query->bo, query->curr_offset+1*sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0);
+			case 1:
+			default:
+				OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_0);
+				OUT_BATCH_REGSEQ(R300_ZB_ZPASS_ADDR, 1);
+				OUT_BATCH_RELOC(0, query->bo, query->curr_offset, 0, RADEON_GEM_DOMAIN_GTT, 0);
+				break;
+		}
+		OUT_BATCH_REGVAL(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL);
+		END_BATCH();
+	}
+
+	query->curr_offset += r300->num_z_pipes * sizeof(uint32_t);
+	assert(query->curr_offset < PAGE_SIZE);
+	query->emitted_begin = GL_FALSE;
+}
+
+void r300InitQueryObjFunctions(struct dd_function_table *functions)
+{
+	functions->NewQueryObject = r300NewQueryObject;
+	functions->DeleteQuery = r300DeleteQuery;
+	functions->BeginQuery = r300BeginQuery;
+	functions->EndQuery = r300EndQuery;
+	functions->CheckQuery = r300CheckQuery;
+	functions->WaitQuery = r300WaitQuery;
+}
diff --git a/src/mesa/drivers/dri/r300/r300_queryobj.h b/src/mesa/drivers/dri/r300/r300_queryobj.h
new file mode 100644
index 0000000..f301f0b
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_queryobj.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2008 Maciej Cencora <m.cencora at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Maciej Cencora <m.cencora at gmail.com>
+ *
+ */
+
+#include "main/imports.h"
+#include "r300_context.h"
+
+extern void r300EmitQueryBegin(GLcontext *ctx);
+extern void r300EmitQueryEnd(GLcontext *ctx);
+
+extern void r300InitQueryObjFunctions(struct dd_function_table *functions);
diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h
index dd32e6c..39b4b61 100644
--- a/src/mesa/drivers/dri/r300/r300_reg.h
+++ b/src/mesa/drivers/dri/r300/r300_reg.h
@@ -1128,6 +1128,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* SU Depth Offset value */
 #define R300_SU_DEPTH_OFFSET                0x42c4
 
+#define R300_SU_REG_DEST		    0x42c8
+#	define R300_RASTER_PIPE_SELECT_0	(1 << 0)
+#	define R300_RASTER_PIPE_SELECT_1	(1 << 1)
+#	define R300_RASTER_PIPE_SELECT_2	(1 << 2)
+#	define R300_RASTER_PIPE_SELECT_3	(1 << 3)
+#	define R300_RASTER_PIPE_SELECT_ALL	0xf
+
 
 /* BEGIN: Rasterization / Interpolators - many guesses */
 
@@ -2014,6 +2021,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define R500_FG_ALPHA_VALUE                0x4be0
 #	define R500_FG_ALPHA_VALUE_MASK 0x0000ffff
 
+#define RV530_FG_ZBREG_DEST                 0x4be8
+#	define RV530_FG_ZBREG_DEST_PIPE_SELECT_0             (1 << 0)
+#	define RV530_FG_ZBREG_DEST_PIPE_SELECT_1             (1 << 1)
+#	define RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL           (3 << 0)
+
 /* gap */
 
 /* Fragment program parameters in 7.16 floating point */
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index 4bf09c2..369c3ed 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -76,6 +76,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_tex.h"
 #include "r300_emit.h"
 #include "r300_fragprog_common.h"
+#include "r300_queryobj.h"
 #include "r300_swtcl.h"
 
 /**




More information about the mesa-commit mailing list