17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2020 Advanced Micro Devices, Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg/* Draw function marshalling for glthread. 257ec681f3Smrg * 267ec681f3Smrg * The purpose of these glDraw wrappers is to upload non-VBO vertex and 277ec681f3Smrg * index data, so that glthread doesn't have to execute synchronously. 287ec681f3Smrg */ 297ec681f3Smrg 307ec681f3Smrg#include "c99_alloca.h" 317ec681f3Smrg 327ec681f3Smrg#include "main/glthread_marshal.h" 337ec681f3Smrg#include "main/dispatch.h" 347ec681f3Smrg#include "main/varray.h" 357ec681f3Smrg 367ec681f3Smrgstatic inline unsigned 377ec681f3Smrgget_index_size(GLenum type) 387ec681f3Smrg{ 397ec681f3Smrg /* GL_UNSIGNED_BYTE - GL_UNSIGNED_BYTE = 0 407ec681f3Smrg * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2 417ec681f3Smrg * GL_UNSIGNED_INT - GL_UNSIGNED_BYTE = 4 427ec681f3Smrg * 437ec681f3Smrg * Divide by 2 to get n=0,1,2, then the index size is: 1 << n 447ec681f3Smrg */ 457ec681f3Smrg return 1 << ((type - GL_UNSIGNED_BYTE) >> 1); 467ec681f3Smrg} 477ec681f3Smrg 487ec681f3Smrgstatic inline bool 497ec681f3Smrgis_index_type_valid(GLenum type) 507ec681f3Smrg{ 517ec681f3Smrg /* GL_UNSIGNED_BYTE = 0x1401 527ec681f3Smrg * GL_UNSIGNED_SHORT = 0x1403 537ec681f3Smrg * GL_UNSIGNED_INT = 0x1405 547ec681f3Smrg * 557ec681f3Smrg * The trick is that bit 1 and bit 2 mean USHORT and UINT, respectively. 567ec681f3Smrg * After clearing those two bits (with ~6), we should get UBYTE. 577ec681f3Smrg * Both bits can't be set, because the enum would be greater than UINT. 587ec681f3Smrg */ 597ec681f3Smrg return type <= GL_UNSIGNED_INT && (type & ~6) == GL_UNSIGNED_BYTE; 607ec681f3Smrg} 617ec681f3Smrg 627ec681f3Smrgstatic ALWAYS_INLINE struct gl_buffer_object * 637ec681f3Smrgupload_indices(struct gl_context *ctx, unsigned count, unsigned index_size, 647ec681f3Smrg const GLvoid **indices) 657ec681f3Smrg{ 667ec681f3Smrg struct gl_buffer_object *upload_buffer = NULL; 677ec681f3Smrg unsigned upload_offset = 0; 687ec681f3Smrg 697ec681f3Smrg assert(count); 707ec681f3Smrg 717ec681f3Smrg _mesa_glthread_upload(ctx, *indices, index_size * count, 727ec681f3Smrg &upload_offset, &upload_buffer, NULL); 737ec681f3Smrg assert(upload_buffer); 747ec681f3Smrg *indices = (const GLvoid*)(intptr_t)upload_offset; 757ec681f3Smrg 767ec681f3Smrg return upload_buffer; 777ec681f3Smrg} 787ec681f3Smrg 797ec681f3Smrgstatic ALWAYS_INLINE struct gl_buffer_object * 807ec681f3Smrgupload_multi_indices(struct gl_context *ctx, unsigned total_count, 817ec681f3Smrg unsigned index_size, unsigned draw_count, 827ec681f3Smrg const GLsizei *count, const GLvoid *const *indices, 837ec681f3Smrg const GLvoid **out_indices) 847ec681f3Smrg{ 857ec681f3Smrg struct gl_buffer_object *upload_buffer = NULL; 867ec681f3Smrg unsigned upload_offset = 0; 877ec681f3Smrg uint8_t *upload_ptr = NULL; 887ec681f3Smrg 897ec681f3Smrg assert(total_count); 907ec681f3Smrg 917ec681f3Smrg _mesa_glthread_upload(ctx, NULL, index_size * total_count, 927ec681f3Smrg &upload_offset, &upload_buffer, &upload_ptr); 937ec681f3Smrg assert(upload_buffer); 947ec681f3Smrg 957ec681f3Smrg for (unsigned i = 0, offset = 0; i < draw_count; i++) { 967ec681f3Smrg if (count[i] == 0) 977ec681f3Smrg continue; 987ec681f3Smrg 997ec681f3Smrg unsigned size = count[i] * index_size; 1007ec681f3Smrg 1017ec681f3Smrg memcpy(upload_ptr + offset, indices[i], size); 1027ec681f3Smrg out_indices[i] = (const GLvoid*)(intptr_t)(upload_offset + offset); 1037ec681f3Smrg offset += size; 1047ec681f3Smrg } 1057ec681f3Smrg 1067ec681f3Smrg return upload_buffer; 1077ec681f3Smrg} 1087ec681f3Smrg 1097ec681f3Smrgstatic ALWAYS_INLINE bool 1107ec681f3Smrgupload_vertices(struct gl_context *ctx, unsigned user_buffer_mask, 1117ec681f3Smrg unsigned start_vertex, unsigned num_vertices, 1127ec681f3Smrg unsigned start_instance, unsigned num_instances, 1137ec681f3Smrg struct glthread_attrib_binding *buffers) 1147ec681f3Smrg{ 1157ec681f3Smrg struct glthread_vao *vao = ctx->GLThread.CurrentVAO; 1167ec681f3Smrg unsigned attrib_mask_iter = vao->Enabled; 1177ec681f3Smrg unsigned num_buffers = 0; 1187ec681f3Smrg 1197ec681f3Smrg assert((num_vertices || !(user_buffer_mask & ~vao->NonZeroDivisorMask)) && 1207ec681f3Smrg (num_instances || !(user_buffer_mask & vao->NonZeroDivisorMask))); 1217ec681f3Smrg 1227ec681f3Smrg if (unlikely(vao->BufferInterleaved & user_buffer_mask)) { 1237ec681f3Smrg /* Slower upload path where some buffers reference multiple attribs, 1247ec681f3Smrg * so we have to use 2 while loops instead of 1. 1257ec681f3Smrg */ 1267ec681f3Smrg unsigned start_offset[VERT_ATTRIB_MAX]; 1277ec681f3Smrg unsigned end_offset[VERT_ATTRIB_MAX]; 1287ec681f3Smrg uint32_t buffer_mask = 0; 1297ec681f3Smrg 1307ec681f3Smrg while (attrib_mask_iter) { 1317ec681f3Smrg unsigned i = u_bit_scan(&attrib_mask_iter); 1327ec681f3Smrg unsigned binding_index = vao->Attrib[i].BufferIndex; 1337ec681f3Smrg 1347ec681f3Smrg if (!(user_buffer_mask & (1 << binding_index))) 1357ec681f3Smrg continue; 1367ec681f3Smrg 1377ec681f3Smrg unsigned stride = vao->Attrib[binding_index].Stride; 1387ec681f3Smrg unsigned instance_div = vao->Attrib[binding_index].Divisor; 1397ec681f3Smrg unsigned element_size = vao->Attrib[i].ElementSize; 1407ec681f3Smrg unsigned offset = vao->Attrib[i].RelativeOffset; 1417ec681f3Smrg unsigned size; 1427ec681f3Smrg 1437ec681f3Smrg if (instance_div) { 1447ec681f3Smrg /* Per-instance attrib. */ 1457ec681f3Smrg 1467ec681f3Smrg /* Figure out how many instances we'll render given instance_div. We 1477ec681f3Smrg * can't use the typical div_round_up() pattern because the CTS uses 1487ec681f3Smrg * instance_div = ~0 for a test, which overflows div_round_up()'s 1497ec681f3Smrg * addition. 1507ec681f3Smrg */ 1517ec681f3Smrg unsigned count = num_instances / instance_div; 1527ec681f3Smrg if (count * instance_div != num_instances) 1537ec681f3Smrg count++; 1547ec681f3Smrg 1557ec681f3Smrg offset += stride * start_instance; 1567ec681f3Smrg size = stride * (count - 1) + element_size; 1577ec681f3Smrg } else { 1587ec681f3Smrg /* Per-vertex attrib. */ 1597ec681f3Smrg offset += stride * start_vertex; 1607ec681f3Smrg size = stride * (num_vertices - 1) + element_size; 1617ec681f3Smrg } 1627ec681f3Smrg 1637ec681f3Smrg unsigned binding_index_bit = 1u << binding_index; 1647ec681f3Smrg 1657ec681f3Smrg /* Update upload offsets. */ 1667ec681f3Smrg if (!(buffer_mask & binding_index_bit)) { 1677ec681f3Smrg start_offset[binding_index] = offset; 1687ec681f3Smrg end_offset[binding_index] = offset + size; 1697ec681f3Smrg } else { 1707ec681f3Smrg if (offset < start_offset[binding_index]) 1717ec681f3Smrg start_offset[binding_index] = offset; 1727ec681f3Smrg if (offset + size > end_offset[binding_index]) 1737ec681f3Smrg end_offset[binding_index] = offset + size; 1747ec681f3Smrg } 1757ec681f3Smrg 1767ec681f3Smrg buffer_mask |= binding_index_bit; 1777ec681f3Smrg } 1787ec681f3Smrg 1797ec681f3Smrg /* Upload buffers. */ 1807ec681f3Smrg while (buffer_mask) { 1817ec681f3Smrg struct gl_buffer_object *upload_buffer = NULL; 1827ec681f3Smrg unsigned upload_offset = 0; 1837ec681f3Smrg unsigned start, end; 1847ec681f3Smrg 1857ec681f3Smrg unsigned binding_index = u_bit_scan(&buffer_mask); 1867ec681f3Smrg 1877ec681f3Smrg start = start_offset[binding_index]; 1887ec681f3Smrg end = end_offset[binding_index]; 1897ec681f3Smrg assert(start < end); 1907ec681f3Smrg 1917ec681f3Smrg const void *ptr = vao->Attrib[binding_index].Pointer; 1927ec681f3Smrg _mesa_glthread_upload(ctx, (uint8_t*)ptr + start, 1937ec681f3Smrg end - start, &upload_offset, 1947ec681f3Smrg &upload_buffer, NULL); 1957ec681f3Smrg assert(upload_buffer); 1967ec681f3Smrg 1977ec681f3Smrg buffers[num_buffers].buffer = upload_buffer; 1987ec681f3Smrg buffers[num_buffers].offset = upload_offset - start; 1997ec681f3Smrg buffers[num_buffers].original_pointer = ptr; 2007ec681f3Smrg num_buffers++; 2017ec681f3Smrg } 2027ec681f3Smrg 2037ec681f3Smrg return true; 2047ec681f3Smrg } 2057ec681f3Smrg 2067ec681f3Smrg /* Faster path where all attribs are separate. */ 2077ec681f3Smrg while (attrib_mask_iter) { 2087ec681f3Smrg unsigned i = u_bit_scan(&attrib_mask_iter); 2097ec681f3Smrg unsigned binding_index = vao->Attrib[i].BufferIndex; 2107ec681f3Smrg 2117ec681f3Smrg if (!(user_buffer_mask & (1 << binding_index))) 2127ec681f3Smrg continue; 2137ec681f3Smrg 2147ec681f3Smrg struct gl_buffer_object *upload_buffer = NULL; 2157ec681f3Smrg unsigned upload_offset = 0; 2167ec681f3Smrg unsigned stride = vao->Attrib[binding_index].Stride; 2177ec681f3Smrg unsigned instance_div = vao->Attrib[binding_index].Divisor; 2187ec681f3Smrg unsigned element_size = vao->Attrib[i].ElementSize; 2197ec681f3Smrg unsigned offset = vao->Attrib[i].RelativeOffset; 2207ec681f3Smrg unsigned size; 2217ec681f3Smrg 2227ec681f3Smrg if (instance_div) { 2237ec681f3Smrg /* Per-instance attrib. */ 2247ec681f3Smrg 2257ec681f3Smrg /* Figure out how many instances we'll render given instance_div. We 2267ec681f3Smrg * can't use the typical div_round_up() pattern because the CTS uses 2277ec681f3Smrg * instance_div = ~0 for a test, which overflows div_round_up()'s 2287ec681f3Smrg * addition. 2297ec681f3Smrg */ 2307ec681f3Smrg unsigned count = num_instances / instance_div; 2317ec681f3Smrg if (count * instance_div != num_instances) 2327ec681f3Smrg count++; 2337ec681f3Smrg 2347ec681f3Smrg offset += stride * start_instance; 2357ec681f3Smrg size = stride * (count - 1) + element_size; 2367ec681f3Smrg } else { 2377ec681f3Smrg /* Per-vertex attrib. */ 2387ec681f3Smrg offset += stride * start_vertex; 2397ec681f3Smrg size = stride * (num_vertices - 1) + element_size; 2407ec681f3Smrg } 2417ec681f3Smrg 2427ec681f3Smrg const void *ptr = vao->Attrib[binding_index].Pointer; 2437ec681f3Smrg _mesa_glthread_upload(ctx, (uint8_t*)ptr + offset, 2447ec681f3Smrg size, &upload_offset, &upload_buffer, NULL); 2457ec681f3Smrg assert(upload_buffer); 2467ec681f3Smrg 2477ec681f3Smrg buffers[num_buffers].buffer = upload_buffer; 2487ec681f3Smrg buffers[num_buffers].offset = upload_offset - offset; 2497ec681f3Smrg buffers[num_buffers].original_pointer = ptr; 2507ec681f3Smrg num_buffers++; 2517ec681f3Smrg } 2527ec681f3Smrg 2537ec681f3Smrg return true; 2547ec681f3Smrg} 2557ec681f3Smrg 2567ec681f3Smrg/* Generic DrawArrays structure NOT supporting user buffers. Ignore the name. */ 2577ec681f3Smrgstruct marshal_cmd_DrawArrays 2587ec681f3Smrg{ 2597ec681f3Smrg struct marshal_cmd_base cmd_base; 2607ec681f3Smrg GLenum mode; 2617ec681f3Smrg GLint first; 2627ec681f3Smrg GLsizei count; 2637ec681f3Smrg GLsizei instance_count; 2647ec681f3Smrg GLuint baseinstance; 2657ec681f3Smrg}; 2667ec681f3Smrg 2677ec681f3Smrguint32_t 2687ec681f3Smrg_mesa_unmarshal_DrawArrays(struct gl_context *ctx, 2697ec681f3Smrg const struct marshal_cmd_DrawArrays *cmd, 2707ec681f3Smrg const uint64_t *last) 2717ec681f3Smrg{ 2727ec681f3Smrg /* Ignore the function name. We use DISPATCH_CMD_DrawArrays 2737ec681f3Smrg * for all DrawArrays variants without user buffers, and 2747ec681f3Smrg * DISPATCH_CMD_DrawArraysInstancedBaseInstance for all DrawArrays 2757ec681f3Smrg * variants with user buffrs. 2767ec681f3Smrg */ 2777ec681f3Smrg const GLenum mode = cmd->mode; 2787ec681f3Smrg const GLint first = cmd->first; 2797ec681f3Smrg const GLsizei count = cmd->count; 2807ec681f3Smrg const GLsizei instance_count = cmd->instance_count; 2817ec681f3Smrg const GLuint baseinstance = cmd->baseinstance; 2827ec681f3Smrg 2837ec681f3Smrg CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch, 2847ec681f3Smrg (mode, first, count, instance_count, 2857ec681f3Smrg baseinstance)); 2867ec681f3Smrg return cmd->cmd_base.cmd_size; 2877ec681f3Smrg} 2887ec681f3Smrg 2897ec681f3Smrgstatic ALWAYS_INLINE void 2907ec681f3Smrgdraw_arrays_async(struct gl_context *ctx, GLenum mode, GLint first, 2917ec681f3Smrg GLsizei count, GLsizei instance_count, GLuint baseinstance) 2927ec681f3Smrg{ 2937ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_DrawArrays); 2947ec681f3Smrg struct marshal_cmd_DrawArrays *cmd = 2957ec681f3Smrg _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArrays, cmd_size); 2967ec681f3Smrg 2977ec681f3Smrg cmd->mode = mode; 2987ec681f3Smrg cmd->first = first; 2997ec681f3Smrg cmd->count = count; 3007ec681f3Smrg cmd->instance_count = instance_count; 3017ec681f3Smrg cmd->baseinstance = baseinstance; 3027ec681f3Smrg} 3037ec681f3Smrg 3047ec681f3Smrg/* Generic DrawArrays structure supporting user buffers. Ignore the name. */ 3057ec681f3Smrgstruct marshal_cmd_DrawArraysInstancedBaseInstance 3067ec681f3Smrg{ 3077ec681f3Smrg struct marshal_cmd_base cmd_base; 3087ec681f3Smrg GLenum mode; 3097ec681f3Smrg GLint first; 3107ec681f3Smrg GLsizei count; 3117ec681f3Smrg GLsizei instance_count; 3127ec681f3Smrg GLuint baseinstance; 3137ec681f3Smrg GLuint user_buffer_mask; 3147ec681f3Smrg}; 3157ec681f3Smrg 3167ec681f3Smrguint32_t 3177ec681f3Smrg_mesa_unmarshal_DrawArraysInstancedBaseInstance(struct gl_context *ctx, 3187ec681f3Smrg const struct marshal_cmd_DrawArraysInstancedBaseInstance *cmd, 3197ec681f3Smrg const uint64_t *last) 3207ec681f3Smrg{ 3217ec681f3Smrg /* Ignore the function name. We use DISPATCH_CMD_DrawArrays 3227ec681f3Smrg * for all DrawArrays variants without user buffers, and 3237ec681f3Smrg * DISPATCH_CMD_DrawArraysInstancedBaseInstance for all DrawArrays 3247ec681f3Smrg * variants with user buffrs. 3257ec681f3Smrg */ 3267ec681f3Smrg const GLenum mode = cmd->mode; 3277ec681f3Smrg const GLint first = cmd->first; 3287ec681f3Smrg const GLsizei count = cmd->count; 3297ec681f3Smrg const GLsizei instance_count = cmd->instance_count; 3307ec681f3Smrg const GLuint baseinstance = cmd->baseinstance; 3317ec681f3Smrg const GLuint user_buffer_mask = cmd->user_buffer_mask; 3327ec681f3Smrg const struct glthread_attrib_binding *buffers = 3337ec681f3Smrg (const struct glthread_attrib_binding *)(cmd + 1); 3347ec681f3Smrg 3357ec681f3Smrg /* Bind uploaded buffers if needed. */ 3367ec681f3Smrg if (user_buffer_mask) { 3377ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 3387ec681f3Smrg false); 3397ec681f3Smrg } 3407ec681f3Smrg 3417ec681f3Smrg CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch, 3427ec681f3Smrg (mode, first, count, instance_count, 3437ec681f3Smrg baseinstance)); 3447ec681f3Smrg 3457ec681f3Smrg /* Restore states. */ 3467ec681f3Smrg if (user_buffer_mask) { 3477ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 3487ec681f3Smrg true); 3497ec681f3Smrg } 3507ec681f3Smrg return cmd->cmd_base.cmd_size; 3517ec681f3Smrg} 3527ec681f3Smrg 3537ec681f3Smrgstatic ALWAYS_INLINE void 3547ec681f3Smrgdraw_arrays_async_user(struct gl_context *ctx, GLenum mode, GLint first, 3557ec681f3Smrg GLsizei count, GLsizei instance_count, GLuint baseinstance, 3567ec681f3Smrg unsigned user_buffer_mask, 3577ec681f3Smrg const struct glthread_attrib_binding *buffers) 3587ec681f3Smrg{ 3597ec681f3Smrg int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]); 3607ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_DrawArraysInstancedBaseInstance) + 3617ec681f3Smrg buffers_size; 3627ec681f3Smrg struct marshal_cmd_DrawArraysInstancedBaseInstance *cmd; 3637ec681f3Smrg 3647ec681f3Smrg cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawArraysInstancedBaseInstance, 3657ec681f3Smrg cmd_size); 3667ec681f3Smrg cmd->mode = mode; 3677ec681f3Smrg cmd->first = first; 3687ec681f3Smrg cmd->count = count; 3697ec681f3Smrg cmd->instance_count = instance_count; 3707ec681f3Smrg cmd->baseinstance = baseinstance; 3717ec681f3Smrg cmd->user_buffer_mask = user_buffer_mask; 3727ec681f3Smrg 3737ec681f3Smrg if (user_buffer_mask) 3747ec681f3Smrg memcpy(cmd + 1, buffers, buffers_size); 3757ec681f3Smrg} 3767ec681f3Smrg 3777ec681f3Smrgstatic ALWAYS_INLINE void 3787ec681f3Smrgdraw_arrays(GLenum mode, GLint first, GLsizei count, GLsizei instance_count, 3797ec681f3Smrg GLuint baseinstance, bool compiled_into_dlist) 3807ec681f3Smrg{ 3817ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 3827ec681f3Smrg 3837ec681f3Smrg struct glthread_vao *vao = ctx->GLThread.CurrentVAO; 3847ec681f3Smrg unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled; 3857ec681f3Smrg 3867ec681f3Smrg if (compiled_into_dlist && ctx->GLThread.ListMode) { 3877ec681f3Smrg _mesa_glthread_finish_before(ctx, "DrawArrays"); 3887ec681f3Smrg /* Use the function that's compiled into a display list. */ 3897ec681f3Smrg CALL_DrawArrays(ctx->CurrentServerDispatch, (mode, first, count)); 3907ec681f3Smrg return; 3917ec681f3Smrg } 3927ec681f3Smrg 3937ec681f3Smrg /* Fast path when nothing needs to be done. 3947ec681f3Smrg * 3957ec681f3Smrg * This is also an error path. Zero counts should still call the driver 3967ec681f3Smrg * for possible GL errors. 3977ec681f3Smrg */ 3987ec681f3Smrg if (ctx->API == API_OPENGL_CORE || !user_buffer_mask || 3997ec681f3Smrg count <= 0 || instance_count <= 0) { 4007ec681f3Smrg draw_arrays_async(ctx, mode, first, count, instance_count, baseinstance); 4017ec681f3Smrg return; 4027ec681f3Smrg } 4037ec681f3Smrg 4047ec681f3Smrg /* Upload and draw. */ 4057ec681f3Smrg struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX]; 4067ec681f3Smrg if (!ctx->GLThread.SupportsNonVBOUploads || 4077ec681f3Smrg !upload_vertices(ctx, user_buffer_mask, first, count, baseinstance, 4087ec681f3Smrg instance_count, buffers)) { 4097ec681f3Smrg _mesa_glthread_finish_before(ctx, "DrawArrays"); 4107ec681f3Smrg CALL_DrawArraysInstancedBaseInstance(ctx->CurrentServerDispatch, 4117ec681f3Smrg (mode, first, count, instance_count, 4127ec681f3Smrg baseinstance)); 4137ec681f3Smrg return; 4147ec681f3Smrg } 4157ec681f3Smrg 4167ec681f3Smrg draw_arrays_async_user(ctx, mode, first, count, instance_count, baseinstance, 4177ec681f3Smrg user_buffer_mask, buffers); 4187ec681f3Smrg} 4197ec681f3Smrg 4207ec681f3Smrgstruct marshal_cmd_MultiDrawArrays 4217ec681f3Smrg{ 4227ec681f3Smrg struct marshal_cmd_base cmd_base; 4237ec681f3Smrg GLenum mode; 4247ec681f3Smrg GLsizei draw_count; 4257ec681f3Smrg GLuint user_buffer_mask; 4267ec681f3Smrg}; 4277ec681f3Smrg 4287ec681f3Smrguint32_t 4297ec681f3Smrg_mesa_unmarshal_MultiDrawArrays(struct gl_context *ctx, 4307ec681f3Smrg const struct marshal_cmd_MultiDrawArrays *cmd, 4317ec681f3Smrg const uint64_t *last) 4327ec681f3Smrg{ 4337ec681f3Smrg const GLenum mode = cmd->mode; 4347ec681f3Smrg const GLsizei draw_count = cmd->draw_count; 4357ec681f3Smrg const GLuint user_buffer_mask = cmd->user_buffer_mask; 4367ec681f3Smrg 4377ec681f3Smrg const char *variable_data = (const char *)(cmd + 1); 4387ec681f3Smrg const GLint *first = (GLint *)variable_data; 4397ec681f3Smrg variable_data += sizeof(GLint) * draw_count; 4407ec681f3Smrg const GLsizei *count = (GLsizei *)variable_data; 4417ec681f3Smrg variable_data += sizeof(GLsizei) * draw_count; 4427ec681f3Smrg const struct glthread_attrib_binding *buffers = 4437ec681f3Smrg (const struct glthread_attrib_binding *)variable_data; 4447ec681f3Smrg 4457ec681f3Smrg /* Bind uploaded buffers if needed. */ 4467ec681f3Smrg if (user_buffer_mask) { 4477ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 4487ec681f3Smrg false); 4497ec681f3Smrg } 4507ec681f3Smrg 4517ec681f3Smrg CALL_MultiDrawArrays(ctx->CurrentServerDispatch, 4527ec681f3Smrg (mode, first, count, draw_count)); 4537ec681f3Smrg 4547ec681f3Smrg /* Restore states. */ 4557ec681f3Smrg if (user_buffer_mask) { 4567ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 4577ec681f3Smrg true); 4587ec681f3Smrg } 4597ec681f3Smrg return cmd->cmd_base.cmd_size; 4607ec681f3Smrg} 4617ec681f3Smrg 4627ec681f3Smrgstatic ALWAYS_INLINE void 4637ec681f3Smrgmulti_draw_arrays_async(struct gl_context *ctx, GLenum mode, 4647ec681f3Smrg const GLint *first, const GLsizei *count, 4657ec681f3Smrg GLsizei draw_count, unsigned user_buffer_mask, 4667ec681f3Smrg const struct glthread_attrib_binding *buffers) 4677ec681f3Smrg{ 4687ec681f3Smrg int first_size = sizeof(GLint) * draw_count; 4697ec681f3Smrg int count_size = sizeof(GLsizei) * draw_count; 4707ec681f3Smrg int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]); 4717ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_MultiDrawArrays) + 4727ec681f3Smrg first_size + count_size + buffers_size; 4737ec681f3Smrg struct marshal_cmd_MultiDrawArrays *cmd; 4747ec681f3Smrg 4757ec681f3Smrg cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawArrays, 4767ec681f3Smrg cmd_size); 4777ec681f3Smrg cmd->mode = mode; 4787ec681f3Smrg cmd->draw_count = draw_count; 4797ec681f3Smrg cmd->user_buffer_mask = user_buffer_mask; 4807ec681f3Smrg 4817ec681f3Smrg char *variable_data = (char*)(cmd + 1); 4827ec681f3Smrg memcpy(variable_data, first, first_size); 4837ec681f3Smrg variable_data += first_size; 4847ec681f3Smrg memcpy(variable_data, count, count_size); 4857ec681f3Smrg 4867ec681f3Smrg if (user_buffer_mask) { 4877ec681f3Smrg variable_data += count_size; 4887ec681f3Smrg memcpy(variable_data, buffers, buffers_size); 4897ec681f3Smrg } 4907ec681f3Smrg} 4917ec681f3Smrg 4927ec681f3Smrgvoid GLAPIENTRY 4937ec681f3Smrg_mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first, 4947ec681f3Smrg const GLsizei *count, GLsizei draw_count) 4957ec681f3Smrg{ 4967ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 4977ec681f3Smrg 4987ec681f3Smrg struct glthread_vao *vao = ctx->GLThread.CurrentVAO; 4997ec681f3Smrg unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled; 5007ec681f3Smrg 5017ec681f3Smrg if (ctx->GLThread.ListMode) 5027ec681f3Smrg goto sync; 5037ec681f3Smrg 5047ec681f3Smrg if (draw_count >= 0 && 5057ec681f3Smrg (ctx->API == API_OPENGL_CORE || !user_buffer_mask)) { 5067ec681f3Smrg multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL); 5077ec681f3Smrg return; 5087ec681f3Smrg } 5097ec681f3Smrg 5107ec681f3Smrg /* If the draw count is too high or negative, the queue can't be used. */ 5117ec681f3Smrg if (!ctx->GLThread.SupportsNonVBOUploads || 5127ec681f3Smrg draw_count < 0 || draw_count > MARSHAL_MAX_CMD_SIZE / 16) 5137ec681f3Smrg goto sync; 5147ec681f3Smrg 5157ec681f3Smrg unsigned min_index = ~0; 5167ec681f3Smrg unsigned max_index_exclusive = 0; 5177ec681f3Smrg 5187ec681f3Smrg for (unsigned i = 0; i < draw_count; i++) { 5197ec681f3Smrg GLsizei vertex_count = count[i]; 5207ec681f3Smrg 5217ec681f3Smrg if (vertex_count < 0) { 5227ec681f3Smrg /* Just call the driver to set the error. */ 5237ec681f3Smrg multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL); 5247ec681f3Smrg return; 5257ec681f3Smrg } 5267ec681f3Smrg if (vertex_count == 0) 5277ec681f3Smrg continue; 5287ec681f3Smrg 5297ec681f3Smrg min_index = MIN2(min_index, first[i]); 5307ec681f3Smrg max_index_exclusive = MAX2(max_index_exclusive, first[i] + vertex_count); 5317ec681f3Smrg } 5327ec681f3Smrg 5337ec681f3Smrg unsigned num_vertices = max_index_exclusive - min_index; 5347ec681f3Smrg if (num_vertices == 0) { 5357ec681f3Smrg /* Nothing to do, but call the driver to set possible GL errors. */ 5367ec681f3Smrg multi_draw_arrays_async(ctx, mode, first, count, draw_count, 0, NULL); 5377ec681f3Smrg return; 5387ec681f3Smrg } 5397ec681f3Smrg 5407ec681f3Smrg /* Upload and draw. */ 5417ec681f3Smrg struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX]; 5427ec681f3Smrg if (!upload_vertices(ctx, user_buffer_mask, min_index, num_vertices, 5437ec681f3Smrg 0, 1, buffers)) 5447ec681f3Smrg goto sync; 5457ec681f3Smrg 5467ec681f3Smrg multi_draw_arrays_async(ctx, mode, first, count, draw_count, 5477ec681f3Smrg user_buffer_mask, buffers); 5487ec681f3Smrg return; 5497ec681f3Smrg 5507ec681f3Smrgsync: 5517ec681f3Smrg _mesa_glthread_finish_before(ctx, "MultiDrawArrays"); 5527ec681f3Smrg CALL_MultiDrawArrays(ctx->CurrentServerDispatch, 5537ec681f3Smrg (mode, first, count, draw_count)); 5547ec681f3Smrg} 5557ec681f3Smrg 5567ec681f3Smrg/* DrawElementsInstancedBaseVertexBaseInstance not supporting user buffers. 5577ec681f3Smrg * Ignore the name. 5587ec681f3Smrg */ 5597ec681f3Smrgstruct marshal_cmd_DrawElementsInstancedARB 5607ec681f3Smrg{ 5617ec681f3Smrg struct marshal_cmd_base cmd_base; 5627ec681f3Smrg GLenum mode; 5637ec681f3Smrg GLenum type; 5647ec681f3Smrg GLsizei count; 5657ec681f3Smrg GLsizei instance_count; 5667ec681f3Smrg GLint basevertex; 5677ec681f3Smrg GLuint baseinstance; 5687ec681f3Smrg const GLvoid *indices; 5697ec681f3Smrg}; 5707ec681f3Smrg 5717ec681f3Smrguint32_t 5727ec681f3Smrg_mesa_unmarshal_DrawElementsInstancedARB(struct gl_context *ctx, 5737ec681f3Smrg const struct marshal_cmd_DrawElementsInstancedARB *cmd, 5747ec681f3Smrg const uint64_t *last) 5757ec681f3Smrg{ 5767ec681f3Smrg /* Ignore the function name. We use DISPATCH_CMD_DrawElementsInstanced- 5777ec681f3Smrg * BaseVertexBaseInstance for all DrawElements variants with user buffers, 5787ec681f3Smrg * and both DISPATCH_CMD_DrawElementsInstancedARB and DISPATCH_CMD_Draw- 5797ec681f3Smrg * RangeElementsBaseVertex for all draw elements variants without user 5807ec681f3Smrg * buffers. 5817ec681f3Smrg */ 5827ec681f3Smrg const GLenum mode = cmd->mode; 5837ec681f3Smrg const GLsizei count = cmd->count; 5847ec681f3Smrg const GLenum type = cmd->type; 5857ec681f3Smrg const GLvoid *indices = cmd->indices; 5867ec681f3Smrg const GLsizei instance_count = cmd->instance_count; 5877ec681f3Smrg const GLint basevertex = cmd->basevertex; 5887ec681f3Smrg const GLuint baseinstance = cmd->baseinstance; 5897ec681f3Smrg 5907ec681f3Smrg CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch, 5917ec681f3Smrg (mode, count, type, indices, 5927ec681f3Smrg instance_count, basevertex, 5937ec681f3Smrg baseinstance)); 5947ec681f3Smrg return cmd->cmd_base.cmd_size; 5957ec681f3Smrg} 5967ec681f3Smrg 5977ec681f3Smrgstruct marshal_cmd_DrawRangeElementsBaseVertex 5987ec681f3Smrg{ 5997ec681f3Smrg struct marshal_cmd_base cmd_base; 6007ec681f3Smrg GLenum mode; 6017ec681f3Smrg GLenum type; 6027ec681f3Smrg GLsizei count; 6037ec681f3Smrg GLint basevertex; 6047ec681f3Smrg GLuint min_index; 6057ec681f3Smrg GLuint max_index; 6067ec681f3Smrg const GLvoid *indices; 6077ec681f3Smrg}; 6087ec681f3Smrg 6097ec681f3Smrguint32_t 6107ec681f3Smrg_mesa_unmarshal_DrawRangeElementsBaseVertex(struct gl_context *ctx, 6117ec681f3Smrg const struct marshal_cmd_DrawRangeElementsBaseVertex *cmd, 6127ec681f3Smrg const uint64_t *last) 6137ec681f3Smrg{ 6147ec681f3Smrg const GLenum mode = cmd->mode; 6157ec681f3Smrg const GLsizei count = cmd->count; 6167ec681f3Smrg const GLenum type = cmd->type; 6177ec681f3Smrg const GLvoid *indices = cmd->indices; 6187ec681f3Smrg const GLint basevertex = cmd->basevertex; 6197ec681f3Smrg const GLuint min_index = cmd->min_index; 6207ec681f3Smrg const GLuint max_index = cmd->max_index; 6217ec681f3Smrg 6227ec681f3Smrg CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch, 6237ec681f3Smrg (mode, min_index, max_index, count, 6247ec681f3Smrg type, indices, basevertex)); 6257ec681f3Smrg return cmd->cmd_base.cmd_size; 6267ec681f3Smrg} 6277ec681f3Smrg 6287ec681f3Smrgstatic ALWAYS_INLINE void 6297ec681f3Smrgdraw_elements_async(struct gl_context *ctx, GLenum mode, GLsizei count, 6307ec681f3Smrg GLenum type, const GLvoid *indices, GLsizei instance_count, 6317ec681f3Smrg GLint basevertex, GLuint baseinstance, 6327ec681f3Smrg bool index_bounds_valid, GLuint min_index, GLuint max_index) 6337ec681f3Smrg{ 6347ec681f3Smrg if (index_bounds_valid) { 6357ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_DrawRangeElementsBaseVertex); 6367ec681f3Smrg struct marshal_cmd_DrawRangeElementsBaseVertex *cmd = 6377ec681f3Smrg _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawRangeElementsBaseVertex, cmd_size); 6387ec681f3Smrg 6397ec681f3Smrg cmd->mode = mode; 6407ec681f3Smrg cmd->count = count; 6417ec681f3Smrg cmd->type = type; 6427ec681f3Smrg cmd->indices = indices; 6437ec681f3Smrg cmd->basevertex = basevertex; 6447ec681f3Smrg cmd->min_index = min_index; 6457ec681f3Smrg cmd->max_index = max_index; 6467ec681f3Smrg } else { 6477ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedARB); 6487ec681f3Smrg struct marshal_cmd_DrawElementsInstancedARB *cmd = 6497ec681f3Smrg _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedARB, cmd_size); 6507ec681f3Smrg 6517ec681f3Smrg cmd->mode = mode; 6527ec681f3Smrg cmd->count = count; 6537ec681f3Smrg cmd->type = type; 6547ec681f3Smrg cmd->indices = indices; 6557ec681f3Smrg cmd->instance_count = instance_count; 6567ec681f3Smrg cmd->basevertex = basevertex; 6577ec681f3Smrg cmd->baseinstance = baseinstance; 6587ec681f3Smrg } 6597ec681f3Smrg} 6607ec681f3Smrg 6617ec681f3Smrgstruct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance 6627ec681f3Smrg{ 6637ec681f3Smrg struct marshal_cmd_base cmd_base; 6647ec681f3Smrg bool index_bounds_valid; 6657ec681f3Smrg GLenum mode; 6667ec681f3Smrg GLenum type; 6677ec681f3Smrg GLsizei count; 6687ec681f3Smrg GLsizei instance_count; 6697ec681f3Smrg GLint basevertex; 6707ec681f3Smrg GLuint baseinstance; 6717ec681f3Smrg GLuint min_index; 6727ec681f3Smrg GLuint max_index; 6737ec681f3Smrg GLuint user_buffer_mask; 6747ec681f3Smrg const GLvoid *indices; 6757ec681f3Smrg struct gl_buffer_object *index_buffer; 6767ec681f3Smrg}; 6777ec681f3Smrg 6787ec681f3Smrguint32_t 6797ec681f3Smrg_mesa_unmarshal_DrawElementsInstancedBaseVertexBaseInstance(struct gl_context *ctx, 6807ec681f3Smrg const struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance *cmd, 6817ec681f3Smrg const uint64_t *last) 6827ec681f3Smrg{ 6837ec681f3Smrg /* Ignore the function name. We use DISPATCH_CMD_DrawElementsInstanced- 6847ec681f3Smrg * BaseVertexBaseInstance for all DrawElements variants with user buffers, 6857ec681f3Smrg * and both DISPATCH_CMD_DrawElementsInstancedARB and DISPATCH_CMD_Draw- 6867ec681f3Smrg * RangeElementsBaseVertex for all draw elements variants without user 6877ec681f3Smrg * buffers. 6887ec681f3Smrg */ 6897ec681f3Smrg const GLenum mode = cmd->mode; 6907ec681f3Smrg const GLsizei count = cmd->count; 6917ec681f3Smrg const GLenum type = cmd->type; 6927ec681f3Smrg const GLvoid *indices = cmd->indices; 6937ec681f3Smrg const GLsizei instance_count = cmd->instance_count; 6947ec681f3Smrg const GLint basevertex = cmd->basevertex; 6957ec681f3Smrg const GLuint baseinstance = cmd->baseinstance; 6967ec681f3Smrg const GLuint min_index = cmd->min_index; 6977ec681f3Smrg const GLuint max_index = cmd->max_index; 6987ec681f3Smrg const GLuint user_buffer_mask = cmd->user_buffer_mask; 6997ec681f3Smrg struct gl_buffer_object *index_buffer = cmd->index_buffer; 7007ec681f3Smrg const struct glthread_attrib_binding *buffers = 7017ec681f3Smrg (const struct glthread_attrib_binding *)(cmd + 1); 7027ec681f3Smrg 7037ec681f3Smrg /* Bind uploaded buffers if needed. */ 7047ec681f3Smrg if (user_buffer_mask) { 7057ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 7067ec681f3Smrg false); 7077ec681f3Smrg } 7087ec681f3Smrg if (index_buffer) { 7097ec681f3Smrg _mesa_InternalBindElementBuffer(ctx, index_buffer); 7107ec681f3Smrg } 7117ec681f3Smrg 7127ec681f3Smrg /* Draw. */ 7137ec681f3Smrg if (cmd->index_bounds_valid && instance_count == 1 && baseinstance == 0) { 7147ec681f3Smrg CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch, 7157ec681f3Smrg (mode, min_index, max_index, count, 7167ec681f3Smrg type, indices, basevertex)); 7177ec681f3Smrg } else { 7187ec681f3Smrg CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch, 7197ec681f3Smrg (mode, count, type, indices, 7207ec681f3Smrg instance_count, basevertex, 7217ec681f3Smrg baseinstance)); 7227ec681f3Smrg } 7237ec681f3Smrg 7247ec681f3Smrg /* Restore states. */ 7257ec681f3Smrg if (index_buffer) { 7267ec681f3Smrg _mesa_InternalBindElementBuffer(ctx, NULL); 7277ec681f3Smrg } 7287ec681f3Smrg if (user_buffer_mask) { 7297ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 7307ec681f3Smrg true); 7317ec681f3Smrg } 7327ec681f3Smrg return cmd->cmd_base.cmd_size; 7337ec681f3Smrg} 7347ec681f3Smrg 7357ec681f3Smrgstatic ALWAYS_INLINE void 7367ec681f3Smrgdraw_elements_async_user(struct gl_context *ctx, GLenum mode, GLsizei count, 7377ec681f3Smrg GLenum type, const GLvoid *indices, GLsizei instance_count, 7387ec681f3Smrg GLint basevertex, GLuint baseinstance, 7397ec681f3Smrg bool index_bounds_valid, GLuint min_index, GLuint max_index, 7407ec681f3Smrg struct gl_buffer_object *index_buffer, 7417ec681f3Smrg unsigned user_buffer_mask, 7427ec681f3Smrg const struct glthread_attrib_binding *buffers) 7437ec681f3Smrg{ 7447ec681f3Smrg int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]); 7457ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance) + 7467ec681f3Smrg buffers_size; 7477ec681f3Smrg struct marshal_cmd_DrawElementsInstancedBaseVertexBaseInstance *cmd; 7487ec681f3Smrg 7497ec681f3Smrg cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_DrawElementsInstancedBaseVertexBaseInstance, cmd_size); 7507ec681f3Smrg cmd->mode = mode; 7517ec681f3Smrg cmd->count = count; 7527ec681f3Smrg cmd->type = type; 7537ec681f3Smrg cmd->indices = indices; 7547ec681f3Smrg cmd->instance_count = instance_count; 7557ec681f3Smrg cmd->basevertex = basevertex; 7567ec681f3Smrg cmd->baseinstance = baseinstance; 7577ec681f3Smrg cmd->min_index = min_index; 7587ec681f3Smrg cmd->max_index = max_index; 7597ec681f3Smrg cmd->user_buffer_mask = user_buffer_mask; 7607ec681f3Smrg cmd->index_bounds_valid = index_bounds_valid; 7617ec681f3Smrg cmd->index_buffer = index_buffer; 7627ec681f3Smrg 7637ec681f3Smrg if (user_buffer_mask) 7647ec681f3Smrg memcpy(cmd + 1, buffers, buffers_size); 7657ec681f3Smrg} 7667ec681f3Smrg 7677ec681f3Smrgstatic void 7687ec681f3Smrgdraw_elements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, 7697ec681f3Smrg GLsizei instance_count, GLint basevertex, GLuint baseinstance, 7707ec681f3Smrg bool index_bounds_valid, GLuint min_index, GLuint max_index, 7717ec681f3Smrg bool compiled_into_dlist) 7727ec681f3Smrg{ 7737ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 7747ec681f3Smrg 7757ec681f3Smrg struct glthread_vao *vao = ctx->GLThread.CurrentVAO; 7767ec681f3Smrg unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled; 7777ec681f3Smrg bool has_user_indices = vao->CurrentElementBufferName == 0; 7787ec681f3Smrg 7797ec681f3Smrg if (compiled_into_dlist && ctx->GLThread.ListMode) 7807ec681f3Smrg goto sync; 7817ec681f3Smrg 7827ec681f3Smrg /* Fast path when nothing needs to be done. 7837ec681f3Smrg * 7847ec681f3Smrg * This is also an error path. Zero counts should still call the driver 7857ec681f3Smrg * for possible GL errors. 7867ec681f3Smrg */ 7877ec681f3Smrg if (ctx->API == API_OPENGL_CORE || 7887ec681f3Smrg count <= 0 || instance_count <= 0 || max_index < min_index || 7897ec681f3Smrg !is_index_type_valid(type) || 7907ec681f3Smrg (!user_buffer_mask && !has_user_indices)) { 7917ec681f3Smrg draw_elements_async(ctx, mode, count, type, indices, instance_count, 7927ec681f3Smrg basevertex, baseinstance, index_bounds_valid, 7937ec681f3Smrg min_index, max_index); 7947ec681f3Smrg return; 7957ec681f3Smrg } 7967ec681f3Smrg 7977ec681f3Smrg if (!ctx->GLThread.SupportsNonVBOUploads) 7987ec681f3Smrg goto sync; 7997ec681f3Smrg 8007ec681f3Smrg bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask; 8017ec681f3Smrg unsigned index_size = get_index_size(type); 8027ec681f3Smrg 8037ec681f3Smrg if (need_index_bounds && !index_bounds_valid) { 8047ec681f3Smrg /* Sync if indices come from a buffer and vertices come from memory 8057ec681f3Smrg * and index bounds are not valid. 8067ec681f3Smrg * 8077ec681f3Smrg * We would have to map the indices to compute the index bounds, and 8087ec681f3Smrg * for that we would have to sync anyway. 8097ec681f3Smrg */ 8107ec681f3Smrg if (!has_user_indices) 8117ec681f3Smrg goto sync; 8127ec681f3Smrg 8137ec681f3Smrg /* Compute the index bounds. */ 8147ec681f3Smrg min_index = ~0; 8157ec681f3Smrg max_index = 0; 8167ec681f3Smrg vbo_get_minmax_index_mapped(count, index_size, 8177ec681f3Smrg ctx->GLThread._RestartIndex[index_size - 1], 8187ec681f3Smrg ctx->GLThread._PrimitiveRestart, indices, 8197ec681f3Smrg &min_index, &max_index); 8207ec681f3Smrg index_bounds_valid = true; 8217ec681f3Smrg } 8227ec681f3Smrg 8237ec681f3Smrg unsigned start_vertex = min_index + basevertex; 8247ec681f3Smrg unsigned num_vertices = max_index + 1 - min_index; 8257ec681f3Smrg 8267ec681f3Smrg /* If there is too much data to upload, sync and let the driver unroll 8277ec681f3Smrg * indices. */ 8287ec681f3Smrg if (util_is_vbo_upload_ratio_too_large(count, num_vertices)) 8297ec681f3Smrg goto sync; 8307ec681f3Smrg 8317ec681f3Smrg struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX]; 8327ec681f3Smrg if (user_buffer_mask && 8337ec681f3Smrg !upload_vertices(ctx, user_buffer_mask, start_vertex, num_vertices, 8347ec681f3Smrg baseinstance, instance_count, buffers)) 8357ec681f3Smrg goto sync; 8367ec681f3Smrg 8377ec681f3Smrg /* Upload indices. */ 8387ec681f3Smrg struct gl_buffer_object *index_buffer = NULL; 8397ec681f3Smrg if (has_user_indices) 8407ec681f3Smrg index_buffer = upload_indices(ctx, count, index_size, &indices); 8417ec681f3Smrg 8427ec681f3Smrg /* Draw asynchronously. */ 8437ec681f3Smrg draw_elements_async_user(ctx, mode, count, type, indices, instance_count, 8447ec681f3Smrg basevertex, baseinstance, index_bounds_valid, 8457ec681f3Smrg min_index, max_index, index_buffer, 8467ec681f3Smrg user_buffer_mask, buffers); 8477ec681f3Smrg return; 8487ec681f3Smrg 8497ec681f3Smrgsync: 8507ec681f3Smrg _mesa_glthread_finish_before(ctx, "DrawElements"); 8517ec681f3Smrg 8527ec681f3Smrg if (compiled_into_dlist && ctx->GLThread.ListMode) { 8537ec681f3Smrg /* Only use the ones that are compiled into display lists. */ 8547ec681f3Smrg if (basevertex) { 8557ec681f3Smrg CALL_DrawElementsBaseVertex(ctx->CurrentServerDispatch, 8567ec681f3Smrg (mode, count, type, indices, basevertex)); 8577ec681f3Smrg } else if (index_bounds_valid) { 8587ec681f3Smrg CALL_DrawRangeElements(ctx->CurrentServerDispatch, 8597ec681f3Smrg (mode, min_index, max_index, count, type, indices)); 8607ec681f3Smrg } else { 8617ec681f3Smrg CALL_DrawElements(ctx->CurrentServerDispatch, (mode, count, type, indices)); 8627ec681f3Smrg } 8637ec681f3Smrg } else if (index_bounds_valid && instance_count == 1 && baseinstance == 0) { 8647ec681f3Smrg CALL_DrawRangeElementsBaseVertex(ctx->CurrentServerDispatch, 8657ec681f3Smrg (mode, min_index, max_index, count, 8667ec681f3Smrg type, indices, basevertex)); 8677ec681f3Smrg } else { 8687ec681f3Smrg CALL_DrawElementsInstancedBaseVertexBaseInstance(ctx->CurrentServerDispatch, 8697ec681f3Smrg (mode, count, type, indices, 8707ec681f3Smrg instance_count, basevertex, 8717ec681f3Smrg baseinstance)); 8727ec681f3Smrg } 8737ec681f3Smrg} 8747ec681f3Smrg 8757ec681f3Smrgstruct marshal_cmd_MultiDrawElementsBaseVertex 8767ec681f3Smrg{ 8777ec681f3Smrg struct marshal_cmd_base cmd_base; 8787ec681f3Smrg bool has_base_vertex; 8797ec681f3Smrg GLenum mode; 8807ec681f3Smrg GLenum type; 8817ec681f3Smrg GLsizei draw_count; 8827ec681f3Smrg GLuint user_buffer_mask; 8837ec681f3Smrg struct gl_buffer_object *index_buffer; 8847ec681f3Smrg}; 8857ec681f3Smrg 8867ec681f3Smrguint32_t 8877ec681f3Smrg_mesa_unmarshal_MultiDrawElementsBaseVertex(struct gl_context *ctx, 8887ec681f3Smrg const struct marshal_cmd_MultiDrawElementsBaseVertex *cmd, 8897ec681f3Smrg const uint64_t *last) 8907ec681f3Smrg{ 8917ec681f3Smrg const GLenum mode = cmd->mode; 8927ec681f3Smrg const GLenum type = cmd->type; 8937ec681f3Smrg const GLsizei draw_count = cmd->draw_count; 8947ec681f3Smrg const GLuint user_buffer_mask = cmd->user_buffer_mask; 8957ec681f3Smrg struct gl_buffer_object *index_buffer = cmd->index_buffer; 8967ec681f3Smrg const bool has_base_vertex = cmd->has_base_vertex; 8977ec681f3Smrg 8987ec681f3Smrg const char *variable_data = (const char *)(cmd + 1); 8997ec681f3Smrg const GLsizei *count = (GLsizei *)variable_data; 9007ec681f3Smrg variable_data += sizeof(GLsizei) * draw_count; 9017ec681f3Smrg const GLvoid *const *indices = (const GLvoid *const *)variable_data; 9027ec681f3Smrg variable_data += sizeof(const GLvoid *const *) * draw_count; 9037ec681f3Smrg const GLsizei *basevertex = NULL; 9047ec681f3Smrg if (has_base_vertex) { 9057ec681f3Smrg basevertex = (GLsizei *)variable_data; 9067ec681f3Smrg variable_data += sizeof(GLsizei) * draw_count; 9077ec681f3Smrg } 9087ec681f3Smrg const struct glthread_attrib_binding *buffers = 9097ec681f3Smrg (const struct glthread_attrib_binding *)variable_data; 9107ec681f3Smrg 9117ec681f3Smrg /* Bind uploaded buffers if needed. */ 9127ec681f3Smrg if (user_buffer_mask) { 9137ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 9147ec681f3Smrg false); 9157ec681f3Smrg } 9167ec681f3Smrg if (index_buffer) { 9177ec681f3Smrg _mesa_InternalBindElementBuffer(ctx, index_buffer); 9187ec681f3Smrg } 9197ec681f3Smrg 9207ec681f3Smrg /* Draw. */ 9217ec681f3Smrg if (has_base_vertex) { 9227ec681f3Smrg CALL_MultiDrawElementsBaseVertex(ctx->CurrentServerDispatch, 9237ec681f3Smrg (mode, count, type, indices, draw_count, 9247ec681f3Smrg basevertex)); 9257ec681f3Smrg } else { 9267ec681f3Smrg CALL_MultiDrawElementsEXT(ctx->CurrentServerDispatch, 9277ec681f3Smrg (mode, count, type, indices, draw_count)); 9287ec681f3Smrg } 9297ec681f3Smrg 9307ec681f3Smrg /* Restore states. */ 9317ec681f3Smrg if (index_buffer) { 9327ec681f3Smrg _mesa_InternalBindElementBuffer(ctx, NULL); 9337ec681f3Smrg } 9347ec681f3Smrg if (user_buffer_mask) { 9357ec681f3Smrg _mesa_InternalBindVertexBuffers(ctx, buffers, user_buffer_mask, 9367ec681f3Smrg true); 9377ec681f3Smrg } 9387ec681f3Smrg return cmd->cmd_base.cmd_size; 9397ec681f3Smrg} 9407ec681f3Smrg 9417ec681f3Smrgstatic ALWAYS_INLINE void 9427ec681f3Smrgmulti_draw_elements_async(struct gl_context *ctx, GLenum mode, 9437ec681f3Smrg const GLsizei *count, GLenum type, 9447ec681f3Smrg const GLvoid *const *indices, GLsizei draw_count, 9457ec681f3Smrg const GLsizei *basevertex, 9467ec681f3Smrg struct gl_buffer_object *index_buffer, 9477ec681f3Smrg unsigned user_buffer_mask, 9487ec681f3Smrg const struct glthread_attrib_binding *buffers) 9497ec681f3Smrg{ 9507ec681f3Smrg int count_size = sizeof(GLsizei) * draw_count; 9517ec681f3Smrg int indices_size = sizeof(indices[0]) * draw_count; 9527ec681f3Smrg int basevertex_size = basevertex ? sizeof(GLsizei) * draw_count : 0; 9537ec681f3Smrg int buffers_size = util_bitcount(user_buffer_mask) * sizeof(buffers[0]); 9547ec681f3Smrg int cmd_size = sizeof(struct marshal_cmd_MultiDrawElementsBaseVertex) + 9557ec681f3Smrg count_size + indices_size + basevertex_size + buffers_size; 9567ec681f3Smrg struct marshal_cmd_MultiDrawElementsBaseVertex *cmd; 9577ec681f3Smrg 9587ec681f3Smrg cmd = _mesa_glthread_allocate_command(ctx, DISPATCH_CMD_MultiDrawElementsBaseVertex, cmd_size); 9597ec681f3Smrg cmd->mode = mode; 9607ec681f3Smrg cmd->type = type; 9617ec681f3Smrg cmd->draw_count = draw_count; 9627ec681f3Smrg cmd->user_buffer_mask = user_buffer_mask; 9637ec681f3Smrg cmd->index_buffer = index_buffer; 9647ec681f3Smrg cmd->has_base_vertex = basevertex != NULL; 9657ec681f3Smrg 9667ec681f3Smrg char *variable_data = (char*)(cmd + 1); 9677ec681f3Smrg memcpy(variable_data, count, count_size); 9687ec681f3Smrg variable_data += count_size; 9697ec681f3Smrg memcpy(variable_data, indices, indices_size); 9707ec681f3Smrg variable_data += indices_size; 9717ec681f3Smrg 9727ec681f3Smrg if (basevertex) { 9737ec681f3Smrg memcpy(variable_data, basevertex, basevertex_size); 9747ec681f3Smrg variable_data += basevertex_size; 9757ec681f3Smrg } 9767ec681f3Smrg 9777ec681f3Smrg if (user_buffer_mask) 9787ec681f3Smrg memcpy(variable_data, buffers, buffers_size); 9797ec681f3Smrg} 9807ec681f3Smrg 9817ec681f3Smrgvoid GLAPIENTRY 9827ec681f3Smrg_mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, 9837ec681f3Smrg GLenum type, 9847ec681f3Smrg const GLvoid *const *indices, 9857ec681f3Smrg GLsizei draw_count, 9867ec681f3Smrg const GLsizei *basevertex) 9877ec681f3Smrg{ 9887ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 9897ec681f3Smrg 9907ec681f3Smrg struct glthread_vao *vao = ctx->GLThread.CurrentVAO; 9917ec681f3Smrg unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled; 9927ec681f3Smrg bool has_user_indices = vao->CurrentElementBufferName == 0; 9937ec681f3Smrg 9947ec681f3Smrg if (ctx->GLThread.ListMode) 9957ec681f3Smrg goto sync; 9967ec681f3Smrg 9977ec681f3Smrg /* Fast path when nothing needs to be done. */ 9987ec681f3Smrg if (draw_count >= 0 && 9997ec681f3Smrg (ctx->API == API_OPENGL_CORE || 10007ec681f3Smrg !is_index_type_valid(type) || 10017ec681f3Smrg (!user_buffer_mask && !has_user_indices))) { 10027ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 10037ec681f3Smrg basevertex, 0, 0, NULL); 10047ec681f3Smrg return; 10057ec681f3Smrg } 10067ec681f3Smrg 10077ec681f3Smrg bool need_index_bounds = user_buffer_mask & ~vao->NonZeroDivisorMask; 10087ec681f3Smrg 10097ec681f3Smrg /* If the draw count is too high or negative, the queue can't be used. 10107ec681f3Smrg * 10117ec681f3Smrg * Sync if indices come from a buffer and vertices come from memory 10127ec681f3Smrg * and index bounds are not valid. We would have to map the indices 10137ec681f3Smrg * to compute the index bounds, and for that we would have to sync anyway. 10147ec681f3Smrg */ 10157ec681f3Smrg if (!ctx->GLThread.SupportsNonVBOUploads || 10167ec681f3Smrg draw_count < 0 || draw_count > MARSHAL_MAX_CMD_SIZE / 32 || 10177ec681f3Smrg (need_index_bounds && !has_user_indices)) 10187ec681f3Smrg goto sync; 10197ec681f3Smrg 10207ec681f3Smrg unsigned index_size = get_index_size(type); 10217ec681f3Smrg unsigned min_index = ~0; 10227ec681f3Smrg unsigned max_index = 0; 10237ec681f3Smrg unsigned total_count = 0; 10247ec681f3Smrg unsigned num_vertices = 0; 10257ec681f3Smrg 10267ec681f3Smrg /* This is always true if there is per-vertex data that needs to be 10277ec681f3Smrg * uploaded. 10287ec681f3Smrg */ 10297ec681f3Smrg if (need_index_bounds) { 10307ec681f3Smrg /* Compute the index bounds. */ 10317ec681f3Smrg for (unsigned i = 0; i < draw_count; i++) { 10327ec681f3Smrg GLsizei vertex_count = count[i]; 10337ec681f3Smrg 10347ec681f3Smrg if (vertex_count < 0) { 10357ec681f3Smrg /* Just call the driver to set the error. */ 10367ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 10377ec681f3Smrg basevertex, 0, 0, NULL); 10387ec681f3Smrg return; 10397ec681f3Smrg } 10407ec681f3Smrg if (vertex_count == 0) 10417ec681f3Smrg continue; 10427ec681f3Smrg 10437ec681f3Smrg unsigned min = ~0, max = 0; 10447ec681f3Smrg vbo_get_minmax_index_mapped(vertex_count, index_size, 10457ec681f3Smrg ctx->GLThread._RestartIndex[index_size - 1], 10467ec681f3Smrg ctx->GLThread._PrimitiveRestart, indices[i], 10477ec681f3Smrg &min, &max); 10487ec681f3Smrg if (basevertex) { 10497ec681f3Smrg min += basevertex[i]; 10507ec681f3Smrg max += basevertex[i]; 10517ec681f3Smrg } 10527ec681f3Smrg min_index = MIN2(min_index, min); 10537ec681f3Smrg max_index = MAX2(max_index, max); 10547ec681f3Smrg total_count += vertex_count; 10557ec681f3Smrg } 10567ec681f3Smrg 10577ec681f3Smrg num_vertices = max_index + 1 - min_index; 10587ec681f3Smrg 10597ec681f3Smrg if (total_count == 0 || num_vertices == 0) { 10607ec681f3Smrg /* Nothing to do, but call the driver to set possible GL errors. */ 10617ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 10627ec681f3Smrg basevertex, 0, 0, NULL); 10637ec681f3Smrg return; 10647ec681f3Smrg } 10657ec681f3Smrg 10667ec681f3Smrg /* If there is too much data to upload, sync and let the driver unroll 10677ec681f3Smrg * indices. */ 10687ec681f3Smrg if (util_is_vbo_upload_ratio_too_large(total_count, num_vertices)) 10697ec681f3Smrg goto sync; 10707ec681f3Smrg } else if (has_user_indices) { 10717ec681f3Smrg /* Only compute total_count for the upload of indices. */ 10727ec681f3Smrg for (unsigned i = 0; i < draw_count; i++) { 10737ec681f3Smrg GLsizei vertex_count = count[i]; 10747ec681f3Smrg 10757ec681f3Smrg if (vertex_count < 0) { 10767ec681f3Smrg /* Just call the driver to set the error. */ 10777ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 10787ec681f3Smrg basevertex, 0, 0, NULL); 10797ec681f3Smrg return; 10807ec681f3Smrg } 10817ec681f3Smrg if (vertex_count == 0) 10827ec681f3Smrg continue; 10837ec681f3Smrg 10847ec681f3Smrg total_count += vertex_count; 10857ec681f3Smrg } 10867ec681f3Smrg 10877ec681f3Smrg if (total_count == 0) { 10887ec681f3Smrg /* Nothing to do, but call the driver to set possible GL errors. */ 10897ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 10907ec681f3Smrg basevertex, 0, 0, NULL); 10917ec681f3Smrg return; 10927ec681f3Smrg } 10937ec681f3Smrg } 10947ec681f3Smrg 10957ec681f3Smrg /* Upload vertices. */ 10967ec681f3Smrg struct glthread_attrib_binding buffers[VERT_ATTRIB_MAX]; 10977ec681f3Smrg if (user_buffer_mask && 10987ec681f3Smrg !upload_vertices(ctx, user_buffer_mask, min_index, num_vertices, 10997ec681f3Smrg 0, 1, buffers)) 11007ec681f3Smrg goto sync; 11017ec681f3Smrg 11027ec681f3Smrg /* Upload indices. */ 11037ec681f3Smrg struct gl_buffer_object *index_buffer = NULL; 11047ec681f3Smrg if (has_user_indices) { 11057ec681f3Smrg const GLvoid **out_indices = alloca(sizeof(indices[0]) * draw_count); 11067ec681f3Smrg 11077ec681f3Smrg index_buffer = upload_multi_indices(ctx, total_count, index_size, 11087ec681f3Smrg draw_count, count, indices, 11097ec681f3Smrg out_indices); 11107ec681f3Smrg indices = out_indices; 11117ec681f3Smrg } 11127ec681f3Smrg 11137ec681f3Smrg /* Draw asynchronously. */ 11147ec681f3Smrg multi_draw_elements_async(ctx, mode, count, type, indices, draw_count, 11157ec681f3Smrg basevertex, index_buffer, user_buffer_mask, 11167ec681f3Smrg buffers); 11177ec681f3Smrg return; 11187ec681f3Smrg 11197ec681f3Smrgsync: 11207ec681f3Smrg _mesa_glthread_finish_before(ctx, "DrawElements"); 11217ec681f3Smrg 11227ec681f3Smrg if (basevertex) { 11237ec681f3Smrg CALL_MultiDrawElementsBaseVertex(ctx->CurrentServerDispatch, 11247ec681f3Smrg (mode, count, type, indices, draw_count, 11257ec681f3Smrg basevertex)); 11267ec681f3Smrg } else { 11277ec681f3Smrg CALL_MultiDrawElementsEXT(ctx->CurrentServerDispatch, 11287ec681f3Smrg (mode, count, type, indices, draw_count)); 11297ec681f3Smrg } 11307ec681f3Smrg} 11317ec681f3Smrg 11327ec681f3Smrgvoid GLAPIENTRY 11337ec681f3Smrg_mesa_marshal_DrawArrays(GLenum mode, GLint first, GLsizei count) 11347ec681f3Smrg{ 11357ec681f3Smrg draw_arrays(mode, first, count, 1, 0, true); 11367ec681f3Smrg} 11377ec681f3Smrg 11387ec681f3Smrgvoid GLAPIENTRY 11397ec681f3Smrg_mesa_marshal_DrawArraysInstancedARB(GLenum mode, GLint first, GLsizei count, 11407ec681f3Smrg GLsizei instance_count) 11417ec681f3Smrg{ 11427ec681f3Smrg draw_arrays(mode, first, count, instance_count, 0, false); 11437ec681f3Smrg} 11447ec681f3Smrg 11457ec681f3Smrgvoid GLAPIENTRY 11467ec681f3Smrg_mesa_marshal_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, 11477ec681f3Smrg GLsizei count, GLsizei instance_count, 11487ec681f3Smrg GLuint baseinstance) 11497ec681f3Smrg{ 11507ec681f3Smrg draw_arrays(mode, first, count, instance_count, baseinstance, false); 11517ec681f3Smrg} 11527ec681f3Smrg 11537ec681f3Smrgvoid GLAPIENTRY 11547ec681f3Smrg_mesa_marshal_DrawElements(GLenum mode, GLsizei count, GLenum type, 11557ec681f3Smrg const GLvoid *indices) 11567ec681f3Smrg{ 11577ec681f3Smrg draw_elements(mode, count, type, indices, 1, 0, 0, false, 0, 0, true); 11587ec681f3Smrg} 11597ec681f3Smrg 11607ec681f3Smrgvoid GLAPIENTRY 11617ec681f3Smrg_mesa_marshal_DrawRangeElements(GLenum mode, GLuint start, GLuint end, 11627ec681f3Smrg GLsizei count, GLenum type, 11637ec681f3Smrg const GLvoid *indices) 11647ec681f3Smrg{ 11657ec681f3Smrg draw_elements(mode, count, type, indices, 1, 0, 0, true, start, end, true); 11667ec681f3Smrg} 11677ec681f3Smrg 11687ec681f3Smrgvoid GLAPIENTRY 11697ec681f3Smrg_mesa_marshal_DrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type, 11707ec681f3Smrg const GLvoid *indices, GLsizei instance_count) 11717ec681f3Smrg{ 11727ec681f3Smrg draw_elements(mode, count, type, indices, instance_count, 0, 0, false, 0, 0, false); 11737ec681f3Smrg} 11747ec681f3Smrg 11757ec681f3Smrgvoid GLAPIENTRY 11767ec681f3Smrg_mesa_marshal_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, 11777ec681f3Smrg const GLvoid *indices, GLint basevertex) 11787ec681f3Smrg{ 11797ec681f3Smrg draw_elements(mode, count, type, indices, 1, basevertex, 0, false, 0, 0, true); 11807ec681f3Smrg} 11817ec681f3Smrg 11827ec681f3Smrgvoid GLAPIENTRY 11837ec681f3Smrg_mesa_marshal_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, 11847ec681f3Smrg GLsizei count, GLenum type, 11857ec681f3Smrg const GLvoid *indices, GLint basevertex) 11867ec681f3Smrg{ 11877ec681f3Smrg draw_elements(mode, count, type, indices, 1, basevertex, 0, true, start, end, false); 11887ec681f3Smrg} 11897ec681f3Smrg 11907ec681f3Smrgvoid GLAPIENTRY 11917ec681f3Smrg_mesa_marshal_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, 11927ec681f3Smrg GLenum type, const GLvoid *indices, 11937ec681f3Smrg GLsizei instance_count, GLint basevertex) 11947ec681f3Smrg{ 11957ec681f3Smrg draw_elements(mode, count, type, indices, instance_count, basevertex, 0, false, 0, 0, false); 11967ec681f3Smrg} 11977ec681f3Smrg 11987ec681f3Smrgvoid GLAPIENTRY 11997ec681f3Smrg_mesa_marshal_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, 12007ec681f3Smrg GLenum type, const GLvoid *indices, 12017ec681f3Smrg GLsizei instance_count, GLuint baseinstance) 12027ec681f3Smrg{ 12037ec681f3Smrg draw_elements(mode, count, type, indices, instance_count, 0, baseinstance, false, 0, 0, false); 12047ec681f3Smrg} 12057ec681f3Smrg 12067ec681f3Smrgvoid GLAPIENTRY 12077ec681f3Smrg_mesa_marshal_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, 12087ec681f3Smrg GLenum type, const GLvoid *indices, 12097ec681f3Smrg GLsizei instance_count, GLint basevertex, 12107ec681f3Smrg GLuint baseinstance) 12117ec681f3Smrg{ 12127ec681f3Smrg draw_elements(mode, count, type, indices, instance_count, basevertex, baseinstance, false, 0, 0, false); 12137ec681f3Smrg} 12147ec681f3Smrg 12157ec681f3Smrgvoid GLAPIENTRY 12167ec681f3Smrg_mesa_marshal_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, 12177ec681f3Smrg GLenum type, const GLvoid *const *indices, 12187ec681f3Smrg GLsizei draw_count) 12197ec681f3Smrg{ 12207ec681f3Smrg _mesa_marshal_MultiDrawElementsBaseVertex(mode, count, type, indices, 12217ec681f3Smrg draw_count, NULL); 12227ec681f3Smrg} 12237ec681f3Smrg 12247ec681f3Smrguint32_t 12257ec681f3Smrg_mesa_unmarshal_DrawArraysInstancedARB(struct gl_context *ctx, const struct marshal_cmd_DrawArraysInstancedARB *cmd, const uint64_t *last) 12267ec681f3Smrg{ 12277ec681f3Smrg unreachable("never used - DrawArraysInstancedBaseInstance is used instead"); 12287ec681f3Smrg return 0; 12297ec681f3Smrg} 12307ec681f3Smrg 12317ec681f3Smrguint32_t 12327ec681f3Smrg_mesa_unmarshal_DrawElements(struct gl_context *ctx, const struct marshal_cmd_DrawElements *cmd, const uint64_t *last) 12337ec681f3Smrg{ 12347ec681f3Smrg unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead"); 12357ec681f3Smrg return 0; 12367ec681f3Smrg} 12377ec681f3Smrg 12387ec681f3Smrguint32_t 12397ec681f3Smrg_mesa_unmarshal_DrawRangeElements(struct gl_context *ctx, const struct marshal_cmd_DrawRangeElements *cmd, const uint64_t *last) 12407ec681f3Smrg{ 12417ec681f3Smrg unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead"); 12427ec681f3Smrg return 0; 12437ec681f3Smrg} 12447ec681f3Smrg 12457ec681f3Smrguint32_t 12467ec681f3Smrg_mesa_unmarshal_DrawElementsBaseVertex(struct gl_context *ctx, const struct marshal_cmd_DrawElementsBaseVertex *cmd, const uint64_t *last) 12477ec681f3Smrg{ 12487ec681f3Smrg unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead"); 12497ec681f3Smrg return 0; 12507ec681f3Smrg} 12517ec681f3Smrg 12527ec681f3Smrguint32_t 12537ec681f3Smrg_mesa_unmarshal_DrawElementsInstancedBaseVertex(struct gl_context *ctx, const struct marshal_cmd_DrawElementsInstancedBaseVertex *cmd, const uint64_t *last) 12547ec681f3Smrg{ 12557ec681f3Smrg unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead"); 12567ec681f3Smrg return 0; 12577ec681f3Smrg} 12587ec681f3Smrg 12597ec681f3Smrguint32_t 12607ec681f3Smrg_mesa_unmarshal_DrawElementsInstancedBaseInstance(struct gl_context *ctx, const struct marshal_cmd_DrawElementsInstancedBaseInstance *cmd, const uint64_t *last) 12617ec681f3Smrg{ 12627ec681f3Smrg unreachable("never used - DrawElementsInstancedBaseVertexBaseInstance is used instead"); 12637ec681f3Smrg return 0; 12647ec681f3Smrg} 12657ec681f3Smrg 12667ec681f3Smrguint32_t 12677ec681f3Smrg_mesa_unmarshal_MultiDrawElementsEXT(struct gl_context *ctx, const struct marshal_cmd_MultiDrawElementsEXT *cmd, const uint64_t *last) 12687ec681f3Smrg{ 12697ec681f3Smrg unreachable("never used - MultiDrawElementsBaseVertex is used instead"); 12707ec681f3Smrg return 0; 12717ec681f3Smrg} 1272