Explorar el Código

Fix MSAA with ARM Mali OpenGL ES (#2818)

* Fix MSAA with ARM Mali OpenGL ES

* indenting
Cedric Guillemet hace 3 años
padre
commit
f0cf1794e7
Se han modificado 8 ficheros con 178 adiciones y 38 borrados
  1. 5 0
      bindings/bf/bgfx.bf
  2. 5 0
      bindings/cs/bgfx.cs
  3. 1 0
      bindings/d/types.d
  4. 3 0
      bindings/zig/bgfx.zig
  5. 1 0
      include/bgfx/defines.h
  6. 1 0
      scripts/bgfx.idl
  7. 2 0
      src/glimports.h
  8. 160 38
      src/renderer_gl.cpp

+ 5 - 0
bindings/bf/bgfx.bf

@@ -1288,6 +1288,11 @@ public static class bgfx
 		/// Microsoft adapter.
 		/// </summary>
 		Microsoft              = 0x1414,
+	
+		/// <summary>
+		/// ARM adapter.
+		/// </summary>
+		Arm                    = 0x13b5,
 	}
 	
 	[AllowDuplicates]

+ 5 - 0
bindings/cs/bgfx.cs

@@ -1287,6 +1287,11 @@ public static partial class bgfx
 		/// Microsoft adapter.
 		/// </summary>
 		Microsoft              = 0x1414,
+	
+		/// <summary>
+		/// ARM adapter.
+		/// </summary>
+		Arm                    = 0x13b5,
 	}
 	
 	[Flags]

+ 1 - 0
bindings/d/types.d

@@ -438,6 +438,7 @@ enum ushort BGFX_PCI_ID_APPLE = 0x106b; /// Apple adapter.
 enum ushort BGFX_PCI_ID_INTEL = 0x8086; /// Intel adapter.
 enum ushort BGFX_PCI_ID_NVIDIA = 0x10de; /// nVidia adapter.
 enum ushort BGFX_PCI_ID_MICROSOFT = 0x1414; /// Microsoft adapter.
+enum ushort BGFX_PCI_ID_ARM = 0x13b5; /// ARM adapter.
 
 enum ubyte BGFX_CUBE_MAP_POSITIVE_X = 0x00; /// Cubemap +x.
 enum ubyte BGFX_CUBE_MAP_NEGATIVE_X = 0x01; /// Cubemap -x.

+ 3 - 0
bindings/zig/bgfx.zig

@@ -789,6 +789,9 @@ pub const PciIdFlags_Nvidia: PciIdFlags                 = 0x10de;
 /// Microsoft adapter.
 pub const PciIdFlags_Microsoft: PciIdFlags              = 0x1414;
 
+/// ARM adapter.
+pub const PciIdFlags_Arm: PciIdFlags                    = 0x13b5;
+
 pub const CubeMapFlags = u32;
 /// Cubemap +x.
 pub const CubeMapFlags_PositiveX: CubeMapFlags              = 0x00000000;

+ 1 - 0
include/bgfx/defines.h

@@ -524,6 +524,7 @@
 #define BGFX_PCI_ID_INTEL                         UINT16_C(0x8086) //!< Intel adapter.
 #define BGFX_PCI_ID_NVIDIA                        UINT16_C(0x10de) //!< nVidia adapter.
 #define BGFX_PCI_ID_MICROSOFT                     UINT16_C(0x1414) //!< Microsoft adapter.
+#define BGFX_PCI_ID_ARM                           UINT16_C(0x13b5) //!< ARM adapter.
 
 #define BGFX_CUBE_MAP_POSITIVE_X                  UINT8_C(0x00) //!< Cubemap +x.
 #define BGFX_CUBE_MAP_NEGATIVE_X                  UINT8_C(0x01) //!< Cubemap -x.

+ 1 - 0
scripts/bgfx.idl

@@ -429,6 +429,7 @@ flag.PciId { bits = 16 , const }
 	.Intel               (0x8086) --- Intel adapter.
 	.Nvidia              (0x10de) --- nVidia adapter.
 	.Microsoft           (0x1414) --- Microsoft adapter.
