X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_setup.c;h=7d40d8cf6617e3988ed2ddbafbc3e9aa0bee3d79;hb=1d35f77228ad540a551a8e09e062b764a6e31f5e;hp=a173e71aba7a88237bcded433b8be5a035decc8d;hpb=68a4f6324712d7eae327ee438a41c432ec72f11d;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index a173e71aba7..7d40d8cf661 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -39,6 +39,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "draw/draw_pipe.h" #include "lp_context.h" #include "lp_memory.h" #include "lp_scene.h" @@ -64,6 +65,9 @@ static boolean try_update_scene_state( struct lp_setup_context *setup ); static void lp_setup_get_empty_scene(struct lp_setup_context *setup) { + struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); + boolean discard = lp->rasterizer ? lp->rasterizer->rasterizer_discard : FALSE; + assert(setup->scene == NULL); setup->scene_idx++; @@ -79,7 +83,7 @@ lp_setup_get_empty_scene(struct lp_setup_context *setup) lp_fence_wait(setup->scene->fence); } - lp_scene_begin_binning(setup->scene, &setup->fb); + lp_scene_begin_binning(setup->scene, &setup->fb, discard); } @@ -114,13 +118,17 @@ first_point( struct lp_setup_context *setup, setup->point( setup, v0 ); } -static void lp_setup_reset( struct lp_setup_context *setup ) +void lp_setup_reset( struct lp_setup_context *setup ) { + unsigned i; + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); /* Reset derived state */ - setup->constants.stored_size = 0; - setup->constants.stored_data = NULL; + for (i = 0; i < Elements(setup->constants); ++i) { + setup->constants[i].stored_size = 0; + setup->constants[i].stored_data = NULL; + } setup->fs.stored = NULL; setup->dirty = ~0; @@ -231,12 +239,14 @@ begin_binning( struct lp_setup_context *setup ) } } - if (setup->active_query) { - ok = lp_scene_bin_everywhere( scene, - LP_RAST_OP_BEGIN_QUERY, - lp_rast_arg_query(setup->active_query) ); - if (!ok) - return FALSE; + for (i = 0; i < PIPE_QUERY_TYPES; ++i) { + if (setup->active_query[i]) { + ok = lp_scene_bin_everywhere( scene, + LP_RAST_OP_BEGIN_QUERY, + lp_rast_arg_query(setup->active_query[i]) ); + if (!ok) + return FALSE; + } } setup->clear.flags = 0; @@ -333,12 +343,8 @@ fail: } -/** - * \param flags bitmask of PIPE_FLUSH_x flags - */ void lp_setup_flush( struct lp_setup_context *setup, - unsigned flags, struct pipe_fence_handle **fence, const char *reason) { @@ -393,7 +399,7 @@ lp_setup_try_clear( struct lp_setup_context *setup, if (flags & PIPE_CLEAR_COLOR) { for (i = 0; i < 4; i++) - color_arg.clear_color[i] = float_to_ubyte(color[i]); + color_arg.clear_color[i] = color[i]; } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { @@ -469,7 +475,7 @@ lp_setup_clear( struct lp_setup_context *setup, unsigned flags ) { if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) { - lp_setup_flush(setup, 0, NULL, __FUNCTION__); + lp_setup_flush(setup, NULL, __FUNCTION__); if (!lp_setup_try_clear( setup, color, depth, stencil, flags )) assert(0); @@ -547,13 +553,21 @@ lp_setup_set_fs_variant( struct lp_setup_context *setup, void lp_setup_set_fs_constants(struct lp_setup_context *setup, - struct pipe_resource *buffer) + unsigned num, + struct pipe_resource **buffers) { - LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); + unsigned i; - pipe_resource_reference(&setup->constants.current, buffer); + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); - setup->dirty |= LP_SETUP_NEW_CONSTANTS; + assert(num <= Elements(setup->constants)); + + for (i = 0; i < num; ++i) { + if (setup->constants[i].current != buffers[i]) { + pipe_resource_reference(&setup->constants[i].current, buffers[i]); + setup->dirty |= LP_SETUP_NEW_CONSTANTS; + } + } } @@ -621,6 +635,15 @@ lp_setup_set_flatshade_first( struct lp_setup_context *setup, setup->flatshade_first = flatshade_first; } +void +lp_setup_set_rasterizer_discard( struct lp_setup_context *setup, + boolean rasterizer_discard ) +{ + if (setup->rasterizer_discard != rasterizer_discard) { + setup->rasterizer_discard = rasterizer_discard; + set_scene_state( setup, SETUP_FLUSHED, __FUNCTION__ ); + } +} void lp_setup_set_vertex_info( struct lp_setup_context *setup, @@ -656,32 +679,62 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex = &setup->fs.current.jit_context.textures[i]; jit_tex->width = tex->width0; jit_tex->height = tex->height0; - jit_tex->depth = tex->depth0; + jit_tex->first_level = view->u.tex.first_level; jit_tex->last_level = tex->last_level; + if (tex->target == PIPE_TEXTURE_3D) { + jit_tex->depth = tex->depth0; + } + else { + jit_tex->depth = tex->array_size; + } + /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&setup->fs.current_tex[i], tex); if (!lp_tex->dt) { - /* regular texture - setup array of mipmap level pointers */ + /* regular texture - setup array of mipmap level offsets */ + void *mip_ptr; int j; - for (j = 0; j <= tex->last_level; j++) { - jit_tex->data[j] = - llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, - LP_TEX_LAYOUT_LINEAR); + /* + * XXX this is messed up we don't want to accidentally trigger + * tiled->linear conversion for levels we don't need. + * So ask for first_level data (which will allocate all levels) + * then if successful get base ptr. + */ + mip_ptr = llvmpipe_get_texture_image_all(lp_tex, view->u.tex.first_level, + LP_TEX_USAGE_READ, + LP_TEX_LAYOUT_LINEAR); + if ((LP_PERF & PERF_TEX_MEM) || !mip_ptr) { + /* out of memory - use dummy tile memory */ + jit_tex->base = lp_dummy_tile; + jit_tex->width = TILE_SIZE/8; + jit_tex->height = TILE_SIZE/8; + jit_tex->depth = 1; + jit_tex->first_level = 0; + jit_tex->last_level = 0; + } + else { + jit_tex->base = lp_tex->linear_img.data; + } + for (j = view->u.tex.first_level; j <= tex->last_level; j++) { + mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j, + LP_TEX_USAGE_READ, + LP_TEX_LAYOUT_LINEAR); + jit_tex->mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)jit_tex->base; + /* + * could get mip offset directly but need call above to + * invoke tiled->linear conversion. + */ + assert(lp_tex->linear_mip_offsets[j] == jit_tex->mip_offsets[j]); jit_tex->row_stride[j] = lp_tex->row_stride[j]; jit_tex->img_stride[j] = lp_tex->img_stride[j]; - if ((LP_PERF & PERF_TEX_MEM) || - !jit_tex->data[j]) { + if (jit_tex->base == lp_dummy_tile) { /* out of memory - use dummy tile memory */ - jit_tex->data[j] = lp_dummy_tile; - jit_tex->width = TILE_SIZE/8; - jit_tex->height = TILE_SIZE/8; - jit_tex->depth = 1; - jit_tex->last_level = 0; + jit_tex->mip_offsets[j] = 0; jit_tex->row_stride[j] = 0; jit_tex->img_stride[j] = 0; } @@ -694,11 +747,12 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); struct sw_winsys *winsys = screen->winsys; - jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, - PIPE_TRANSFER_READ); + jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt, + PIPE_TRANSFER_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; - assert(jit_tex->data[0]); + jit_tex->mip_offsets[0] = 0; + assert(jit_tex->base); } } } @@ -713,7 +767,7 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, void lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, unsigned num, - const struct pipe_sampler_state **samplers) + struct pipe_sampler_state **samplers) { unsigned i; @@ -731,7 +785,7 @@ lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, jit_tex->min_lod = sampler->min_lod; jit_tex->max_lod = sampler->max_lod; jit_tex->lod_bias = sampler->lod_bias; - COPY_4V(jit_tex->border_color, sampler->border_color); + COPY_4V(jit_tex->border_color, sampler->border_color.f); } } @@ -753,20 +807,20 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup, /* check the render targets */ for (i = 0; i < setup->fb.nr_cbufs; i++) { if (setup->fb.cbufs[i]->texture == texture) - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; } if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; } /* check textures referenced by the scene */ for (i = 0; i < Elements(setup->scenes); i++) { if (lp_scene_is_resource_referenced(setup->scenes[i], texture)) { - return PIPE_REFERENCED_FOR_READ; + return LP_REFERENCED_FOR_READ; } } - return PIPE_UNREFERENCED; + return LP_UNREFERENCED; } @@ -778,19 +832,32 @@ try_update_scene_state( struct lp_setup_context *setup ) { boolean new_scene = (setup->fs.stored == NULL); struct lp_scene *scene = setup->scene; + unsigned i; assert(scene); if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; + float* fstored; unsigned i, j; + unsigned size; + + /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */ + size = 4 * 16 * sizeof(uint8_t); + size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float); + stored = lp_scene_alloc_aligned(scene, size, LP_MAX_VECTOR_LENGTH); - stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); if (!stored) { assert(!new_scene); return FALSE; } + /* Store floating point colour */ + fstored = (float*)(stored + 4*16); + for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) { + fstored[i] = setup->blend_color.current.color[i % 4]; + } + /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); @@ -799,46 +866,49 @@ try_update_scene_state( struct lp_setup_context *setup ) } setup->blend_color.stored = stored; - setup->fs.current.jit_context.blend_color = setup->blend_color.stored; + setup->fs.current.jit_context.u8_blend_color = stored; + setup->fs.current.jit_context.f_blend_color = fstored; setup->dirty |= LP_SETUP_NEW_FS; } - if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { - struct pipe_resource *buffer = setup->constants.current; + if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { + for (i = 0; i < Elements(setup->constants); ++i) { + struct pipe_resource *buffer = setup->constants[i].current; - if(buffer) { - unsigned current_size = buffer->width0; - const void *current_data = llvmpipe_resource_data(buffer); + if (buffer) { + unsigned current_size = buffer->width0; + const void *current_data = llvmpipe_resource_data(buffer); - /* TODO: copy only the actually used constants? */ + /* TODO: copy only the actually used constants? */ - if(setup->constants.stored_size != current_size || - !setup->constants.stored_data || - memcmp(setup->constants.stored_data, - current_data, - current_size) != 0) { - void *stored; + if (setup->constants[i].stored_size != current_size || + !setup->constants[i].stored_data || + memcmp(setup->constants[i].stored_data, + current_data, + current_size) != 0) { + void *stored; - stored = lp_scene_alloc(scene, current_size); - if (!stored) { - assert(!new_scene); - return FALSE; - } + stored = lp_scene_alloc(scene, current_size); + if (!stored) { + assert(!new_scene); + return FALSE; + } - memcpy(stored, - current_data, - current_size); - setup->constants.stored_size = current_size; - setup->constants.stored_data = stored; + memcpy(stored, + current_data, + current_size); + setup->constants[i].stored_size = current_size; + setup->constants[i].stored_data = stored; + } + } + else { + setup->constants[i].stored_size = 0; + setup->constants[i].stored_data = NULL; } - } - else { - setup->constants.stored_size = 0; - setup->constants.stored_data = NULL; - } - setup->fs.current.jit_context.constants = setup->constants.stored_data; - setup->dirty |= LP_SETUP_NEW_FS; + setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data; + setup->dirty |= LP_SETUP_NEW_FS; + } } @@ -849,7 +919,6 @@ try_update_scene_state( struct lp_setup_context *setup ) sizeof setup->fs.current) != 0) { struct lp_rast_state *stored; - uint i; /* The fs state that's been stored in the scene is different from * the new, current state. So allocate a new lp_rast_state object @@ -912,6 +981,12 @@ lp_setup_update_state( struct lp_setup_context *setup, llvmpipe_update_derived(lp); } + if (lp->setup->dirty) { + llvmpipe_update_setup(lp); + } + + assert(setup->setup.variant); + /* Will probably need to move this somewhere else, just need * to know about vertex shader point size attribute. */ @@ -978,7 +1053,9 @@ lp_setup_destroy( struct lp_setup_context *setup ) pipe_resource_reference(&setup->fs.current_tex[i], NULL); } - pipe_resource_reference(&setup->constants.current, NULL); + for (i = 0; i < Elements(setup->constants); i++) { + pipe_resource_reference(&setup->constants[i].current, NULL); + } /* free the scenes in the 'empty' queue */ for (i = 0; i < Elements(setup->scenes); i++) { @@ -990,6 +1067,8 @@ lp_setup_destroy( struct lp_setup_context *setup ) lp_scene_destroy(scene); } + lp_fence_reference(&setup->last_fence, NULL); + FREE( setup ); } @@ -1004,11 +1083,13 @@ lp_setup_create( struct pipe_context *pipe, struct draw_context *draw ) { struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); - struct lp_setup_context *setup = CALLOC_STRUCT(lp_setup_context); + struct lp_setup_context *setup; unsigned i; - if (!setup) - return NULL; + setup = CALLOC_STRUCT(lp_setup_context); + if (!setup) { + goto no_setup; + } lp_setup_init_vbuf(setup); @@ -1019,8 +1100,9 @@ lp_setup_create( struct pipe_context *pipe, setup->num_threads = screen->num_threads; setup->vbuf = draw_vbuf_stage(draw, &setup->base); - if (!setup->vbuf) - goto fail; + if (!setup->vbuf) { + goto no_vbuf; + } draw_set_rasterize_stage(draw, setup->vbuf); draw_set_render(draw, &setup->base); @@ -1028,6 +1110,9 @@ lp_setup_create( struct pipe_context *pipe, /* create some empty scenes */ for (i = 0; i < MAX_SCENES; i++) { setup->scenes[i] = lp_scene_create( pipe ); + if (!setup->scenes[i]) { + goto no_scenes; + } } setup->triangle = first_triangle; @@ -1038,11 +1123,17 @@ lp_setup_create( struct pipe_context *pipe, return setup; -fail: - if (setup->vbuf) - ; +no_scenes: + for (i = 0; i < MAX_SCENES; i++) { + if (setup->scenes[i]) { + lp_scene_destroy(setup->scenes[i]); + } + } + setup->vbuf->destroy(setup->vbuf); +no_vbuf: FREE(setup); +no_setup: return NULL; } @@ -1055,8 +1146,17 @@ lp_setup_begin_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { /* init the query to its beginning state */ - assert(setup->active_query == NULL); + assert(setup->active_query[pq->type] == NULL); + + set_scene_state(setup, SETUP_ACTIVE, "begin_query"); + setup->active_query[pq->type] = pq; + + /* XXX: It is possible that a query is created before the scene + * has been created. This means that setup->scene == NULL resulting + * in the query not being binned and thus is ignored. + */ + if (setup->scene) { if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_BEGIN_QUERY, @@ -1072,8 +1172,6 @@ lp_setup_begin_query(struct lp_setup_context *setup, } } } - - setup->active_query = pq; } @@ -1083,10 +1181,12 @@ lp_setup_begin_query(struct lp_setup_context *setup, void lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) { - union lp_rast_cmd_arg dummy = { 0 }; + set_scene_state(setup, SETUP_ACTIVE, "end_query"); - assert(setup->active_query == pq); - setup->active_query = NULL; + if (pq->type != PIPE_QUERY_TIMESTAMP) { + assert(setup->active_query[pq->type] == pq); + setup->active_query[pq->type] = NULL; + } /* Setup will automatically re-issue any query which carried over a * scene boundary, and the rasterizer automatically "ends" queries @@ -1101,8 +1201,8 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) if (!lp_scene_bin_everywhere(setup->scene, LP_RAST_OP_END_QUERY, - dummy)) { - lp_setup_flush(setup, 0, NULL, __FUNCTION__); + lp_rast_arg_query(pq))) { + lp_setup_flush(setup, NULL, __FUNCTION__); } } else {