summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQicheng Christopher Li <chrisl@vmware.com>2010-05-06 11:45:42 -0600
committerBrian Paul <brianp@vmware.com>2010-05-06 11:45:45 -0600
commit86afe8250edaa2e6129c937a62a695f616c48d70 (patch)
treec3800f2b0ff2daf025865d4ab3003b9741041b7e
parentf587615e13cf55504c6060d4621506d65b608774 (diff)
llvmpipe: implement occlusion query
OpenGL occlusion queries work now. The Mesa demos, glean test and piglit tests all pass. A few enhancements are possible in the future. -Brian Signed-off-by: Brian Paul <brianp@vmware.com>
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.c43
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_depth.h3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.c85
-rw-r--r--src/gallium/drivers/llvmpipe/lp_query.h24
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c64
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h8
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c41
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h10
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c3
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c28
14 files changed, 277 insertions, 50 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index 1b59a13c94..e05bbe5011 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -72,6 +72,7 @@
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_flow.h"
+#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_swizzle.h"
@@ -445,6 +446,42 @@ get_s_shift_and_mask(const struct util_format_description *format_desc,
}
+/**
+ * Perform the occlusion test and increase the counter.
+ * Test the depth mask. Add the number of channel which has none zero mask
+ * into the occlusion counter. e.g. maskvalue is {-1, -1, -1, -1}.
+ * The counter will add 4.
+ *
+ * \param type holds element type of the mask vector.
+ * \param maskvalue is the depth test mask.
+ * \param counter is a pointer of the uint32 counter.
+ */
+static void
+lp_build_occlusion_count(LLVMBuilderRef builder,
+ struct lp_type type,
+ LLVMValueRef maskvalue,
+ LLVMValueRef counter)
+{
+ LLVMValueRef countmask = lp_build_const_int_vec(type, 1);
+ LLVMValueRef countv = LLVMBuildAnd(builder, maskvalue, countmask, "countv");
+ LLVMTypeRef i8v16 = LLVMVectorType(LLVMInt8Type(), 16);
+ LLVMValueRef counti = LLVMBuildBitCast(builder, countv, i8v16, "counti");
+ LLVMValueRef maskarray[4] = {
+ LLVMConstInt(LLVMInt32Type(), 0, 0),
+ LLVMConstInt(LLVMInt32Type(), 4, 0),
+ LLVMConstInt(LLVMInt32Type(), 8, 0),
+ LLVMConstInt(LLVMInt32Type(), 12, 0),
+ };
+ LLVMValueRef shufflemask = LLVMConstVector(maskarray, 4);
+ LLVMValueRef shufflev = LLVMBuildShuffleVector(builder, counti, LLVMGetUndef(i8v16), shufflemask, "shufflev");
+ LLVMValueRef shuffle = LLVMBuildBitCast(builder, shufflev, LLVMInt32Type(), "shuffle");
+ LLVMValueRef count = lp_build_intrinsic_unary(builder, "llvm.ctpop.i32", LLVMInt32Type(), shuffle);
+ LLVMValueRef orig = LLVMBuildLoad(builder, counter, "orig");
+ LLVMValueRef incr = LLVMBuildAdd(builder, orig, count, "incr");
+ LLVMBuildStore(builder, incr, counter);
+}
+
+
/**
* Generate code for performing depth and/or stencil tests.
@@ -470,7 +507,8 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder,
LLVMValueRef stencil_refs[2],
LLVMValueRef z_src,
LLVMValueRef zs_dst_ptr,
- LLVMValueRef face)
+ LLVMValueRef face,
+ LLVMValueRef counter)
{
struct lp_build_context bld;
struct lp_build_context sbld;
@@ -682,4 +720,7 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder,
if (depth->enabled && stencil[0].enabled)
lp_build_mask_update(mask, z_pass);
+
+ if (counter)
+ lp_build_occlusion_count(builder, type, mask->value, counter);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
index 27dd46b625..e257a5bd7d 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.h
@@ -60,7 +60,8 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder,
LLVMValueRef stencil_refs[2],
LLVMValueRef zs_src,
LLVMValueRef zs_dst_ptr,
- LLVMValueRef facing);
+ LLVMValueRef facing,
+ LLVMValueRef counter);
#endif /* !LP_BLD_DEPTH_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 4e597b2479..de7fe7a179 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -82,11 +82,7 @@ struct llvmpipe_context {
unsigned dirty; /**< Mask of LP_NEW_x flags */
- /* Counter for occlusion queries. Note this supports overlapping
- * queries.
- */
- uint64_t occlusion_count;
- unsigned active_query_count;
+ int active_query_count;
/** Mapped vertex buffers */
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 5d0268c68c..fc43d0bf5a 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -146,7 +146,8 @@ enum {
lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_BLEND_COLOR, "blend_color")
#define lp_jit_context_textures(_builder, _ptr) \
- lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES, "textures")
+ lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CTX_TEXTURES, "textures")
+
/** Indexes into jit_function[] array */
@@ -169,7 +170,8 @@ typedef void
const int32_t c3,
const int32_t *step1,
const int32_t *step2,
- const int32_t *step3);
+ const int32_t *step3,
+ uint32_t *counter);
void
diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c
index 5554285425..a1836bbde9 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.c
+++ b/src/gallium/drivers/llvmpipe/lp_query.c
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,15 +19,15 @@
* 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 NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS 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.
*
**************************************************************************/
-/* Author:
- * Keith Whitwell <keith@tungstengraphics.com>
+/* Authors:
+ * Keith Whitwell, Qicheng Christopher Li, Brian Paul
*/
#include "draw/draw_context.h"
@@ -34,12 +35,10 @@
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_query.h"
+#include "lp_rast.h"
+#include "lp_rast_priv.h"
#include "lp_state.h"
-
-struct llvmpipe_query {
- uint64_t start;
- uint64_t end;
-};
+#include "lp_setup_context.h"
static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
@@ -51,15 +50,46 @@ static struct pipe_query *
llvmpipe_create_query(struct pipe_context *pipe,
unsigned type)
{
+ struct llvmpipe_query *pq;
+
assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
- return (struct pipe_query *)CALLOC_STRUCT( llvmpipe_query );
+
+ pq = CALLOC_STRUCT( llvmpipe_query );
+ if (pq) {
+ pipe_mutex_init(pq->mutex);
+ }
+
+ return (struct pipe_query *) pq;
}
static void
llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
- FREE(q);
+ struct llvmpipe_query *pq = llvmpipe_query(q);
+ pipe_mutex_destroy(pq->mutex);
+ FREE(pq);
+}
+
+
+static boolean
+llvmpipe_get_query_result(struct pipe_context *pipe,
+ struct pipe_query *q,
+ boolean wait,
+ uint64_t *result )
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
+ struct llvmpipe_query *pq = llvmpipe_query(q);
+
+ if (!pq->done) {
+ lp_setup_flush(llvmpipe->setup, TRUE);
+ }
+
+ if (pq->done) {
+ *result = pq->result;
+ }
+
+ return pq->done;
}
@@ -67,9 +97,20 @@ static void
llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
- struct llvmpipe_query *sq = llvmpipe_query(q);
-
- sq->start = llvmpipe->occlusion_count;
+ struct llvmpipe_query *pq = llvmpipe_query(q);
+
+ /* Check if the query is already in the scene. If so, we need to
+ * flush the scene now. Real apps shouldn't re-use a query in a
+ * frame of rendering.
+ */
+ if (pq->binned) {
+ struct pipe_fence_handle *fence;
+ pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &fence);
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ }
+
+ lp_setup_begin_query(llvmpipe->setup, pq);
+
llvmpipe->active_query_count++;
llvmpipe->dirty |= LP_NEW_QUERY;
}
@@ -79,26 +120,16 @@ static void
llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
- struct llvmpipe_query *sq = llvmpipe_query(q);
+ struct llvmpipe_query *pq = llvmpipe_query(q);
+
+ lp_setup_end_query(llvmpipe->setup, pq);
+ assert(llvmpipe->active_query_count);
llvmpipe->active_query_count--;
- sq->end = llvmpipe->occlusion_count;
llvmpipe->dirty |= LP_NEW_QUERY;
}
-static boolean
-llvmpipe_get_query_result(struct pipe_context *pipe,
- struct pipe_query *q,
- boolean wait,
- uint64_t *result )
-{
- struct llvmpipe_query *sq = llvmpipe_query(q);
- *result = sq->end - sq->start;
- return TRUE;
-}
-
-
void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
{
llvmpipe->pipe.create_query = llvmpipe_create_query;
diff --git a/src/gallium/drivers/llvmpipe/lp_query.h b/src/gallium/drivers/llvmpipe/lp_query.h
index fa9fcd8713..721c41cb5c 100644
--- a/src/gallium/drivers/llvmpipe/lp_query.h
+++ b/src/gallium/drivers/llvmpipe/lp_query.h
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,14 +26,33 @@
*
**************************************************************************/
-/* Author:
- * Keith Whitwell
+/* Authors:
+ * Keith Whitwell, Qicheng Christopher Li, Brian Paul
*/
#ifndef LP_QUERY_H
#define LP_QUERY_H
+#include <limits.h>
+#include "os/os_thread.h"
+#include "lp_limits.h"
+
+
struct llvmpipe_context;
+
+
+struct llvmpipe_query {
+ uint64_t count[LP_MAX_THREADS]; /**< a counter for each thread */
+ uint64_t result; /**< total of all counters */
+
+ pipe_mutex mutex;
+ unsigned num_tiles, tile_count;
+
+ boolean done;
+ boolean binned; /**< has this query been binned in the scene? */
+};
+
+
extern void llvmpipe_init_query_funcs(struct llvmpipe_context * );
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index a00a592f2f..6bb868bf1a 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -34,6 +34,7 @@
#include "lp_debug.h"
#include "lp_fence.h"
#include "lp_perf.h"
+#include "lp_query.h"
#include "lp_rast.h"
#include "lp_rast_priv.h"
#include "lp_tile_soa.h"
@@ -442,7 +443,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
color,
depth,
INT_MIN, INT_MIN, INT_MIN,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, &task->vis_counter);
}
}
}
@@ -502,7 +503,8 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task,
c1, c2, c3,
inputs->step[0],
inputs->step[1],
- inputs->step[2]);
+ inputs->step[2],
+ &task->vis_counter);
}
@@ -602,6 +604,60 @@ lp_rast_fence(struct lp_rasterizer_task *task,
}
+/**
+ * Begin a new occlusion query.
+ * This is a bin command put in all bins.
+ * Called per thread.
+ */
+void
+lp_rast_begin_query(struct lp_rasterizer_task *task,
+ const union lp_rast_cmd_arg arg)
+{
+ /* Reset the the per-task counter */
+ task->vis_counter = 0;
+}
+
+
+/**
+ * End the current occlusion query.
+ * This is a bin command put in all bins.
+ * Called per thread.
+ */
+void
+lp_rast_end_query(struct lp_rasterizer_task *task,
+ const union lp_rast_cmd_arg arg)
+{
+ struct llvmpipe_query *pq = arg.query_obj;
+
+ pipe_mutex_lock(pq->mutex);
+ {
+ /* Accumulate the visible fragment counter from this tile in
+ * the query object.
+ */
+ pq->count[task->thread_index] += task->vis_counter;
+
+ /* check if this is the last tile in the scene */
+ pq->tile_count++;
+ if (pq->tile_count == pq->num_tiles) {
+ uint i;
+
+ /* sum the per-thread counters for the query */
+ pq->result = 0;
+ for (i = 0; i < LP_MAX_THREADS; i++) {
+ pq->result += pq->count[i];
+ }
+
+ /* reset counters (in case this query is re-used in the scene) */
+ memset(pq->count, 0, sizeof(pq->count));
+
+ pq->tile_count = 0;
+ pq->binned = FALSE;
+ pq->done = TRUE;
+ }
+ }
+ pipe_mutex_unlock(pq->mutex);
+}
+
/**
@@ -650,6 +706,8 @@ static struct {
RAST(set_state),
RAST(store_color),
RAST(fence),
+ RAST(begin_query),
+ RAST(end_query),
};
static void
@@ -956,3 +1014,5 @@ lp_rast_get_num_threads( struct lp_rasterizer *rast )
{
return rast->num_threads;
}
+
+
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index e2f6f92677..881f475189 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -157,6 +157,7 @@ union lp_rast_cmd_arg {
uint8_t clear_color[4];
unsigned clear_zstencil;
struct lp_fence *fence;
+ struct llvmpipe_query *query_obj;
};
@@ -233,4 +234,11 @@ void lp_rast_store_color( struct lp_rasterizer_task *,
const union lp_rast_cmd_arg );
+void lp_rast_begin_query(struct lp_rasterizer_task *,
+ const union lp_rast_cmd_arg );
+
+void lp_rast_end_query(struct lp_rasterizer_task *,
+ const union lp_rast_cmd_arg );
+
+
#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 5884d12721..0ceba209e0 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -59,6 +59,9 @@ struct lp_rasterizer_task
/** "my" index */
unsigned thread_index;
+ /* occlude counter for visiable pixels */
+ uint32_t vis_counter;
+
pipe_semaphore work_ready;
pipe_semaphore work_done;
};
@@ -221,7 +224,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
color,
depth,
INT_MIN, INT_MIN, INT_MIN,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, &task->vis_counter );
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 0bf75de901..de9d4366a8 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -32,6 +32,8 @@
* lp_setup_flush().
*/
+#include <limits.h>
+
#include "pipe/p_defines.h"
#include "util/u_framebuffer.h"
#include "util/u_inlines.h"
@@ -43,11 +45,13 @@
#include "lp_texture.h"
#include "lp_debug.h"
#include "lp_fence.h"
+#include "lp_query.h"
#include "lp_rast.h"
#include "lp_setup_context.h"
#include "lp_screen.h"
#include "lp_state.h"
#include "state_tracker/sw_winsys.h"
+#include "lp_rast_priv.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
@@ -856,3 +860,40 @@ fail:
return NULL;
}
+
+/**
+ * Put a BeginQuery command into all bins.
+ */
+void
+lp_setup_begin_query(struct lp_setup_context *setup,
+ struct llvmpipe_query *pq)
+{
+ struct lp_scene * scene = lp_setup_get_current_scene(setup);
+ union lp_rast_cmd_arg cmd_arg;
+
+ /* init the query to its beginning state */
+ pq->done = FALSE;
+ pq->tile_count = 0;
+ pq->num_tiles = scene->tiles_x * scene->tiles_y;
+ assert(pq->num_tiles > 0);
+
+ memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */
+
+ cmd_arg.query_obj = pq;
+ lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg);
+ pq->binned = TRUE;
+}
+
+
+/**
+ * Put an EndQuery command into all bins.
+ */
+void
+lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq)
+{
+ struct lp_scene * scene = lp_setup_get_current_scene(setup);
+ union lp_rast_cmd_arg cmd_arg;
+
+ cmd_arg.query_obj = pq;
+ lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg);
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index e10d37d8d0..10db03b9c6 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -53,12 +53,15 @@ struct lp_shader_input {
};
struct pipe_resource;
+struct pipe_query;
struct pipe_surface;
struct pipe_blend_color;
struct pipe_screen;
struct pipe_framebuffer_state;
struct lp_fragment_shader;
struct lp_jit_context;
+struct llvmpipe_query;
+
struct lp_setup_context *
lp_setup_create( struct pipe_context *pipe,
@@ -140,5 +143,12 @@ void
lp_setup_set_vertex_info( struct lp_setup_context *setup,
struct vertex_info *info );
+void
+lp_setup_begin_query(struct lp_setup_context *setup,
+ struct llvmpipe_query *pq);
+
+void
+lp_setup_end_query(struct lp_setup_context *setup,
+ struct llvmpipe_query *pq);
#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 18143807c9..848cb49f91 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -73,6 +73,7 @@ struct lp_fragment_shader_variant_key
unsigned nr_cbufs:8;
unsigned flatshade:1;
unsigned scissor:1;
+ unsigned occlusion_count:1;
struct {
ubyte colormask;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 113d77ab78..2edfcb28ce 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -163,7 +163,8 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
LP_NEW_DEPTH_STENCIL_ALPHA |
LP_NEW_RASTERIZER |
LP_NEW_SAMPLER |
- LP_NEW_SAMPLER_VIEW))
+ LP_NEW_SAMPLER_VIEW |
+ LP_NEW_QUERY))
llvmpipe_update_fs( llvmpipe );
if (llvmpipe->dirty & LP_NEW_BLEND_COLOR)
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 5f861d6ca4..6c81114482 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -148,7 +148,8 @@ generate_depth_stencil(LLVMBuilderRef builder,
LLVMValueRef stencil_refs[2],
LLVMValueRef src,
LLVMValueRef dst_ptr,
- LLVMValueRef facing)
+ LLVMValueRef facing,
+ LLVMValueRef counter)
{
const struct util_format_description *format_desc;
struct lp_type dst_type;
@@ -195,7 +196,8 @@ generate_depth_stencil(LLVMBuilderRef builder,
stencil_refs,
src,
dst_ptr,
- facing);
+ facing,
+ counter);
}
@@ -400,7 +402,8 @@ generate_fs(struct llvmpipe_context *lp,
LLVMValueRef c2,
LLVMValueRef step0_ptr,
LLVMValueRef step1_ptr,
- LLVMValueRef step2_ptr)
+ LLVMValueRef step2_ptr,
+ LLVMValueRef counter)
{
const struct tgsi_token *tokens = shader->base.tokens;
LLVMTypeRef vec_type;
@@ -466,7 +469,7 @@ generate_fs(struct llvmpipe_context *lp,
if (early_depth_stencil_test)
generate_depth_stencil(builder, key,
type, &mask,
- stencil_refs, z, depth_ptr, facing);
+ stencil_refs, z, depth_ptr, facing, counter);
lp_build_tgsi_soa(builder, tokens, type, &mask,
consts_ptr, interp->pos, interp->inputs,
@@ -513,7 +516,7 @@ generate_fs(struct llvmpipe_context *lp,
if (!early_depth_stencil_test)
generate_depth_stencil(builder, key,
type, &mask,
- stencil_refs, z, depth_ptr, facing);
+ stencil_refs, z, depth_ptr, facing, counter);
lp_build_mask_end(&mask);
@@ -620,7 +623,7 @@ generate_fragment(struct llvmpipe_context *lp,
LLVMTypeRef fs_elem_type;
LLVMTypeRef fs_int_vec_type;
LLVMTypeRef blend_vec_type;
- LLVMTypeRef arg_types[15];
+ LLVMTypeRef arg_types[16];
LLVMTypeRef func_type;
LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type();
LLVMValueRef context_ptr;
@@ -631,7 +634,7 @@ generate_fragment(struct llvmpipe_context *lp,
LLVMValueRef dady_ptr;
LLVMValueRef color_ptr_ptr;
LLVMValueRef depth_ptr;
- LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr;
+ LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr, counter = NULL;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
LLVMValueRef x0;
@@ -696,6 +699,7 @@ generate_fragment(struct llvmpipe_context *lp,
arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step0 */
arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step1 */
arg_types[14] = LLVMPointerType(int32_vec4_type, 0);/* step2 */
+ arg_types[15] = LLVMPointerType(LLVMInt32Type(), 0);/* counter */
func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
@@ -743,6 +747,11 @@ generate_fragment(struct llvmpipe_context *lp,
lp_build_name(step1_ptr, "step1");
lp_build_name(step2_ptr, "step2");
+ if (key->occlusion_count) {
+ counter = LLVMGetParam(function, 15);
+ lp_build_name(counter, "counter");
+ }
+
/*
* Function body
*/
@@ -787,7 +796,7 @@ generate_fragment(struct llvmpipe_context *lp,
facing,
do_tri_test,
c0, c1, c2,
- step0_ptr, step1_ptr, step2_ptr);
+ step0_ptr, step1_ptr, step2_ptr, counter);
for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++)
for(chan = 0; chan < NUM_CHANNELS; ++chan)
@@ -1123,6 +1132,9 @@ make_variant_key(struct llvmpipe_context *lp,
key->flatshade = lp->rasterizer->flatshade;
key->scissor = lp->rasterizer->scissor;
+ if (lp->active_query_count) {
+ key->occlusion_count = TRUE;
+ }
if (lp->framebuffer.nr_cbufs) {
memcpy(&key->blend, lp->blend, sizeof key->blend);