mesa: Compute effective buffer bindings in the vao.

Compute VAO buffer binding information past the position/generic0 mapping.
Scan for duplicate buffer bindings and collapse them into derived
effective buffer binding index and effective attribute mask variables.
Provide a set of helper functions to access the distilled
information in the VAO. All of them prefixed with _mesa_draw_...
to indicate that they are meant to query draw information.

v2: Also group user space arrays containing interleaved arrays.
    Add _Eff*Offset to be copied on attribute and binding copy.
    Update comments.

Reviewed-by: Brian Paul <brianp@vmware.com>
Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
This commit is contained in:
Mathias Fröhlich 2018-04-01 20:18:36 +02:00 committed by Mathias Fröhlich
parent fb4011ace9
commit d1698d4311
8 changed files with 682 additions and 7 deletions

View file

@ -451,8 +451,116 @@ _mesa_initialize_vao(struct gl_context *ctx,
/**
* Updates the derived gl_vertex_arrays when a gl_array_attributes
* or a gl_vertex_buffer_binding has changed.
* Compute the offset range for the provided binding.
*
* This is a helper function for the below.
*/
static void
compute_vbo_offset_range(const struct gl_vertex_array_object *vao,
const struct gl_vertex_buffer_binding *binding,
GLsizeiptr* min, GLsizeiptr* max)
{
/* The function is meant to work on VBO bindings */
assert(_mesa_is_bufferobj(binding->BufferObj));
/* Start with an inverted range of relative offsets. */
GLuint min_offset = ~(GLuint)0;
GLuint max_offset = 0;
/* We work on the unmapped originaly VAO array entries. */
GLbitfield mask = vao->_Enabled & binding->_BoundArrays;
/* The binding should be active somehow, not to return inverted ranges */
assert(mask);
while (mask) {
const int i = u_bit_scan(&mask);
const GLuint off = vao->VertexAttrib[i].RelativeOffset;
min_offset = MIN2(off, min_offset);
max_offset = MAX2(off, max_offset);
}
*min = binding->Offset + (GLsizeiptr)min_offset;
*max = binding->Offset + (GLsizeiptr)max_offset;
}
/**
* Update the unique binding and pos/generic0 map tracking in the vao.
*
* The idea is to build up information in the vao so that a consuming
* backend can execute the following to set up buffer and vertex element
* information:
*
* const GLbitfield inputs_read = VERT_BIT_ALL; // backend vp inputs
*
* // Attribute data is in a VBO.
* GLbitfield vbomask = inputs_read & _mesa_draw_vbo_array_bits(ctx);
* while (vbomask) {
* // The attribute index to start pulling a binding
* const gl_vert_attrib i = ffs(vbomask) - 1;
* const struct gl_vertex_buffer_binding *const binding
* = _mesa_draw_buffer_binding(vao, i);
*
* <insert code to handle the vertex buffer object at binding>
*
* const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
* GLbitfield attrmask = vbomask & boundmask;
* assert(attrmask);
* // Walk attributes belonging to the binding
* while (attrmask) {
* const gl_vert_attrib attr = u_bit_scan(&attrmask);
* const struct gl_array_attributes *const attrib
* = _mesa_draw_array_attrib(vao, attr);
*
* <insert code to handle the vertex element refering to the binding>
* }
* vbomask &= ~boundmask;
* }
*
* // Process user space buffers
* GLbitfield usermask = inputs_read & _mesa_draw_user_array_bits(ctx);
* while (usermask) {
* // The attribute index to start pulling a binding
* const gl_vert_attrib i = ffs(usermask) - 1;
* const struct gl_vertex_buffer_binding *const binding
* = _mesa_draw_buffer_binding(vao, i);
*
* <insert code to handle a set of interleaved user space arrays at binding>
*
* const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
* GLbitfield attrmask = usermask & boundmask;
* assert(attrmask);
* // Walk interleaved attributes with a common stride and instance divisor
* while (attrmask) {
* const gl_vert_attrib attr = u_bit_scan(&attrmask);
* const struct gl_array_attributes *const attrib
* = _mesa_draw_array_attrib(vao, attr);
*
* <insert code to handle non vbo vertex arrays>
* }
* usermask &= ~boundmask;
* }
*
* // Process values that should have better been uniforms in the application
* GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
* while (curmask) {
* const gl_vert_attrib attr = u_bit_scan(&curmask);
* const struct gl_array_attributes *const attrib
* = _mesa_draw_current_attrib(ctx, attr);
*
* <insert code to handle current values>
* }
*
*
* Note that the scan below must not incoporate any context state.
* The rationale is that once a VAO is finalized it should not
* be touched anymore. That means, do not incorporate the
* gl_context::Array._DrawVAOEnabledAttribs bitmask into this scan.
* A backend driver may further reduce the handled vertex processing
* inputs based on their vertex shader inputs. But scanning for
* collapsable binding points to reduce relocs is done based on the
* enabled arrays.
* Also VAOs may be shared between contexts due to their use in dlists
* thus no context state should bleed into the VAO.
*/
void
_mesa_update_vao_derived_arrays(struct gl_context *ctx,
@ -461,11 +569,281 @@ _mesa_update_vao_derived_arrays(struct gl_context *ctx,
/* Make sure we do not run into problems with shared objects */
assert(!vao->SharedAndImmutable || vao->NewArrays == 0);
/*
* Stay tuned, the next series scans for duplicate bindings in this
* function. So that drivers can easily know the minimum unique set
* of bindings.
/* Limit used for common binding scanning below. */
const GLsizeiptr MaxRelativeOffset =
ctx->Const.MaxVertexAttribRelativeOffset;
/* The gl_vertex_array_object::_AttributeMapMode denotes the way
* VERT_ATTRIB_{POS,GENERIC0} mapping is done.
*
* This mapping is used to map between the OpenGL api visible
* VERT_ATTRIB_* arrays to mesa driver arrayinputs or shader inputs.
* The mapping only depends on the enabled bits of the
* VERT_ATTRIB_{POS,GENERIC0} arrays and is tracked in the VAO.
*
* This map needs to be applied when finally translating to the bitmasks
* as consumed by the driver backends. The duplicate scanning is here
* can as well be done in the OpenGL API numbering without this map.
*/
const gl_attribute_map_mode mode = vao->_AttributeMapMode;
/* Enabled array bits. */
const GLbitfield enabled = vao->_Enabled;
/* VBO array bits. */
const GLbitfield vbos = vao->VertexAttribBufferMask;
/* Compute and store effectively enabled and mapped vbo arrays */
vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos);
/* Walk those enabled arrays that have a real vbo attached */
GLbitfield mask = enabled;
while (mask) {
/* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
const int i = ffs(mask) - 1;
/* The binding from the first to be processed attribute. */
const GLuint bindex = vao->VertexAttrib[i].BufferBindingIndex;
struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
/* The scan goes different for user space arrays than vbos */
if (_mesa_is_bufferobj(binding->BufferObj)) {
/* The bound arrays. */
const GLbitfield bound = enabled & binding->_BoundArrays;
/* Start this current effective binding with the actual bound arrays */
GLbitfield eff_bound_arrays = bound;
/*
* If there is nothing left to scan just update the effective binding
* information. If the VAO is already only using a single binding point
* we end up here. So the overhead of this scan for an application
* carefully preparing the VAO for draw is low.
*/
GLbitfield scanmask = mask & vbos & ~bound;
/* Is there something left to scan? */
if (scanmask == 0) {
/* Just update the back reference from the attrib to the binding and
* the effective offset.
*/
GLbitfield attrmask = eff_bound_arrays;
while (attrmask) {
const int j = u_bit_scan(&attrmask);
struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
/* Update the index into the common binding point and offset */
attrib2->_EffBufferBindingIndex = bindex;
attrib2->_EffRelativeOffset = attrib2->RelativeOffset;
assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
/* Only enabled arrays shall appear in the unique bindings */
assert(attrib2->Enabled);
}
/* Finally this is the set of effectively bound arrays with the
* original binding offset.
*/
binding->_EffOffset = binding->Offset;
/* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
binding->_EffBoundArrays =
_mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
} else {
/* In the VBO case, scan for attribute/binding
* combinations with relative bindings in the range of
* [0, ctx->Const.MaxVertexAttribRelativeOffset].
* Note that this does also go beyond just interleaved arrays
* as long as they use the same VBO, binding parameters and the
* offsets stay within bounds that the backend still can handle.
*/
GLsizeiptr min_offset, max_offset;
compute_vbo_offset_range(vao, binding, &min_offset, &max_offset);
assert(max_offset <= min_offset + MaxRelativeOffset);
/* Now scan. */
while (scanmask) {
/* Do not use u_bit_scan as we can walk multiple
* attrib arrays at once
*/
const int j = ffs(scanmask) - 1;
const struct gl_array_attributes *attrib2 =
&vao->VertexAttrib[j];
const struct gl_vertex_buffer_binding *binding2 =
&vao->BufferBinding[attrib2->BufferBindingIndex];
/* Remove those attrib bits from the mask that are bound to the
* same effective binding point.
*/
const GLbitfield bound2 = enabled & binding2->_BoundArrays;
scanmask &= ~bound2;
/* Check if we have an identical binding */
if (binding->Stride != binding2->Stride)
continue;
if (binding->InstanceDivisor != binding2->InstanceDivisor)
continue;
if (binding->BufferObj != binding2->BufferObj)
continue;
/* Check if we can fold both bindings into a common binding */
GLsizeiptr min_offset2, max_offset2;
compute_vbo_offset_range(vao, binding2,
&min_offset2, &max_offset2);
/* If the relative offset is within the limits ... */
if (min_offset + MaxRelativeOffset < max_offset2)
continue;
if (min_offset2 + MaxRelativeOffset < max_offset)
continue;
/* ... add this array to the effective binding */
eff_bound_arrays |= bound2;
min_offset = MIN2(min_offset, min_offset2);
max_offset = MAX2(max_offset, max_offset2);
assert(max_offset <= min_offset + MaxRelativeOffset);
}
/* Update the back reference from the attrib to the binding */
GLbitfield attrmask = eff_bound_arrays;
while (attrmask) {
const int j = u_bit_scan(&attrmask);
struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
const struct gl_vertex_buffer_binding *binding2 =
&vao->BufferBinding[attrib2->BufferBindingIndex];
/* Update the index into the common binding point and offset */
attrib2->_EffBufferBindingIndex = bindex;
attrib2->_EffRelativeOffset =
binding2->Offset + attrib2->RelativeOffset - min_offset;
assert(attrib2->_EffRelativeOffset <= MaxRelativeOffset);
/* Only enabled arrays shall appear in the unique bindings */
assert(attrib2->Enabled);
}
/* Finally this is the set of effectively bound arrays */
binding->_EffOffset = min_offset;
/* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
binding->_EffBoundArrays =
_mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
}
/* Mark all the effective bound arrays as processed. */
mask &= ~eff_bound_arrays;
} else {
/* Scanning of common bindings for user space arrays.
*/
const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
const GLbitfield bound = VERT_BIT(i);
/* Note that user space array pointers can only happen using a one
* to one binding point to array mapping.
* The OpenGL 4.x/ARB_vertex_attrib_binding api does not support
* user space arrays collected at multiple binding points.
* The only provider of user space interleaved arrays with a single
* binding point is the mesa internal vbo module. But that one
* provides a perfect interleaved set of arrays.
*
* If this would not be true we would potentially get attribute arrays
* with user space pointers that may not lie within the
* MaxRelativeOffset range but still attached to a single binding.
* Then we would need to store the effective attribute and binding
* grouping information in a seperate array beside
* gl_array_attributes/gl_vertex_buffer_binding.
*/
assert(_mesa_bitcount(binding->_BoundArrays & vao->_Enabled) == 1
|| (vao->_Enabled & ~binding->_BoundArrays) == 0);
/* Start this current effective binding with the array */
GLbitfield eff_bound_arrays = bound;
const GLubyte *ptr = attrib->Ptr;
unsigned vertex_end = attrib->_ElementSize;
/* Walk other user space arrays and see which are interleaved
* using the same binding parameters.
*/
GLbitfield scanmask = mask & ~vbos & ~bound;
while (scanmask) {
const int j = u_bit_scan(&scanmask);
const struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
const struct gl_vertex_buffer_binding *binding2 =
&vao->BufferBinding[attrib2->BufferBindingIndex];
/* See the comment at the same assert above. */
assert(_mesa_bitcount(binding2->_BoundArrays & vao->_Enabled) == 1
|| (vao->_Enabled & ~binding->_BoundArrays) == 0);
/* Check if we have an identical binding */
if (binding->Stride != binding2->Stride)
continue;
if (binding->InstanceDivisor != binding2->InstanceDivisor)
continue;
if (ptr <= attrib2->Ptr) {
if (ptr + binding->Stride < attrib2->Ptr + attrib2->_ElementSize)
continue;
unsigned end = attrib2->Ptr + attrib2->_ElementSize - ptr;
vertex_end = MAX2(vertex_end, end);
} else {
if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
continue;
vertex_end += (GLsizei)(ptr - attrib2->Ptr);
ptr = attrib2->Ptr;
}
/* User space buffer object */
assert(!_mesa_is_bufferobj(binding2->BufferObj));
eff_bound_arrays |= VERT_BIT(j);
}
/* Update the back reference from the attrib to the binding */
GLbitfield attrmask = eff_bound_arrays;
while (attrmask) {
const int j = u_bit_scan(&attrmask);
struct gl_array_attributes *attrib2 = &vao->VertexAttrib[j];
/* Update the index into the common binding point and the offset */
attrib2->_EffBufferBindingIndex = bindex;
attrib2->_EffRelativeOffset = attrib2->Ptr - ptr;
assert(attrib2->_EffRelativeOffset <= binding->Stride);
/* Only enabled arrays shall appear in the unique bindings */
assert(attrib2->Enabled);
}
/* Finally this is the set of effectively bound arrays */
binding->_EffOffset = (GLintptr)ptr;
/* The bound arrays past the VERT_ATTRIB_{POS,GENERIC0} mapping. */
binding->_EffBoundArrays =
_mesa_vao_enable_to_vp_inputs(mode, eff_bound_arrays);
/* Mark all the effective bound arrays as processed. */
mask &= ~eff_bound_arrays;
}
}
#ifndef NDEBUG
/* Make sure the above code works as expected. */
for (gl_vert_attrib attr = 0; attr < VERT_ATTRIB_MAX; ++attr) {
/* Query the original api defined attrib/binding information ... */
const unsigned char *const map =_mesa_vao_attribute_map[mode];
const struct gl_array_attributes *attrib = &vao->VertexAttrib[map[attr]];
if (attrib->Enabled) {
const struct gl_vertex_buffer_binding *binding =
&vao->BufferBinding[attrib->BufferBindingIndex];
/* ... and compare that with the computed attrib/binding */
const struct gl_vertex_buffer_binding *binding2 =
&vao->BufferBinding[attrib->_EffBufferBindingIndex];
assert(binding->Stride == binding2->Stride);
assert(binding->InstanceDivisor == binding2->InstanceDivisor);
assert(binding->BufferObj == binding2->BufferObj);
if (_mesa_is_bufferobj(binding->BufferObj)) {
assert(attrib->_EffRelativeOffset <= MaxRelativeOffset);
assert(binding->Offset + attrib->RelativeOffset ==
binding2->_EffOffset + attrib->_EffRelativeOffset);
} else {
assert(attrib->_EffRelativeOffset < binding->Stride);
assert((GLintptr)attrib->Ptr ==
binding2->_EffOffset + attrib->_EffRelativeOffset);
}
}
}
#endif
}

View file

@ -30,6 +30,7 @@
#include "glheader.h"
#include "mtypes.h"
#include "glformats.h"
#include "vbo/vbo.h"
struct gl_context;
@ -146,6 +147,191 @@ _mesa_get_vao_vp_inputs(const struct gl_vertex_array_object *vao)
}
/**
* Helper functions for consuming backends to walk the
* ctx->Array._DrawVAO for driver side array setup.
* Note that mesa provides preprocessed minimal binding information
* in the VAO. See _mesa_update_vao_derived_arrays for documentation.
*/
/**
* Return enabled vertex attribute bits for draw.
*/
static inline GLbitfield
_mesa_draw_array_bits(const struct gl_context *ctx)
{
return ctx->Array._DrawVAOEnabledAttribs;
}
/**
* Return enabled buffer object vertex attribute bits for draw.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline GLbitfield
_mesa_draw_vbo_array_bits(const struct gl_context *ctx)
{
const struct gl_vertex_array_object *const vao = ctx->Array._DrawVAO;
assert(vao->NewArrays == 0);
return vao->_EffEnabledVBO & ctx->Array._DrawVAOEnabledAttribs;
}
/**
* Return enabled user space vertex attribute bits for draw.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline GLbitfield
_mesa_draw_user_array_bits(const struct gl_context *ctx)
{
const struct gl_vertex_array_object *const vao = ctx->Array._DrawVAO;
assert(vao->NewArrays == 0);
return ~vao->_EffEnabledVBO & ctx->Array._DrawVAOEnabledAttribs;
}
/**
* Return enabled current values attribute bits for draw.
*/
static inline GLbitfield
_mesa_draw_current_bits(const struct gl_context *ctx)
{
return ~ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_ALL;
}
/**
* Return vertex buffer binding provided the attribute struct.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline const struct gl_vertex_buffer_binding*
_mesa_draw_buffer_binding_from_attrib(const struct gl_vertex_array_object *vao,
const struct gl_array_attributes *attrib)
{
assert(vao->NewArrays == 0);
return &vao->BufferBinding[attrib->_EffBufferBindingIndex];
}
/**
* Return vertex array attribute provided the attribute number.
*/
static inline const struct gl_array_attributes*
_mesa_draw_array_attrib(const struct gl_vertex_array_object *vao,
gl_vert_attrib attr)
{
assert(vao->NewArrays == 0);
const gl_attribute_map_mode map_mode = vao->_AttributeMapMode;
return &vao->VertexAttrib[_mesa_vao_attribute_map[map_mode][attr]];
}
/**
* Return vertex buffer binding provided an attribute number.
*/
static inline const struct gl_vertex_buffer_binding*
_mesa_draw_buffer_binding(const struct gl_vertex_array_object *vao,
gl_vert_attrib attr)
{
const struct gl_array_attributes *const attrib
= _mesa_draw_array_attrib(vao, attr);
return _mesa_draw_buffer_binding_from_attrib(vao, attrib);
}
/**
* Return vertex attribute bits bound at the provided binding.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline GLbitfield
_mesa_draw_bound_attrib_bits(const struct gl_vertex_buffer_binding *binding)
{
return binding->_EffBoundArrays;
}
/**
* Return the vertex offset bound at the provided binding.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline GLintptr
_mesa_draw_binding_offset(const struct gl_vertex_buffer_binding *binding)
{
return binding->_EffOffset;
}
/**
* Return the relative offset of the provided attrib.
*
* Needs the a fully updated VAO ready for draw.
*/
static inline GLushort
_mesa_draw_attributes_relative_offset(const struct gl_array_attributes *attrib)
{
return attrib->_EffRelativeOffset;
}
/**
* Return a current value vertex array attribute provided the attribute number.
*/
static inline const struct gl_array_attributes*
_mesa_draw_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
{
return _vbo_current_attrib(ctx, attr);
}
/**
* Return true if we have the VERT_ATTRIB_EDGEFLAG array enabled.
*/
static inline bool
_mesa_draw_edge_flag_array_enabled(const struct gl_context *ctx)
{
return ctx->Array._DrawVAOEnabledAttribs & VERT_BIT_EDGEFLAG;
}
/**
* Return the attrib for the given attribute.
*/
static inline const struct gl_array_attributes*
_mesa_draw_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
{
if (ctx->Array._DrawVAOEnabledAttribs & VERT_BIT(attr)) {
const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
return _mesa_draw_array_attrib(vao, attr);
} else {
return _vbo_current_attrib(ctx, attr);
}
}
/**
* Return the attrib, binding pair for the given attribute.
*/
static inline void
_mesa_draw_attrib_and_binding(const struct gl_context *ctx, gl_vert_attrib attr,
const struct gl_array_attributes **attrib,
const struct gl_vertex_buffer_binding **binding)
{
if (ctx->Array._DrawVAOEnabledAttribs & VERT_BIT(attr)) {
const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
*attrib = _mesa_draw_array_attrib(vao, attr);
*binding = _mesa_draw_buffer_binding_from_attrib(vao, *attrib);
} else {
*attrib = _vbo_current_attrib(ctx, attr);
*binding = _vbo_current_binding(ctx);
}
}
/*
* API functions
*/

View file

@ -1552,6 +1552,7 @@ copy_array_object(struct gl_context *ctx,
/* _Enabled must be the same than on push */
dest->_Enabled = src->_Enabled;
dest->_EffEnabledVBO = src->_EffEnabledVBO;
/* The bitmask of bound VBOs needs to match the VertexBinding array */
dest->VertexAttribBufferMask = src->VertexAttribBufferMask;
dest->_AttributeMapMode = src->_AttributeMapMode;

View file

@ -1426,6 +1426,32 @@ struct gl_array_attributes
unsigned _ElementSize:8; /**< Size of each element in bytes */
/** Index into gl_vertex_array_object::BufferBinding[] array */
unsigned BufferBindingIndex:6;
/**
* Derived effective buffer binding index
*
* Index into the gl_vertex_buffer_binding array of the vao.
* Similar to BufferBindingIndex, but with the mapping of the
* position/generic0 attributes applied and with identical
* gl_vertex_buffer_binding entries collapsed to a single
* entry within the vao.
*
* The value is valid past calling _mesa_update_vao_derived_arrays.
* Note that _mesa_update_vao_derived_arrays is called when binding
* the VAO to Array._DrawVAO.
*/
unsigned _EffBufferBindingIndex:6;
/**
* Derived effective relative offset.
*
* Relative offset to the effective buffers offset in
* gl_vertex_buffer_binding::_EffOffset.
*
* The value is valid past calling _mesa_update_vao_derived_arrays.
* Note that _mesa_update_vao_derived_arrays is called when binding
* the VAO to Array._DrawVAO.
*/
GLushort _EffRelativeOffset;
};
@ -1441,6 +1467,35 @@ struct gl_vertex_buffer_binding
GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
struct gl_buffer_object *BufferObj; /**< GL_ARB_vertex_buffer_object */
GLbitfield _BoundArrays; /**< Arrays bound to this binding point */
/**
* Derived effective bound arrays.
*
* The effective binding handles enabled arrays past the
* position/generic0 attribute mapping and reduces the refered
* gl_vertex_buffer_binding entries to a unique subset.
*
* The value is valid past calling _mesa_update_vao_derived_arrays.
* Note that _mesa_update_vao_derived_arrays is called when binding
* the VAO to Array._DrawVAO.
*/
GLbitfield _EffBoundArrays;
/**
* Derived offset.
*
* The absolute offset to that we can collapse some attributes
* to this unique effective binding.
* For user space array bindings this contains the smallest pointer value
* in the bound and interleaved arrays.
* For VBO bindings this contains an offset that lets the attributes
* _EffRelativeOffset stay positive and in bounds with
* Const.MaxVertexAttribRelativeOffset
*
* The value is valid past calling _mesa_update_vao_derived_arrays.
* Note that _mesa_update_vao_derived_arrays is called when binding
* the VAO to Array._DrawVAO.
*/
GLintptr _EffOffset;
};
@ -1495,6 +1550,15 @@ struct gl_vertex_array_object
/** Mask of VERT_BIT_* values indicating which arrays are enabled */
GLbitfield _Enabled;
/**
* Mask of VERT_BIT_* enabled arrays past position/generic0 mapping
*
* The value is valid past calling _mesa_update_vao_derived_arrays.
* Note that _mesa_update_vao_derived_arrays is called when binding
* the VAO to Array._DrawVAO.
*/
GLbitfield _EffEnabledVBO;
/** Denotes the way the position/generic0 attribute is mapped */
gl_attribute_map_mode _AttributeMapMode;

