Browse Source

On OS X + Intel, use dummy color textures for shadow maps to work around a driver bug. Fixes #225.

Lasse Öörni 11 years ago
parent
commit
76d5ffdcf8

+ 11 - 0
Source/Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -205,6 +205,7 @@ Graphics::Graphics(Context* context_) :
     numPrimitives_(0),
     numPrimitives_(0),
     numBatches_(0),
     numBatches_(0),
     maxScratchBufferRequest_(0),
     maxScratchBufferRequest_(0),
+    dummyColorFormat_(0),
     shadowMapFormat_(GL_DEPTH_COMPONENT16),
     shadowMapFormat_(GL_DEPTH_COMPONENT16),
     hiresShadowMapFormat_(GL_DEPTH_COMPONENT24),
     hiresShadowMapFormat_(GL_DEPTH_COMPONENT24),
     defaultTextureFilterMode_(FILTER_BILINEAR),
     defaultTextureFilterMode_(FILTER_BILINEAR),
@@ -2579,6 +2580,16 @@ void Graphics::CheckFeatureSupport(String& extensions)
         lightPrepassSupport_ = true;
         lightPrepassSupport_ = true;
     if (numSupportedRTs >= 4)
     if (numSupportedRTs >= 4)
         deferredSupport_ = true;
         deferredSupport_ = true;
+    
+    #if defined(__APPLE__) && !defined(IOS)
+    // On Apple check for an Intel driver and use shadow map RGBA dummy color textures, because mixing
+    // depth-only FBO rendering and backbuffer rendering will bug, resulting in a black screen in full
+    // screen mode, and incomplete shadow maps in windowed mode
+    String renderer((const char*)glGetString(GL_RENDERER));
+    if (renderer.Contains("Intel", false))
+        dummyColorFormat_ = GetRGBAFormat();
+    #endif
+    
     #else
     #else
     // Check for best supported depth renderbuffer format for GLES2
     // Check for best supported depth renderbuffer format for GLES2
     if (CheckExtension(extensions, "GL_OES_depth24"))
     if (CheckExtension(extensions, "GL_OES_depth24"))

+ 4 - 2
Source/Engine/Graphics/OpenGL/OGLGraphics.h

@@ -266,8 +266,8 @@ public:
     unsigned GetNumPrimitives() const { return numPrimitives_; }
     unsigned GetNumPrimitives() const { return numPrimitives_; }
     /// Return number of batches drawn this frame.
     /// Return number of batches drawn this frame.
     unsigned GetNumBatches() const { return numBatches_; }
     unsigned GetNumBatches() const { return numBatches_; }
-    /// Return dummy color texture format for shadow maps.
-    unsigned GetDummyColorFormat() const { return 0; }
+    /// Return dummy color texture format for shadow maps. 0 if not needed, may be nonzero on OS X to work around an Intel driver issue.
+    unsigned GetDummyColorFormat() const { return dummyColorFormat_; }
     /// Return shadow map depth texture format, or 0 if not supported.
     /// Return shadow map depth texture format, or 0 if not supported.
     unsigned GetShadowMapFormat() const { return shadowMapFormat_; }
     unsigned GetShadowMapFormat() const { return shadowMapFormat_; }
     /// Return 24-bit shadow map depth texture format, or 0 if not supported.
     /// Return 24-bit shadow map depth texture format, or 0 if not supported.
@@ -503,6 +503,8 @@ private:
     Vector<GPUObject*> gpuObjects_;
     Vector<GPUObject*> gpuObjects_;
     /// Scratch buffers.
     /// Scratch buffers.
     Vector<ScratchBuffer> scratchBuffers_;
     Vector<ScratchBuffer> scratchBuffers_;
+    /// Shadow map dummy color texture format.
+    unsigned dummyColorFormat_;
     /// Shadow map depth texture format.
     /// Shadow map depth texture format.
     unsigned shadowMapFormat_;
     unsigned shadowMapFormat_;
     /// Shadow map 24-bit depth texture format.
     /// Shadow map 24-bit depth texture format.

+ 14 - 3
Source/Engine/Graphics/Renderer.cpp

@@ -871,8 +871,10 @@ Texture2D* Renderer::GetShadowMap(Light* light, Camera* camera, unsigned viewWid
     
     
     SharedPtr<Texture2D> newShadowMap(new Texture2D(context_));
     SharedPtr<Texture2D> newShadowMap(new Texture2D(context_));
     int retries = 3;
     int retries = 3;
+    unsigned dummyColorFormat = graphics_->GetDummyColorFormat();
     
     
-    // OpenGL: create shadow map only. Color rendertarget is not needed
+    // OpenGL: create shadow map only in normal cases. Color rendertarget is only needed for a workaround
+    // of an OS X + Intel bug
     #ifdef URHO3D_OPENGL
     #ifdef URHO3D_OPENGL
     while (retries)
     while (retries)
     {
     {
@@ -888,13 +890,22 @@ Texture2D* Renderer::GetShadowMap(Light* light, Camera* camera, unsigned viewWid
             newShadowMap->SetFilterMode(FILTER_BILINEAR);
             newShadowMap->SetFilterMode(FILTER_BILINEAR);
             newShadowMap->SetShadowCompare(true);
             newShadowMap->SetShadowCompare(true);
             #endif
             #endif
+            if (dummyColorFormat)
+            {
+                // If no dummy color rendertarget for this size exists yet, create one now
+                if (!colorShadowMaps_.Contains(searchKey))
+                {
+                    colorShadowMaps_[searchKey] = new Texture2D(context_);
+                    colorShadowMaps_[searchKey]->SetSize(width, height, dummyColorFormat, TEXTURE_RENDERTARGET);
+                }
+                // Link the color rendertarget to the shadow map
+                newShadowMap->GetRenderSurface()->SetLinkedRenderTarget(colorShadowMaps_[searchKey]->GetRenderSurface());
+            }
             break;
             break;
         }
         }
     }
     }
     #else
     #else
     // Direct3D9: create shadow map and dummy color rendertarget
     // Direct3D9: create shadow map and dummy color rendertarget
-    unsigned dummyColorFormat = graphics_->GetDummyColorFormat();
-    
     while (retries)
     while (retries)
     {
     {
         if (!newShadowMap->SetSize(width, height, shadowMapFormat, TEXTURE_DEPTHSTENCIL))
         if (!newShadowMap->SetSize(width, height, shadowMapFormat, TEXTURE_DEPTHSTENCIL))

+ 5 - 3
Source/Engine/Graphics/View.cpp

@@ -1445,7 +1445,7 @@ void View::ExecuteRenderPathCommands()
                 if (!lightQueues_.Empty())
                 if (!lightQueues_.Empty())
                 {
                 {
                     PROFILE(RenderLights);
                     PROFILE(RenderLights);
-                    
+
                     SetRenderTargets(command);
                     SetRenderTargets(command);
                     
                     
                     for (Vector<LightBatchQueue>::Iterator i = lightQueues_.Begin(); i != lightQueues_.End(); ++i)
                     for (Vector<LightBatchQueue>::Iterator i = lightQueues_.Begin(); i != lightQueues_.End(); ++i)
@@ -1456,7 +1456,7 @@ void View::ExecuteRenderPathCommands()
                             RenderShadowMap(*i);
                             RenderShadowMap(*i);
                             SetRenderTargets(command);
                             SetRenderTargets(command);
                         }
                         }
-                        
+
                         SetTextures(command);
                         SetTextures(command);
                         graphics_->SetFillMode(camera_->GetFillMode());
                         graphics_->SetFillMode(camera_->GetFillMode());
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(), camera_->GetProjection());
                         graphics_->SetClipPlane(camera_->GetUseClipping(), camera_->GetClipPlane(), camera_->GetView(), camera_->GetProjection());
@@ -2771,10 +2771,12 @@ void View::RenderShadowMap(const LightBatchQueue& queue)
     graphics_->SetClipPlane(false);
     graphics_->SetClipPlane(false);
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
     graphics_->SetRenderTarget(0, shadowMap->GetRenderSurface()->GetLinkedRenderTarget());
     graphics_->SetRenderTarget(0, shadowMap->GetRenderSurface()->GetLinkedRenderTarget());
+    for (unsigned i = 1; i < MAX_RENDERTARGETS; ++i)
+        graphics_->SetRenderTarget(i, (RenderSurface*)0);
     graphics_->SetDepthStencil(shadowMap);
     graphics_->SetDepthStencil(shadowMap);
     graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
     graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
     graphics_->Clear(CLEAR_DEPTH);
     graphics_->Clear(CLEAR_DEPTH);
-    
+
     // Set shadow depth bias
     // Set shadow depth bias
     const BiasParameters& parameters = queue.light_->GetShadowBias();
     const BiasParameters& parameters = queue.light_->GetShadowBias();