From 86afe8250edaa2e6129c937a62a695f616c48d70 Mon Sep 17 00:00:00 2001 From: Qicheng Christopher Li Date: Thu, 6 May 2010 11:45:42 -0600 Subject: [PATCH] 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 --- src/gallium/drivers/llvmpipe/lp_bld_depth.c | 43 +++++++++- src/gallium/drivers/llvmpipe/lp_bld_depth.h | 3 +- src/gallium/drivers/llvmpipe/lp_context.h | 6 +- src/gallium/drivers/llvmpipe/lp_jit.h | 6 +- src/gallium/drivers/llvmpipe/lp_query.c | 85 +++++++++++++------ src/gallium/drivers/llvmpipe/lp_query.h | 24 +++++- src/gallium/drivers/llvmpipe/lp_rast.c | 64 +++++++++++++- src/gallium/drivers/llvmpipe/lp_rast.h | 8 ++ src/gallium/drivers/llvmpipe/lp_rast_priv.h | 5 +- src/gallium/drivers/llvmpipe/lp_setup.c | 41 +++++++++ src/gallium/drivers/llvmpipe/lp_setup.h | 10 +++ src/gallium/drivers/llvmpipe/lp_state.h | 1 + .../drivers/llvmpipe/lp_state_derived.c | 3 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 28 ++++-- 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 1b59a13c946..e05bbe5011a 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 27dd46b625d..e257a5bd7d0 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 4e597b24796..de7fe7a1796 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 5d0268c68c4..fc43d0bf5aa 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 5554285425d..a1836bbde91 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 +/* 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 fa9fcd87139..721c41cb5c9 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 +#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 a00a592f2fe..6bb868bf1a9 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 e2f6f926779..881f475189e 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 5884d12721e..0ceba209e06 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 0bf75de901a..de9d4366a8c 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 + #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 e10d37d8d04..10db03b9c69 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 18143807c91..848cb49f919 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 113d77ab788..2edfcb28ce6 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 5f861d6ca4d..6c81114482d 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); -- 2.30.2