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:
Marek Olšák
2020-05-30 17:42:46 -04:00
committed by Marge Bot
parent 66c2c9c6a9
commit a2d7f4fe5a
6 changed files with 443 additions and 46 deletions

View File

@@ -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" />

View File

@@ -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"/>

View File

@@ -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);

View File

@@ -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)

View File

@@ -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));
}

View File

@@ -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)