Explorar el Código

OpenGL: Fixes to ensure depth buffer with no stencil component can be properly bound

BearishSun hace 9 años
padre
commit
a0ab82851c

+ 7 - 8
Source/BansheeGLRenderAPI/Include/BsGLFrameBufferObject.h

@@ -38,7 +38,7 @@ namespace bs { namespace ct
         ~GLFrameBufferObject();
 
 		/**
-		 * Binds a color surface to the specific attachment point.
+		 * Binds a color surface to the specific attachment point. Call rebuild() to apply changes.
 		 *
 		 * @param[in]	attachment	Attachment point index in the range [0, BS_MAX_MULTIPLE_RENDER_TARGETS).
 		 * @param[in]	target		Description of the color surface to attach.
@@ -50,14 +50,14 @@ namespace bs { namespace ct
         void bindSurface(UINT32 attachment, const GLSurfaceDesc& target);
 
 		/**
-		 * Unbinds the attachment at the specified attachment index.
+		 * Unbinds the attachment at the specified attachment index. Call rebuild() to apply changes.
 		 *
 		 * @param[in]	attachment	Attachment point index in the range [0, BS_MAX_MULTIPLE_RENDER_TARGETS).
 		 */
         void unbindSurface(UINT32 attachment);
 
 		/**
-		 * Binds a depth/stencil buffer.
+		 * Binds a depth/stencil buffer. Call rebuild() to apply changes.
 		 *
 		 * @note	
 		 * Multisample counts of depth/stencil and color surfaces must match.
@@ -65,9 +65,12 @@ namespace bs { namespace ct
 		 */
 		void bindDepthStencil(SPtr<GLPixelBuffer> depthStencilBuffer);
 
-		/**	Unbinds a depth stencil buffer. */
+		/**	Unbinds a depth stencil buffer. Call rebuild() to apply changes. */
 		void unbindDepthStencil();
         
+		/**	Rebuilds internal frame buffer object. Should be called whenever surfaces changes or is bound/unbound. */
+		void rebuild();
+
 		/** Binds the frame buffer object to the OpenGL pipeline, making it used for any further rendering operations. */
         void bind();
 
@@ -77,10 +80,6 @@ namespace bs { namespace ct
 		/**	Returns internal OpenGL frame buffer id. */
 		GLuint getGLFBOID() const { return mFB; }
 
-    private:
-		/**	Rebuilds internal frame buffer object. Should be called whenever surfaces change. */
-        void rebuild();
-
 	private:
         GLuint mFB;
 

+ 4 - 1
Source/BansheeGLRenderAPI/Include/BsGLPixelFormat.h

@@ -31,7 +31,10 @@ namespace bs { namespace ct
 		static GLenum getGLInternalFormat(PixelFormat mFormat, bool hwGamma = false);
 	
 		/** Returns an OpenGL type that should be used for creating a buffer for the specified depth/stencil format. */
-		static GLenum getDepthStencilTypeFromFormat(PixelFormat mFormat);
+		static GLenum getDepthStencilTypeFromPF(PixelFormat mFormat);
+
+		/** Returns an OpenGL format that should be used for creating a buffer for the specified depth/stencil format. */
+		static GLenum getDepthStencilFormatFromPF(PixelFormat mFormat);
 
 		/** Converts engine GPU buffer format to OpenGL GPU buffer format. */
 		static GLenum getBufferFormat(GpuBufferFormat format);

+ 12 - 11
Source/BansheeGLRenderAPI/Source/BsGLFrameBufferObject.cpp

@@ -28,26 +28,17 @@ namespace bs { namespace ct
     {
         assert(attachment < BS_MAX_MULTIPLE_RENDER_TARGETS);
         mColor[attachment] = target;
-
-		if(mColor[0].buffer)
-			rebuild();
     }
 
     void GLFrameBufferObject::unbindSurface(UINT32 attachment)
     {
         assert(attachment < BS_MAX_MULTIPLE_RENDER_TARGETS);
         mColor[attachment].buffer = nullptr;
-
-		if(mColor[0].buffer)
-			rebuild();
     }
 
 	void GLFrameBufferObject::bindDepthStencil(SPtr<GLPixelBuffer> depthStencilBuffer)
 	{
 		mDepthStencilBuffer = depthStencilBuffer;
-
-		if (mColor[0].buffer)
-			rebuild();
 	}
 
 	void GLFrameBufferObject::unbindDepthStencil()
@@ -100,8 +91,18 @@ namespace bs { namespace ct
             }
         }
 
-		if(mDepthStencilBuffer != nullptr)
-			mDepthStencilBuffer->bindToFramebuffer(GL_DEPTH_STENCIL_ATTACHMENT, 0, bindAllLayers);
+		if (mDepthStencilBuffer != nullptr)
+		{
+			GLenum depthStencilFormat = GLPixelUtil::getDepthStencilFormatFromPF(mDepthStencilBuffer->getFormat());
+
+			GLenum attachmentPoint;
+			if (depthStencilFormat == GL_DEPTH_STENCIL)
+				attachmentPoint = GL_DEPTH_STENCIL_ATTACHMENT;
+			else // Depth only
+				attachmentPoint = GL_DEPTH_ATTACHMENT;
+
+			mDepthStencilBuffer->bindToFramebuffer(attachmentPoint, 0, true);
+		}
 
 		// Do glDrawBuffer calls
 		GLenum bufs[BS_MAX_MULTIPLE_RENDER_TARGETS];

+ 21 - 1
Source/BansheeGLRenderAPI/Source/BsGLPixelFormat.cpp

@@ -179,7 +179,7 @@ namespace bs { namespace ct
         }
     }
 
-	GLenum GLPixelUtil::getDepthStencilTypeFromFormat(PixelFormat mFormat)
+	GLenum GLPixelUtil::getDepthStencilTypeFromPF(PixelFormat mFormat)
 	{
 		switch(mFormat)
 		{
@@ -199,6 +199,26 @@ namespace bs { namespace ct
 		return PF_D32_S8X24;
 	}
 		
+	GLenum GLPixelUtil::getDepthStencilFormatFromPF(PixelFormat mFormat)
+	{
+		switch (mFormat)
+		{
+		case PF_D32_S8X24:
+			return GL_DEPTH_STENCIL;
+		case PF_D24S8:
+			return GL_DEPTH_STENCIL;
+		case PF_D32:
+			return GL_DEPTH_COMPONENT;
+		case PF_D16:
+			return GL_DEPTH_COMPONENT;
+		default:
+			break;
+		}
+
+		LOGERR("Invalid depth stencil format");
+		return GL_DEPTH_STENCIL;
+	}
+
 	GLenum GLPixelUtil::getBufferFormat(GpuBufferFormat format)
 	{
 		static bool lookupInitialized = false;

+ 2 - 0
Source/BansheeGLRenderAPI/Source/BsGLRenderTexture.cpp

@@ -113,6 +113,8 @@ namespace bs
 
 			mFB->bindDepthStencil(depthStencilBuffer);
 		}
+
+		mFB->rebuild();
 	}
 
 	void GLRenderTexture::getCustomAttribute(const String& name, void* data) const

+ 4 - 3
Source/BansheeGLRenderAPI/Source/BsGLTexture.cpp

@@ -89,17 +89,18 @@ namespace bs { namespace ct
 		}
 		else if((usage & TU_DEPTHSTENCIL) != 0 && mProperties.getTextureType() == TEX_TYPE_2D)
 		{
-			GLenum depthStencilFormat = GLPixelUtil::getDepthStencilTypeFromFormat(mInternalFormat);
+			GLenum depthStencilType = GLPixelUtil::getDepthStencilTypeFromPF(mInternalFormat);
+			GLenum depthStencilFormat = GLPixelUtil::getDepthStencilFormatFromPF(mInternalFormat);
 
 			if (numFaces <= 1)
 			{
 				glTexImage2D(GL_TEXTURE_2D, 0, mGLFormat, width, height, 0,
-					GL_DEPTH_STENCIL, depthStencilFormat, nullptr);
+							 depthStencilFormat, depthStencilType, nullptr);
 			}
 			else
 			{
 				glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, mGLFormat, width, height, numFaces, 0,
-					GL_DEPTH_STENCIL, depthStencilFormat, nullptr);
+							 depthStencilFormat, depthStencilType, nullptr);
 			}
 		}
 		else