Blender V4.3
gl_vertex_array.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 by Mike Erwin. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include "gl_batch.hh"
13#include "gl_context.hh"
14#include "gl_index_buffer.hh"
15#include "gl_storage_buffer.hh"
16#include "gl_vertex_buffer.hh"
17
18#include "gl_vertex_array.hh"
19
20namespace blender::gpu {
21
22/* -------------------------------------------------------------------- */
27static uint16_t vbo_bind(const ShaderInterface *interface,
28 const GPUVertFormat *format,
29 uint v_first,
30 uint v_len,
31 const bool use_instancing)
32{
33 uint16_t enabled_attrib = 0;
34 const uint attr_len = format->attr_len;
35 uint stride = format->stride;
36 uint offset = 0;
37 GLuint divisor = (use_instancing) ? 1 : 0;
38
39 for (uint a_idx = 0; a_idx < attr_len; a_idx++) {
40 const GPUVertAttr *a = &format->attrs[a_idx];
41
42 if (format->deinterleaved) {
43 offset += ((a_idx == 0) ? 0 : format->attrs[a_idx - 1].size) * v_len;
44 stride = a->size;
45 }
46 else {
47 offset = a->offset;
48 }
49
50 /* This is in fact an offset in memory. */
51 const GLvoid *pointer = (const GLubyte *)intptr_t(offset + v_first * stride);
52 const GLenum type = to_gl(static_cast<GPUVertCompType>(a->comp_type));
53
54 for (uint n_idx = 0; n_idx < a->name_len; n_idx++) {
55 const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
56 const ShaderInput *input = interface->attr_get(name);
57
58 if (input == nullptr || input->location == -1) {
59 continue;
60 }
61
62 enabled_attrib |= (1 << input->location);
63
64 if (ELEM(a->comp_len, 16, 12, 8)) {
65 BLI_assert(a->fetch_mode == GPU_FETCH_FLOAT);
66 BLI_assert(a->comp_type == GPU_COMP_F32);
67 for (int i = 0; i < a->comp_len / 4; i++) {
68 glEnableVertexAttribArray(input->location + i);
69 glVertexAttribDivisor(input->location + i, divisor);
70 glVertexAttribPointer(
71 input->location + i, 4, type, GL_FALSE, stride, (const GLubyte *)pointer + i * 16);
72 }
73 }
74 else {
75 glEnableVertexAttribArray(input->location);
76 glVertexAttribDivisor(input->location, divisor);
77
78 switch (a->fetch_mode) {
79 case GPU_FETCH_FLOAT:
81 glVertexAttribPointer(input->location, a->comp_len, type, GL_FALSE, stride, pointer);
82 break;
84 glVertexAttribPointer(input->location, a->comp_len, type, GL_TRUE, stride, pointer);
85 break;
86 case GPU_FETCH_INT:
87 glVertexAttribIPointer(input->location, a->comp_len, type, stride, pointer);
88 break;
89 }
90 }
91 }
92 }
93 return enabled_attrib;
94}
95
96void GLVertArray::update_bindings(const GLuint vao,
97 const Batch *batch_, /* Should be GLBatch. */
98 const ShaderInterface *interface,
99 const int base_instance)
100{
101 const GLBatch *batch = static_cast<const GLBatch *>(batch_);
102 uint16_t attr_mask = interface->enabled_attr_mask_;
103
104 glBindVertexArray(vao);
105
106 /* Reverse order so first VBO'S have more prevalence (in term of attribute override). */
107 for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) {
108 GLVertBuf *vbo = batch->verts_(v);
109 if (vbo) {
110 vbo->bind();
111 attr_mask &= ~vbo_bind(interface, &vbo->format, 0, vbo->vertex_len, false);
112 }
113 }
114
115 for (int v = GPU_BATCH_INST_VBO_MAX_LEN - 1; v > -1; v--) {
116 GLVertBuf *vbo = batch->inst_(v);
117 if (vbo) {
118 vbo->bind();
119 attr_mask &= ~vbo_bind(interface, &vbo->format, base_instance, vbo->vertex_len, true);
120 }
121 }
122
123 if (batch->resource_id_buf) {
124 const ShaderInput *input = interface->attr_get("drw_ResourceID");
125 int component_len = 1;
126 if (input == nullptr) {
127 /* Uses Custom IDs */
128 input = interface->attr_get("vertex_in_drw_ResourceID");
129 component_len = 2;
130 }
131 if (input) {
132 dynamic_cast<GLStorageBuf *>(unwrap(batch->resource_id_buf))->bind_as(GL_ARRAY_BUFFER);
133 glEnableVertexAttribArray(input->location);
134 glVertexAttribDivisor(input->location, 1);
135 glVertexAttribIPointer(
136 input->location, component_len, to_gl(GPU_COMP_I32), 0, (GLvoid *)nullptr);
137 attr_mask &= ~(1 << input->location);
138 }
139 }
140
141 if (attr_mask != 0) {
142 for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) {
143 if (attr_mask & mask) {
144 GLContext *ctx = GLContext::get();
145 /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style.
146 * Fix issues for some drivers (see #75069). */
147 glBindVertexBuffer(a, ctx->default_attr_vbo_, intptr_t(0), intptr_t(0));
148 glEnableVertexAttribArray(a);
149 glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0);
150 glVertexAttribBinding(a, a);
151 }
152 }
153 }
154
155 if (batch->elem) {
156 /* Binds the index buffer. This state is also saved in the VAO. */
157 static_cast<GLIndexBuf *>(batch->elem)->bind();
158 }
159}
160
161void GLVertArray::update_bindings(const GLuint vao,
162 const uint v_first,
163 const GPUVertFormat *format,
164 const ShaderInterface *interface)
165{
166 glBindVertexArray(vao);
167
168 vbo_bind(interface, format, v_first, 0, false);
169}
170
173} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int uint
#define ELEM(...)
#define GPU_BATCH_INST_VBO_MAX_LEN
Definition GPU_batch.hh:33
#define GPU_BATCH_VBO_MAX_LEN
Definition GPU_batch.hh:32
BLI_INLINE const char * GPU_vertformat_attr_name_get(const GPUVertFormat *format, const GPUVertAttr *attr, uint n_idx)
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
@ GPU_FETCH_INT_TO_FLOAT
GPUVertCompType
@ GPU_COMP_F32
@ GPU_COMP_I32
ATTR_WARN_UNUSED_RESULT const BMVert * v
static GLContext * get()
const ShaderInput * attr_get(const char *name) const
struct @620::@622 batch
format
void update_bindings(const GLuint vao, const Batch *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