diff --git a/src/mesa/main/glthread.h b/src/mesa/main/glthread.h index d752ca9ef7a..05d8ebd6b53 100644 --- a/src/mesa/main/glthread.h +++ b/src/mesa/main/glthread.h @@ -102,6 +102,7 @@ struct glthread_vao { GLbitfield BufferEnabled; /**< "Enabled" converted to buffer bindings. */ GLbitfield BufferInterleaved; /**< Bitmask of buffers used by multiple attribs. */ GLbitfield UserPointerMask; /**< Bitmask of buffer bindings. */ + GLbitfield NonNullPointerMask; /**< Bitmask of buffer bindings with non-NULL user pointers. */ GLbitfield NonZeroDivisorMask; /**< Bitmask of buffer bindings. */ struct glthread_attrib Attrib[VERT_ATTRIB_MAX]; diff --git a/src/mesa/main/glthread_draw.c b/src/mesa/main/glthread_draw.c index a8b8b1b7498..bc7c33bb4c0 100644 --- a/src/mesa/main/glthread_draw.c +++ b/src/mesa/main/glthread_draw.c @@ -427,15 +427,30 @@ draw_arrays_async_user(struct gl_context *ctx, GLenum mode, GLint first, memcpy(cmd + 1, buffers, buffers_size); } +static inline unsigned +get_user_buffer_mask(struct gl_context *ctx) +{ + struct glthread_vao *vao = ctx->GLThread.CurrentVAO; + + /* BufferEnabled means which attribs are enabled in terms of buffer + * binding slots (not attrib slots). + * + * UserPointerMask means which buffer bindings don't have a buffer bound. + * + * NonNullPointerMask means which buffer bindings have a NULL pointer. + * Those are not uploaded. This can happen when an attrib is enabled, but + * the shader doesn't use it, so it's ignored by mesa/state_tracker. + */ + return vao->BufferEnabled & vao->UserPointerMask & vao->NonNullPointerMask; +} + static ALWAYS_INLINE void draw_arrays(GLenum mode, GLint first, GLsizei count, GLsizei instance_count, GLuint baseinstance, bool compiled_into_dlist) { GET_CURRENT_CONTEXT(ctx); - - struct glthread_vao *vao = ctx->GLThread.CurrentVAO; unsigned user_buffer_mask = - ctx->API == API_OPENGL_CORE ? 0 : vao->UserPointerMask & vao->BufferEnabled; + ctx->API == API_OPENGL_CORE ? 0 : get_user_buffer_mask(ctx); if (compiled_into_dlist && ctx->GLThread.ListMode) { _mesa_glthread_finish_before(ctx, "DrawArrays"); @@ -552,11 +567,9 @@ _mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first, const GLsizei *count, GLsizei draw_count) { GET_CURRENT_CONTEXT(ctx); - - struct glthread_vao *vao = ctx->GLThread.CurrentVAO; unsigned user_buffer_mask = ctx->API == API_OPENGL_CORE || draw_count <= 0 ? - 0 : vao->UserPointerMask & vao->BufferEnabled; + 0 : get_user_buffer_mask(ctx); if (ctx->GLThread.ListMode) goto sync; @@ -898,10 +911,9 @@ draw_elements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, bool compiled_into_dlist) { GET_CURRENT_CONTEXT(ctx); - struct glthread_vao *vao = ctx->GLThread.CurrentVAO; unsigned user_buffer_mask = - ctx->API == API_OPENGL_CORE ? 0 : vao->UserPointerMask & vao->BufferEnabled; + ctx->API == API_OPENGL_CORE ? 0 : get_user_buffer_mask(ctx); bool has_user_indices = vao->CurrentElementBufferName == 0 && indices; if (compiled_into_dlist && ctx->GLThread.ListMode) @@ -1151,10 +1163,9 @@ _mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, const GLsizei *basevertex) { GET_CURRENT_CONTEXT(ctx); - struct glthread_vao *vao = ctx->GLThread.CurrentVAO; unsigned user_buffer_mask = - ctx->API == API_OPENGL_CORE ? 0 : vao->UserPointerMask & vao->BufferEnabled; + ctx->API == API_OPENGL_CORE ? 0 : get_user_buffer_mask(ctx); bool has_user_indices = vao->CurrentElementBufferName == 0; if (ctx->GLThread.ListMode) diff --git a/src/mesa/main/glthread_varray.c b/src/mesa/main/glthread_varray.c index f4f2bde2158..a309ffe21aa 100644 --- a/src/mesa/main/glthread_varray.c +++ b/src/mesa/main/glthread_varray.c @@ -51,6 +51,7 @@ _mesa_glthread_reset_vao(struct glthread_vao *vao) vao->Enabled = 0; vao->BufferEnabled = 0; vao->UserPointerMask = 0; + vao->NonNullPointerMask = 0; vao->NonZeroDivisorMask = 0; for (unsigned i = 0; i < ARRAY_SIZE(vao->Attrib); i++) { @@ -363,6 +364,11 @@ attrib_pointer(struct glthread_state *glthread, struct glthread_vao *vao, vao->UserPointerMask &= ~(1u << attrib); else vao->UserPointerMask |= 1u << attrib; + + if (pointer) + vao->NonNullPointerMask |= 1u << attrib; + else + vao->NonNullPointerMask &= ~(1u << attrib); } void @@ -447,6 +453,11 @@ bind_vertex_buffer(struct glthread_state *glthread, struct glthread_vao *vao, vao->UserPointerMask &= ~(1u << i); else vao->UserPointerMask |= 1u << i; + + if (offset) + vao->NonNullPointerMask |= 1u << i; + else + vao->NonNullPointerMask &= ~(1u << i); } void