[Bf-blender-cvs] [c0640ddff93] blender-v3.3-release: MacOS: Resolve purple rendering artifacts in EEVEE materials by increasing sampler limit.

Jason Fielder noreply at git.blender.org
Wed Sep 21 14:27:08 CEST 2022


Commit: c0640ddff93664bb6bf7ea3b57146ed3ca462340
Author: Jason Fielder
Date:   Tue Sep 6 07:55:21 2022 +0200
Branches: blender-v3.3-release
https://developer.blender.org/rBc0640ddff93664bb6bf7ea3b57146ed3ca462340

MacOS: Resolve purple rendering artifacts in EEVEE materials by increasing sampler limit.

Enables a feature flag during OpenGL device initialisation on macOS, which increases the available number of texture samplers available for use within shaders. Enabling this flag removes purple rendering artifacts present in certain EEVEE materials, when the existing limit of 16 is exceeded.

This feature flag is supported on Apple Silicon and AMD GPUs, for devices supporting macOS 11.0+. Device initialisation first tests whether GL device creation with the flag is supported, if not, we fall back to standard initialisation.

Other solutions would not be trivial or incur additional performance overhead or feature limitations. Other workarounds, such as texture atlas's, could already be created by artists.

{F13245498}

{F13245497}

Reviewed By: jbakker

Maniphest Tasks: T57759, T63935

Differential Revision: https://developer.blender.org/D15336

===================================================================

M	intern/ghost/intern/GHOST_ContextCGL.mm

===================================================================

diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index dd800ef52a3..0076ddcb16c 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -200,7 +200,8 @@ static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
                            bool coreProfile,
                            bool stereoVisual,
                            bool needAlpha,
-                           bool softwareGL)
+                           bool softwareGL,
+                           bool increasedSamplerLimit)
 {
   attribs.clear();
 
@@ -217,6 +218,12 @@ static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
   else {
     attribs.push_back(NSOpenGLPFAAccelerated);
     attribs.push_back(NSOpenGLPFANoRecovery);
+
+    /* Attempt to initialise device with extended sampler limit.
+     * Resolves EEVEE purple rendering artifacts on macOS. */
+    if (increasedSamplerLimit) {
+      attribs.push_back((NSOpenGLPixelFormatAttribute)400);
+    }
   }
 
   if (stereoVisual)
@@ -232,82 +239,123 @@ static void makeAttribList(std::vector<NSOpenGLPixelFormatAttribute> &attribs,
 
 GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
 {
-  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  @autoreleasepool {
 
 #ifdef GHOST_OPENGL_ALPHA
-  static const bool needAlpha = true;
+    static const bool needAlpha = true;
 #else
-  static const bool needAlpha = false;
+    static const bool needAlpha = false;
 #endif
 
-  /* Command-line argument would be better. */
-  static bool softwareGL = getenv("BLENDER_SOFTWAREGL");
-
-  std::vector<NSOpenGLPixelFormatAttribute> attribs;
-  attribs.reserve(40);
-  makeAttribList(attribs, m_coreProfile, m_stereoVisual, needAlpha, softwareGL);
+    /* Command-line argument would be better. */
+    static bool softwareGL = getenv("BLENDER_SOFTWAREGL");
+
+    NSOpenGLPixelFormat *pixelFormat = nil;
+    std::vector<NSOpenGLPixelFormatAttribute> attribs;
+    bool increasedSamplerLimit = false;
+
+    /* Attempt to initialize device with increased sampler limit.
+     * If this is unsupported and initialization fails, initialize GL Context as normal.
+     *
+     * NOTE: This is not available when using the SoftwareGL path, or for Intel-based
+     * platforms. */
+    if (!softwareGL) {
+      if (@available(macos 11.0, *)) {
+        increasedSamplerLimit = true;
+      }
+    }
+    const int max_ctx_attempts = increasedSamplerLimit ? 2 : 1;
+    for (int ctx_create_attempt = 0; ctx_create_attempt < max_ctx_attempts; ctx_create_attempt++) {
+
+      attribs.clear();
+      attribs.reserve(40);
+      makeAttribList(attribs, m_stereoVisual, needAlpha, softwareGL, increasedSamplerLimit);
+
+      pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+      if (pixelFormat == nil) {
+        /* If pixel format creation fails when testing increased sampler limit,
+         * attempt intialisation again with feature disabled, otherwise, fail. */
+        if (increasedSamplerLimit) {
+          increasedSamplerLimit = false;
+          continue;
+        }
+        return GHOST_kFailure;
+      }
 
-  NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
-  if (pixelFormat == nil) {
-    goto error;
-  }
+      /* Attempt to create context. */
+      m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+                                                   shareContext:s_sharedOpenGLContext];
+      [pixelFormat release];
+
+      if (m_openGLContext == nil) {
+        /* If context creation fails when testing increased sampler limit,
+         * attempt re-creation with feature disabled. Otherwise, error. */
+        if (increasedSamplerLimit) {
+          increasedSamplerLimit = false;
+          continue;
+        }
+
+        /* Default context creation attempt failed. */
+        return GHOST_kFailure;
+      }
 
-  m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
-                                               shareContext:s_sharedOpenGLContext];
-  [pixelFormat release];
+      /* Created GL context successfully, activate. */
+      [m_openGLContext makeCurrentContext];
 
-  [m_openGLContext makeCurrentContext];
+      /* When increasing sampler limit, verify created context is a supported configuration. */
+      if (increasedSamplerLimit) {
+        const char *vendor = (const char *)glGetString(GL_VENDOR);
+        const char *renderer = (const char *)glGetString(GL_RENDERER);
+
+        /* If generated context type is unsupported, release existing context and
+         * fallback to creating a normal context below. */
+        if (strstr(vendor, "Intel") || strstr(renderer, "Software")) {
+          [m_openGLContext release];
+          m_openGLContext = nil;
+          increasedSamplerLimit = false;
+          continue;
+        }
+      }
+    }
 
-  if (m_debug) {
-    GLint major = 0, minor = 0;
-    glGetIntegerv(GL_MAJOR_VERSION, &major);
-    glGetIntegerv(GL_MINOR_VERSION, &minor);
-    fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
-    fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
-  }
+    if (m_debug) {
+      GLint major = 0, minor = 0;
+      glGetIntegerv(GL_MAJOR_VERSION, &major);
+      glGetIntegerv(GL_MINOR_VERSION, &minor);
+      fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
+      fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
+    }
 
 #ifdef GHOST_WAIT_FOR_VSYNC
-  {
-    GLint swapInt = 1;
-    /* Wait for vertical-sync, to avoid tearing artifacts. */
-    [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
-  }
+    {
+      GLint swapInt = 1;
+      /* Wait for vertical-sync, to avoid tearing artifacts. */
+      [m_openGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+    }
 #endif
 
-  initContextGLEW();
-
-  if (m_metalView) {
-    if (m_defaultFramebuffer == 0) {
-      /* Create a virtual frame-buffer. */
-      [m_openGLContext makeCurrentContext];
-      metalInitFramebuffer();
+    if (m_metalView) {
+      if (m_defaultFramebuffer == 0) {
+        /* Create a virtual frame-buffer. */
+        [m_openGLContext makeCurrentContext];
+        metalInitFramebuffer();
+        initClearGL();
+      }
+    }
+    else if (m_openGLView) {
+      [m_openGLView setOpenGLContext:m_openGLContext];
+      [m_openGLContext setView:m_openGLView];
       initClearGL();
     }
-  }
-  else if (m_openGLView) {
-    [m_openGLView setOpenGLContext:m_openGLContext];
-    [m_openGLContext setView:m_openGLView];
-    initClearGL();
-  }
-
-  [m_openGLContext flushBuffer];
 
-  if (s_sharedCount == 0)
-    s_sharedOpenGLContext = m_openGLContext;
+    [m_openGLContext flushBuffer];
 
-  s_sharedCount++;
-
-  [pool drain];
+    if (s_sharedCount == 0)
+      s_sharedOpenGLContext = m_openGLContext;
 
+    s_sharedCount++;
+  }
   return GHOST_kSuccess;
-
-error:
-
-  [pixelFormat release];
-
-  [pool drain];
-
-  return GHOST_kFailure;
 }
 
 GHOST_TSuccess GHOST_ContextCGL::releaseNativeHandles()



More information about the Bf-blender-cvs mailing list