+	.Arm                 (0x13b5) --- ARM adapter.
 	()
 
 flag.CubeMap { bits = 8, const }

+ 2 - 0
src/glimports.h

@@ -228,6 +228,7 @@ typedef void           (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GL
 typedef void           (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
 typedef void           (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
 typedef void           (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+typedef void           (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
 #endif // GL_IMPORT_TYPEDEFS
 
 #if BGFX_USE_GL_DYNAMIC_LIB
@@ -495,6 +496,7 @@ GL_IMPORT______(true,  PFNGLGETINTERNALFORMATI64VPROC,             glGetInternal
 #endif // BGFX_USE_GL_DYNAMIC_LIB
 
 GL_IMPORT______(true,  PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC,    glGetTranslatedShaderSourceANGLE);
+GL_IMPORT______(true, PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC, glFramebufferTexture2DMultisampleEXT);
 
 #if !BGFX_CONFIG_RENDERER_OPENGL
 GL_IMPORT______(true,  PFNGLPOINTSIZEPROC,                         glPointSize);

+ 160 - 38
src/renderer_gl.cpp

@@ -2143,6 +2143,7 @@ namespace bgfx { namespace gl
 		{ "Advanced Micro Devices, Inc.", BGFX_PCI_ID_AMD    },
 		{ "Intel",                        BGFX_PCI_ID_INTEL  },
 		{ "ATI Technologies Inc.",        BGFX_PCI_ID_AMD    },
+		{ "ARM",                          BGFX_PCI_ID_ARM    },
 	};
 
 	struct Workaround
@@ -2185,6 +2186,7 @@ namespace bgfx { namespace gl
 			, m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT)
 			, m_backBufferFbo(0)
 			, m_msaaBackBufferFbo(0)
+			, m_msaaBlitProgram(0)
 			, m_clearQuadColor(BGFX_INVALID_HANDLE)
 			, m_clearQuadDepth(BGFX_INVALID_HANDLE)
 		{
@@ -3801,34 +3803,122 @@ namespace bgfx { namespace gl
 		void createMsaaFbo(uint32_t _width, uint32_t _height, uint32_t _msaa)
 		{
 			if (0 == m_msaaBackBufferFbo // iOS
-			&&  1 < _msaa)
+				&&  1 < _msaa)
 			{
 				GLenum storageFormat = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER)
-					? GL_SRGB8_ALPHA8
-					: GL_RGBA8
-					;
+									   ? GL_SRGB8_ALPHA8
+									   : GL_RGBA8
+				;
+				GLenum attachment = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || m_gles3
+					? GL_DEPTH_STENCIL_ATTACHMENT
+					: GL_DEPTH_ATTACHMENT;
 
 				GL_CHECK(glGenFramebuffers(1, &m_msaaBackBufferFbo) );
 				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
-				GL_CHECK(glGenRenderbuffers(BX_COUNTOF(m_msaaBackBufferRbos), m_msaaBackBufferRbos) );
-				GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_msaaBackBufferRbos[0]) );
-				GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msaa, storageFormat, _width, _height) );
-				GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_msaaBackBufferRbos[1]) );
-				GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msaa, GL_DEPTH24_STENCIL8, _width, _height) );
-				GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_msaaBackBufferRbos[0]) );
-
-				GLenum attachment = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || m_gles3
-					? GL_DEPTH_STENCIL_ATTACHMENT
-					: GL_DEPTH_ATTACHMENT
-					;
-				GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, m_msaaBackBufferRbos[1]) );
+				if (g_caps.vendorId == BGFX_PCI_ID_ARM && m_gles3) {
+					GL_CHECK(glGenTextures(BX_COUNTOF(m_msaaBackBufferTextures), m_msaaBackBufferTextures));
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_msaaBackBufferTextures[0]));
+					GL_CHECK(glTexStorage2D(GL_TEXTURE_2D, 1, storageFormat, _width, _height));
+					GL_CHECK(glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+																  GL_COLOR_ATTACHMENT0,
+																  GL_TEXTURE_2D,
+																  m_msaaBackBufferTextures[0], 0,
+																  _msaa));
+					GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo));
+
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_msaaBackBufferTextures[1]));
+					GL_CHECK(glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, _width, _height));
+					GL_CHECK(glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+																  attachment,
+																  GL_TEXTURE_2D,
+																  m_msaaBackBufferTextures[1], 0,
+																  _msaa));
+					GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+
+					BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER),
+							  "glCheckFramebufferStatus failed 0x%08x",
+							  glCheckFramebufferStatus(GL_FRAMEBUFFER)
+					);
 