View file

@ -604,6 +604,11 @@ update_array(struct gl_context *ctx,
/* The Stride and Ptr fields are not set by update_array_format() */
struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
array->Stride = stride;
/* For updating the pointer we would need to add the vao->NewArrays flag
* to the VAO. But but that is done already unconditionally in
* _mesa_update_array_format called above.
*/
assert((vao->NewArrays | ~vao->_Enabled) & VERT_BIT(attrib));
array->Ptr = ptr;
/* Update the vertex buffer binding */
@ -2868,6 +2873,8 @@ _mesa_copy_vertex_attrib_array(struct gl_context *ctx,
dst->Ptr = src->Ptr;
dst->Enabled = src->Enabled;
dst->_ElementSize = src->_ElementSize;
dst->_EffBufferBindingIndex = src->_EffBufferBindingIndex;
dst->_EffRelativeOffset = src->_EffRelativeOffset;
}
void
@ -2879,6 +2886,8 @@ _mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
dst->Stride = src->Stride;
dst->InstanceDivisor = src->InstanceDivisor;
dst->_BoundArrays = src->_BoundArrays;
dst->_EffBoundArrays = src->_EffBoundArrays;
dst->_EffOffset = src->_EffOffset;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
}

View file

@ -186,6 +186,14 @@ void
_vbo_update_inputs(struct gl_context *ctx, struct vbo_inputs *inputs);
const struct gl_array_attributes*
_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr);
const struct gl_vertex_buffer_binding*
_vbo_current_binding(const struct gl_context *ctx);
void GLAPIENTRY
_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);

