X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Fdraw%2Fdraw_context.c;h=baebc16036c028d4c7028e4f40201e8caeace163;hb=877128505431adaf817dc8069172ebe4a1cdf5d8;hp=6980631b365c9b60a5e6dd212739cf537c90d697;hpb=26097c4855b97ee6e362c19df11d51fb7fd42192;p=mesa.git diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 6980631b365..baebc16036c 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 VMWARE 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. @@ -27,7 +27,7 @@ /* * Authors: - * Keith Whitwell + * Keith Whitwell */ @@ -37,7 +37,11 @@ #include "util/u_cpu_detect.h" #include "util/u_inlines.h" #include "util/u_helpers.h" +#include "util/u_prim.h" +#include "util/u_format.h" #include "draw_context.h" +#include "draw_pipe.h" +#include "draw_prim_assembler.h" #include "draw_vs.h" #include "draw_gs.h" @@ -46,7 +50,7 @@ #include "gallivm/lp_bld_limits.h" #include "draw_llvm.h" -static boolean +boolean draw_get_option_use_llvm(void) { static boolean first = TRUE; @@ -57,7 +61,7 @@ draw_get_option_use_llvm(void) #ifdef PIPE_ARCH_X86 util_cpu_detect(); - /* require SSE2 due to LLVM PR6960. */ + /* require SSE2 due to LLVM PR6960. XXX Might be fixed by now? */ if (!util_cpu_caps.has_sse2) value = FALSE; #endif @@ -77,6 +81,9 @@ draw_create_context(struct pipe_context *pipe, boolean try_llvm) if (draw == NULL) goto err_out; + /* we need correct cpu caps for disabling denorms in draw_vbo() */ + util_cpu_detect(); + #if HAVE_LLVM if (try_llvm && draw_get_option_use_llvm()) { draw->llvm = draw_llvm_create(draw); @@ -90,6 +97,10 @@ draw_create_context(struct pipe_context *pipe, boolean try_llvm) if (!draw_init(draw)) goto err_destroy; + draw->ia = draw_prim_assembler_create(draw); + if (!draw->ia) + goto err_destroy; + return draw; err_destroy: @@ -137,6 +148,7 @@ boolean draw_init(struct draw_context *draw) draw->clip_z = TRUE; draw->pt.user.planes = (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) &(draw->plane[0]); + draw->pt.user.eltMax = ~0; if (!draw_pipeline_init( draw )) return FALSE; @@ -153,9 +165,24 @@ boolean draw_init(struct draw_context *draw) draw->quads_always_flatshade_last = !draw->pipe->screen->get_param( draw->pipe->screen, PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION); + draw->floating_point_depth = false; + return TRUE; } +/* + * Called whenever we're starting to draw a new instance. + * Some internal structures don't want to have to reset internal + * members on each invocation (because their state might have to persist + * between multiple primitive restart rendering call) but might have to + * for each new instance. + * This is particularly the case for primitive id's in geometry shader. + */ +void draw_new_instance(struct draw_context *draw) +{ + draw_geometry_shader_new_instance(draw->gs.geometry_shader); +} + void draw_destroy( struct draw_context *draw ) { @@ -187,6 +214,7 @@ void draw_destroy( struct draw_context *draw ) draw->render->destroy( draw->render ); */ + draw_prim_assembler_destroy(draw->ia); draw_pipeline_destroy( draw ); draw_pt_destroy( draw ); draw_vs_destroy( draw ); @@ -208,15 +236,20 @@ void draw_flush( struct draw_context *draw ) /** - * Specify the Minimum Resolvable Depth factor for polygon offset. + * Specify the depth stencil format for the draw pipeline. This function + * determines the Minimum Resolvable Depth factor for polygon offset. * This factor potentially depends on the number of Z buffer bits, * the rasterization algorithm and the arithmetic performed on Z - * values between vertex shading and rasterization. It will vary - * from one driver to another. + * values between vertex shading and rasterization. */ -void draw_set_mrd(struct draw_context *draw, double mrd) +void draw_set_zs_format(struct draw_context *draw, enum pipe_format format) { - draw->mrd = mrd; + const struct util_format_description *desc = util_format_description(format); + + draw->floating_point_depth = + (util_get_depth_format_type(desc) == UTIL_FORMAT_TYPE_FLOAT); + + draw->mrd = util_get_depth_format_mrd(desc); } @@ -229,6 +262,10 @@ static void update_clip_flags( struct draw_context *draw ) draw->rasterizer && draw->rasterizer->depth_clip); draw->clip_user = draw->rasterizer && draw->rasterizer->clip_plane_enable != 0; + draw->clip_points_xy = draw->clip_xy && + (!draw->driver.bypass_clip_points || + (draw->rasterizer && + !draw->rasterizer->point_tri_clip)); } /** @@ -254,17 +291,23 @@ void draw_set_rasterizer_state( struct draw_context *draw, * Some hardware can turn off clipping altogether - in particular any * hardware with a TNL unit can do its own clipping, even if it is * relying on the draw module for some other reason. + * Setting bypass_clip_points to achieve d3d-style point clipping (the driver + * will need to do the "vp scissoring") _requires_ the driver to implement + * wide points / point sprites itself (points will still be clipped if rasterizer + * point_tri_clip isn't set). Only relevant if bypass_clip_xy isn't set. */ void draw_set_driver_clipping( struct draw_context *draw, boolean bypass_clip_xy, boolean bypass_clip_z, - boolean guard_band_xy) + boolean guard_band_xy, + boolean bypass_clip_points) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clip_xy = bypass_clip_xy; draw->driver.bypass_clip_z = bypass_clip_z; draw->driver.guard_band_xy = guard_band_xy; + draw->driver.bypass_clip_points = bypass_clip_points; update_clip_flags(draw); } @@ -289,7 +332,7 @@ void draw_set_rasterize_stage( struct draw_context *draw, void draw_set_clip_state( struct draw_context *draw, const struct pipe_clip_state *clip ) { - draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); memcpy(&draw->plane[6], clip->ucp, sizeof(clip->ucp)); } @@ -298,21 +341,29 @@ void draw_set_clip_state( struct draw_context *draw, /** * Set the draw module's viewport state. */ -void draw_set_viewport_state( struct draw_context *draw, - const struct pipe_viewport_state *viewport ) +void draw_set_viewport_states( struct draw_context *draw, + unsigned start_slot, + unsigned num_viewports, + const struct pipe_viewport_state *vps ) { - draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); - draw->viewport = *viewport; /* struct copy */ - draw->identity_viewport = (viewport->scale[0] == 1.0f && - viewport->scale[1] == 1.0f && - viewport->scale[2] == 1.0f && - viewport->scale[3] == 1.0f && - viewport->translate[0] == 0.0f && - viewport->translate[1] == 0.0f && - viewport->translate[2] == 0.0f && - viewport->translate[3] == 0.0f); - - draw_vs_set_viewport( draw, viewport ); + const struct pipe_viewport_state *viewport = vps; + draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); + + debug_assert(start_slot < PIPE_MAX_VIEWPORTS); + debug_assert((start_slot + num_viewports) <= PIPE_MAX_VIEWPORTS); + + memcpy(draw->viewports + start_slot, vps, + sizeof(struct pipe_viewport_state) * num_viewports); + + draw->identity_viewport = (num_viewports == 1) && + (viewport->scale[0] == 1.0f && + viewport->scale[1] == 1.0f && + viewport->scale[2] == 1.0f && + viewport->scale[3] == 1.0f && + viewport->translate[0] == 0.0f && + viewport->translate[1] == 0.0f && + viewport->translate[2] == 0.0f && + viewport->translate[3] == 0.0f); } @@ -351,9 +402,11 @@ draw_set_vertex_elements(struct draw_context *draw, */ void draw_set_mapped_vertex_buffer(struct draw_context *draw, - unsigned attr, const void *buffer) + unsigned attr, const void *buffer, + size_t size) { - draw->pt.user.vbuffer[attr] = buffer; + draw->pt.user.vbuffer[attr].map = buffer; + draw->pt.user.vbuffer[attr].size = size; } @@ -368,16 +421,16 @@ draw_set_mapped_constant_buffer(struct draw_context *draw, shader_type == PIPE_SHADER_GEOMETRY); debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS); + draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); + switch (shader_type) { case PIPE_SHADER_VERTEX: draw->pt.user.vs_constants[slot] = buffer; draw->pt.user.vs_constants_size[slot] = size; - draw_vs_set_constants(draw, slot, buffer, size); break; case PIPE_SHADER_GEOMETRY: draw->pt.user.gs_constants[slot] = buffer; draw->pt.user.gs_constants_size[slot] = size; - draw_gs_set_constants(draw, slot, buffer, size); break; default: assert(0 && "invalid shader type in draw_set_mapped_constant_buffer"); @@ -468,7 +521,7 @@ draw_alloc_extra_vertex_attrib(struct draw_context *draw, uint n; slot = draw_find_shader_output(draw, semantic_name, semantic_index); - if (slot > 0) { + if (slot >= 0) { return slot; } @@ -512,6 +565,28 @@ draw_get_shader_info(const struct draw_context *draw) } } +/** + * Prepare outputs slots from the draw module + * + * Certain parts of the draw module can emit additional + * outputs that can be quite useful to the backends, a good + * example of it is the process of decomposing primitives + * into wireframes (aka. lines) which normally would lose + * the face-side information, but using this method we can + * inject another shader output which passes the original + * face side information to the backend. + */ +void +draw_prepare_shader_outputs(struct draw_context *draw) +{ + draw_remove_extra_vertex_attribs(draw); + draw_prim_assembler_prepare_outputs(draw->ia); + draw_unfilled_prepare_outputs(draw, draw->pipeline.unfilled); + if (draw->pipeline.aapoint) + draw_aapoint_prepare_outputs(draw, draw->pipeline.aapoint); + if (draw->pipeline.aaline) + draw_aaline_prepare_outputs(draw, draw->pipeline.aaline); +} /** * Ask the draw module for the location/slot of the given vertex attribute in @@ -524,9 +599,10 @@ draw_get_shader_info(const struct draw_context *draw) * attributes (such as texcoords for AA lines). The driver can call this * function to find those attributes. * - * Zero is returned if the attribute is not found since this is - * a don't care / undefined situtation. Returning -1 would be a bit more - * work for the drivers. + * -1 is returned if the attribute is not found since this is + * an undefined situation. Note, that zero is valid and can + * be used by any of the attributes, because position is not + * required to be attribute 0 or even at all present. */ int draw_find_shader_output(const struct draw_context *draw, @@ -549,7 +625,7 @@ draw_find_shader_output(const struct draw_context *draw, } } - return 0; + return -1; } @@ -575,24 +651,55 @@ draw_num_shader_outputs(const struct draw_context *draw) } +/** + * Return total number of the vertex shader outputs. This function + * also counts any extra vertex output attributes that may + * be filled in by some draw stages (such as AA point, AA line, + * front face). + */ +uint +draw_total_vs_outputs(const struct draw_context *draw) +{ + const struct tgsi_shader_info *info = &draw->vs.vertex_shader->info; + + return info->num_outputs + draw->extra_shader_outputs.num;; +} + +/** + * Return total number of the geometry shader outputs. This function + * also counts any extra geometry output attributes that may + * be filled in by some draw stages (such as AA point, AA line, front + * face). + */ +uint +draw_total_gs_outputs(const struct draw_context *draw) +{ + const struct tgsi_shader_info *info; + + if (!draw->gs.geometry_shader) + return 0; + + info = &draw->gs.geometry_shader->info; + + return info->num_outputs + draw->extra_shader_outputs.num; +} + + /** * Provide TGSI sampler objects for vertex/geometry shaders that use * texture fetches. This state only needs to be set once per context. * This might only be used by software drivers for the time being. */ void -draw_texture_samplers(struct draw_context *draw, - uint shader, - uint num_samplers, - struct tgsi_sampler **samplers) +draw_texture_sampler(struct draw_context *draw, + uint shader, + struct tgsi_sampler *sampler) { if (shader == PIPE_SHADER_VERTEX) { - draw->vs.tgsi.num_samplers = num_samplers; - draw->vs.tgsi.samplers = samplers; + draw->vs.tgsi.sampler = sampler; } else { debug_assert(shader == PIPE_SHADER_GEOMETRY); - draw->gs.tgsi.num_samplers = num_samplers; - draw->gs.tgsi.samplers = samplers; + draw->gs.tgsi.sampler = sampler; } } @@ -615,7 +722,8 @@ void draw_set_render( struct draw_context *draw, */ void draw_set_indexes(struct draw_context *draw, - const void *elements, unsigned elem_size) + const void *elements, unsigned elem_size, + unsigned elem_buffer_space) { assert(elem_size == 0 || elem_size == 1 || @@ -623,6 +731,10 @@ draw_set_indexes(struct draw_context *draw, elem_size == 4); draw->pt.user.elts = elements; draw->pt.user.eltSizeIB = elem_size; + if (elem_size) + draw->pt.user.eltMax = elem_buffer_space / elem_size; + else + draw->pt.user.eltMax = 0; } @@ -673,6 +785,31 @@ draw_current_shader_position_output(const struct draw_context *draw) } +/** + * Return the index of the shader output which will contain the + * viewport index. + */ +uint +draw_current_shader_viewport_index_output(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->viewport_index_output; + return 0; +} + +/** + * Returns true if there's a geometry shader bound and the geometry + * shader writes out a viewport index. + */ +boolean +draw_current_shader_uses_viewport_index(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.writes_viewport_index; + return FALSE; +} + + /** * Return the index of the shader output which will contain the * vertex position. @@ -686,9 +823,39 @@ draw_current_shader_clipvertex_output(const struct draw_context *draw) uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index) { + debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->clipdistance_output[index]; return draw->vs.clipdistance_output[index]; } + +uint +draw_current_shader_num_written_clipdistances(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.num_written_clipdistance; + return draw->vs.vertex_shader->info.num_written_clipdistance; +} + + +uint +draw_current_shader_culldistance_output(const struct draw_context *draw, int index) +{ + debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->culldistance_output[index]; + return draw->vs.vertex_shader->culldistance_output[index]; +} + +uint +draw_current_shader_num_written_culldistances(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.num_written_culldistance; + return draw->vs.vertex_shader->info.num_written_culldistance; +} + /** * Return a pointer/handle for a driver/CSO rasterizer object which * disabled culling, stippling, unfilled tris, etc. @@ -714,7 +881,9 @@ draw_get_rasterizer_no_cull( struct draw_context *draw, rast.scissor = scissor; rast.flatshade = flatshade; rast.front_ccw = 1; - rast.gl_rasterization_rules = draw->rasterizer->gl_rasterization_rules; + rast.half_pixel_center = draw->rasterizer->half_pixel_center; + rast.bottom_edge_rule = draw->rasterizer->bottom_edge_rule; + rast.clip_halfz = draw->rasterizer->clip_halfz; draw->rasterizer_no_cull[scissor][flatshade] = pipe->create_rasterizer_state(pipe, &rast); @@ -737,22 +906,6 @@ draw_set_mapped_so_targets(struct draw_context *draw, draw->so.num_targets = num_targets; } -void -draw_set_mapped_so_buffers(struct draw_context *draw, - void *buffers[PIPE_MAX_SO_BUFFERS], - unsigned num_buffers) -{ -} - -void -draw_set_so_state(struct draw_context *draw, - struct pipe_stream_output_info *state) -{ - memcpy(&draw->so.state, - state, - sizeof(struct pipe_stream_output_info)); -} - void draw_set_sampler_views(struct draw_context *draw, unsigned shader_stage, @@ -762,11 +915,13 @@ draw_set_sampler_views(struct draw_context *draw, unsigned i; debug_assert(shader_stage < PIPE_SHADER_TYPES); - debug_assert(num <= PIPE_MAX_SAMPLERS); + debug_assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); + + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); for (i = 0; i < num; ++i) draw->sampler_views[shader_stage][i] = views[i]; - for (i = num; i < PIPE_MAX_SAMPLERS; ++i) + for (i = num; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; ++i) draw->sampler_views[shader_stage][i] = NULL; draw->num_sampler_views[shader_stage] = num; @@ -783,6 +938,8 @@ draw_set_samplers(struct draw_context *draw, debug_assert(shader_stage < PIPE_SHADER_TYPES); debug_assert(num <= PIPE_MAX_SAMPLERS); + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + for (i = 0; i < num; ++i) draw->samplers[shader_stage][i] = samplers[i]; for (i = num; i < PIPE_MAX_SAMPLERS; ++i) @@ -791,15 +948,15 @@ draw_set_samplers(struct draw_context *draw, draw->num_samplers[shader_stage] = num; #ifdef HAVE_LLVM - if (draw->llvm && shader_stage == PIPE_SHADER_VERTEX) - draw_llvm_set_sampler_state(draw); + if (draw->llvm) + draw_llvm_set_sampler_state(draw, shader_stage); #endif } void draw_set_mapped_texture(struct draw_context *draw, unsigned shader_stage, - unsigned sampler_idx, + unsigned sview_idx, uint32_t width, uint32_t height, uint32_t depth, uint32_t first_level, uint32_t last_level, const void *base_ptr, @@ -807,16 +964,15 @@ draw_set_mapped_texture(struct draw_context *draw, uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS], uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]) { - if (shader_stage == PIPE_SHADER_VERTEX) { #ifdef HAVE_LLVM - if (draw->llvm) - draw_llvm_set_mapped_texture(draw, - sampler_idx, - width, height, depth, first_level, - last_level, base_ptr, - row_stride, img_stride, mip_offsets); + if (draw->llvm) + draw_llvm_set_mapped_texture(draw, + shader_stage, + sview_idx, + width, height, depth, first_level, + last_level, base_ptr, + row_stride, img_stride, mip_offsets); #endif - } } /** @@ -858,3 +1014,69 @@ draw_get_shader_param(unsigned shader, enum pipe_shader_cap param) return draw_get_shader_param_no_llvm(shader, param); } +/** + * Enables or disables collection of statistics. + * + * Draw module is capable of generating statistics for the vertex + * processing pipeline. Collection of that data isn't free and so + * it's disabled by default. The users of the module can enable + * (or disable) this functionality through this function. + * The actual data will be emitted through the VBUF interface, + * the 'pipeline_statistics' callback to be exact. + */ +void +draw_collect_pipeline_statistics(struct draw_context *draw, + boolean enable) +{ + draw->collect_statistics = enable; +} + +/** + * Computes clipper invocation statistics. + * + * Figures out how many primitives would have been + * sent to the clipper given the specified + * prim info data. + */ +void +draw_stats_clipper_primitives(struct draw_context *draw, + const struct draw_prim_info *prim_info) +{ + if (draw->collect_statistics) { + unsigned start, i; + for (start = i = 0; + i < prim_info->primitive_count; + start += prim_info->primitive_lengths[i], i++) + { + draw->statistics.c_invocations += + u_decomposed_prims_for_vertices(prim_info->prim, + prim_info->primitive_lengths[i]); + } + } +} + + +/** + * Returns true if the draw module will inject the frontface + * info into the outputs. + * + * Given the specified primitive and rasterizer state + * the function will figure out if the draw module + * will inject the front-face information into shader + * outputs. This is done to preserve the front-facing + * info when decomposing primitives into wireframes. + */ +boolean +draw_will_inject_frontface(const struct draw_context *draw) +{ + unsigned reduced_prim = u_reduced_prim(draw->pt.prim); + const struct pipe_rasterizer_state *rast = draw->rasterizer; + + if (reduced_prim != PIPE_PRIM_TRIANGLES) { + return FALSE; + } + + return (rast && + (rast->fill_front != PIPE_POLYGON_MODE_FILL || + rast->fill_back != PIPE_POLYGON_MODE_FILL)); +}