glthread: handle ARB_vertex_attrib_binding
This handles ARB_vertex_attrib_binding for vertex uploads correctly. Before this, the extension might have led to crashes if non-VBO vertex attribs were present. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5303>
This commit is contained in:
@@ -597,12 +597,14 @@
|
||||
<param name="index" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayElementBuffer" no_error="true">
|
||||
<function name="VertexArrayElementBuffer" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAElementBuffer(ctx, vaobj, buffer);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="buffer" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexBuffer" no_error="true">
|
||||
<function name="VertexArrayVertexBuffer" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAVertexBuffer(ctx, vaobj, bindingindex, buffer, offset, stride);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="bindingindex" type="GLuint" />
|
||||
<param name="buffer" type="GLuint" />
|
||||
@@ -610,7 +612,8 @@
|
||||
<param name="stride" type="GLsizei" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexBuffers" no_error="true">
|
||||
<function name="VertexArrayVertexBuffers" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAVertexBuffers(ctx, vaobj, first, count, buffers, offsets, strides);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="first" type="GLuint" />
|
||||
<param name="count" type="GLsizei" />
|
||||
@@ -619,7 +622,8 @@
|
||||
<param name="strides" type="const GLsizei *" count="count"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayAttribFormat">
|
||||
<function name="VertexArrayAttribFormat"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="attribindex" type="GLuint" />
|
||||
<param name="size" type="GLint" />
|
||||
@@ -628,7 +632,8 @@
|
||||
<param name="relativeoffset" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayAttribIFormat">
|
||||
<function name="VertexArrayAttribIFormat"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="attribindex" type="GLuint" />
|
||||
<param name="size" type="GLint" />
|
||||
@@ -636,7 +641,8 @@
|
||||
<param name="relativeoffset" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayAttribLFormat">
|
||||
<function name="VertexArrayAttribLFormat"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="attribindex" type="GLuint" />
|
||||
<param name="size" type="GLint" />
|
||||
@@ -644,13 +650,15 @@
|
||||
<param name="relativeoffset" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayAttribBinding" no_error="true">
|
||||
<function name="VertexArrayAttribBinding" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribBinding(ctx, vaobj, attribindex, bindingindex);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="attribindex" type="GLuint" />
|
||||
<param name="bindingindex" type="GLuint" />
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayBindingDivisor" no_error="true">
|
||||
<function name="VertexArrayBindingDivisor" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSABindingDivisor(ctx, vaobj, bindingindex, divisor);">
|
||||
<param name="vaobj" type="GLuint" />
|
||||
<param name="bindingindex" type="GLuint" />
|
||||
<param name="divisor" type="GLuint" />
|
||||
|
@@ -7,14 +7,16 @@
|
||||
|
||||
<category name="GL_ARB_vertex_attrib_binding" number="125">
|
||||
|
||||
<function name="BindVertexBuffer" es2="3.1" no_error="true">
|
||||
<function name="BindVertexBuffer" es2="3.1" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_VertexBuffer(ctx, bindingindex, buffer, offset, stride);">
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
<param name="buffer" type="GLuint"/>
|
||||
<param name="offset" type="GLintptr"/>
|
||||
<param name="stride" type="GLsizei"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexAttribFormat" es2="3.1">
|
||||
<function name="VertexAttribFormat" es2="3.1"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_AttribFormat(ctx, attribindex, size, type, relativeoffset);">
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
<param name="type" type="GLenum"/>
|
||||
@@ -22,31 +24,36 @@
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexAttribIFormat" es2="3.1">
|
||||
<function name="VertexAttribIFormat" es2="3.1"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_AttribFormat(ctx, attribindex, size, type, relativeoffset);">
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
<param name="type" type="GLenum"/>
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexAttribLFormat">
|
||||
<function name="VertexAttribLFormat"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_AttribFormat(ctx, attribindex, size, type, relativeoffset);">
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
<param name="type" type="GLenum"/>
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexAttribBinding" es2="3.1" no_error="true">
|
||||
<function name="VertexAttribBinding" es2="3.1" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_AttribBinding(ctx, attribindex, bindingindex);">
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexBindingDivisor" es2="3.1" no_error="true">
|
||||
<function name="VertexBindingDivisor" es2="3.1" no_error="true"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_BindingDivisor(ctx, bindingindex, divisor);">
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
<param name="divisor" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayBindVertexBufferEXT">
|
||||
<function name="VertexArrayBindVertexBufferEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAVertexBuffer(ctx, vaobj, bindingindex, buffer, offset, stride);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
<param name="buffer" type="GLuint"/>
|
||||
@@ -54,7 +61,8 @@
|
||||
<param name="stride" type="GLsizei"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexAttribFormatEXT">
|
||||
<function name="VertexArrayVertexAttribFormatEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
@@ -63,7 +71,8 @@
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexAttribIFormatEXT">
|
||||
<function name="VertexArrayVertexAttribIFormatEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
@@ -71,7 +80,8 @@
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexAttribLFormatEXT">
|
||||
<function name="VertexArrayVertexAttribLFormatEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribFormat(ctx, vaobj, attribindex, size, type, relativeoffset);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="size" type="GLint"/>
|
||||
@@ -79,13 +89,15 @@
|
||||
<param name="relativeoffset" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexAttribBindingEXT">
|
||||
<function name="VertexArrayVertexAttribBindingEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSAAttribBinding(ctx, vaobj, attribindex, bindingindex);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="attribindex" type="GLuint"/>
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
</function>
|
||||
|
||||
<function name="VertexArrayVertexBindingDivisorEXT">
|
||||
<function name="VertexArrayVertexBindingDivisorEXT"
|
||||
marshal_call_after="if (COMPAT) _mesa_glthread_DSABindingDivisor(ctx, vaobj, bindingindex, divisor);">
|
||||
<param name="vaobj" type="GLuint"/>
|
||||
<param name="bindingindex" type="GLuint"/>
|
||||
<param name="divisor" type="GLuint"/>
|
||||
|
@@ -66,15 +66,23 @@ struct glthread_attrib_binding {
|
||||
struct glthread_vao {
|
||||
GLuint Name;
|
||||
GLuint CurrentElementBufferName;
|
||||
GLbitfield UserEnabled; /**< Vertex attrib arrays enabled by the user. */
|
||||
GLbitfield UserEnabled; /**< Vertex attribs enabled by the user. */
|
||||
GLbitfield Enabled; /**< UserEnabled with POS vs GENERIC0 aliasing resolved. */
|
||||
GLbitfield UserPointerMask;
|
||||
GLbitfield NonZeroDivisorMask;
|
||||
GLbitfield BufferEnabled; /**< "Enabled" converted to buffer bindings. */
|
||||
GLbitfield BufferInterleaved; /**< Bitmask of buffers used by multiple attribs. */
|
||||
GLbitfield UserPointerMask; /**< Bitmask of buffer bindings. */
|
||||
GLbitfield NonZeroDivisorMask; /**< Bitmask of buffer bindings. */
|
||||
|
||||
struct {
|
||||
/* Per attrib: */
|
||||
GLuint ElementSize;
|
||||
GLuint RelativeOffset;
|
||||
GLuint BufferIndex; /**< Referring to Attrib[BufferIndex]. */
|
||||
|
||||
/* Per buffer binding: */
|
||||
GLsizei Stride;
|
||||
GLuint Divisor;
|
||||
int EnabledAttribCount; /**< Number of enabled attribs using this buffer. */
|
||||
const void *Pointer;
|
||||
} Attrib[VERT_ATTRIB_MAX];
|
||||
};
|
||||
@@ -207,6 +215,31 @@ void _mesa_glthread_DSAAttribPointer(struct gl_context *ctx, GLuint vao,
|
||||
GLuint buffer, gl_vert_attrib attrib,
|
||||
GLint size, GLenum type, GLsizei stride,
|
||||
GLintptr offset);
|
||||
void _mesa_glthread_AttribFormat(struct gl_context *ctx, GLuint attribindex,
|
||||
GLint size, GLenum type, GLuint relativeoffset);
|
||||
void _mesa_glthread_DSAAttribFormat(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint attribindex, GLint size, GLenum type,
|
||||
GLuint relativeoffset);
|
||||
void _mesa_glthread_VertexBuffer(struct gl_context *ctx, GLuint bindingindex,
|
||||
GLuint buffer, GLintptr offset, GLsizei stride);
|
||||
void _mesa_glthread_DSAVertexBuffer(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint bindingindex, GLuint buffer,
|
||||
GLintptr offset, GLsizei stride);
|
||||
void _mesa_glthread_DSAVertexBuffers(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint first, GLsizei count,
|
||||
const GLuint *buffers,
|
||||
const GLintptr *offsets,
|
||||
const GLsizei *strides);
|
||||
void _mesa_glthread_BindingDivisor(struct gl_context *ctx, GLuint bindingindex,
|
||||
GLuint divisor);
|
||||
void _mesa_glthread_DSABindingDivisor(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint bindingindex, GLuint divisor);
|
||||
void _mesa_glthread_AttribBinding(struct gl_context *ctx, GLuint attribindex,
|
||||
GLuint bindingindex);
|
||||
void _mesa_glthread_DSAAttribBinding(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint attribindex, GLuint bindingindex);
|
||||
void _mesa_glthread_DSAElementBuffer(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint buffer);
|
||||
void _mesa_glthread_PushClientAttrib(struct gl_context *ctx, GLbitfield mask,
|
||||
bool set_default);
|
||||
void _mesa_glthread_PopClientAttrib(struct gl_context *ctx);
|
||||
|
@@ -113,20 +113,111 @@ upload_vertices(struct gl_context *ctx, unsigned user_buffer_mask,
|
||||
struct glthread_attrib_binding *buffers)
|
||||
{
|
||||
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
|
||||
unsigned attrib_mask_iter = user_buffer_mask;
|
||||
unsigned attrib_mask_iter = vao->Enabled;
|
||||
unsigned num_buffers = 0;
|
||||
|
||||
assert((num_vertices || !(user_buffer_mask & ~vao->NonZeroDivisorMask)) &&
|
||||
(num_instances || !(user_buffer_mask & vao->NonZeroDivisorMask)));
|
||||
|
||||
if (unlikely(vao->BufferInterleaved & user_buffer_mask)) {
|
||||
/* Slower upload path where some buffers reference multiple attribs,
|
||||
* so we have to use 2 while loops instead of 1.
|
||||
*/
|
||||
unsigned start_offset[VERT_ATTRIB_MAX];
|
||||
unsigned end_offset[VERT_ATTRIB_MAX];
|
||||
uint32_t buffer_mask = 0;
|
||||
|
||||
while (attrib_mask_iter) {
|
||||
unsigned i = u_bit_scan(&attrib_mask_iter);
|
||||
unsigned binding_index = vao->Attrib[i].BufferIndex;
|
||||
|
||||
if (!(user_buffer_mask & (1 << binding_index)))
|
||||
continue;
|
||||
|
||||
unsigned stride = vao->Attrib[binding_index].Stride;
|
||||
unsigned instance_div = vao->Attrib[binding_index].Divisor;
|
||||
unsigned element_size = vao->Attrib[i].ElementSize;
|
||||
unsigned offset = vao->Attrib[i].RelativeOffset;
|
||||
unsigned size;
|
||||
|
||||
if (instance_div) {
|
||||
/* Per-instance attrib. */
|
||||
|
||||
/* Figure out how many instances we'll render given instance_div. We
|
||||
* can't use the typical div_round_up() pattern because the CTS uses
|
||||
* instance_div = ~0 for a test, which overflows div_round_up()'s
|
||||
* addition.
|
||||
*/
|
||||
unsigned count = num_instances / instance_div;
|
||||
if (count * instance_div != num_instances)
|
||||
count++;
|
||||
|
||||
offset += stride * start_instance;
|
||||
size = stride * (count - 1) + element_size;
|
||||
} else {
|
||||
/* Per-vertex attrib. */
|
||||
offset += stride * start_vertex;
|
||||
size = stride * (num_vertices - 1) + element_size;
|
||||
}
|
||||
|
||||
unsigned binding_index_bit = 1u << binding_index;
|
||||
|
||||
/* Update upload offsets. */
|
||||
if (!(buffer_mask & binding_index_bit)) {
|
||||
start_offset[binding_index] = offset;
|
||||
end_offset[binding_index] = offset + size;
|
||||
} else {
|
||||
if (offset < start_offset[binding_index])
|
||||
start_offset[binding_index] = offset;
|
||||
if (offset + size > end_offset[binding_index])
|
||||
end_offset[binding_index] = offset + size;
|
||||
}
|
||||
|
||||
buffer_mask |= binding_index_bit;
|
||||
}
|
||||
|
||||
/* Upload buffers. */
|
||||
while (buffer_mask) {
|
||||
struct gl_buffer_object *upload_buffer = NULL;
|
||||
unsigned upload_offset = 0;
|
||||
unsigned start, end;
|
||||
|
||||
unsigned binding_index = u_bit_scan(&buffer_mask);
|
||||
|
||||
start = start_offset[binding_index];
|
||||
end = end_offset[binding_index];
|
||||
assert(start < end);
|
||||
|
||||
const void *ptr = vao->Attrib[binding_index].Pointer;
|
||||
_mesa_glthread_upload(ctx, (uint8_t*)ptr + start,
|
||||
end - start, &upload_offset,
|
||||
&upload_buffer, NULL);
|
||||
assert(upload_buffer);
|
||||
|
||||
buffers[num_buffers].buffer = upload_buffer;
|
||||
buffers[num_buffers].offset = upload_offset - start;
|
||||
buffers[num_buffers].original_pointer = ptr;
|
||||
num_buffers++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Faster path where all attribs are separate. */
|
||||
while (attrib_mask_iter) {
|
||||
unsigned i = u_bit_scan(&attrib_mask_iter);
|
||||
unsigned binding_index = vao->Attrib[i].BufferIndex;
|
||||
|
||||
if (!(user_buffer_mask & (1 << binding_index)))
|
||||
continue;
|
||||
|
||||
struct gl_buffer_object *upload_buffer = NULL;
|
||||
unsigned upload_offset = 0;
|
||||
unsigned stride = vao->Attrib[i].Stride;
|
||||
unsigned instance_div = vao->Attrib[i].Divisor;
|
||||
unsigned stride = vao->Attrib[binding_index].Stride;
|
||||
unsigned instance_div = vao->Attrib[binding_index].Divisor;
|
||||
unsigned element_size = vao->Attrib[i].ElementSize;
|
||||
unsigned offset, size;
|
||||
unsigned offset = vao->Attrib[i].RelativeOffset;
|
||||
unsigned size;
|
||||
|
||||
if (instance_div) {
|
||||
/* Per-instance attrib. */
|
||||
@@ -140,15 +231,15 @@ upload_vertices(struct gl_context *ctx, unsigned user_buffer_mask,
|
||||
if (count * instance_div != num_instances)
|
||||
count++;
|
||||
|
||||
offset = stride * start_instance;
|
||||
offset += stride * start_instance;
|
||||
size = stride * (count - 1) + element_size;
|
||||
} else {
|
||||
/* Per-vertex attrib. */
|
||||
offset = stride * start_vertex;
|
||||
offset += stride * start_vertex;
|
||||
size = stride * (num_vertices - 1) + element_size;
|
||||
}
|
||||
|
||||
const void *ptr = vao->Attrib[i].Pointer;
|
||||
const void *ptr = vao->Attrib[binding_index].Pointer;
|
||||
_mesa_glthread_upload(ctx, (uint8_t*)ptr + offset,
|
||||
size, &upload_offset, &upload_buffer, NULL);
|
||||
assert(upload_buffer);
|
||||
@@ -158,6 +249,7 @@ upload_vertices(struct gl_context *ctx, unsigned user_buffer_mask,
|
||||
buffers[num_buffers].original_pointer = ptr;
|
||||
num_buffers++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -233,7 +325,7 @@ draw_arrays(GLenum mode, GLint first, GLsizei count, GLsizei instance_count,
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->Enabled;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
|
||||
|
||||
if (compiled_into_dlist && ctx->GLThread.inside_dlist) {
|
||||
_mesa_glthread_finish_before(ctx, "DrawArrays");
|
||||
@@ -347,7 +439,7 @@ _mesa_marshal_MultiDrawArrays(GLenum mode, const GLint *first,
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->Enabled;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
|
||||
|
||||
if (ctx->GLThread.inside_dlist)
|
||||
goto sync;
|
||||
@@ -511,7 +603,7 @@ draw_elements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->Enabled;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
|
||||
bool has_user_indices = vao->CurrentElementBufferName == 0;
|
||||
|
||||
if (compiled_into_dlist && ctx->GLThread.inside_dlist)
|
||||
@@ -724,7 +816,7 @@ _mesa_marshal_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
struct glthread_vao *vao = ctx->GLThread.CurrentVAO;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->Enabled;
|
||||
unsigned user_buffer_mask = vao->UserPointerMask & vao->BufferEnabled;
|
||||
bool has_user_indices = vao->CurrentElementBufferName == 0;
|
||||
|
||||
if (ctx->GLThread.inside_dlist)
|
||||
|
@@ -85,7 +85,7 @@ _mesa_glthread_has_non_vbo_vertices_or_indices(const struct gl_context *ctx)
|
||||
|
||||
return ctx->API != API_OPENGL_CORE &&
|
||||
(vao->CurrentElementBufferName == 0 ||
|
||||
(vao->UserPointerMask & vao->Enabled));
|
||||
(vao->UserPointerMask & vao->BufferEnabled));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -95,7 +95,7 @@ _mesa_glthread_has_non_vbo_vertices(const struct gl_context *ctx)
|
||||
const struct glthread_vao *vao = glthread->CurrentVAO;
|
||||
|
||||
return ctx->API != API_OPENGL_CORE &&
|
||||
(vao->UserPointerMask & vao->Enabled);
|
||||
(vao->UserPointerMask & vao->BufferEnabled);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -106,7 +106,7 @@ _mesa_glthread_has_non_vbo_vertices_or_indirect(const struct gl_context *ctx)
|
||||
|
||||
return ctx->API != API_OPENGL_CORE &&
|
||||
(glthread->CurrentDrawIndirectBufferName == 0 ||
|
||||
(vao->UserPointerMask & vao->Enabled));
|
||||
(vao->UserPointerMask & vao->BufferEnabled));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -118,7 +118,7 @@ _mesa_glthread_has_non_vbo_vertices_or_indices_or_indirect(const struct gl_conte
|
||||
return ctx->API != API_OPENGL_CORE &&
|
||||
(glthread->CurrentDrawIndirectBufferName == 0 ||
|
||||
vao->CurrentElementBufferName == 0 ||
|
||||
(vao->UserPointerMask & vao->Enabled));
|
||||
(vao->UserPointerMask & vao->BufferEnabled));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -33,9 +33,6 @@
|
||||
#include "main/dispatch.h"
|
||||
#include "main/varray.h"
|
||||
|
||||
/* TODO:
|
||||
* - Handle ARB_vertex_attrib_binding (incl. EXT_dsa and ARB_dsa)
|
||||
*/
|
||||
|
||||
void
|
||||
_mesa_glthread_reset_vao(struct glthread_vao *vao)
|
||||
@@ -52,6 +49,7 @@ _mesa_glthread_reset_vao(struct glthread_vao *vao)
|
||||
vao->CurrentElementBufferName = 0;
|
||||
vao->UserEnabled = 0;
|
||||
vao->Enabled = 0;
|
||||
vao->BufferEnabled = 0;
|
||||
vao->UserPointerMask = 0;
|
||||
vao->NonZeroDivisorMask = 0;
|
||||
|
||||
@@ -61,8 +59,11 @@ _mesa_glthread_reset_vao(struct glthread_vao *vao)
|
||||
elem_size = 16;
|
||||
|
||||
vao->Attrib[i].ElementSize = elem_size;
|
||||
vao->Attrib[i].RelativeOffset = 0;
|
||||
vao->Attrib[i].BufferIndex = i;
|
||||
vao->Attrib[i].Stride = elem_size;
|
||||
vao->Attrib[i].Divisor = 0;
|
||||
vao->Attrib[i].EnabledAttribCount = 0;
|
||||
vao->Attrib[i].Pointer = NULL;
|
||||
}
|
||||
}
|
||||
@@ -212,6 +213,30 @@ _mesa_glthread_PrimitiveRestartIndex(struct gl_context *ctx, GLuint index)
|
||||
update_primitive_restart(ctx);
|
||||
}
|
||||
|
||||
static inline void
|
||||
enable_buffer(struct glthread_vao *vao, unsigned binding_index)
|
||||
{
|
||||
int attrib_count = ++vao->Attrib[binding_index].EnabledAttribCount;
|
||||
|
||||
if (attrib_count == 1)
|
||||
vao->BufferEnabled |= 1 << binding_index;
|
||||
else if (attrib_count == 2)
|
||||
vao->BufferInterleaved |= 1 << binding_index;
|
||||
}
|
||||
|
||||
static inline void
|
||||
disable_buffer(struct glthread_vao *vao, unsigned binding_index)
|
||||
{
|
||||
int attrib_count = --vao->Attrib[binding_index].EnabledAttribCount;
|
||||
|
||||
if (attrib_count == 0)
|
||||
vao->BufferEnabled &= ~(1 << binding_index);
|
||||
else if (attrib_count == 1)
|
||||
vao->BufferInterleaved &= ~(1 << binding_index);
|
||||
else
|
||||
assert(attrib_count >= 0);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj,
|
||||
gl_vert_attrib attrib, bool enable)
|
||||
@@ -230,17 +255,63 @@ _mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj,
|
||||
if (!vao)
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
vao->UserEnabled |= 1u << attrib;
|
||||
else
|
||||
vao->UserEnabled &= ~(1u << attrib);
|
||||
const unsigned attrib_bit = 1u << attrib;
|
||||
|
||||
/* The generic0 attribute superseeds the position attribute */
|
||||
if (enable && !(vao->UserEnabled & attrib_bit)) {
|
||||
vao->UserEnabled |= attrib_bit;
|
||||
|
||||
/* The generic0 attribute supersedes the position attribute. We need to
|
||||
* update BufferBindingEnabled accordingly.
|
||||
*/
|
||||
if (attrib == VERT_ATTRIB_POS) {
|
||||
if (!(vao->UserEnabled & VERT_BIT_GENERIC0))
|
||||
enable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex);
|
||||
} else {
|
||||
enable_buffer(vao, vao->Attrib[attrib].BufferIndex);
|
||||
|
||||
if (attrib == VERT_ATTRIB_GENERIC0 && vao->UserEnabled & VERT_BIT_POS)
|
||||
disable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex);
|
||||
}
|
||||
} else if (!enable && (vao->UserEnabled & attrib_bit)) {
|
||||
vao->UserEnabled &= ~attrib_bit;
|
||||
|
||||
/* The generic0 attribute supersedes the position attribute. We need to
|
||||
* update BufferBindingEnabled accordingly.
|
||||
*/
|
||||
if (attrib == VERT_ATTRIB_POS) {
|
||||
if (!(vao->UserEnabled & VERT_BIT_GENERIC0))
|
||||
disable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex);
|
||||
} else {
|
||||
disable_buffer(vao, vao->Attrib[attrib].BufferIndex);
|
||||
|
||||
if (attrib == VERT_ATTRIB_GENERIC0 && vao->UserEnabled & VERT_BIT_POS)
|
||||
enable_buffer(vao, vao->Attrib[VERT_ATTRIB_POS].BufferIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/* The generic0 attribute supersedes the position attribute. */
|
||||
vao->Enabled = vao->UserEnabled;
|
||||
if (vao->Enabled & VERT_BIT_GENERIC0)
|
||||
vao->Enabled &= ~VERT_BIT_POS;
|
||||
}
|
||||
|
||||
static void
|
||||
set_attrib_binding(struct glthread_state *glthread, struct glthread_vao *vao,
|
||||
gl_vert_attrib attrib, unsigned new_binding_index)
|
||||
{
|
||||
unsigned old_binding_index = vao->Attrib[attrib].BufferIndex;
|
||||
|
||||
if (old_binding_index != new_binding_index) {
|
||||
vao->Attrib[attrib].BufferIndex = new_binding_index;
|
||||
|
||||
if (vao->Enabled & (1u << attrib)) {
|
||||
/* Update BufferBindingEnabled. */
|
||||
enable_buffer(vao, new_binding_index);
|
||||
disable_buffer(vao, old_binding_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _mesa_glthread_AttribDivisor(struct gl_context *ctx, const GLuint *vaobj,
|
||||
gl_vert_attrib attrib, GLuint divisor)
|
||||
{
|
||||
@@ -253,6 +324,8 @@ void _mesa_glthread_AttribDivisor(struct gl_context *ctx, const GLuint *vaobj,
|
||||
|
||||
vao->Attrib[attrib].Divisor = divisor;
|
||||
|
||||
set_attrib_binding(&ctx->GLThread, vao, attrib, attrib);
|
||||
|
||||
if (divisor)
|
||||
vao->NonZeroDivisorMask |= 1u << attrib;
|
||||
else
|
||||
@@ -273,6 +346,9 @@ attrib_pointer(struct glthread_state *glthread, struct glthread_vao *vao,
|
||||
vao->Attrib[attrib].ElementSize = elem_size;
|
||||
vao->Attrib[attrib].Stride = stride ? stride : elem_size;
|
||||
vao->Attrib[attrib].Pointer = pointer;
|
||||
vao->Attrib[attrib].RelativeOffset = 0;
|
||||
|
||||
set_attrib_binding(glthread, vao, attrib, attrib);
|
||||
|
||||
if (buffer != 0)
|
||||
vao->UserPointerMask &= ~(1u << attrib);
|
||||
@@ -309,6 +385,182 @@ _mesa_glthread_DSAAttribPointer(struct gl_context *ctx, GLuint vaobj,
|
||||
(const void*)offset);
|
||||
}
|
||||
|
||||
static void
|
||||
attrib_format(struct glthread_state *glthread, struct glthread_vao *vao,
|
||||
GLuint attribindex, GLint size, GLenum type,
|
||||
GLuint relativeoffset)
|
||||
{
|
||||
if (attribindex >= VERT_ATTRIB_GENERIC_MAX)
|
||||
return;
|
||||
|
||||
unsigned elem_size = _mesa_bytes_per_vertex_attrib(size, type);
|
||||
|
||||
unsigned i = VERT_ATTRIB_GENERIC(attribindex);
|
||||
vao->Attrib[i].ElementSize = elem_size;
|
||||
vao->Attrib[i].RelativeOffset = relativeoffset;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_AttribFormat(struct gl_context *ctx, GLuint attribindex,
|
||||
GLint size, GLenum type, GLuint relativeoffset)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
|
||||
attrib_format(glthread, glthread->CurrentVAO, attribindex, size, type,
|
||||
relativeoffset);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSAAttribFormat(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint attribindex, GLint size, GLenum type,
|
||||
GLuint relativeoffset)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
struct glthread_vao *vao = lookup_vao(ctx, vaobj);
|
||||
|
||||
if (vao)
|
||||
attrib_format(glthread, vao, attribindex, size, type, relativeoffset);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_vertex_buffer(struct glthread_state *glthread, struct glthread_vao *vao,
|
||||
GLuint bindingindex, GLuint buffer, GLintptr offset,
|
||||
GLsizei stride)
|
||||
{
|
||||
if (bindingindex >= VERT_ATTRIB_GENERIC_MAX)
|
||||
return;
|
||||
|
||||
unsigned i = VERT_ATTRIB_GENERIC(bindingindex);
|
||||
vao->Attrib[i].Pointer = (const void*)offset;
|
||||
vao->Attrib[i].Stride = stride;
|
||||
|
||||
if (buffer != 0)
|
||||
vao->UserPointerMask &= ~(1u << i);
|
||||
else
|
||||
vao->UserPointerMask |= 1u << i;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_VertexBuffer(struct gl_context *ctx, GLuint bindingindex,
|
||||
GLuint buffer, GLintptr offset, GLsizei stride)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
|
||||
bind_vertex_buffer(glthread, glthread->CurrentVAO, bindingindex, buffer,
|
||||
offset, stride);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSAVertexBuffer(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint bindingindex, GLuint buffer,
|
||||
GLintptr offset, GLsizei stride)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
struct glthread_vao *vao = lookup_vao(ctx, vaobj);
|
||||
|
||||
if (vao)
|
||||
bind_vertex_buffer(glthread, vao, bindingindex, buffer, offset, stride);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSAVertexBuffers(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint first, GLsizei count,
|
||||
const GLuint *buffers,
|
||||
const GLintptr *offsets,
|
||||
const GLsizei *strides)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
struct glthread_vao *vao;
|
||||
|
||||
vao = lookup_vao(ctx, vaobj);
|
||||
if (!vao)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
bind_vertex_buffer(glthread, vao, first + i, buffers[i], offsets[i],
|
||||
strides[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
binding_divisor(struct glthread_state *glthread, struct glthread_vao *vao,
|
||||
GLuint bindingindex, GLuint divisor)
|
||||
{
|
||||
if (bindingindex >= VERT_ATTRIB_GENERIC_MAX)
|
||||
return;
|
||||
|
||||
unsigned i = VERT_ATTRIB_GENERIC(bindingindex);
|
||||
vao->Attrib[i].Divisor = divisor;
|
||||
|
||||
if (divisor)
|
||||
vao->NonZeroDivisorMask |= 1u << i;
|
||||
else
|
||||
vao->NonZeroDivisorMask &= ~(1u << i);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_BindingDivisor(struct gl_context *ctx, GLuint bindingindex,
|
||||
GLuint divisor)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
|
||||
binding_divisor(glthread, glthread->CurrentVAO, bindingindex, divisor);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSABindingDivisor(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint bindingindex, GLuint divisor)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
struct glthread_vao *vao = lookup_vao(ctx, vaobj);
|
||||
|
||||
if (vao)
|
||||
binding_divisor(glthread, vao, bindingindex, divisor);
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_AttribBinding(struct gl_context *ctx, GLuint attribindex,
|
||||
GLuint bindingindex)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
|
||||
if (attribindex >= VERT_ATTRIB_GENERIC_MAX ||
|
||||
bindingindex >= VERT_ATTRIB_GENERIC_MAX)
|
||||
return;
|
||||
|
||||
set_attrib_binding(glthread, glthread->CurrentVAO,
|
||||
VERT_ATTRIB_GENERIC(attribindex),
|
||||
VERT_ATTRIB_GENERIC(bindingindex));
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSAAttribBinding(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint attribindex, GLuint bindingindex)
|
||||
{
|
||||
struct glthread_state *glthread = &ctx->GLThread;
|
||||
|
||||
if (attribindex >= VERT_ATTRIB_GENERIC_MAX ||
|
||||
bindingindex >= VERT_ATTRIB_GENERIC_MAX)
|
||||
return;
|
||||
|
||||
struct glthread_vao *vao = lookup_vao(ctx, vaobj);
|
||||
if (vao) {
|
||||
set_attrib_binding(glthread, vao,
|
||||
VERT_ATTRIB_GENERIC(attribindex),
|
||||
VERT_ATTRIB_GENERIC(bindingindex));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_DSAElementBuffer(struct gl_context *ctx, GLuint vaobj,
|
||||
GLuint buffer)
|
||||
{
|
||||
struct glthread_vao *vao = lookup_vao(ctx, vaobj);
|
||||
|
||||
if (vao)
|
||||
vao->CurrentElementBufferName = buffer;
|
||||
}
|
||||
|
||||
void
|
||||
_mesa_glthread_PushClientAttrib(struct gl_context *ctx, GLbitfield mask,
|
||||
bool set_default)
|
||||
|
Reference in New Issue
Block a user