Mesh Batch Cache: Port Texture paint batches to new batch request
[blender.git] / source / blender / gpu / GPU_batch.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2016 by Mike Erwin.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/gpu/GPU_batch.h
27  *  \ingroup gpu
28  *
29  * GPU geometry batch
30  * Contains VAOs + VBOs + Shader representing a drawable entity.
31  */
32
33 #ifndef __GPU_BATCH_H__
34 #define __GPU_BATCH_H__
35
36 #include "GPU_vertex_buffer.h"
37 #include "GPU_element.h"
38 #include "GPU_shader_interface.h"
39 #include "GPU_shader.h"
40
41 typedef enum {
42         GPU_BATCH_READY_TO_FORMAT,
43         GPU_BATCH_READY_TO_BUILD,
44         GPU_BATCH_BUILDING,
45         GPU_BATCH_READY_TO_DRAW
46 } GPUBatchPhase;
47
48 #define GPU_BATCH_VBO_MAX_LEN 3
49 #define GPU_BATCH_VAO_STATIC_LEN 3
50 #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16
51
52 typedef struct GPUBatch {
53         /* geometry */
54         GPUVertBuf *verts[GPU_BATCH_VBO_MAX_LEN]; /* verts[0] is required, others can be NULL */
55         GPUVertBuf *inst; /* instance attribs */
56         GPUIndexBuf *elem; /* NULL if element list not needed */
57         uint32_t gl_prim_type;
58
59         /* cached values (avoid dereferencing later) */
60         uint32_t vao_id;
61         uint32_t program;
62         const struct GPUShaderInterface *interface;
63
64         /* book-keeping */
65         uint owns_flag;
66         struct GPUContext *context; /* used to free all vaos. this implies all vaos were created under the same context. */
67         GPUBatchPhase phase;
68         bool program_in_use;
69
70         /* Vao management: remembers all geometry state (vertex attrib bindings & element buffer)
71          * for each shader interface. Start with a static number of vaos and fallback to dynamic count
72          * if necessary. Once a batch goes dynamic it does not go back. */
73         bool is_dynamic_vao_count;
74         union {
75                 /* Static handle count */
76                 struct {
77                         const struct GPUShaderInterface *interfaces[GPU_BATCH_VAO_STATIC_LEN];
78                         uint32_t vao_ids[GPU_BATCH_VAO_STATIC_LEN];
79                 } static_vaos;
80                 /* Dynamic handle count */
81                 struct {
82                         uint count;
83                         const struct GPUShaderInterface **interfaces;
84                         uint32_t *vao_ids;
85                 } dynamic_vaos;
86         };
87
88         /* XXX This is the only solution if we want to have some data structure using
89          * batches as key to identify nodes. We must destroy these nodes with this callback. */
90         void (*free_callback)(struct GPUBatch *, void *);
91         void *callback_data;
92 } GPUBatch;
93
94 enum {
95         GPU_BATCH_OWNS_VBO = (1 << 0),
96         /* each vbo index gets bit-shifted */
97         GPU_BATCH_OWNS_INSTANCES = (1 << 30),
98         GPU_BATCH_OWNS_INDEX = (1u << 31u),
99 };
100
101 GPUBatch *GPU_batch_create_ex(GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag);
102 void GPU_batch_init_ex(GPUBatch *, GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag);
103 GPUBatch *GPU_batch_duplicate(GPUBatch *batch_src);
104
105 #define GPU_batch_create(prim, verts, elem) \
106         GPU_batch_create_ex(prim, verts, elem, 0)
107 #define GPU_batch_init(batch, prim, verts, elem) \
108         GPU_batch_init_ex(batch, prim, verts, elem, 0)
109
110 void GPU_batch_clear(GPUBatch *); /* Same as discard but does not free. */
111 void GPU_batch_discard(GPUBatch *); /* verts & elem are not discarded */
112
113 void GPU_batch_vao_cache_clear(GPUBatch *);
114
115 void GPU_batch_callback_free_set(GPUBatch *, void (*callback)(GPUBatch *, void *), void *);
116
117 void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
118
119 int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
120
121 #define GPU_batch_vertbuf_add(batch, verts) \
122         GPU_batch_vertbuf_add_ex(batch, verts, false)
123
124 void GPU_batch_program_set_no_use(GPUBatch *, uint32_t program, const GPUShaderInterface *);
125 void GPU_batch_program_set(GPUBatch *, uint32_t program, const GPUShaderInterface *);
126 void GPU_batch_program_set_builtin(GPUBatch *batch, GPUBuiltinShader shader_id);
127 /* Entire batch draws with one shader program, but can be redrawn later with another program. */
128 /* Vertex shader's inputs must be compatible with the batch's vertex format. */
129
130 void GPU_batch_program_use_begin(GPUBatch *); /* call before Batch_Uniform (temp hack?) */
131 void GPU_batch_program_use_end(GPUBatch *);
132
133 void GPU_batch_uniform_1ui(GPUBatch *, const char *name, int value);
134 void GPU_batch_uniform_1i(GPUBatch *, const char *name, int value);
135 void GPU_batch_uniform_1b(GPUBatch *, const char *name, bool value);
136 void GPU_batch_uniform_1f(GPUBatch *, const char *name, float value);
137 void GPU_batch_uniform_2f(GPUBatch *, const char *name, float x, float y);
138 void GPU_batch_uniform_3f(GPUBatch *, const char *name, float x, float y, float z);
139 void GPU_batch_uniform_4f(GPUBatch *, const char *name, float x, float y, float z, float w);
140 void GPU_batch_uniform_2fv(GPUBatch *, const char *name, const float data[2]);
141 void GPU_batch_uniform_3fv(GPUBatch *, const char *name, const float data[3]);
142 void GPU_batch_uniform_4fv(GPUBatch *, const char *name, const float data[4]);
143 void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, int len, const float *data);
144 void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, int len, const float *data);
145 void GPU_batch_uniform_mat4(GPUBatch *, const char *name, const float data[4][4]);
146
147 void GPU_batch_draw(GPUBatch *);
148
149 /* This does not bind/unbind shader and does not call GPU_matrix_bind() */
150 void GPU_batch_draw_range_ex(GPUBatch *, int v_first, int v_count, bool force_instance);
151
152 /* Does not even need batch */
153 void GPU_draw_primitive(GPUPrimType, int v_count);
154
155 #if 0 /* future plans */
156
157 /* Can multiple batches share a GPUVertBuf? Use ref count? */
158
159
160 /* We often need a batch with its own data, to be created and discarded together. */
161 /* WithOwn variants reduce number of system allocations. */
162
163 typedef struct BatchWithOwnVertexBuffer {
164         GPUBatch batch;
165         GPUVertBuf verts; /* link batch.verts to this */
166 } BatchWithOwnVertexBuffer;
167
168 typedef struct BatchWithOwnElementList {
169         GPUBatch batch;
170         GPUIndexBuf elem; /* link batch.elem to this */
171 } BatchWithOwnElementList;
172
173 typedef struct BatchWithOwnVertexBufferAndElementList {
174         GPUBatch batch;
175         GPUIndexBuf elem; /* link batch.elem to this */
176         GPUVertBuf verts; /* link batch.verts to this */
177 } BatchWithOwnVertexBufferAndElementList;
178
179 GPUBatch *create_BatchWithOwnVertexBuffer(GPUPrimType, GPUVertFormat *, uint v_len, GPUIndexBuf *);
180 GPUBatch *create_BatchWithOwnElementList(GPUPrimType, GPUVertBuf *, uint prim_len);
181 GPUBatch *create_BatchWithOwnVertexBufferAndElementList(GPUPrimType, GPUVertFormat *, uint v_len, uint prim_len);
182 /* verts: shared, own */
183 /* elem: none, shared, own */
184 GPUBatch *create_BatchInGeneral(GPUPrimType, VertexBufferStuff, ElementListStuff);
185
186 #endif /* future plans */
187
188 void gpu_batch_init(void);
189 void gpu_batch_exit(void);
190
191 /* Macros */
192
193 #define GPU_BATCH_DISCARD_SAFE(batch) do { \
194         if (batch != NULL) { \
195                 GPU_batch_discard(batch); \
196                 batch = NULL; \
197         } \
198 } while (0)
199
200 #define GPU_BATCH_CLEAR_SAFE(batch) do { \
201         if (batch != NULL) { \
202                 GPU_batch_clear(batch); \
203                 memset(batch, 0, sizeof(*(batch))); \
204         } \
205 } while (0)
206
207 #define GPU_BATCH_DISCARD_ARRAY_SAFE(_batch_array, _len) do { \
208         if (_batch_array != NULL) { \
209                 BLI_assert(_len > 0); \
210                 for (int _i = 0; _i < _len; _i++) { \
211                         GPU_BATCH_DISCARD_SAFE(_batch_array[_i]); \
212                 } \
213                 MEM_freeN(_batch_array); \
214         } \
215 } while (0)
216
217 #endif /* __GPU_BATCH_H__ */