Merge branch 'blender2.7'
[blender.git] / source / blender / gpu / intern / gpu_uniformbuffer.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup gpu
22  */
23
24 #include <string.h>
25 #include "MEM_guardedalloc.h"
26
27 #include "BLI_blenlib.h"
28
29 #include "gpu_codegen.h"
30 #include "gpu_context_private.h"
31
32 #include "GPU_extensions.h"
33 #include "GPU_glew.h"
34 #include "GPU_material.h"
35 #include "GPU_uniformbuffer.h"
36
37 typedef enum eGPUUniformBufferFlag {
38         GPU_UBO_FLAG_INITIALIZED = (1 << 0),
39         GPU_UBO_FLAG_DIRTY = (1 << 1),
40 } eGPUUniformBufferFlag;
41
42 typedef enum eGPUUniformBufferType {
43         GPU_UBO_STATIC = 0,
44         GPU_UBO_DYNAMIC = 1,
45 } eGPUUniformBufferType;
46
47 struct GPUUniformBuffer {
48         int size;           /* in bytes */
49         GLuint bindcode;    /* opengl identifier for UBO */
50         int bindpoint;      /* current binding point */
51         eGPUUniformBufferType type;
52 };
53
54 #define GPUUniformBufferStatic GPUUniformBuffer
55
56 typedef struct GPUUniformBufferDynamic {
57         GPUUniformBuffer buffer;
58         void *data;                  /* Continuous memory block to copy to GPU. */
59         char flag;
60 } GPUUniformBufferDynamic;
61
62 /* Prototypes */
63 static eGPUType get_padded_gpu_type(struct LinkData *link);
64 static void gpu_uniformbuffer_inputs_sort(struct ListBase *inputs);
65
66 /* Only support up to this type, if you want to extend it, make sure the
67  * padding logic is correct for the new types. */
68 #define MAX_UBO_GPU_TYPE GPU_VEC4
69
70 static void gpu_uniformbuffer_initialize(GPUUniformBuffer *ubo, const void *data)
71 {
72         glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
73         glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW);
74         glBindBuffer(GL_UNIFORM_BUFFER, 0);
75 }
76
77 GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
78 {
79         GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic");
80         ubo->size = size;
81         ubo->bindpoint = -1;
82
83         /* Generate Buffer object */
84         ubo->bindcode = GPU_buf_alloc();
85
86         if (!ubo->bindcode) {
87                 if (err_out)
88                         BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
89                 GPU_uniformbuffer_free(ubo);
90                 return NULL;
91         }
92
93         if (ubo->size > GPU_max_ubo_size()) {
94                 if (err_out)
95                         BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
96                 GPU_uniformbuffer_free(ubo);
97                 return NULL;
98         }
99
100         gpu_uniformbuffer_initialize(ubo, data);
101         return ubo;
102 }
103
104 /**
105  * Create dynamic UBO from parameters
106  * Return NULL if failed to create or if \param inputs: is empty.
107  *
108  * \param inputs: ListBase of BLI_genericNodeN(GPUInput)
109  */
110 GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_out[256])
111 {
112         /* There is no point on creating an UBO if there is no arguments. */
113         if (BLI_listbase_is_empty(inputs)) {
114                 return NULL;
115         }
116
117         GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), "GPUUniformBufferDynamic");
118         ubo->buffer.type = GPU_UBO_DYNAMIC;
119         ubo->buffer.bindpoint = -1;
120         ubo->flag = GPU_UBO_FLAG_DIRTY;
121
122         /* Generate Buffer object. */
123         ubo->buffer.bindcode = GPU_buf_alloc();
124
125         if (!ubo->buffer.bindcode) {
126                 if (err_out)
127                         BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
128                 GPU_uniformbuffer_free(&ubo->buffer);
129                 return NULL;
130         }
131
132         if (ubo->buffer.size > GPU_max_ubo_size()) {
133                 if (err_out)
134                         BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
135                 GPU_uniformbuffer_free(&ubo->buffer);
136                 return NULL;
137         }
138
139         /* Make sure we comply to the ubo alignment requirements. */
140         gpu_uniformbuffer_inputs_sort(inputs);
141
142         for (LinkData *link = inputs->first; link; link = link->next) {
143                 const eGPUType gputype = get_padded_gpu_type(link);
144                 ubo->buffer.size += gputype * sizeof(float);
145         }
146
147         /* Allocate the data. */
148         ubo->data = MEM_mallocN(ubo->buffer.size, __func__);
149
150         /* Now that we know the total ubo size we can start populating it. */
151         float *offset = ubo->data;
152         for (LinkData *link = inputs->first; link; link = link->next) {
153                 GPUInput *input = link->data;
154                 memcpy(offset, input->vec, input->type * sizeof(float));
155                 offset += get_padded_gpu_type(link);
156         }
157
158         /* Note since we may create the UBOs in the CPU in a different thread than the main drawing one,
159          * we don't create the UBO in the GPU here. This will happen when we first bind the UBO.
160          */
161
162         return &ubo->buffer;
163 }
164
165 /**
166  * Free the data
167  */
168 static void gpu_uniformbuffer_dynamic_free(GPUUniformBuffer *ubo_)
169 {
170         BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
171         GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
172
173         ubo->buffer.size = 0;
174         if (ubo->data) {
175                 MEM_freeN(ubo->data);
176         }
177 }
178
179 void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
180 {
181         if (ubo->type == GPU_UBO_DYNAMIC) {
182                 gpu_uniformbuffer_dynamic_free(ubo);
183         }
184
185         GPU_buf_free(ubo->bindcode);
186         MEM_freeN(ubo);
187 }
188
189 static void gpu_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
190 {
191         glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
192         glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data);
193         glBindBuffer(GL_UNIFORM_BUFFER, 0);
194 }
195
196 void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
197 {
198         BLI_assert(ubo->type == GPU_UBO_STATIC);
199         gpu_uniformbuffer_update(ubo, data);
200 }
201
202 /**
203  * We need to recalculate the internal data, and re-generate it
204  * from its populated items.
205  */
206 void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_)
207 {
208         BLI_assert(ubo_->type == GPU_UBO_DYNAMIC);
209         GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_;
210
211         if (ubo->flag & GPU_UBO_FLAG_INITIALIZED) {
212                 gpu_uniformbuffer_update(ubo_, ubo->data);
213         }
214         else {
215                 ubo->flag |= GPU_UBO_FLAG_INITIALIZED;
216                 gpu_uniformbuffer_initialize(ubo_, ubo->data);
217         }
218
219         ubo->flag &= ~GPU_UBO_FLAG_DIRTY;
220 }
221
222 /**
223  * We need to pad some data types (vec3) on the C side
224  * To match the GPU expected memory block alignment.
225  */
226 static eGPUType get_padded_gpu_type(LinkData *link)
227 {
228         GPUInput *input = link->data;
229         eGPUType gputype = input->type;
230
231         /* Unless the vec3 is followed by a float we need to treat it as a vec4. */
232         if (gputype == GPU_VEC3 &&
233             (link->next != NULL) &&
234             (((GPUInput *)link->next->data)->type != GPU_FLOAT))
235         {
236                 gputype = GPU_VEC4;
237         }
238
239         return gputype;
240 }
241
242 /**
243  * Returns 1 if the first item shold be after second item.
244  * We make sure the vec4 uniforms come first.
245  */
246 static int inputs_cmp(const void *a, const void *b)
247 {
248         const LinkData *link_a = a, *link_b = b;
249         const GPUInput *input_a = link_a->data, *input_b = link_b->data;
250         return input_a->type < input_b->type ? 1 : 0;
251 }
252
253 /**
254  * Make sure we respect the expected alignment of UBOs.
255  * vec4, pad vec3 as vec4, then vec2, then floats.
256  */
257 static void gpu_uniformbuffer_inputs_sort(ListBase *inputs)
258 {
259         /* Order them as vec4, vec3, vec2, float. */
260         BLI_listbase_sort(inputs, inputs_cmp);
261
262         /* Creates a lookup table for the different types; */
263         LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL};
264         eGPUType cur_type = MAX_UBO_GPU_TYPE + 1;
265
266         for (LinkData *link = inputs->first; link; link = link->next) {
267                 GPUInput *input = link->data;
268                 if (input->type == cur_type) {
269                         continue;
270                 }
271                 else {
272                         inputs_lookup[input->type] = link;
273                         cur_type = input->type;
274                 }
275         }
276
277         /* If there is no GPU_VEC3 there is no need for alignment. */
278         if (inputs_lookup[GPU_VEC3] == NULL) {
279                 return;
280         }
281
282         LinkData *link = inputs_lookup[GPU_VEC3];
283         while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) {
284                 LinkData *link_next = link->next;
285
286                 /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for alignment. */
287                 if ((link_next == NULL) ||
288                     ((GPUInput *)link_next->data)->type == GPU_FLOAT)
289                 {
290                         break;
291                 }
292
293                 /* If there is a float, move it next to current vec3. */
294                 if (inputs_lookup[GPU_FLOAT] != NULL) {
295                         LinkData *float_input = inputs_lookup[GPU_FLOAT];
296                         inputs_lookup[GPU_FLOAT] = float_input->next;
297
298                         BLI_remlink(inputs, float_input);
299                         BLI_insertlinkafter(inputs, link, float_input);
300                 }
301
302                 link = link_next;
303         }
304 }
305
306 void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
307 {
308         if (number >= GPU_max_ubo_binds()) {
309                 fprintf(stderr, "Not enough UBO slots.\n");
310                 return;
311         }
312
313         if (ubo->type == GPU_UBO_DYNAMIC) {
314                 GPUUniformBufferDynamic *ubo_dynamic = (GPUUniformBufferDynamic *)ubo;
315                 if (ubo_dynamic->flag & GPU_UBO_FLAG_DIRTY) {
316                         GPU_uniformbuffer_dynamic_update(ubo);
317                 }
318         }
319
320         if (ubo->bindcode != 0) {
321                 glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
322         }
323
324         ubo->bindpoint = number;
325 }
326
327 void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo)
328 {
329         ubo->bindpoint = -1;
330 }
331
332 int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo)
333 {
334         return ubo->bindpoint;
335 }
336
337 #undef MAX_UBO_GPU_TYPE