14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg /* 294a49301eSmrg * Authors: 30af69d88dSmrg * Keith Whitwell <keithw@vmware.com> 314a49301eSmrg */ 324a49301eSmrg 334a49301eSmrg#include "draw/draw_context.h" 343464ebd5Sriastradh#include "draw/draw_gs.h" 357ec681f3Smrg#include "draw/draw_tess.h" 364a49301eSmrg#include "draw/draw_private.h" 374a49301eSmrg#include "draw/draw_pt.h" 38af69d88dSmrg#include "draw/draw_vbuf.h" 393464ebd5Sriastradh#include "draw/draw_vs.h" 404a49301eSmrg#include "tgsi/tgsi_dump.h" 414a49301eSmrg#include "util/u_math.h" 424a49301eSmrg#include "util/u_prim.h" 437ec681f3Smrg#include "util/format/u_format.h" 443464ebd5Sriastradh#include "util/u_draw.h" 454a49301eSmrg 464a49301eSmrg 473464ebd5SriastradhDEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE) 483464ebd5SriastradhDEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE) 494a49301eSmrg 504a49301eSmrg/* Overall we split things into: 513464ebd5Sriastradh * - frontend -- prepare fetch_elts, draw_elts - eg vsplit 524a49301eSmrg * - middle -- fetch, shade, cliptest, viewport 534a49301eSmrg * - pipeline -- the prim pipeline: clipping, wide lines, etc 544a49301eSmrg * - backend -- the vbuf_render provided by the driver. 554a49301eSmrg */ 564a49301eSmrgstatic boolean 57af69d88dSmrgdraw_pt_arrays(struct draw_context *draw, 584a49301eSmrg unsigned prim, 597ec681f3Smrg bool index_bias_varies, 607ec681f3Smrg const struct pipe_draw_start_count_bias *draw_info, 617ec681f3Smrg unsigned num_draws) 624a49301eSmrg{ 634a49301eSmrg struct draw_pt_front_end *frontend = NULL; 644a49301eSmrg struct draw_pt_middle_end *middle = NULL; 657ec681f3Smrg unsigned opt = PT_SHADE; 664a49301eSmrg 677ec681f3Smrg unsigned out_prim = prim; 684a49301eSmrg 697ec681f3Smrg if (draw->gs.geometry_shader) 707ec681f3Smrg out_prim = draw->gs.geometry_shader->output_primitive; 717ec681f3Smrg else if (draw->tes.tess_eval_shader) 727ec681f3Smrg out_prim = get_tes_output_prim(draw->tes.tess_eval_shader); 733464ebd5Sriastradh 747ec681f3Smrg if (!draw->render) { 757ec681f3Smrg opt |= PT_PIPELINE; 767ec681f3Smrg } 774a49301eSmrg 787ec681f3Smrg if (draw_need_pipeline(draw, 797ec681f3Smrg draw->rasterizer, 807ec681f3Smrg out_prim)) { 817ec681f3Smrg opt |= PT_PIPELINE; 827ec681f3Smrg } 833464ebd5Sriastradh 847ec681f3Smrg if ((draw->clip_xy || 857ec681f3Smrg draw->clip_z || 867ec681f3Smrg draw->clip_user) && !draw->pt.test_fse) { 877ec681f3Smrg opt |= PT_CLIPTEST; 884a49301eSmrg } 894a49301eSmrg 903464ebd5Sriastradh if (draw->pt.middle.llvm) { 913464ebd5Sriastradh middle = draw->pt.middle.llvm; 924a49301eSmrg } else { 937ec681f3Smrg if (opt == PT_SHADE && !draw->pt.no_fse) 943464ebd5Sriastradh middle = draw->pt.middle.fetch_shade_emit; 953464ebd5Sriastradh else 963464ebd5Sriastradh middle = draw->pt.middle.general; 974a49301eSmrg } 984a49301eSmrg 99af69d88dSmrg frontend = draw->pt.frontend; 100af69d88dSmrg 10101e04c3fSmrg if (frontend) { 102af69d88dSmrg if (draw->pt.prim != prim || draw->pt.opt != opt) { 103af69d88dSmrg /* In certain conditions switching primitives requires us to flush 104af69d88dSmrg * and validate the different stages. One example is when smooth 105af69d88dSmrg * lines are active but first drawn with triangles and then with 106af69d88dSmrg * lines. 107af69d88dSmrg */ 108af69d88dSmrg draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 109af69d88dSmrg frontend = NULL; 110af69d88dSmrg } else if (draw->pt.eltSize != draw->pt.user.eltSize) { 111af69d88dSmrg /* Flush draw state if eltSize changed. 112af69d88dSmrg * This could be improved so only the frontend is flushed since it 113af69d88dSmrg * converts all indices to ushorts and the fetch part of the middle 114af69d88dSmrg * always prepares both linear and indexed. 115af69d88dSmrg */ 116af69d88dSmrg frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE ); 117af69d88dSmrg frontend = NULL; 118af69d88dSmrg } 119af69d88dSmrg } 1203464ebd5Sriastradh 121af69d88dSmrg if (!frontend) { 122af69d88dSmrg frontend = draw->pt.front.vsplit; 1234a49301eSmrg 124af69d88dSmrg frontend->prepare( frontend, prim, middle, opt ); 1254a49301eSmrg 126af69d88dSmrg draw->pt.frontend = frontend; 127af69d88dSmrg draw->pt.eltSize = draw->pt.user.eltSize; 128af69d88dSmrg draw->pt.prim = prim; 129af69d88dSmrg draw->pt.opt = opt; 130af69d88dSmrg } 131af69d88dSmrg 132af69d88dSmrg if (draw->pt.rebind_parameters) { 133af69d88dSmrg /* update constants, viewport dims, clip planes, etc */ 134af69d88dSmrg middle->bind_parameters(middle); 135af69d88dSmrg draw->pt.rebind_parameters = FALSE; 136af69d88dSmrg } 137af69d88dSmrg 1387ec681f3Smrg 1397ec681f3Smrg for (unsigned i = 0; i < num_draws; i++) { 1407ec681f3Smrg unsigned count = draw_info[i].count; 1417ec681f3Smrg /* Sanitize primitive length: 1427ec681f3Smrg */ 1437ec681f3Smrg unsigned first, incr; 1447ec681f3Smrg 1457ec681f3Smrg if (prim == PIPE_PRIM_PATCHES) { 1467ec681f3Smrg first = draw->pt.vertices_per_patch; 1477ec681f3Smrg incr = draw->pt.vertices_per_patch; 1487ec681f3Smrg } else 1497ec681f3Smrg draw_pt_split_prim(prim, &first, &incr); 1507ec681f3Smrg count = draw_pt_trim_count(draw_info[i].count, first, incr); 1517ec681f3Smrg draw->pt.user.eltBias = draw->pt.user.eltSize ? 1527ec681f3Smrg (index_bias_varies ? draw_info[i].index_bias : draw_info[0].index_bias) : 1537ec681f3Smrg 0; 1547ec681f3Smrg if (count >= first) 1557ec681f3Smrg frontend->run( frontend, draw_info[i].start, count ); 1567ec681f3Smrg 1577ec681f3Smrg if (draw->pt.user.increment_draw_id) 1587ec681f3Smrg draw->pt.user.drawid++; 1597ec681f3Smrg } 1604a49301eSmrg 1614a49301eSmrg return TRUE; 1624a49301eSmrg} 1634a49301eSmrg 164af69d88dSmrgvoid draw_pt_flush( struct draw_context *draw, unsigned flags ) 165af69d88dSmrg{ 166af69d88dSmrg assert(flags); 167af69d88dSmrg 168af69d88dSmrg if (draw->pt.frontend) { 169af69d88dSmrg draw->pt.frontend->flush( draw->pt.frontend, flags ); 170af69d88dSmrg 171af69d88dSmrg /* don't prepare if we only are flushing the backend */ 172af69d88dSmrg if (flags & DRAW_FLUSH_STATE_CHANGE) 173af69d88dSmrg draw->pt.frontend = NULL; 174af69d88dSmrg } 175af69d88dSmrg 176af69d88dSmrg if (flags & DRAW_FLUSH_PARAMETER_CHANGE) { 177af69d88dSmrg draw->pt.rebind_parameters = TRUE; 178af69d88dSmrg } 179af69d88dSmrg} 180af69d88dSmrg 181af69d88dSmrg 1824a49301eSmrg 1834a49301eSmrgboolean draw_pt_init( struct draw_context *draw ) 1844a49301eSmrg{ 1853464ebd5Sriastradh draw->pt.test_fse = debug_get_option_draw_fse(); 1863464ebd5Sriastradh draw->pt.no_fse = debug_get_option_draw_no_fse(); 1874a49301eSmrg 1883464ebd5Sriastradh draw->pt.front.vsplit = draw_pt_vsplit(draw); 1893464ebd5Sriastradh if (!draw->pt.front.vsplit) 1904a49301eSmrg return FALSE; 1914a49301eSmrg 1924a49301eSmrg draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw ); 1934a49301eSmrg if (!draw->pt.middle.fetch_shade_emit) 1944a49301eSmrg return FALSE; 1954a49301eSmrg 1964a49301eSmrg draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw ); 1974a49301eSmrg if (!draw->pt.middle.general) 1984a49301eSmrg return FALSE; 1994a49301eSmrg 2007ec681f3Smrg#ifdef DRAW_LLVM_AVAILABLE 2013464ebd5Sriastradh if (draw->llvm) 2023464ebd5Sriastradh draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw ); 2033464ebd5Sriastradh#endif 2043464ebd5Sriastradh 2054a49301eSmrg return TRUE; 2064a49301eSmrg} 2074a49301eSmrg 2084a49301eSmrg 2094a49301eSmrgvoid draw_pt_destroy( struct draw_context *draw ) 2104a49301eSmrg{ 2113464ebd5Sriastradh if (draw->pt.middle.llvm) { 2123464ebd5Sriastradh draw->pt.middle.llvm->destroy( draw->pt.middle.llvm ); 2133464ebd5Sriastradh draw->pt.middle.llvm = NULL; 2143464ebd5Sriastradh } 2153464ebd5Sriastradh 2164a49301eSmrg if (draw->pt.middle.general) { 2174a49301eSmrg draw->pt.middle.general->destroy( draw->pt.middle.general ); 2184a49301eSmrg draw->pt.middle.general = NULL; 2194a49301eSmrg } 2204a49301eSmrg 2214a49301eSmrg if (draw->pt.middle.fetch_shade_emit) { 2224a49301eSmrg draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit ); 2234a49301eSmrg draw->pt.middle.fetch_shade_emit = NULL; 2244a49301eSmrg } 2254a49301eSmrg 2263464ebd5Sriastradh if (draw->pt.front.vsplit) { 2273464ebd5Sriastradh draw->pt.front.vsplit->destroy( draw->pt.front.vsplit ); 2283464ebd5Sriastradh draw->pt.front.vsplit = NULL; 2294a49301eSmrg } 2304a49301eSmrg} 2314a49301eSmrg 2324a49301eSmrg 2334a49301eSmrg/** 2344a49301eSmrg * Debug- print the first 'count' vertices. 2354a49301eSmrg */ 2364a49301eSmrgstatic void 2377ec681f3Smrgdraw_print_arrays(struct draw_context *draw, uint prim, int start, uint count, int index_bias) 2384a49301eSmrg{ 2394a49301eSmrg uint i; 2404a49301eSmrg 2414a49301eSmrg debug_printf("Draw arrays(prim = %u, start = %u, count = %u)\n", 2424a49301eSmrg prim, start, count); 2434a49301eSmrg 2444a49301eSmrg for (i = 0; i < count; i++) { 2454a49301eSmrg uint ii = 0; 2464a49301eSmrg uint j; 2474a49301eSmrg 2483464ebd5Sriastradh if (draw->pt.user.eltSize) { 2494a49301eSmrg /* indexed arrays */ 2503464ebd5Sriastradh 2514a49301eSmrg switch (draw->pt.user.eltSize) { 2524a49301eSmrg case 1: 2534a49301eSmrg { 254af69d88dSmrg const ubyte *elem = (const ubyte *) draw->pt.user.elts; 2554a49301eSmrg ii = elem[start + i]; 2564a49301eSmrg } 2574a49301eSmrg break; 2584a49301eSmrg case 2: 2594a49301eSmrg { 260af69d88dSmrg const ushort *elem = (const ushort *) draw->pt.user.elts; 2614a49301eSmrg ii = elem[start + i]; 2624a49301eSmrg } 2634a49301eSmrg break; 2644a49301eSmrg case 4: 2654a49301eSmrg { 266af69d88dSmrg const uint *elem = (const uint *) draw->pt.user.elts; 2674a49301eSmrg ii = elem[start + i]; 2684a49301eSmrg } 2694a49301eSmrg break; 2704a49301eSmrg default: 2714a49301eSmrg assert(0); 2723464ebd5Sriastradh return; 2734a49301eSmrg } 2747ec681f3Smrg ii += index_bias; 2753464ebd5Sriastradh debug_printf("Element[%u + %u] + %i -> Vertex %u:\n", start, i, 2767ec681f3Smrg index_bias, ii); 2774a49301eSmrg } 2784a49301eSmrg else { 2794a49301eSmrg /* non-indexed arrays */ 2804a49301eSmrg ii = start + i; 2814a49301eSmrg debug_printf("Vertex %u:\n", ii); 2824a49301eSmrg } 2834a49301eSmrg 2844a49301eSmrg for (j = 0; j < draw->pt.nr_vertex_elements; j++) { 2854a49301eSmrg uint buf = draw->pt.vertex_element[j].vertex_buffer_index; 286af69d88dSmrg ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf].map; 2873464ebd5Sriastradh 2883464ebd5Sriastradh if (draw->pt.vertex_element[j].instance_divisor) { 2893464ebd5Sriastradh ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor; 2903464ebd5Sriastradh } 2913464ebd5Sriastradh 2923464ebd5Sriastradh ptr += draw->pt.vertex_buffer[buf].buffer_offset; 2934a49301eSmrg ptr += draw->pt.vertex_buffer[buf].stride * ii; 2944a49301eSmrg ptr += draw->pt.vertex_element[j].src_offset; 2954a49301eSmrg 2964a49301eSmrg debug_printf(" Attr %u: ", j); 2974a49301eSmrg switch (draw->pt.vertex_element[j].src_format) { 2984a49301eSmrg case PIPE_FORMAT_R32_FLOAT: 2994a49301eSmrg { 3004a49301eSmrg float *v = (float *) ptr; 3013464ebd5Sriastradh debug_printf("R %f @ %p\n", v[0], (void *) v); 3024a49301eSmrg } 3034a49301eSmrg break; 3044a49301eSmrg case PIPE_FORMAT_R32G32_FLOAT: 3054a49301eSmrg { 3064a49301eSmrg float *v = (float *) ptr; 3073464ebd5Sriastradh debug_printf("RG %f %f @ %p\n", v[0], v[1], (void *) v); 3084a49301eSmrg } 3094a49301eSmrg break; 3104a49301eSmrg case PIPE_FORMAT_R32G32B32_FLOAT: 3114a49301eSmrg { 3124a49301eSmrg float *v = (float *) ptr; 3133464ebd5Sriastradh debug_printf("RGB %f %f %f @ %p\n", v[0], v[1], v[2], (void *) v); 3144a49301eSmrg } 3154a49301eSmrg break; 3164a49301eSmrg case PIPE_FORMAT_R32G32B32A32_FLOAT: 3174a49301eSmrg { 3184a49301eSmrg float *v = (float *) ptr; 3193464ebd5Sriastradh debug_printf("RGBA %f %f %f %f @ %p\n", v[0], v[1], v[2], v[3], 3204a49301eSmrg (void *) v); 3214a49301eSmrg } 3224a49301eSmrg break; 3233464ebd5Sriastradh case PIPE_FORMAT_B8G8R8A8_UNORM: 3243464ebd5Sriastradh { 3253464ebd5Sriastradh ubyte *u = (ubyte *) ptr; 3263464ebd5Sriastradh debug_printf("BGRA %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3], 3273464ebd5Sriastradh (void *) u); 3283464ebd5Sriastradh } 3293464ebd5Sriastradh break; 330af69d88dSmrg case PIPE_FORMAT_A8R8G8B8_UNORM: 331af69d88dSmrg { 332af69d88dSmrg ubyte *u = (ubyte *) ptr; 333af69d88dSmrg debug_printf("ARGB %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3], 334af69d88dSmrg (void *) u); 335af69d88dSmrg } 336af69d88dSmrg break; 3374a49301eSmrg default: 3383464ebd5Sriastradh debug_printf("other format %s (fix me)\n", 3393464ebd5Sriastradh util_format_name(draw->pt.vertex_element[j].src_format)); 3403464ebd5Sriastradh } 3413464ebd5Sriastradh } 3423464ebd5Sriastradh } 3433464ebd5Sriastradh} 3443464ebd5Sriastradh 3453464ebd5Sriastradh 3463464ebd5Sriastradh/** Helper code for below */ 3477ec681f3Smrgstatic inline void 3487ec681f3Smrgprim_restart_loop(struct draw_context *draw, 3497ec681f3Smrg const struct pipe_draw_info *info, 3507ec681f3Smrg const struct pipe_draw_start_count_bias *draw_info, 3517ec681f3Smrg const void *elements) 3523464ebd5Sriastradh{ 353af69d88dSmrg const unsigned elt_max = draw->pt.user.eltMax; 3547ec681f3Smrg struct pipe_draw_start_count_bias cur = *draw_info; 3557ec681f3Smrg cur.count = 0; 3567ec681f3Smrg 357af69d88dSmrg /* The largest index within a loop using the i variable as the index. 358af69d88dSmrg * Used for overflow detection */ 359af69d88dSmrg const unsigned MAX_LOOP_IDX = 0xffffffff; 3603464ebd5Sriastradh 3617ec681f3Smrg for (unsigned j = 0; j < draw_info->count; j++) { 3627ec681f3Smrg unsigned restart_idx = 0; 3637ec681f3Smrg unsigned i = draw_overflow_uadd(draw_info->start, j, MAX_LOOP_IDX); 3643464ebd5Sriastradh switch (draw->pt.user.eltSize) { 3653464ebd5Sriastradh case 1: 3667ec681f3Smrg restart_idx = ((const uint8_t*)elements)[i]; 3673464ebd5Sriastradh break; 3683464ebd5Sriastradh case 2: 3697ec681f3Smrg restart_idx = ((const uint16_t*)elements)[i]; 3703464ebd5Sriastradh break; 3713464ebd5Sriastradh case 4: 3727ec681f3Smrg restart_idx = ((const uint32_t*)elements)[i]; 3733464ebd5Sriastradh break; 3743464ebd5Sriastradh default: 3753464ebd5Sriastradh assert(0 && "bad eltSize in draw_arrays()"); 3764a49301eSmrg } 3777ec681f3Smrg 3787ec681f3Smrg if (i < elt_max && restart_idx == info->restart_index) { 3797ec681f3Smrg if (cur.count > 0) { 3807ec681f3Smrg /* draw elts up to prev pos */ 3817ec681f3Smrg draw_pt_arrays(draw, info->mode, info->index_bias_varies, &cur, 1); 3827ec681f3Smrg } 3837ec681f3Smrg /* begin new prim at next elt */ 3847ec681f3Smrg cur.start = i + 1; 3857ec681f3Smrg cur.count = 0; 3867ec681f3Smrg } 3877ec681f3Smrg else { 3887ec681f3Smrg cur.count++; 3897ec681f3Smrg } 3907ec681f3Smrg } 3917ec681f3Smrg if (cur.count > 0) { 3927ec681f3Smrg draw_pt_arrays(draw, info->mode, info->index_bias_varies, &cur, 1); 3937ec681f3Smrg } 3947ec681f3Smrg} 3957ec681f3Smrg 3967ec681f3Smrg/** 3977ec681f3Smrg * For drawing prims with primitive restart enabled. 3987ec681f3Smrg * Scan for restart indexes and draw the runs of elements/vertices between 3997ec681f3Smrg * the restarts. 4007ec681f3Smrg */ 4017ec681f3Smrgstatic void 4027ec681f3Smrgdraw_pt_arrays_restart(struct draw_context *draw, 4037ec681f3Smrg const struct pipe_draw_info *info, 4047ec681f3Smrg const struct pipe_draw_start_count_bias *draw_info, 4057ec681f3Smrg unsigned num_draws) 4067ec681f3Smrg{ 4077ec681f3Smrg const unsigned prim = info->mode; 4087ec681f3Smrg 4097ec681f3Smrg assert(info->primitive_restart); 4107ec681f3Smrg 4117ec681f3Smrg if (draw->pt.user.eltSize) { 4127ec681f3Smrg /* indexed prims (draw_elements) */ 4137ec681f3Smrg for (unsigned i = 0; i < num_draws; i++) 4147ec681f3Smrg prim_restart_loop(draw, info, &draw_info[i], draw->pt.user.elts); 4154a49301eSmrg } 4163464ebd5Sriastradh else { 4173464ebd5Sriastradh /* Non-indexed prims (draw_arrays). 4187ec681f3Smrg * Primitive restart should have been handled in gallium frontends. 4193464ebd5Sriastradh */ 4207ec681f3Smrg draw_pt_arrays(draw, prim, info->index_bias_varies, draw_info, num_draws); 4213464ebd5Sriastradh } 4224a49301eSmrg} 4234a49301eSmrg 4244a49301eSmrg 4254a49301eSmrg/** 426af69d88dSmrg * Resolve true values within pipe_draw_info. 427af69d88dSmrg * If we're rendering from transform feedback/stream output 428af69d88dSmrg * buffers both the count and max_index need to be computed 429af69d88dSmrg * from the attached stream output target. 4304a49301eSmrg */ 431af69d88dSmrgstatic void 432af69d88dSmrgresolve_draw_info(const struct pipe_draw_info *raw_info, 4337ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 4347ec681f3Smrg const struct pipe_draw_start_count_bias *raw_draw, 435af69d88dSmrg struct pipe_draw_info *info, 4367ec681f3Smrg struct pipe_draw_start_count_bias *draw, 437af69d88dSmrg struct pipe_vertex_buffer *vertex_buffer) 438cdc920a0Smrg{ 439af69d88dSmrg memcpy(info, raw_info, sizeof(struct pipe_draw_info)); 4407ec681f3Smrg memcpy(draw, raw_draw, sizeof(struct pipe_draw_start_count_bias)); 4417ec681f3Smrg 4427ec681f3Smrg struct draw_so_target *target = 4437ec681f3Smrg (struct draw_so_target *)indirect->count_from_stream_output; 4447ec681f3Smrg assert(vertex_buffer != NULL); 4457ec681f3Smrg draw->count = vertex_buffer->stride == 0 ? 0 : 4467ec681f3Smrg target->internal_offset / vertex_buffer->stride; 4477ec681f3Smrg 4487ec681f3Smrg /* Stream output draw can not be indexed */ 4497ec681f3Smrg debug_assert(!info->index_size); 4507ec681f3Smrg info->max_index = draw->count - 1; 4517ec681f3Smrg} 4527ec681f3Smrg 4537ec681f3Smrg/* 4547ec681f3Smrg * Loop over all instances and execute draws for them. 4557ec681f3Smrg */ 4567ec681f3Smrgstatic void 4577ec681f3Smrgdraw_instances(struct draw_context *draw, 4587ec681f3Smrg unsigned drawid_offset, 4597ec681f3Smrg const struct pipe_draw_info *info, 4607ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 4617ec681f3Smrg unsigned num_draws) 4627ec681f3Smrg{ 4637ec681f3Smrg unsigned instance; 4643464ebd5Sriastradh 4657ec681f3Smrg draw->start_instance = info->start_instance; 4663464ebd5Sriastradh 4677ec681f3Smrg for (instance = 0; instance < info->instance_count; instance++) { 4687ec681f3Smrg unsigned instance_idx = instance + info->start_instance; 4697ec681f3Smrg draw->instance_id = instance; 4707ec681f3Smrg /* check for overflow */ 4717ec681f3Smrg if (instance_idx < instance || 4727ec681f3Smrg instance_idx < draw->start_instance) { 4737ec681f3Smrg /* if we overflown just set the instance id to the max */ 4747ec681f3Smrg draw->instance_id = 0xffffffff; 4757ec681f3Smrg } 4767ec681f3Smrg 4777ec681f3Smrg draw->pt.user.drawid = drawid_offset; 4787ec681f3Smrg draw_new_instance(draw); 4797ec681f3Smrg 4807ec681f3Smrg if (info->primitive_restart) { 4817ec681f3Smrg draw_pt_arrays_restart(draw, info, draws, num_draws); 4827ec681f3Smrg } 4837ec681f3Smrg else { 4847ec681f3Smrg draw_pt_arrays(draw, info->mode, info->index_bias_varies, draws, num_draws); 4857ec681f3Smrg } 4863464ebd5Sriastradh } 4873464ebd5Sriastradh} 4883464ebd5Sriastradh 4893464ebd5Sriastradh/** 4903464ebd5Sriastradh * Draw vertex arrays. 4913464ebd5Sriastradh * This is the main entrypoint into the drawing module. If drawing an indexed 492af69d88dSmrg * primitive, the draw_set_indexes() function should have already been called 493af69d88dSmrg * to specify the element/index buffer information. 4943464ebd5Sriastradh */ 4953464ebd5Sriastradhvoid 4963464ebd5Sriastradhdraw_vbo(struct draw_context *draw, 4977ec681f3Smrg const struct pipe_draw_info *info, 4987ec681f3Smrg unsigned drawid_offset, 4997ec681f3Smrg const struct pipe_draw_indirect_info *indirect, 5007ec681f3Smrg const struct pipe_draw_start_count_bias *draws, 5017ec681f3Smrg unsigned num_draws, 5027ec681f3Smrg uint8_t patch_vertices) 5033464ebd5Sriastradh{ 504af69d88dSmrg unsigned index_limit; 505af69d88dSmrg unsigned fpstate = util_fpstate_get(); 506af69d88dSmrg struct pipe_draw_info resolved_info; 5077ec681f3Smrg struct pipe_draw_start_count_bias resolved_draw; 5087ec681f3Smrg struct pipe_draw_info *use_info = (struct pipe_draw_info *)info; 5097ec681f3Smrg struct pipe_draw_start_count_bias *use_draws = (struct pipe_draw_start_count_bias *)draws; 510af69d88dSmrg 511361fc4cbSmaya if (info->instance_count == 0) 512361fc4cbSmaya return; 513361fc4cbSmaya 514af69d88dSmrg /* Make sure that denorms are treated like zeros. This is 515af69d88dSmrg * the behavior required by D3D10. OpenGL doesn't care. 516af69d88dSmrg */ 517af69d88dSmrg util_fpstate_set_denorms_to_zero(fpstate); 518af69d88dSmrg 5197ec681f3Smrg if (indirect && indirect->count_from_stream_output) { 5207ec681f3Smrg resolve_draw_info(info, indirect, &draws[0], &resolved_info, 5217ec681f3Smrg &resolved_draw, &(draw->pt.vertex_buffer[0])); 5227ec681f3Smrg use_info = &resolved_info; 5237ec681f3Smrg use_draws = &resolved_draw; 5247ec681f3Smrg num_draws = 1; 5257ec681f3Smrg } 526cdc920a0Smrg 52701e04c3fSmrg if (info->index_size) 5283464ebd5Sriastradh assert(draw->pt.user.elts); 5293464ebd5Sriastradh 5307ec681f3Smrg draw->pt.user.min_index = use_info->index_bounds_valid ? use_info->min_index : 0; 5317ec681f3Smrg draw->pt.user.max_index = use_info->index_bounds_valid ? use_info->max_index : ~0; 5327ec681f3Smrg draw->pt.user.eltSize = use_info->index_size ? draw->pt.user.eltSizeIB : 0; 5337ec681f3Smrg draw->pt.user.drawid = drawid_offset; 5347ec681f3Smrg draw->pt.user.increment_draw_id = use_info->increment_draw_id; 5357ec681f3Smrg draw->pt.user.viewid = 0; 5367ec681f3Smrg draw->pt.vertices_per_patch = patch_vertices; 5373464ebd5Sriastradh 5387ec681f3Smrg if (0) { 5397ec681f3Smrg for (unsigned i = 0; i < num_draws; i++) 5407ec681f3Smrg debug_printf("draw_vbo(mode=%u start=%u count=%u):\n", 5417ec681f3Smrg use_info->mode, use_draws[i].start, use_draws[i].count); 5427ec681f3Smrg } 5434a49301eSmrg 5443464ebd5Sriastradh if (0) 5454a49301eSmrg tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); 5463464ebd5Sriastradh 5473464ebd5Sriastradh if (0) { 5483464ebd5Sriastradh unsigned int i; 5494a49301eSmrg debug_printf("Elements:\n"); 5504a49301eSmrg for (i = 0; i < draw->pt.nr_vertex_elements; i++) { 5513464ebd5Sriastradh debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n", 5523464ebd5Sriastradh i, 5533464ebd5Sriastradh draw->pt.vertex_element[i].src_offset, 5543464ebd5Sriastradh draw->pt.vertex_element[i].instance_divisor, 5553464ebd5Sriastradh draw->pt.vertex_element[i].vertex_buffer_index, 5563464ebd5Sriastradh util_format_name(draw->pt.vertex_element[i].src_format)); 5574a49301eSmrg } 5584a49301eSmrg debug_printf("Buffers:\n"); 5594a49301eSmrg for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { 560af69d88dSmrg debug_printf(" %u: stride=%u offset=%u size=%d ptr=%p\n", 5613464ebd5Sriastradh i, 5624a49301eSmrg draw->pt.vertex_buffer[i].stride, 5634a49301eSmrg draw->pt.vertex_buffer[i].buffer_offset, 564af69d88dSmrg (int) draw->pt.user.vbuffer[i].size, 565af69d88dSmrg draw->pt.user.vbuffer[i].map); 5664a49301eSmrg } 5674a49301eSmrg } 5684a49301eSmrg 5697ec681f3Smrg if (0) { 5707ec681f3Smrg for (unsigned i = 0; i < num_draws; i++) 5717ec681f3Smrg draw_print_arrays(draw, use_info->mode, use_draws[i].start, MIN2(use_draws[i].count, 20), 5727ec681f3Smrg use_info->index_bias_varies ? use_draws[i].index_bias : use_draws[0].index_bias); 5737ec681f3Smrg } 5743464ebd5Sriastradh 575af69d88dSmrg index_limit = util_draw_max_index(draw->pt.vertex_buffer, 576af69d88dSmrg draw->pt.vertex_element, 577af69d88dSmrg draw->pt.nr_vertex_elements, 5787ec681f3Smrg use_info); 5797ec681f3Smrg#ifdef DRAW_LLVM_AVAILABLE 580af69d88dSmrg if (!draw->llvm) 581af69d88dSmrg#endif 582af69d88dSmrg { 583af69d88dSmrg if (index_limit == 0) { 58401e04c3fSmrg /* one of the buffers is too small to do any valid drawing */ 585af69d88dSmrg debug_warning("draw: VBO too small to draw anything\n"); 586af69d88dSmrg util_fpstate_set(fpstate); 587af69d88dSmrg return; 588af69d88dSmrg } 589af69d88dSmrg } 590af69d88dSmrg 591af69d88dSmrg /* If we're collecting stats then make sure we start from scratch */ 592af69d88dSmrg if (draw->collect_statistics) { 593af69d88dSmrg memset(&draw->statistics, 0, sizeof(draw->statistics)); 594af69d88dSmrg } 595af69d88dSmrg 596af69d88dSmrg draw->pt.max_index = index_limit - 1; 5977ec681f3Smrg draw->start_index = use_draws[0].start; 5983464ebd5Sriastradh 5993464ebd5Sriastradh /* 6003464ebd5Sriastradh * TODO: We could use draw->pt.max_index to further narrow 6017ec681f3Smrg * the min_index/max_index hints given by gallium frontends. 6023464ebd5Sriastradh */ 6033464ebd5Sriastradh 6047ec681f3Smrg if (use_info->view_mask) { 6057ec681f3Smrg u_foreach_bit(i, use_info->view_mask) { 6067ec681f3Smrg draw->pt.user.viewid = i; 6077ec681f3Smrg draw_instances(draw, drawid_offset, use_info, use_draws, num_draws); 608af69d88dSmrg } 6097ec681f3Smrg } else 6107ec681f3Smrg draw_instances(draw, drawid_offset, use_info, use_draws, num_draws); 611af69d88dSmrg 612af69d88dSmrg /* If requested emit the pipeline statistics for this run */ 613af69d88dSmrg if (draw->collect_statistics) { 614af69d88dSmrg draw->render->pipeline_statistics(draw->render, &draw->statistics); 615af69d88dSmrg } 616af69d88dSmrg util_fpstate_set(fpstate); 6174a49301eSmrg} 618