2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2005 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Brecht Van Lommel.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/gpu/intern/gpu_extensions.c
31 * Wrap OpenGL features such as textures, shaders and GLSL
32 * with checks for drivers and GPU support.
35 #include "BLI_utildefines.h"
36 #include "BLI_math_base.h"
37 #include "BLI_math_vector.h"
39 #include "BKE_global.h"
40 #include "MEM_guardedalloc.h"
42 #include "GPU_extensions.h"
43 #include "GPU_framebuffer.h"
45 #include "GPU_texture.h"
47 #include "intern/gpu_private.h"
54 # include "BLI_winstuff.h"
57 /* Extensions support */
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
68 static struct GPUGlobal {
73 GLint maxtexturesfrag;
74 GLint maxtexturesgeom;
75 GLint maxtexturesvert;
79 int samples_color_texture_max;
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 */
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
97 bool depth_blitting_workaround;
98 /* Crappy driver don't know how to map framebuffer slot to output vars...
99 * We need to have no "holes" in the output buffer slots. */
100 bool unused_fb_slot_workaround;
104 static void gpu_detect_mip_render_workaround(void)
107 float *source_pix = MEM_callocN(sizeof(float) * 4 * 6 * cube_size * cube_size, __func__);
108 float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f};
110 GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL);
111 MEM_freeN(source_pix);
113 GPU_texture_bind(tex, 0);
114 GPU_texture_generate_mipmap(tex);
115 glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0);
116 glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0);
117 GPU_texture_unbind(tex);
119 GPUFrameBuffer *fb = GPU_framebuffer_create();
120 GPU_framebuffer_texture_attach(fb, tex, 0, 1);
121 GPU_framebuffer_bind(fb);
122 GPU_framebuffer_clear_color(fb, clear_color);
123 GPU_framebuffer_restore();
124 GPU_framebuffer_free(fb);
126 float *data = GPU_texture_read(tex, GPU_DATA_FLOAT, 1);
127 GG.mip_render_workaround = !equals_v4v4(clear_color, data);
130 GPU_texture_free(tex);
135 bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
137 return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
142 int GPU_max_texture_size(void)
144 return GG.maxtexsize;
147 int GPU_max_texture_layers(void)
149 return GG.maxtexlayers;
152 int GPU_max_textures(void)
154 return GG.maxtextures;
157 int GPU_max_textures_frag(void)
159 return GG.maxtexturesfrag;
162 int GPU_max_textures_geom(void)
164 return GG.maxtexturesgeom;
167 int GPU_max_textures_vert(void)
169 return GG.maxtexturesvert;
172 float GPU_max_texture_anisotropy(void)
174 return GG.max_anisotropy;
177 int GPU_max_color_texture_samples(void)
179 return GG.samples_color_texture_max;
182 int GPU_max_cube_map_size(void)
184 return GG.maxcubemapsize;
187 int GPU_max_ubo_binds(void)
189 return GG.maxubobinds;
192 int GPU_max_ubo_size(void)
194 return GG.maxubosize;
197 float GPU_max_line_width(void)
199 return GG.line_width_range[1];
202 void GPU_get_dfdy_factors(float fac[2])
204 copy_v2_v2(fac, GG.dfdyfactors);
207 bool GPU_mip_render_workaround(void)
209 return GG.mip_render_workaround;
212 bool GPU_depth_blitting_workaround(void)
214 return GG.depth_blitting_workaround;
217 bool GPU_unused_fb_slot_workaround(void)
219 return GG.unused_fb_slot_workaround;
222 void gpu_extensions_init(void)
224 /* during 2.8 development each platform has its own OpenGL minimum requirements
225 * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions
226 * see developer.blender.org/T49012 for details
228 BLI_assert(GLEW_VERSION_3_3);
230 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag);
231 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert);
232 glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom);
233 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures);
235 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize);
236 glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers);
237 glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize);
239 if (GLEW_EXT_texture_filter_anisotropic)
240 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy);
242 GG.max_anisotropy = 1.0f;
244 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds);
245 glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
247 glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, GG.line_width_range);
251 glBindFramebuffer(GL_FRAMEBUFFER, 0);
252 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret);
253 /* We expect FRONT_LEFT to be the default buffer. */
254 BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT);
258 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &r);
259 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, &g);
260 glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, &b);
261 GG.colordepth = r + g + b; /* Assumes same depth for RGB. */
263 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max);
265 const char *vendor = (const char *)glGetString(GL_VENDOR);
266 const char *renderer = (const char *)glGetString(GL_RENDERER);
267 const char *version = (const char *)glGetString(GL_VERSION);
269 if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) {
270 GG.device = GPU_DEVICE_ATI;
271 GG.driver = GPU_DRIVER_OFFICIAL;
274 if (strstr(version, "4.5.13399") ||
275 strstr(version, "4.5.13417") ||
276 strstr(version, "4.5.13422"))
278 /* The renderers include:
279 * Mobility Radeon HD 5000;
283 * And many others... */
285 GG.unused_fb_slot_workaround = true;
289 #if defined(__APPLE__)
290 if (strstr(renderer, "AMD Radeon Pro") ||
291 strstr(renderer, "AMD Radeon R9") ||
292 strstr(renderer, "AMD Radeon RX"))
294 GG.depth_blitting_workaround = true;
298 else if (strstr(vendor, "NVIDIA")) {
299 GG.device = GPU_DEVICE_NVIDIA;
300 GG.driver = GPU_DRIVER_OFFICIAL;
302 else if (strstr(vendor, "Intel") ||
303 /* src/mesa/drivers/dri/intel/intel_context.c */
304 strstr(renderer, "Mesa DRI Intel") ||
305 strstr(renderer, "Mesa DRI Mobile Intel"))
307 GG.device = GPU_DEVICE_INTEL;
308 GG.driver = GPU_DRIVER_OFFICIAL;
310 if (strstr(renderer, "UHD Graphics") ||
311 /* Not UHD but affected by the same bugs. */
312 strstr(renderer, "HD Graphics 530") ||
313 strstr(renderer, "Kaby Lake GT2"))
315 GG.device |= GPU_DEVICE_INTEL_UHD;
318 else if ((strstr(renderer, "Mesa DRI R")) ||
319 (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
320 (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
321 (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
323 GG.device = GPU_DEVICE_ATI;
324 GG.driver = GPU_DRIVER_OPENSOURCE;
326 else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) {
327 GG.device = GPU_DEVICE_NVIDIA;
328 GG.driver = GPU_DRIVER_OPENSOURCE;
330 else if (strstr(vendor, "Mesa")) {
331 GG.device = GPU_DEVICE_SOFTWARE;
332 GG.driver = GPU_DRIVER_SOFTWARE;
334 else if (strstr(vendor, "Microsoft")) {
335 GG.device = GPU_DEVICE_SOFTWARE;
336 GG.driver = GPU_DRIVER_SOFTWARE;
338 else if (strstr(renderer, "Apple Software Renderer")) {
339 GG.device = GPU_DEVICE_SOFTWARE;
340 GG.driver = GPU_DRIVER_SOFTWARE;
342 else if (strstr(renderer, "llvmpipe")) {
343 GG.device = GPU_DEVICE_SOFTWARE;
344 GG.driver = GPU_DRIVER_SOFTWARE;
347 printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n");
348 GG.device = GPU_DEVICE_ANY;
349 GG.driver = GPU_DRIVER_ANY;
354 #elif defined(__APPLE__)
360 gpu_detect_mip_render_workaround();
362 if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
364 printf("GPU: Bypassing workaround detection.\n");
365 printf("GPU: OpenGL indentification strings\n");
366 printf("GPU: vendor: %s\n", vendor);
367 printf("GPU: renderer: %s\n", renderer);
368 printf("GPU: version: %s\n\n", version);
369 GG.mip_render_workaround = true;
370 GG.depth_blitting_workaround = true;
371 GG.unused_fb_slot_workaround = true;
374 /* df/dy calculation factors, those are dependent on driver */
375 if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
376 GG.dfdyfactors[0] = 1.0;
377 GG.dfdyfactors[1] = -1.0;
379 else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) &&
380 (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
381 strstr(version, "4.0.0 - Build 9.18.10.3186") ||
382 strstr(version, "4.0.0 - Build 9.18.10.3165") ||
383 strstr(version, "3.1.0 - Build 9.17.10.3347") ||
384 strstr(version, "3.1.0 - Build 9.17.10.4101") ||
385 strstr(version, "3.3.0 - Build 8.15.10.2618")))
387 GG.dfdyfactors[0] = -1.0;
388 GG.dfdyfactors[1] = 1.0;
391 GG.dfdyfactors[0] = 1.0;
392 GG.dfdyfactors[1] = 1.0;
396 GPU_invalid_tex_init();
399 void gpu_extensions_exit(void)
401 GPU_invalid_tex_free();
404 int GPU_color_depth(void)
406 return GG.colordepth;
409 bool GPU_mem_stats_supported(void)
411 return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM);
415 void GPU_mem_stats_get(int *totalmem, int *freemem)
417 /* TODO(merwin): use Apple's platform API to get this info */
419 if (GLEW_NVX_gpu_memory_info) {
420 /* returned value in Kb */
421 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
423 glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
425 else if (GLEW_ATI_meminfo) {
428 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);