Merge branch 'master' into blender2.8
[blender.git] / source / blender / gpu / intern / gpu_extensions.c
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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Brecht Van Lommel.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/gpu/intern/gpu_extensions.c
29  *  \ingroup gpu
30  *
31  * Wrap OpenGL features such as textures, shaders and GLSL
32  * with checks for drivers and GPU support.
33  */
34
35 #include "BLI_utildefines.h"
36 #include "BLI_math_base.h"
37 #include "BLI_math_vector.h"
38
39 #include "BKE_global.h"
40 #include "MEM_guardedalloc.h"
41
42 #include "GPU_extensions.h"
43 #include "GPU_framebuffer.h"
44 #include "GPU_glew.h"
45 #include "GPU_texture.h"
46
47 #include "intern/gpu_private.h"
48
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52
53 #ifdef WIN32
54 #  include "BLI_winstuff.h"
55 #endif
56
57 /* Extensions support */
58
59 /* -- extension: version of GL that absorbs it
60  * EXT_gpu_shader4: 3.0
61  * ARB_framebuffer object: 3.0
62  * EXT_framebuffer_multisample_blit_scaled: ???
63  * ARB_draw_instanced: 3.1
64  * ARB_texture_multisample: 3.2
65  * ARB_texture_query_lod: 4.0
66  */
67
68 static struct GPUGlobal {
69         GLint maxtexsize;
70         GLint maxtexlayers;
71         GLint maxcubemapsize;
72         GLint maxtextures;
73         GLint maxtexturesfrag;
74         GLint maxtexturesgeom;
75         GLint maxtexturesvert;
76         GLint maxubosize;
77         GLint maxubobinds;
78         int colordepth;
79         int samples_color_texture_max;
80         GPUDeviceType device;
81         GPUOSType os;
82         GPUDriverType driver;
83         float line_width_range[2];
84         /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
85          * calculate dfdy in shader differently when drawing to an offscreen buffer. First
86          * number is factor on screen and second is off-screen */
87         float dfdyfactors[2];
88         float max_anisotropy;
89         /* Some Intel drivers have issues with using mips as framebuffer targets if
90          * GL_TEXTURE_MAX_LEVEL is higher than the target mip.
91          * We need a workaround in this cases. */
92         bool mip_render_workaround;
93         /* There is an issue with the glBlitFramebuffer on MacOS with radeon pro graphics.
94          * Blitting depth with GL_DEPTH24_STENCIL8 is buggy so the workaround is to use
95          * GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will
96          * still be broken. */
97         bool depth_blitting_workaround;
98 } GG = {1, 0};
99
100
101 static void gpu_detect_mip_render_workaround(void)
102 {
103         int cube_size = 2;
104         float *source_pix = MEM_callocN(sizeof(float) * 4 * 6 * cube_size * cube_size, __func__);
105         float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
106
107         GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL);
108         MEM_freeN(source_pix);
109
110         GPU_texture_bind(tex, 0);
111         GPU_texture_generate_mipmap(tex);
112         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
113         glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0);
114         GPU_texture_unbind(tex);
115
116         GPUFrameBuffer *fb = GPU_framebuffer_create();
117         GPU_framebuffer_texture_attach(fb, tex, 0, 1);
118         GPU_framebuffer_bind(fb);
119         GPU_framebuffer_clear_color(fb, clear_color);
120         GPU_framebuffer_restore();
121         GPU_framebuffer_free(fb);
122
123         float *data = GPU_texture_read(tex, GPU_DATA_FLOAT, 1);
124         GG.mip_render_workaround = !equals_v4v4(clear_color, data);
125
126         MEM_freeN(data);
127         GPU_texture_free(tex);
128 }
129
130 /* GPU Types */
131
132 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
133 {
134         return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
135 }
136
137 /* GPU Extensions */
138
139 int GPU_max_texture_size(void)
140 {
141         return GG.maxtexsize;
142 }
143
144 int GPU_max_texture_layers(void)
145 {
146         return GG.maxtexlayers;
147 }
148
149 int GPU_max_textures(void)
150 {
151         return GG.maxtextures;
152 }
153
154 int GPU_max_textures_frag(void)
155 {
156         return GG.maxtexturesfrag;
157 }
158
159 int GPU_max_textures_geom(void)
160 {
161         return GG.maxtexturesgeom;
162 }
163
164 int GPU_max_textures_vert(void)
165 {
166         return GG.maxtexturesvert;
167 }
168
169 float GPU_max_texture_anisotropy(void)
170 {
171         return GG.max_anisotropy;
172 }
173
174 int GPU_max_color_texture_samples(void)
175 {
176         return GG.samples_color_texture_max;
177 }
178
179 int GPU_max_cube_map_size(void)
180 {
181         return GG.maxcubemapsize;
182 }
183
184 int GPU_max_ubo_binds(void)
185 {
186         return GG.maxubobinds;
187 }
188
189 int GPU_max_ubo_size(void)
190 {
191         return GG.maxubosize;
192 }
193
194 float GPU_max_line_width(void)
195 {
196         return GG.line_width_range[1];
197 }
198
199 void GPU_get_dfdy_factors(float fac[2])
200 {
201         copy_v2_v2(fac, GG.dfdyfactors);
202 }
203
204 bool GPU_mip_render_workaround(void)
205 {
206         return GG.mip_render_workaround;
207 }
208
209 bool GPU_depth_blitting_workaround(void)
210 {
211         return GG.depth_blitting_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 #if defined(__APPLE__)
266                 if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9")) {
267                         GG.depth_blitting_workaround = true;
268                 }
269 #endif
270         }
271         else if (strstr(vendor, "NVIDIA")) {
272                 GG.device = GPU_DEVICE_NVIDIA;
273                 GG.driver = GPU_DRIVER_OFFICIAL;
274         }
275         else if (strstr(vendor, "Intel") ||
276                  /* src/mesa/drivers/dri/intel/intel_context.c */
277                  strstr(renderer, "Mesa DRI Intel") ||
278                  strstr(renderer, "Mesa DRI Mobile Intel"))
279         {
280                 GG.device = GPU_DEVICE_INTEL;
281                 GG.driver = GPU_DRIVER_OFFICIAL;
282         }
283         else if ((strstr(renderer, "Mesa DRI R")) ||
284                  (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
285                  (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
286                  (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
287         {
288                 GG.device = GPU_DEVICE_ATI;
289                 GG.driver = GPU_DRIVER_OPENSOURCE;
290         }
291         else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
292                 GG.device = GPU_DEVICE_NVIDIA;
293                 GG.driver = GPU_DRIVER_OPENSOURCE;
294         }
295         else if (strstr(vendor, "Mesa")) {
296                 GG.device = GPU_DEVICE_SOFTWARE;
297                 GG.driver = GPU_DRIVER_SOFTWARE;
298         }
299         else if (strstr(vendor, "Microsoft")) {
300                 GG.device = GPU_DEVICE_SOFTWARE;
301                 GG.driver = GPU_DRIVER_SOFTWARE;
302         }
303         else if (strstr(renderer, "Apple Software Renderer")) {
304                 GG.device = GPU_DEVICE_SOFTWARE;
305                 GG.driver = GPU_DRIVER_SOFTWARE;
306         }
307         else {
308                 printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
309                 GG.device = GPU_DEVICE_ANY;
310                 GG.driver = GPU_DRIVER_ANY;
311         }
312
313 #ifdef _WIN32
314         GG.os = GPU_OS_WIN;
315 #elif defined(__APPLE__)
316         GG.os = GPU_OS_MAC;
317 #else
318         GG.os = GPU_OS_UNIX;
319 #endif
320
321         gpu_detect_mip_render_workaround();
322
323         /* df/dy calculation factors, those are dependent on driver */
324         if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
325                 GG.dfdyfactors[0] = 1.0;
326                 GG.dfdyfactors[1] = -1.0;
327         }
328         else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
329                  (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
330                   strstr(version, "4.0.0 - Build 9.18.10.3186") ||
331                   strstr(version, "4.0.0 - Build 9.18.10.3165") ||
332                   strstr(version, "3.1.0 - Build 9.17.10.3347") ||
333                   strstr(version, "3.1.0 - Build 9.17.10.4101") ||
334                   strstr(version, "3.3.0 - Build 8.15.10.2618")))
335         {
336                 GG.dfdyfactors[0] = -1.0;
337                 GG.dfdyfactors[1] = 1.0;
338         }
339         else {
340                 GG.dfdyfactors[0] = 1.0;
341                 GG.dfdyfactors[1] = 1.0;
342         }
343
344
345         GPU_invalid_tex_init();
346 }
347
348 void gpu_extensions_exit(void)
349 {
350         GPU_invalid_tex_free();
351 }
352
353 int GPU_color_depth(void)
354 {
355         return GG.colordepth;
356 }
357
358 bool GPU_mem_stats_supported(void)
359 {
360         return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
361 }
362
363
364 void GPU_mem_stats_get(int *totalmem, int *freemem)
365 {
366         /* TODO(merwin): use Apple's platform API to get this info */
367
368         if (GLEW_NVX_gpu_memory_info) {
369                 /* returned value in Kb */
370                 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
371
372                 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
373         }
374         else if (GLEW_ATI_meminfo) {
375                 int stats[4];
376
377                 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
378                 *freemem = stats[0];
379                 *totalmem = 0;
380         }
381         else {
382                 *totalmem = 0;
383                 *freemem = 0;
384         }
385 }