-				BX_ASSERT(GL_FRAMEBUFFER_COMPLETE ==  glCheckFramebufferStatus(GL_FRAMEBUFFER)
+					if (0 == m_msaaBlitProgram) {
+						static const char msaa_blit_vs[]{R"(#version 300 es
+							precision highp float;
+							out vec2 UV;
+							void main() {
+								float x = -1.0 + float((gl_VertexID & 1) << 2);
+								float y = -1.0 + float((gl_VertexID & 2) << 1);
+								gl_Position = vec4(x, y, 0, 1);
+								UV = vec2(gl_Position.x + 1.0, gl_Position.y + 1.0) * 0.5;
+							}
+						)"};
+
+						static const char msaa_blit_fs[]{R"(#version 300 es
+							precision mediump float;
+							in vec2 UV;
+							uniform sampler2D msaaTexture;
+							out vec4 oFragColor;
+							void main() {
+								oFragColor = texture(msaaTexture, UV);
+							}
+						)"};
+
+						const GLchar *const vs = msaa_blit_vs;
+						const GLchar *const fs = msaa_blit_fs;
+						GLuint shader_vs = glCreateShader(GL_VERTEX_SHADER);
+						BX_WARN(0 != shader_vs, "Failed to create msaa Blit Vertex shader.");
+						GL_CHECK(glShaderSource(shader_vs, 1, &vs, nullptr));
+						GL_CHECK(glCompileShader(shader_vs));
+						GLint compiled = 0;
+						GL_CHECK(glGetShaderiv(shader_vs, GL_COMPILE_STATUS, &compiled));
+						BX_WARN(0 == shader_vs, "Unable to compile msaa Blit Vertex shader.");
+						
+						GLuint shader_fs = glCreateShader(GL_FRAGMENT_SHADER);
+						BX_WARN(0 != shader_fs, "Failed to create msaa Blit Fragment shader.");
+						GL_CHECK(glShaderSource(shader_fs, 1, &fs, nullptr));
+						GL_CHECK(glCompileShader(shader_fs));
+						compiled = 0;
+						GL_CHECK(glGetShaderiv(shader_fs, GL_COMPILE_STATUS, &compiled));
+						BX_WARN(0 == shader_vs, "Unable to compile msaa Blit Fragment shader.");
+						
+						m_msaaBlitProgram = glCreateProgram();
+						if (m_msaaBlitProgram)
+						{
+							GL_CHECK(glAttachShader(m_msaaBlitProgram, shader_vs));
+							GL_CHECK(glAttachShader(m_msaaBlitProgram, shader_fs));
+							
+							GL_CHECK(glLinkProgram(m_msaaBlitProgram));
+							GLint linked = 0;
+							glGetProgramiv(m_msaaBlitProgram, GL_LINK_STATUS, &linked);
+							if (0 == linked) {
+								char log[1024];
+								GL_CHECK(glGetProgramInfoLog(m_msaaBlitProgram, sizeof(log), NULL,
+															 log));
+								BX_TRACE("%d: %s", linked, log);
+							}
+							
+							GL_CHECK(glDetachShader(m_msaaBlitProgram, shader_vs));
+							GL_CHECK(glDeleteShader(shader_vs));
+							GL_CHECK(glDetachShader(m_msaaBlitProgram, shader_fs));
+							GL_CHECK(glDeleteShader(shader_fs));
+						}
+					}
+				}
+				else
+				{
+					GL_CHECK(glGenRenderbuffers(BX_COUNTOF(m_msaaBackBufferRbos), m_msaaBackBufferRbos));
+					GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_msaaBackBufferRbos[0]) );
+					GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msaa, storageFormat, _width, _height) );
+					GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_msaaBackBufferRbos[1]) );
+					GL_CHECK(glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msaa, GL_DEPTH24_STENCIL8, _width, _height) );
+					GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_msaaBackBufferRbos[0]) );
+					
+					GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, m_msaaBackBufferRbos[1]) );
+					
+					BX_ASSERT(GL_FRAMEBUFFER_COMPLETE ==  glCheckFramebufferStatus(GL_FRAMEBUFFER)
 					, "glCheckFramebufferStatus failed 0x%08x"
 					, glCheckFramebufferStatus(GL_FRAMEBUFFER)
 					);
