mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 17:30:12 +01:00
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:
parent
fb4011ace9
commit
d1698d4311
8 changed files with 682 additions and 7 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue