Blender  V3.3
gl_vertex_array.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2016 by Mike Erwin. All rights reserved. */
3 
10 
11 #include "gl_batch.hh"
12 #include "gl_context.hh"
13 #include "gl_index_buffer.hh"
14 #include "gl_vertex_buffer.hh"
15 
16 #include "gl_vertex_array.hh"
17 
18 namespace blender::gpu {
19 
20 /* -------------------------------------------------------------------- */
25 static uint16_t vbo_bind(const ShaderInterface *interface,
26  const GPUVertFormat *format,
27  uint v_first,
28  uint v_len,
29  const bool use_instancing)
30 {
31  uint16_t enabled_attrib = 0;
32  const uint attr_len = format->attr_len;
33  uint stride = format->stride;
34  uint offset = 0;
35  GLuint divisor = (use_instancing) ? 1 : 0;
36 
37  for (uint a_idx = 0; a_idx < attr_len; a_idx++) {
38  const GPUVertAttr *a = &format->attrs[a_idx];
39 
40  if (format->deinterleaved) {
41  offset += ((a_idx == 0) ? 0 : format->attrs[a_idx - 1].size) * v_len;
42  stride = a->size;
43  }
44  else {
45  offset = a->offset;
46  }
47 
48  /* This is in fact an offset in memory. */
49  const GLvoid *pointer = (const GLubyte *)(intptr_t)(offset + v_first * stride);
50  const GLenum type = to_gl(static_cast<GPUVertCompType>(a->comp_type));
51 
52  for (uint n_idx = 0; n_idx < a->name_len; n_idx++) {
53  const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
54  const ShaderInput *input = interface->attr_get(name);
55 
56  if (input == nullptr || input->location == -1) {
57  continue;
58  }
59 
60  enabled_attrib |= (1 << input->location);
61 
62  if (ELEM(a->comp_len, 16, 12, 8)) {
63  BLI_assert(a->fetch_mode == GPU_FETCH_FLOAT);
64  BLI_assert(a->comp_type == GPU_COMP_F32);
65  for (int i = 0; i < a->comp_len / 4; i++) {
66  glEnableVertexAttribArray(input->location + i);
67  glVertexAttribDivisor(input->location + i, divisor);
68  glVertexAttribPointer(
69  input->location + i, 4, type, GL_FALSE, stride, (const GLubyte *)pointer + i * 16);
70  }
71  }
72  else {
73  glEnableVertexAttribArray(input->location);
74  glVertexAttribDivisor(input->location, divisor);
75 
76  switch (a->fetch_mode) {
77  case GPU_FETCH_FLOAT:
79  glVertexAttribPointer(input->location, a->comp_len, type, GL_FALSE, stride, pointer);
80  break;
82  glVertexAttribPointer(input->location, a->comp_len, type, GL_TRUE, stride, pointer);
83  break;
84  case GPU_FETCH_INT:
85  glVertexAttribIPointer(input->location, a->comp_len, type, stride, pointer);
86  break;
87  }
88  }
89  }
90  }
91  return enabled_attrib;
92 }
93 
94 void GLVertArray::update_bindings(const GLuint vao,
95  const GPUBatch *batch_, /* Should be GLBatch. */
96  const ShaderInterface *interface,
97  const int base_instance)
98 {
99  const GLBatch *batch = static_cast<const GLBatch *>(batch_);
100  uint16_t attr_mask = interface->enabled_attr_mask_;
101 
102  glBindVertexArray(vao);
103 
104  /* Reverse order so first VBO'S have more prevalence (in term of attribute override). */
105  for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) {
106  GLVertBuf *vbo = batch->verts_(v);
107  if (vbo) {
108  vbo->bind();
109  attr_mask &= ~vbo_bind(interface, &vbo->format, 0, vbo->vertex_len, false);
110  }
111  }
112 
113  for (int v = GPU_BATCH_INST_VBO_MAX_LEN - 1; v > -1; v--) {
114  GLVertBuf *vbo = batch->inst_(v);
115  if (vbo) {
116  vbo->bind();
117  attr_mask &= ~vbo_bind(interface, &vbo->format, base_instance, vbo->vertex_len, true);
118  }
119  }
120 
121  if (attr_mask != 0 && GLContext::vertex_attrib_binding_support) {
122  for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) {
123  if (attr_mask & mask) {
124  GLContext *ctx = GLContext::get();
125  /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style.
126  * Fix issues for some drivers (see T75069). */
127  glBindVertexBuffer(a, ctx->default_attr_vbo_, (intptr_t)0, (intptr_t)0);
128  glEnableVertexAttribArray(a);
129  glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0);
130  glVertexAttribBinding(a, a);
131  }
132  }
133  }
134 
135  if (batch->elem) {
136  /* Binds the index buffer. This state is also saved in the VAO. */
137  static_cast<GLIndexBuf *>(unwrap(batch->elem))->bind();
138  }
139 }
140 
141 void GLVertArray::update_bindings(const GLuint vao,
142  const uint v_first,
143  const GPUVertFormat *format,
144  const ShaderInterface *interface)
145 {
146  glBindVertexArray(vao);
147 
148  vbo_bind(interface, format, v_first, 0, false);
149 }
150 
153 } // namespace blender::gpu
#define BLI_assert(a)
Definition: BLI_assert.h:46
unsigned int uint
Definition: BLI_sys_types.h:67
#define ELEM(...)
GPUBatch
Definition: GPU_batch.h:78
#define GPU_BATCH_INST_VBO_MAX_LEN
Definition: GPU_batch.h:21
#define GPU_BATCH_VBO_MAX_LEN
Definition: GPU_batch.h:20
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei stride
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
@ GPU_FETCH_INT_TO_FLOAT
BLI_INLINE const char * GPU_vertformat_attr_name_get(const GPUVertFormat *format, const GPUVertAttr *attr, uint n_idx)
GPUVertCompType
@ GPU_COMP_F32
ATTR_WARN_UNUSED_RESULT const BMVert * v
static bool vertex_attrib_binding_support
Definition: gl_context.hh:71
static GLContext * get()
Definition: gl_context.hh:117
const ShaderInput * attr_get(const char *name) const
struct @653::@655 batch
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_global KernelShaderEvalInput * input
format
Definition: logImageCore.h:38
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static unsigned a[3]
Definition: RandGen.cpp:78
void update_bindings(const GLuint vao, const GPUBatch *batch, const ShaderInterface *interface, int base_instance)
static Context * unwrap(GPUContext *ctx)
static uint16_t vbo_bind(const ShaderInterface *interface, const GPUVertFormat *format, uint v_first, uint v_len, const bool use_instancing)
static GLenum to_gl(const GPUAttachmentType type)
unsigned short uint16_t
Definition: stdint.h:79
_W64 int intptr_t
Definition: stdint.h:118