Blender  V3.3
gpu_batch.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 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_math_base.h"
14 
15 #include "GPU_batch.h"
16 #include "GPU_batch_presets.h"
17 #include "GPU_platform.h"
18 #include "GPU_shader.h"
19 
20 #include "gpu_backend.hh"
21 #include "gpu_context_private.hh"
23 #include "gpu_shader_private.hh"
25 
26 #include "gpu_batch_private.hh"
27 
28 #include <cstring>
29 
30 using namespace blender::gpu;
31 
32 /* -------------------------------------------------------------------- */
37 {
39  memset(batch, 0, sizeof(*batch));
40  return batch;
41 }
42 
45  GPUIndexBuf *elem,
46  eGPUBatchFlag owns_flag)
47 {
49  GPU_batch_init_ex(batch, prim_type, verts, elem, owns_flag);
50  return batch;
51 }
52 
54  GPUPrimType prim_type,
56  GPUIndexBuf *elem,
57  eGPUBatchFlag owns_flag)
58 {
59  BLI_assert(verts != nullptr);
60  /* Do not pass any other flag */
61  BLI_assert((owns_flag & ~(GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX)) == 0);
62 
63  batch->verts[0] = verts;
64  for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; v++) {
65  batch->verts[v] = nullptr;
66  }
67  for (auto &v : batch->inst) {
68  v = nullptr;
69  }
70  batch->elem = elem;
71  batch->prim_type = prim_type;
72  batch->flag = owns_flag | GPU_BATCH_INIT | GPU_BATCH_DIRTY;
73  batch->shader = nullptr;
74 }
75 
76 void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src)
77 {
79  batch_dst, GPU_PRIM_POINTS, batch_src->verts[0], batch_src->elem, GPU_BATCH_INVALID);
80 
81  batch_dst->prim_type = batch_src->prim_type;
82  for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; v++) {
83  batch_dst->verts[v] = batch_src->verts[v];
84  }
85 }
86 
88 {
89  if (batch->flag & GPU_BATCH_OWNS_INDEX) {
91  }
92  if (batch->flag & GPU_BATCH_OWNS_VBO_ANY) {
93  for (int v = 0; (v < GPU_BATCH_VBO_MAX_LEN) && batch->verts[v]; v++) {
94  if (batch->flag & (GPU_BATCH_OWNS_VBO << v)) {
96  }
97  }
98  }
99  if (batch->flag & GPU_BATCH_OWNS_INST_VBO_ANY) {
100  for (int v = 0; (v < GPU_BATCH_INST_VBO_MAX_LEN) && batch->inst[v]; v++) {
101  if (batch->flag & (GPU_BATCH_OWNS_INST_VBO << v)) {
103  }
104  }
105  }
106  batch->flag = GPU_BATCH_INVALID;
107 }
108 
110 {
112 
113  delete static_cast<Batch *>(batch);
114 }
115 
118 /* -------------------------------------------------------------------- */
122 void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
123 {
124  BLI_assert(inst);
125  batch->flag |= GPU_BATCH_DIRTY;
126 
127  if (batch->inst[0] && (batch->flag & GPU_BATCH_OWNS_INST_VBO)) {
128  GPU_vertbuf_discard(batch->inst[0]);
129  }
130  batch->inst[0] = inst;
131 
133 }
134 
135 void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
136 {
137  BLI_assert(elem);
138  batch->flag |= GPU_BATCH_DIRTY;
139 
140  if (batch->elem && (batch->flag & GPU_BATCH_OWNS_INDEX)) {
142  }
143  batch->elem = elem;
144 
146 }
147 
149 {
150  BLI_assert(insts);
151  batch->flag |= GPU_BATCH_DIRTY;
152 
153  for (uint v = 0; v < GPU_BATCH_INST_VBO_MAX_LEN; v++) {
154  if (batch->inst[v] == nullptr) {
155  /* for now all VertexBuffers must have same vertex_len */
156  if (batch->inst[0]) {
157  /* Allow for different size of vertex buffer (will choose the smallest number of verts). */
158  // BLI_assert(insts->vertex_len == batch->inst[0]->vertex_len);
159  }
160 
161  batch->inst[v] = insts;
163  return v;
164  }
165  }
166  /* we only make it this far if there is no room for another GPUVertBuf */
167  BLI_assert_msg(0, "Not enough Instance VBO slot in batch");
168  return -1;
169 }
170 
172 {
173  BLI_assert(verts);
174  batch->flag |= GPU_BATCH_DIRTY;
175 
176  for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
177  if (batch->verts[v] == nullptr) {
178  /* for now all VertexBuffers must have same vertex_len */
179  if (batch->verts[0] != nullptr) {
180  /* This is an issue for the HACK inside DRW_vbo_request(). */
181  // BLI_assert(verts->vertex_len == batch->verts[0]->vertex_len);
182  }
183  batch->verts[v] = verts;
185  return v;
186  }
187  }
188  /* we only make it this far if there is no room for another GPUVertBuf */
189  BLI_assert_msg(0, "Not enough VBO slot in batch");
190  return -1;
191 }
192 
194 {
195  for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) {
196  if (batch->verts[v] == verts) {
197  return true;
198  }
199  }
200  return false;
201 }
202 
205 /* -------------------------------------------------------------------- */
212 {
213  batch->shader = shader;
214  GPU_shader_bind(batch->shader);
215 }
216 
219 /* -------------------------------------------------------------------- */
224 {
225  GPU_shader_bind(batch->shader);
226  GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
227 }
228 
229 void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count)
230 {
231  GPU_shader_bind(batch->shader);
232  GPU_batch_draw_advanced(batch, v_first, v_count, 0, 0);
233 }
234 
236 {
237  BLI_assert(batch->inst[0] == nullptr);
238 
239  GPU_shader_bind(batch->shader);
240  GPU_batch_draw_advanced(batch, 0, 0, 0, i_count);
241 }
242 
244  GPUBatch *gpu_batch, int v_first, int v_count, int i_first, int i_count)
245 {
246  BLI_assert(Context::get()->shader != nullptr);
247  Batch *batch = static_cast<Batch *>(gpu_batch);
248 
249  if (v_count == 0) {
250  if (batch->elem) {
251  v_count = batch->elem_()->index_len_get();
252  }
253  else {
254  v_count = batch->verts_(0)->vertex_len;
255  }
256  }
257  if (i_count == 0) {
258  i_count = (batch->inst[0]) ? batch->inst_(0)->vertex_len : 1;
259  /* Meh. This is to be able to use different numbers of verts in instance VBO's. */
260  if (batch->inst[1] != nullptr) {
261  i_count = min_ii(i_count, batch->inst_(1)->vertex_len);
262  }
263  }
264 
265  if (v_count == 0 || i_count == 0) {
266  /* Nothing to draw. */
267  return;
268  }
269 
270  batch->draw(v_first, v_count, i_first, i_count);
271 }
272 
275 /* -------------------------------------------------------------------- */
280  eGPUBuiltinShader shader_id,
281  eGPUShaderConfig sh_cfg)
282 {
283  GPUShader *shader = GPU_shader_get_builtin_shader_with_config(shader_id, sh_cfg);
284  GPU_batch_set_shader(batch, shader);
285 }
286 
288 {
290 }
291 
293 {
295 }
296 
299 /* -------------------------------------------------------------------- */
304 {
306 }
307 
309 {
311 }
312 
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
MINLINE int min_ii(int a, int b)
unsigned int uint
Definition: BLI_sys_types.h:67
#define SET_FLAG_FROM_TEST(value, test, flag)
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
eGPUBatchFlag
Definition: GPU_batch.h:25
@ GPU_BATCH_INVALID
Definition: GPU_batch.h:27
@ GPU_BATCH_DIRTY
Definition: GPU_batch.h:46
@ GPU_BATCH_INIT
Definition: GPU_batch.h:42
@ GPU_BATCH_OWNS_INDEX
Definition: GPU_batch.h:39
@ GPU_BATCH_OWNS_INST_VBO
Definition: GPU_batch.h:34
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:30
@ GPU_BATCH_OWNS_VBO_ANY
Definition: GPU_batch.h:32
@ GPU_BATCH_OWNS_INST_VBO_ANY
Definition: GPU_batch.h:36
void gpu_batch_presets_exit(void)
void gpu_batch_presets_init(void)
struct GPUIndexBuf GPUIndexBuf
void GPU_indexbuf_discard(GPUIndexBuf *elem)
GPUPrimType
Definition: GPU_primitive.h:18
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
struct GPUShader GPUShader
Definition: GPU_shader.h:20
eGPUShaderConfig
Definition: GPU_shader.h:364
@ GPU_SHADER_CFG_DEFAULT
Definition: GPU_shader.h:365
GPUShader * GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg)
void GPU_shader_bind(GPUShader *shader)
Definition: gpu_shader.cc:491
eGPUBuiltinShader
Definition: GPU_shader.h:189
void GPU_vertbuf_discard(GPUVertBuf *)
struct GPUVertBuf GPUVertBuf
#define GPU_VERTBUF_DISCARD_SAFE(verts)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
static Context * get()
Definition: gpu_context.cc:82
static GPUBackend * get()
Definition: gpu_context.cc:292
virtual Batch * batch_alloc()=0
static float verts[][3]
void GPU_batch_discard(GPUBatch *batch)
Definition: gpu_batch.cc:109
int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
Definition: gpu_batch.cc:171
void GPU_batch_init_ex(GPUBatch *batch, GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:53
GPUBatch * GPU_batch_create_ex(GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:43
void GPU_batch_draw_instanced(GPUBatch *batch, int i_count)
Definition: gpu_batch.cc:235
void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src)
Definition: gpu_batch.cc:76
void GPU_batch_draw_advanced(GPUBatch *gpu_batch, int v_first, int v_count, int i_first, int i_count)
Definition: gpu_batch.cc:243
void GPU_batch_set_shader(GPUBatch *batch, GPUShader *shader)
Definition: gpu_batch.cc:211
void GPU_batch_draw_range(GPUBatch *batch, int v_first, int v_count)
Definition: gpu_batch.cc:229
void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
Definition: gpu_batch.cc:135
void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, eGPUBuiltinShader shader_id, eGPUShaderConfig sh_cfg)
Definition: gpu_batch.cc:279
int GPU_batch_instbuf_add_ex(GPUBatch *batch, GPUVertBuf *insts, bool own_vbo)
Definition: gpu_batch.cc:148
GPUBatch * GPU_batch_calloc()
Definition: gpu_batch.cc:36
void GPU_batch_program_set_imm_shader(GPUBatch *batch)
Definition: gpu_batch.cc:292
void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id)
Definition: gpu_batch.cc:287
void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
Definition: gpu_batch.cc:122
void gpu_batch_init()
Definition: gpu_batch.cc:303
void GPU_batch_clear(GPUBatch *batch)
Definition: gpu_batch.cc:87
bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *verts)
Definition: gpu_batch.cc:193
void GPU_batch_draw(GPUBatch *batch)
Definition: gpu_batch.cc:223
void gpu_batch_exit()
Definition: gpu_batch.cc:308
struct @653::@655 batch
GPUShader * immGetShader()