Blender V4.5
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
8
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/* -------------------------------------------------------------------- */
25
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)) {
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_TRUE, stride, pointer);
82 break;
83 case GPU_FETCH_INT:
84 glVertexAttribIPointer(input->location, a->comp_len, type, stride, pointer);
85 break;
86 }
87 }
88 }
89 }
90 return enabled_attrib;
91}
92
93void GLVertArray::update_bindings(const GLuint vao,
94 const Batch *batch_, /* Should be GLBatch. */
96 const int base_instance)
97{
98 const GLBatch *batch = static_cast<const GLBatch *>(batch_);
99 uint16_t attr_mask = interface->enabled_attr_mask_;
100
101 glBindVertexArray(vao);
102
103 /* Reverse order so first VBO'S have more prevalence (in term of attribute override). */
104 for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) {
105 GLVertBuf *vbo = batch->verts_(v);
106 if (vbo) {
107 vbo->bind();
108 attr_mask &= ~vbo_bind(interface, &vbo->format, 0, vbo->vertex_len, false);
109 }
110 }
111
112 for (int v = GPU_BATCH_INST_VBO_MAX_LEN - 1; v > -1; v--) {
113 GLVertBuf *vbo = batch->inst_(v);
114 if (vbo) {
115 vbo->bind();
116 attr_mask &= ~vbo_bind(interface, &vbo->format, base_instance, vbo->vertex_len, true);
117 }
118 }
119
120 if (batch->resource_id_buf) {
121 const ShaderInput *input = interface->attr_get("in_resource_id");
122 int component_len = 1;
123 if (input == nullptr) {
124 /* Uses Custom IDs */
125 input = interface->attr_get("in_resource_id_custom_id");
126 component_len = 2;
127 }
128 if (input) {
129 dynamic_cast<GLStorageBuf *>(unwrap(batch->resource_id_buf))->bind_as(GL_ARRAY_BUFFER);
130 glEnableVertexAttribArray(input->location);
131 glVertexAttribDivisor(input->location, 1);
132 glVertexAttribIPointer(
133 input->location, component_len, to_gl(GPU_COMP_U32), 0, (GLvoid *)nullptr);
134 attr_mask &= ~(1 << input->location);
135 }
136 }
137
138 if (attr_mask != 0) {
139 for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) {
140 if (attr_mask & mask) {
141 GLContext *ctx = GLContext::get();
142 /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style.
143 * Fix issues for some drivers (see #75069). */
144 glBindVertexBuffer(a, ctx->default_attr_vbo_, intptr_t(0), intptr_t(0));
145 glEnableVertexAttribArray(a);
146 glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0);
147 glVertexAttribBinding(a, a);
148 }
149 }
150 }
151
152 if (batch->elem) {
153 /* Binds the index buffer. This state is also saved in the VAO. */
154 static_cast<GLIndexBuf *>(batch->elem)->bind();
155 }
156}
157
158void GLVertArray::update_bindings(const GLuint vao,
159 const uint v_first,
160 const GPUVertFormat *format,
162{
163 glBindVertexArray(vao);
164
165 vbo_bind(interface, format, v_first, 0, false);
166}
167
169
170} // namespace blender::gpu
#define BLI_assert(a)
Definition BLI_assert.h:46
unsigned int uint
#define ELEM(...)
static constexpr int GPU_BATCH_VBO_MAX_LEN
Definition GPU_batch.hh:31
static constexpr int GPU_BATCH_INST_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
GPUVertCompType
@ GPU_COMP_F32
@ GPU_COMP_U32
ATTR_WARN_UNUSED_RESULT const BMVert * v
static GLContext * get()
struct @242053044010324116347033273112253060004051364061::@051143074301336237271216303350234260141112266062 batch
#define input
format
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
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)
i
Definition text_draw.cc:230