Merge branch 'blender2.7'
[blender.git] / source / blender / gpu / intern / gpu_extensions.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  * Wrap OpenGL features such as textures, shaders and GLSL
24  * with checks for drivers and GPU support.
25  */
26
27 #include "BLI_utildefines.h"
28 #include "BLI_math_base.h"
29 #include "BLI_math_vector.h"
30
31 #include "BKE_global.h"
32 #include "MEM_guardedalloc.h"
33
34 #include "GPU_extensions.h"
35 #include "GPU_framebuffer.h"
36 #include "GPU_glew.h"
37 #include "GPU_texture.h"
38
39 #include "intern/gpu_private.h"
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44
45 #ifdef WIN32
46 #  include "BLI_winstuff.h"
47 #endif
48
49 /* Extensions support */
50
51 /* -- extension: version of GL that absorbs it
52  * EXT_gpu_shader4: 3.0
53  * ARB_framebuffer object: 3.0
54  * EXT_framebuffer_multisample_blit_scaled: ???
55  * ARB_draw_instanced: 3.1
56  * ARB_texture_multisample: 3.2
57  * ARB_texture_query_lod: 4.0
58  */
59
60 static struct GPUGlobal {
61         GLint maxtexsize;
62         GLint maxtexlayers;
63         GLint maxcubemapsize;
64         GLint maxtextures;
65         GLint maxtexturesfrag;
66         GLint maxtexturesgeom;
67         GLint maxtexturesvert;
68         GLint maxubosize;
69         GLint maxubobinds;
70         int colordepth;
71         int samples_color_texture_max;
72         eGPUDeviceType device;
73         eGPUOSType os;
74         eGPUDriverType driver;
75         float line_width_range[2];
76         /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
77          * calculate dfdy in shader differently when drawing to an offscreen buffer. First
78          * number is factor on screen and second is off-screen */
79         float dfdyfactors[2];
80         float max_anisotropy;
81         /* Some Intel drivers have issues with using mips as framebuffer targets if
82          * GL_TEXTURE_MAX_LEVEL is higher than the target mip.
83          * We need a workaround in this cases. */
84         bool mip_render_workaround;
85         /* There is an issue with the glBlitFramebuffer on MacOS with radeon pro graphics.
86          * Blitting depth with GL_DEPTH24_STENCIL8 is buggy so the workaround is to use
87          * GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will
88          * still be broken. */
89         bool depth_blitting_workaround;
90         /* Crappy driver don't know how to map framebuffer slot to output vars...
91          * We need to have no "holes" in the output buffer slots. */
92         bool unused_fb_slot_workaround;
93 } GG = {1, 0};
94
95
96 static void gpu_detect_mip_render_workaround(void)
97 {
98         int cube_size = 2;
99         float *source_pix = MEM_callocN(sizeof(float) * 4 * 6 * cube_size * cube_size, __func__);
100         float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
101
102         GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL);
103         MEM_freeN(source_pix);
104
105         GPU_texture_bind(tex, 0);
106         GPU_texture_generate_mipmap(tex);
107         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
108         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0);
109         GPU_texture_unbind(tex);
110
111         GPUFrameBuffer *fb = GPU_framebuffer_create();
112         GPU_framebuffer_texture_attach(fb, tex, 0, 1);
113         GPU_framebuffer_bind(fb);
114         GPU_framebuffer_clear_color(fb, clear_color);
115         GPU_framebuffer_restore();
116         GPU_framebuffer_free(fb);
117
118         float *data = GPU_texture_read(tex, GPU_DATA_FLOAT, 1);
119         GG.mip_render_workaround = !equals_v4v4(clear_color, data);
120
121         MEM_freeN(data);
122         GPU_texture_free(tex);
123 }
124
125 /* GPU Types */
126
127 bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
128 {
129         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
130 }
131
132 /* GPU Extensions */
133
134 int GPU_max_texture_size(void)
135 {
136         return GG.maxtexsize;
137 }
138
139 int GPU_max_texture_layers(void)
140 {
141         return GG.maxtexlayers;
142 }
143
144 int GPU_max_textures(void)
145 {
146         return GG.maxtextures;
147 }
148
149 int GPU_max_textures_frag(void)
150 {
151         return GG.maxtexturesfrag;
152 }
153
154 int GPU_max_textures_geom(void)
155 {
156         return GG.maxtexturesgeom;
157 }
158
159 int GPU_max_textures_vert(void)
160 {
161         return GG.maxtexturesvert;
162 }
163
164 float GPU_max_texture_anisotropy(void)
165 {
166         return GG.max_anisotropy;
167 }
168
169 int GPU_max_color_texture_samples(void)
170 {
171         return GG.samples_color_texture_max;
172 }
173
174 int GPU_max_cube_map_size(void)
175 {
176         return GG.maxcubemapsize;
177 }
178
179 int GPU_max_ubo_binds(void)
180 {
181         return GG.maxubobinds;
182 }
183
184 int GPU_max_ubo_size(void)
185 {
186         return GG.maxubosize;
187 }
188
189 float GPU_max_line_width(void)
190 {
191         return GG.line_width_range[1];
192 }
193
194 void GPU_get_dfdy_factors(float fac[2])
195 {
196         copy_v2_v2(fac, GG.dfdyfactors);
197 }
198
199 bool GPU_mip_render_workaround(void)
200 {
201         return GG.mip_render_workaround;
202 }
203
204 bool GPU_depth_blitting_workaround(void)
205 {
206         return GG.depth_blitting_workaround;
207 }
208
209 bool GPU_unused_fb_slot_workaround(void)
210 {
211         return GG.unused_fb_slot_workaround;
212 }
213
214 void gpu_extensions_init(void)
215 {
216         /* during 2.8 development each platform has its own OpenGL minimum requirements
217          * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
218          * see developer.blender.org/T49012 for details
219          */
220         BLI_assert(GLEW_VERSION_3_3);
221
222         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag);
223         glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert);
224         glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom);
225         glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
226
227         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
228         glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
229         glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
230
231         if (GLEW_EXT_texture_filter_anisotropic)
232                 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);
233         else
234                 GG.max_anisotropy = 1.0f;
235
236         glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
237         glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
238
239         glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, GG.line_width_range);
240
241 #ifndef NDEBUG
242         GLint ret;
243         glBindFramebuffer(GL_FRAMEBUFFER, 0);
244         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret);
245         /* We expect FRONT_LEFT to be the default buffer. */
246         BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT);
247 #endif
248
249         GLint r, g, b;
250         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
251         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
252         glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
253         GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
254
255         glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
256
257         const char *vendor = (const char *)glGetString(GL_VENDOR);
258         const char *renderer = (const char *)glGetString(GL_RENDERER);
259         const char *version = (const char *)glGetString(GL_VERSION);
260
261         if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
262                 GG.device = GPU_DEVICE_ATI;
263                 GG.driver = GPU_DRIVER_OFFICIAL;
264
265 #ifdef _WIN32
266                 if (strstr(version, "4.5.13399") ||
267                     strstr(version, "4.5.13417") ||
268                     strstr(version, "4.5.13422"))
269                 {
270                         /* The renderers include:
271                          *   Mobility Radeon HD 5000;
272                          *   Radeon HD 7500M;
273                          *   Radeon HD 7570M;
274                          *   Radeon HD 7600M;
275                          * And many others... */
276
277                         GG.unused_fb_slot_workaround = true;
278                 }
279 #endif
280
281 #if defined(__APPLE__)
282                 if (strstr(renderer, "AMD Radeon Pro") ||
283                     strstr(renderer, "AMD Radeon R9") ||
284                     strstr(renderer, "AMD Radeon RX"))
285                 {
286                         GG.depth_blitting_workaround = true;
287                 }
288 #endif
289         }
290         else if (strstr(vendor, "NVIDIA")) {
291                 GG.device = GPU_DEVICE_NVIDIA;
292                 GG.driver = GPU_DRIVER_OFFICIAL;
293         }
294         else if (strstr(vendor, "Intel") ||
295                  /* src/mesa/drivers/dri/intel/intel_context.c */
296                  strstr(renderer, "Mesa DRI Intel") ||
297                  strstr(renderer, "Mesa DRI Mobile Intel"))
298         {
299                 GG.device = GPU_DEVICE_INTEL;
300                 GG.driver = GPU_DRIVER_OFFICIAL;
301
302                 if (strstr(renderer, "UHD Graphics") ||
303                     /* Not UHD but affected by the same bugs. */
304                     strstr(renderer, "HD Graphics 530") ||
305                     strstr(renderer, "Kaby Lake GT2"))
306                 {
307                         GG.device |= GPU_DEVICE_INTEL_UHD;
308                 }
309         }
310         else if ((strstr(renderer, "Mesa DRI R")) ||
311                  (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
312                  (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
313                  (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
314         {
315                 GG.device = GPU_DEVICE_ATI;
316                 GG.driver = GPU_DRIVER_OPENSOURCE;
317         }
318         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
319                 GG.device = GPU_DEVICE_NVIDIA;
320                 GG.driver = GPU_DRIVER_OPENSOURCE;
321         }
322         else if (strstr(vendor, "Mesa")) {
323                 GG.device = GPU_DEVICE_SOFTWARE;
324                 GG.driver = GPU_DRIVER_SOFTWARE;
325         }
326         else if (strstr(vendor, "Microsoft")) {
327                 GG.device = GPU_DEVICE_SOFTWARE;
328                 GG.driver = GPU_DRIVER_SOFTWARE;
329         }
330         else if (strstr(renderer, "Apple Software Renderer")) {
331                 GG.device = GPU_DEVICE_SOFTWARE;
332                 GG.driver = GPU_DRIVER_SOFTWARE;
333         }
334         else if (strstr(renderer, "llvmpipe")) {
335                 GG.device = GPU_DEVICE_SOFTWARE;
336                 GG.driver = GPU_DRIVER_SOFTWARE;
337         }
338         else {
339                 printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
340                 printf("Detected OpenGL configuration:\n");
341                 printf("Vendor: %s\n", vendor);
342                 printf("Renderer: %s\n", renderer);
343                 GG.device = GPU_DEVICE_ANY;
344                 GG.driver = GPU_DRIVER_ANY;
345         }
346
347 #ifdef _WIN32
348         GG.os = GPU_OS_WIN;
349 #elif defined(__APPLE__)
350         GG.os = GPU_OS_MAC;
351 #else
352         GG.os = GPU_OS_UNIX;
353 #endif
354
355         gpu_detect_mip_render_workaround();
356
357         if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
358                 printf("\n");
359                 printf("GPU: Bypassing workaround detection.\n");
360                 printf("GPU: OpenGL identification strings\n");
361                 printf("GPU: vendor: %s\n", vendor);
362                 printf("GPU: renderer: %s\n", renderer);
363                 printf("GPU: version: %s\n\n", version);
364                 GG.mip_render_workaround = true;
365                 GG.depth_blitting_workaround = true;
366                 GG.unused_fb_slot_workaround = true;
367         }
368
369         /* df/dy calculation factors, those are dependent on driver */
370         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
371                 GG.dfdyfactors[0] = 1.0;
372                 GG.dfdyfactors[1] = -1.0;
373         }
374         else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
375                  (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
376                   strstr(version, "4.0.0 - Build 9.18.10.3186") ||
377                   strstr(version, "4.0.0 - Build 9.18.10.3165") ||
378                   strstr(version, "3.1.0 - Build 9.17.10.3347") ||
379                   strstr(version, "3.1.0 - Build 9.17.10.4101") ||
380                   strstr(version, "3.3.0 - Build 8.15.10.2618")))
381         {
382                 GG.dfdyfactors[0] = -1.0;
383                 GG.dfdyfactors[1] = 1.0;
384         }
385         else {
386                 GG.dfdyfactors[0] = 1.0;
387                 GG.dfdyfactors[1] = 1.0;
388         }
389
390
391         GPU_invalid_tex_init();
392 }
393
394 void gpu_extensions_exit(void)
395 {
396         GPU_invalid_tex_free();
397 }
398
399 int GPU_color_depth(void)
400 {
401         return GG.colordepth;
402 }
403
404 bool GPU_mem_stats_supported(void)
405 {
406         return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
407 }
408
409
410 void GPU_mem_stats_get(int *totalmem, int *freemem)
411 {
412         /* TODO(merwin): use Apple's platform API to get this info */
413
414         if (GLEW_NVX_gpu_memory_info) {
415                 /* returned value in Kb */
416                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
417
418                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
419         }
420         else if (GLEW_ATI_meminfo) {
421                 int stats[4];
422
423                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
424                 *freemem = stats[0];
425                 *totalmem = 0;
426         }
427         else {
428                 *totalmem = 0;
429                 *freemem = 0;
430         }
431 }