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