X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_setup.c;h=550062ffcfce3664057f7654480f518459d8b086;hb=59fa26902d56e068de1769a62d8329e6777bba92;hp=4c8167a9e7dbcf8f382c43279d47342cafcd747a;hpb=a62edcce4eb4c800d972817a20ee874bf2a2c3ef;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 4c8167a9e7d..550062ffcfc 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -39,8 +39,9 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "util/u_viewport.h" #include "draw/draw_pipe.h" -#include "os/os_time.h" +#include "util/os_time.h" #include "lp_context.h" #include "lp_memory.h" #include "lp_scene.h" @@ -52,7 +53,7 @@ #include "lp_setup_context.h" #include "lp_screen.h" #include "lp_state.h" -#include "state_tracker/sw_winsys.h" +#include "frontend/sw_winsys.h" #include "draw/draw_context.h" #include "draw/draw_vbuf.h" @@ -69,7 +70,7 @@ lp_setup_get_empty_scene(struct lp_setup_context *setup) assert(setup->scene == NULL); setup->scene_idx++; - setup->scene_idx %= Elements(setup->scenes); + setup->scene_idx %= ARRAY_SIZE(setup->scenes); setup->scene = setup->scenes[setup->scene_idx]; @@ -81,7 +82,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, setup->rasterizer_discard); + lp_scene_begin_binning(setup->scene, &setup->fb); } @@ -123,7 +124,7 @@ void lp_setup_reset( struct lp_setup_context *setup ) LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); /* Reset derived state */ - for (i = 0; i < Elements(setup->constants); ++i) { + for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) { setup->constants[i].stored_size = 0; setup->constants[i].stored_data = NULL; } @@ -164,7 +165,7 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup ) if (setup->last_fence) setup->last_fence->issued = TRUE; - pipe_mutex_lock(screen->rast_mutex); + mtx_lock(&screen->rast_mutex); /* FIXME: We enqueue the scene then wait on the rasterizer to finish. * This means we never actually run any vertex stuff in parallel to @@ -178,7 +179,7 @@ lp_setup_rasterize_scene( struct lp_setup_context *setup ) */ lp_rast_queue_scene(screen->rast, scene); lp_rast_finish(screen->rast); - pipe_mutex_unlock(screen->rast_mutex); + mtx_unlock(&screen->rast_mutex); lp_scene_end_rasterization(setup->scene); lp_setup_reset( setup ); @@ -360,6 +361,8 @@ lp_setup_flush( struct lp_setup_context *setup, if (fence) { lp_fence_reference((struct lp_fence **)fence, setup->last_fence); + if (!*fence) + *fence = (struct pipe_fence_handle *)lp_fence_create(0); } } @@ -406,23 +409,7 @@ lp_setup_try_clear_color_buffer(struct lp_setup_context *setup, LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); - if (util_format_is_pure_integer(format)) { - /* - * We expect int/uint clear values here, though some APIs - * might disagree (but in any case util_pack_color() - * couldn't handle it)... - */ - if (util_format_is_pure_sint(format)) { - util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); - } - else { - assert(util_format_is_pure_uint(format)); - util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); - } - } - else { - util_pack_color(color->f, format, &uc); - } + util_pack_color_union(format, &uc, color); if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; @@ -453,7 +440,7 @@ lp_setup_try_clear_color_buffer(struct lp_setup_context *setup, else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil - * buffers which the app or state-tracker might issue + * buffers which the app or gallium frontend might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); @@ -476,22 +463,30 @@ lp_setup_try_clear_zs(struct lp_setup_context *setup, uint64_t zsvalue = 0; uint32_t zmask32; uint8_t smask8; + enum pipe_format format = setup->fb.zsbuf->format; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; - zsvalue = util_pack64_z_stencil(setup->fb.zsbuf->format, - depth, - stencil); + zsvalue = util_pack64_z_stencil(format, depth, stencil); - zsmask = util_pack64_mask_z_stencil(setup->fb.zsbuf->format, - zmask32, - smask8); + zsmask = util_pack64_mask_z_stencil(format, zmask32, smask8); zsvalue &= zsmask; + if (format == PIPE_FORMAT_Z24X8_UNORM || + format == PIPE_FORMAT_X8Z24_UNORM) { + /* + * Make full mask if there's "X" bits so we can do full + * clear (without rmw). + */ + uint32_t zsmask_full = 0; + zsmask_full = util_pack_mask_z_stencil(format, ~0, ~0); + zsmask |= ~zsmask_full; + } + if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; @@ -509,7 +504,7 @@ lp_setup_try_clear_zs(struct lp_setup_context *setup, else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil - * buffers which the app or state-tracker might issue + * buffers which the app or gallium frontend might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); @@ -572,13 +567,15 @@ lp_setup_set_triangle_state( struct lp_setup_context *setup, boolean ccw_is_frontface, boolean scissor, boolean half_pixel_center, - boolean bottom_edge_rule) + boolean bottom_edge_rule, + boolean multisample) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); setup->ccw_is_frontface = ccw_is_frontface; setup->cullmode = cull_mode; setup->triangle = first_triangle; + setup->multisample = multisample; setup->pixel_offset = half_pixel_center ? 0.5f : 0.0f; setup->bottom_edge_rule = bottom_edge_rule; @@ -642,17 +639,110 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup, LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); - assert(num <= Elements(setup->constants)); + assert(num <= ARRAY_SIZE(setup->constants)); for (i = 0; i < num; ++i) { util_copy_constant_buffer(&setup->constants[i].current, &buffers[i]); } - for (; i < Elements(setup->constants); i++) { + for (; i < ARRAY_SIZE(setup->constants); i++) { util_copy_constant_buffer(&setup->constants[i].current, NULL); } setup->dirty |= LP_SETUP_NEW_CONSTANTS; } +void +lp_setup_set_fs_ssbos(struct lp_setup_context *setup, + unsigned num, + struct pipe_shader_buffer *buffers) +{ + unsigned i; + + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers); + + assert(num <= ARRAY_SIZE(setup->ssbos)); + + for (i = 0; i < num; ++i) { + util_copy_shader_buffer(&setup->ssbos[i].current, &buffers[i]); + } + for (; i < ARRAY_SIZE(setup->ssbos); i++) { + util_copy_shader_buffer(&setup->ssbos[i].current, NULL); + } + setup->dirty |= LP_SETUP_NEW_SSBOS; +} + +void +lp_setup_set_fs_images(struct lp_setup_context *setup, + unsigned num, + struct pipe_image_view *images) +{ + unsigned i; + + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) images); + + assert(num <= ARRAY_SIZE(setup->images)); + + for (i = 0; i < num; ++i) { + struct pipe_image_view *image = &images[i]; + util_copy_image_view(&setup->images[i].current, &images[i]); + + struct pipe_resource *res = image->resource; + struct llvmpipe_resource *lp_res = llvmpipe_resource(res); + struct lp_jit_image *jit_image; + + jit_image = &setup->fs.current.jit_context.images[i]; + if (!lp_res) + continue; + if (!lp_res->dt) { + /* regular texture - setup array of mipmap level offsets */ + if (llvmpipe_resource_is_texture(res)) { + jit_image->base = lp_res->tex_data; + } else + jit_image->base = lp_res->data; + + jit_image->width = res->width0; + jit_image->height = res->height0; + jit_image->depth = res->depth0; + jit_image->num_samples = res->nr_samples; + + if (llvmpipe_resource_is_texture(res)) { + uint32_t mip_offset = lp_res->mip_offsets[image->u.tex.level]; + + jit_image->width = u_minify(jit_image->width, image->u.tex.level); + jit_image->height = u_minify(jit_image->height, image->u.tex.level); + + if (res->target == PIPE_TEXTURE_1D_ARRAY || + res->target == PIPE_TEXTURE_2D_ARRAY || + res->target == PIPE_TEXTURE_3D || + res->target == PIPE_TEXTURE_CUBE || + res->target == PIPE_TEXTURE_CUBE_ARRAY) { + /* + * For array textures, we don't have first_layer, instead + * adjust last_layer (stored as depth) plus the mip level offsets + * (as we have mip-first layout can't just adjust base ptr). + * XXX For mip levels, could do something similar. + */ + jit_image->depth = image->u.tex.last_layer - image->u.tex.first_layer + 1; + mip_offset += image->u.tex.first_layer * lp_res->img_stride[image->u.tex.level]; + } else + jit_image->depth = u_minify(jit_image->depth, image->u.tex.level); + + jit_image->row_stride = lp_res->row_stride[image->u.tex.level]; + jit_image->img_stride = lp_res->img_stride[image->u.tex.level]; + jit_image->sample_stride = lp_res->sample_stride; + jit_image->base = (uint8_t *)jit_image->base + mip_offset; + } + else { + unsigned view_blocksize = util_format_get_blocksize(image->format); + jit_image->width = image->u.buf.size / view_blocksize; + jit_image->base = (uint8_t *)jit_image->base + image->u.buf.offset; + } + } + } + for (; i < ARRAY_SIZE(setup->images); i++) { + util_copy_image_view(&setup->images[i].current, NULL); + } + setup->dirty |= LP_SETUP_NEW_FS; +} void lp_setup_set_alpha_ref_value( struct lp_setup_context *setup, @@ -713,27 +803,38 @@ lp_setup_set_scissors( struct lp_setup_context *setup, setup->dirty |= LP_SETUP_NEW_SCISSOR; } +void +lp_setup_set_sample_mask(struct lp_setup_context *setup, + uint32_t sample_mask) +{ + if (setup->fs.current.jit_context.sample_mask != sample_mask) { + setup->fs.current.jit_context.sample_mask = sample_mask; + setup->dirty |= LP_SETUP_NEW_FS; + } +} void -lp_setup_set_flatshade_first( struct lp_setup_context *setup, - boolean flatshade_first ) +lp_setup_set_flatshade_first(struct lp_setup_context *setup, + boolean flatshade_first) { setup->flatshade_first = flatshade_first; } void -lp_setup_set_rasterizer_discard( struct lp_setup_context *setup, - boolean rasterizer_discard ) +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__ ); + setup->line = first_line; + setup->point = first_point; + setup->triangle = first_triangle; } } void -lp_setup_set_vertex_info( struct lp_setup_context *setup, - struct vertex_info *vertex_info ) +lp_setup_set_vertex_info(struct lp_setup_context *setup, + struct vertex_info *vertex_info) { /* XXX: just silently holding onto the pointer: */ @@ -763,15 +864,8 @@ lp_setup_set_viewports(struct lp_setup_context *setup, for (i = 0; i < num_viewports; i++) { float min_depth; float max_depth; - - if (lp->rasterizer->clip_halfz == 0) { - float half_depth = viewports[i].scale[2]; - min_depth = viewports[i].translate[2] - half_depth; - max_depth = min_depth + half_depth * 2.0f; - } else { - min_depth = viewports[i].translate[2]; - max_depth = min_depth + viewports[i].scale[2]; - } + util_viewport_zmin_zmax(&viewports[i], lp->rasterizer->clip_halfz, + &min_depth, &max_depth); if (setup->viewports[i].min_depth != min_depth || setup->viewports[i].max_depth != max_depth) { @@ -791,13 +885,15 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views) { - unsigned i; + unsigned i, max_tex_num; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); - for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { + max_tex_num = MAX2(num, setup->fs.current_tex_num); + + for (i = 0; i < max_tex_num; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { @@ -839,6 +935,8 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->mip_offsets[0] = 0; jit_tex->row_stride[0] = 0; jit_tex->img_stride[0] = 0; + jit_tex->num_samples = 0; + jit_tex->sample_stride = 0; } else { jit_tex->width = res->width0; @@ -846,6 +944,8 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->depth = res->depth0; jit_tex->first_level = first_level; jit_tex->last_level = last_level; + jit_tex->num_samples = res->nr_samples; + jit_tex->sample_stride = 0; if (llvmpipe_resource_is_texture(res)) { for (j = first_level; j <= last_level; j++) { @@ -854,10 +954,12 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->img_stride[j] = lp_tex->img_stride[j]; } - if (view->target == PIPE_TEXTURE_1D_ARRAY || - view->target == PIPE_TEXTURE_2D_ARRAY || - view->target == PIPE_TEXTURE_CUBE || - view->target == PIPE_TEXTURE_CUBE_ARRAY) { + jit_tex->sample_stride = lp_tex->sample_stride; + + if (res->target == PIPE_TEXTURE_1D_ARRAY || + res->target == PIPE_TEXTURE_2D_ARRAY || + res->target == PIPE_TEXTURE_CUBE || + res->target == PIPE_TEXTURE_CUBE_ARRAY) { /* * For array textures, we don't have first_layer, instead * adjust last_layer (stored as depth) plus the mip level offsets @@ -879,8 +981,8 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, } else { /* - * For buffers, we don't have first_element, instead adjust - * last_element (stored as width) plus the base pointer. + * For buffers, we don't have "offset", instead adjust + * the size (stored as width) plus the base pointer. */ unsigned view_blocksize = util_format_get_blocksize(view->format); /* probably don't really need to fill that out */ @@ -889,12 +991,10 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->img_stride[0] = 0; /* everything specified in number of elements here. */ - jit_tex->width = view->u.buf.last_element - view->u.buf.first_element + 1; - jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.first_element * - view_blocksize; + jit_tex->width = view->u.buf.size / view_blocksize; + jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.offset; /* XXX Unsure if we need to sanitize parameters? */ - assert(view->u.buf.first_element <= view->u.buf.last_element); - assert(view->u.buf.last_element * view_blocksize < res->width0); + assert(view->u.buf.offset + view->u.buf.size <= res->width0); } } } @@ -914,10 +1014,16 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, jit_tex->height = res->height0; jit_tex->depth = res->depth0; jit_tex->first_level = jit_tex->last_level = 0; + jit_tex->num_samples = res->nr_samples; + jit_tex->sample_stride = 0; assert(jit_tex->base); } } + else { + pipe_resource_reference(&setup->fs.current_tex[i], NULL); + } } + setup->fs.current_tex_num = num; setup->dirty |= LP_SETUP_NEW_FS; } @@ -976,12 +1082,22 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup, } /* check textures referenced by the scene */ - for (i = 0; i < Elements(setup->scenes); i++) { + for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) { if (lp_scene_is_resource_referenced(setup->scenes[i], texture)) { return LP_REFERENCED_FOR_READ; } } + for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { + if (setup->ssbos[i].current.buffer == texture) + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; + } + + for (i = 0; i < ARRAY_SIZE(setup->images); i++) { + if (setup->images[i].current.resource == texture) + return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; + } + return LP_UNREFERENCED; } @@ -1067,7 +1183,7 @@ try_update_scene_state( struct lp_setup_context *setup ) } if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { - for (i = 0; i < Elements(setup->constants); ++i) { + for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) { struct pipe_resource *buffer = setup->constants[i].current.buffer; const unsigned current_size = MIN2(setup->constants[i].current.buffer_size, LP_MAX_TGSI_CONST_BUFFER_SIZE); @@ -1085,7 +1201,7 @@ try_update_scene_state( struct lp_setup_context *setup ) current_data = (ubyte *) setup->constants[i].current.user_buffer; } - if (current_data) { + if (current_data && current_size >= sizeof(float)) { current_data += setup->constants[i].current.buffer_offset; /* TODO: copy only the actually used constants? */ @@ -1119,13 +1235,33 @@ try_update_scene_state( struct lp_setup_context *setup ) } num_constants = - setup->constants[i].stored_size / (sizeof(float) * 4); + DIV_ROUND_UP(setup->constants[i].stored_size, lp_get_constant_buffer_stride(scene->pipe->screen)); setup->fs.current.jit_context.num_constants[i] = num_constants; setup->dirty |= LP_SETUP_NEW_FS; } } + if (setup->dirty & LP_SETUP_NEW_SSBOS) { + for (i = 0; i < ARRAY_SIZE(setup->ssbos); ++i) { + struct pipe_resource *buffer = setup->ssbos[i].current.buffer; + const ubyte *current_data = NULL; + if (!buffer) + continue; + /* resource buffer */ + current_data = (ubyte *) llvmpipe_resource_data(buffer); + if (current_data) { + current_data += setup->ssbos[i].current.buffer_offset; + + setup->fs.current.jit_context.ssbos[i] = (const uint32_t *)current_data; + setup->fs.current.jit_context.num_ssbos[i] = setup->ssbos[i].current.buffer_size; + } else { + setup->fs.current.jit_context.ssbos[i] = NULL; + setup->fs.current.jit_context.num_ssbos[i] = 0; + } + setup->dirty |= LP_SETUP_NEW_FS; + } + } if (setup->dirty & LP_SETUP_NEW_FS) { if (!setup->fs.stored || memcmp(setup->fs.stored, @@ -1152,7 +1288,7 @@ try_update_scene_state( struct lp_setup_context *setup ) /* The scene now references the textures in the rasterization * state record. Note that now. */ - for (i = 0; i < Elements(setup->fs.current_tex); i++) { + for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, setup->fs.current_tex[i], @@ -1207,7 +1343,7 @@ lp_setup_update_state( struct lp_setup_context *setup, /* Will probably need to move this somewhere else, just need * to know about vertex shader point size attribute. */ - setup->psize = lp->psize_slot; + setup->psize_slot = lp->psize_slot; setup->viewport_index_slot = lp->viewport_index_slot; setup->layer_slot = lp->layer_slot; setup->face_slot = lp->face_slot; @@ -1269,16 +1405,20 @@ lp_setup_destroy( struct lp_setup_context *setup ) util_unreference_framebuffer_state(&setup->fb); - for (i = 0; i < Elements(setup->fs.current_tex); i++) { + for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { pipe_resource_reference(&setup->fs.current_tex[i], NULL); } - for (i = 0; i < Elements(setup->constants); i++) { + for (i = 0; i < ARRAY_SIZE(setup->constants); i++) { pipe_resource_reference(&setup->constants[i].current.buffer, NULL); } + for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) { + pipe_resource_reference(&setup->ssbos[i].current.buffer, NULL); + } + /* free the scenes in the 'empty' queue */ - for (i = 0; i < Elements(setup->scenes); i++) { + for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) { struct lp_scene *scene = setup->scenes[i]; if (scene->fence) @@ -1341,6 +1481,10 @@ lp_setup_create( struct pipe_context *pipe, setup->dirty = ~0; + /* Initialize empty default fb correctly, so the rect is empty */ + setup->framebuffer.x1 = -1; + setup->framebuffer.y1 = -1; + return setup; no_scenes: @@ -1370,6 +1514,7 @@ lp_setup_begin_query(struct lp_setup_context *setup, if (!(pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || + pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS)) return; @@ -1420,6 +1565,7 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || + pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS || pq->type == PIPE_QUERY_TIMESTAMP) { if (pq->type == PIPE_QUERY_TIMESTAMP && @@ -1456,6 +1602,7 @@ fail: */ if (pq->type == PIPE_QUERY_OCCLUSION_COUNTER || pq->type == PIPE_QUERY_OCCLUSION_PREDICATE || + pq->type == PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE || pq->type == PIPE_QUERY_PIPELINE_STATISTICS) { unsigned i;