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