Blender  V3.3
gl_immediate.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 #include "gpu_context_private.hh"
11 #include "gpu_shader_private.hh"
13 
14 #include "gl_context.hh"
15 #include "gl_debug.hh"
16 #include "gl_primitive.hh"
17 #include "gl_vertex_array.hh"
18 
19 #include "gl_immediate.hh"
20 
21 namespace blender::gpu {
22 
23 /* -------------------------------------------------------------------- */
28 {
29  glGenVertexArrays(1, &vao_id_);
30  glBindVertexArray(vao_id_); /* Necessary for glObjectLabel. */
31 
32  buffer.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
33  glGenBuffers(1, &buffer.vbo_id);
34  glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id);
35  glBufferData(GL_ARRAY_BUFFER, buffer.buffer_size, nullptr, GL_DYNAMIC_DRAW);
36 
37  buffer_strict.buffer_size = DEFAULT_INTERNAL_BUFFER_SIZE;
38  glGenBuffers(1, &buffer_strict.vbo_id);
39  glBindBuffer(GL_ARRAY_BUFFER, buffer_strict.vbo_id);
40  glBufferData(GL_ARRAY_BUFFER, buffer_strict.buffer_size, nullptr, GL_DYNAMIC_DRAW);
41 
42  glBindBuffer(GL_ARRAY_BUFFER, 0);
43  glBindVertexArray(0);
44 
45  debug::object_label(GL_VERTEX_ARRAY, vao_id_, "Immediate");
46  debug::object_label(GL_BUFFER, buffer.vbo_id, "ImmediateVbo");
47  debug::object_label(GL_BUFFER, buffer_strict.vbo_id, "ImmediateVboStrict");
48 }
49 
51 {
52  glDeleteVertexArrays(1, &vao_id_);
53 
54  glDeleteBuffers(1, &buffer.vbo_id);
55  glDeleteBuffers(1, &buffer_strict.vbo_id);
56 }
57 
60 /* -------------------------------------------------------------------- */
65 {
66  /* How many bytes do we need for this draw call? */
67  const size_t bytes_needed = vertex_buffer_size(&vertex_format, vertex_len);
68  /* Does the current buffer have enough room? */
69  const size_t available_bytes = buffer_size() - buffer_offset();
70 
71  GL_CHECK_RESOURCES("Immediate");
72 
73  glBindBuffer(GL_ARRAY_BUFFER, vbo_id());
74 
75  bool recreate_buffer = false;
76  if (bytes_needed > buffer_size()) {
77  /* expand the internal buffer */
78  buffer_size() = bytes_needed;
79  recreate_buffer = true;
80  }
81  else if (bytes_needed < DEFAULT_INTERNAL_BUFFER_SIZE &&
83  /* shrink the internal buffer */
85  recreate_buffer = true;
86  }
87 
88  /* ensure vertex data is aligned */
89  /* Might waste a little space, but it's safe. */
90  const uint pre_padding = padding(buffer_offset(), vertex_format.stride);
91 
92  if (!recreate_buffer && ((bytes_needed + pre_padding) <= available_bytes)) {
93  buffer_offset() += pre_padding;
94  }
95  else {
96  /* orphan this buffer & start with a fresh one */
97  glBufferData(GL_ARRAY_BUFFER, buffer_size(), nullptr, GL_DYNAMIC_DRAW);
98  buffer_offset() = 0;
99  }
100 
101 #ifndef NDEBUG
102  {
103  GLint bufsize;
104  glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufsize);
105  BLI_assert(buffer_offset() + bytes_needed <= bufsize);
106  }
107 #endif
108 
109  GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
110  if (!strict_vertex_len) {
111  access |= GL_MAP_FLUSH_EXPLICIT_BIT;
112  }
113  void *data = glMapBufferRange(GL_ARRAY_BUFFER, buffer_offset(), bytes_needed, access);
114  BLI_assert(data != nullptr);
115 
116  bytes_mapped_ = bytes_needed;
117  return (uchar *)data;
118 }
119 
121 {
122  BLI_assert(prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */
123 
124  uint buffer_bytes_used = bytes_mapped_;
125  if (!strict_vertex_len) {
126  if (vertex_idx != vertex_len) {
128  buffer_bytes_used = vertex_buffer_size(&vertex_format, vertex_len);
129  /* unused buffer bytes are available to the next immBegin */
130  }
131  /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */
132  glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used);
133  }
134  glUnmapBuffer(GL_ARRAY_BUFFER);
135 
136  if (vertex_len > 0) {
138 
139  /* We convert the offset in vertex offset from the buffer's start.
140  * This works because we added some padding to align the first vertex. */
141  uint v_first = buffer_offset() / vertex_format.stride;
143  vao_id_, v_first, &vertex_format, reinterpret_cast<Shader *>(shader)->interface);
144 
145  /* Update matrices. */
147 
148 #ifdef __APPLE__
149  glDisable(GL_PRIMITIVE_RESTART);
150 #endif
151  glDrawArrays(to_gl(prim_type), 0, vertex_len);
152 #ifdef __APPLE__
153  glEnable(GL_PRIMITIVE_RESTART);
154 #endif
155  /* These lines are causing crash on startup on some old GPU + drivers.
156  * They are not required so just comment them. (T55722) */
157  // glBindBuffer(GL_ARRAY_BUFFER, 0);
158  // glBindVertexArray(0);
159  }
160 
161  buffer_offset() += buffer_bytes_used;
162 }
163 
166 } // namespace blender::gpu
#define BLI_assert(a)
Definition: BLI_assert.h:46
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define glEnable
#define glDisable
@ GPU_PRIM_NONE
Definition: GPU_primitive.h:33
void GPU_shader_bind(GPUShader *shader)
Definition: gpu_shader.cc:491
static GLContext * get()
Definition: gl_context.hh:117
uchar * begin() override
Definition: gl_immediate.cc:64
virtual void apply_state()=0
#define GL_CHECK_RESOURCES(info)
Definition: gl_debug.hh:67
#define DEFAULT_INTERNAL_BUFFER_SIZE
Definition: gl_immediate.hh:21
uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len)
uint padding(uint offset, uint alignment)
void update_bindings(const GLuint vao, const GPUBatch *batch, const ShaderInterface *interface, int base_instance)
void object_label(GLenum type, GLuint object, const char *name)
Definition: gl_debug.cc:328
static GLenum to_gl(const GPUAttachmentType type)