-
-				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
+				}
 			}
 		}
 
@@ -3840,11 +3930,28 @@ namespace bgfx { namespace gl
 				GL_CHECK(glDeleteFramebuffers(1, &m_msaaBackBufferFbo) );
 				m_msaaBackBufferFbo = 0;
 
-				if (0 != m_msaaBackBufferRbos[0])
+				if (g_caps.vendorId == BGFX_PCI_ID_ARM && m_gles3)
 				{
-					GL_CHECK(glDeleteRenderbuffers(BX_COUNTOF(m_msaaBackBufferRbos), m_msaaBackBufferRbos) );
-					m_msaaBackBufferRbos[0] = 0;
-					m_msaaBackBufferRbos[1] = 0;
+					if (0 != m_msaaBackBufferTextures[0])
+					{
+						GL_CHECK(glDeleteTextures(BX_COUNTOF(m_msaaBackBufferTextures), m_msaaBackBufferTextures));
+						m_msaaBackBufferTextures[0] = 0;
+						m_msaaBackBufferTextures[1] = 0;
+					}
+					if (0 != m_msaaBlitProgram)
+					{
+						GL_CHECK(glDeleteProgram(m_msaaBlitProgram) );
+						m_msaaBlitProgram = 0;
+					}
+				}
+				else
+				{
+					if (0 != m_msaaBackBufferRbos[0])
+					{
+						GL_CHECK(glDeleteRenderbuffers(BX_COUNTOF(m_msaaBackBufferRbos), m_msaaBackBufferRbos));
+						m_msaaBackBufferRbos[0] = 0;
+						m_msaaBackBufferRbos[1] = 0;
+					}
 				}
 			}
 		}
@@ -3861,20 +3968,31 @@ namespace bgfx { namespace gl
 				uint32_t width  = m_resolution.width;
 				uint32_t height = m_resolution.height;
 				GLenum filter = BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || !m_gles3
-					? GL_NEAREST
-					: GL_LINEAR
-					;
-				GL_CHECK(glBlitFramebuffer(0
-					, 0
-					, width
-					, height
-					, 0
-					, 0
-					, width
-					, height
-					, GL_COLOR_BUFFER_BIT
-					, filter
-					) );
+								? GL_NEAREST
+								: GL_LINEAR
+				;
+				if (g_caps.vendorId == BGFX_PCI_ID_ARM && m_gles3)
+				{
+					GL_CHECK(glUseProgram(m_msaaBlitProgram));
+					GL_CHECK(glActiveTexture(GL_TEXTURE0));
+					GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_msaaBackBufferTextures[0]));
+					GL_CHECK(glDrawArrays(GL_TRIANGLES, 0, 3));
+				}
+				else
+				{
+					GL_CHECK(glBlitFramebuffer(0
+							 , 0
+							 , width
+							 , height
+							 , 0
+							 , 0
+							 , width
+							 , height
+							 , GL_COLOR_BUFFER_BIT
+							 , filter
+					));
+				}
+
 				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) );
 			}
 		}
@@ -4541,7 +4659,11 @@ namespace bgfx { namespace gl
 		GLenum m_readPixelsFmt;
 		GLuint m_backBufferFbo;
 		GLuint m_msaaBackBufferFbo;
-		GLuint m_msaaBackBufferRbos[2];
+		union {
+			GLuint m_msaaBackBufferRbos[2];
+			GLuint m_msaaBackBufferTextures[2];
+		};
+		GLuint m_msaaBlitProgram;
 		GlContext m_glctx;
 		bool m_needPresent;