View file

@ -234,6 +234,23 @@ _vbo_DestroyContext(struct gl_context *ctx)
}
const struct gl_array_attributes *
_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
{
const struct vbo_context *vbo = vbo_context_const(ctx);
const gl_vertex_processing_mode vmp = ctx->VertexProgram._VPMode;
return &vbo->current[_vbo_attribute_alias_map[vmp][attr]];
}
const struct gl_vertex_buffer_binding *
_vbo_current_binding(const struct gl_context *ctx)
{
const struct vbo_context *vbo = vbo_context_const(ctx);
return &vbo->binding;
}
/*
* Helper function for _vbo_draw_indirect below that additionally takes a zero
* initialized array of _mesa_prim scratch space memory as the last argument.

View file

@ -60,6 +60,13 @@ vbo_context(struct gl_context *ctx)
}
static inline const struct vbo_context *
vbo_context_const(const struct gl_context *ctx)
{
return ctx->vbo_context;
}
/**
* Array to apply the fixed function material aliasing map to
* an attribute value used in vbo processing inputs to an attribute
@ -209,7 +216,12 @@ _vbo_set_attrib_format(struct gl_context *ctx,
const GLboolean doubles = vbo_attrtype_to_double_flag(type);
_mesa_update_array_format(ctx, vao, attr, size, type, GL_RGBA,
GL_FALSE, integer, doubles, offset);
/* Ptr for userspace arrays */
/* Ptr for userspace arrays.
* For updating the pointer we would need to add the vao->NewArrays flag
* to the VAO. But but that is done already unconditionally in
* _mesa_update_array_format called above.
*/
assert((vao->NewArrays | ~vao->_Enabled) & VERT_BIT(attr));
vao->VertexAttrib[attr].Ptr = ADD_POINTERS(buffer_offset, offset);
}