diff --git a/bindings/bf/bgfx.bf b/bindings/bf/bgfx.bf index 5902503d8..163c4b47e 100644 --- a/bindings/bf/bgfx.bf +++ b/bindings/bf/bgfx.bf @@ -1288,6 +1288,11 @@ public static class bgfx /// Microsoft adapter. /// Microsoft = 0x1414, + + /// + /// ARM adapter. + /// + Arm = 0x13b5, } [AllowDuplicates] diff --git a/bindings/cs/bgfx.cs b/bindings/cs/bgfx.cs index 7ee7bebb7..23ad28423 100644 --- a/bindings/cs/bgfx.cs +++ b/bindings/cs/bgfx.cs @@ -1287,6 +1287,11 @@ public static partial class bgfx /// Microsoft adapter. /// Microsoft = 0x1414, + + /// + /// ARM adapter. + /// + Arm = 0x13b5, } [Flags] diff --git a/bindings/d/types.d b/bindings/d/types.d index 2f7a26dc6..fa9b32aa0 100644 --- a/bindings/d/types.d +++ b/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. diff --git a/bindings/zig/bgfx.zig b/bindings/zig/bgfx.zig index 0244a56be..1cfdfe0bf 100644 --- a/bindings/zig/bgfx.zig +++ b/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; diff --git a/include/bgfx/defines.h b/include/bgfx/defines.h index 3d7dcc165..9e30eeb4b 100644 --- a/include/bgfx/defines.h +++ b/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. diff --git a/scripts/bgfx.idl b/scripts/bgfx.idl index 572f1a6ef..dd27df0e7 100644 --- a/scripts/bgfx.idl +++ b/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 } diff --git a/src/glimports.h b/src/glimports.h index 8cc8854e4..502a2b311 100644 --- a/src/glimports.h +++ b/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); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index ca14f089c..22fffcb22 100644 --- a/src/renderer_gl.cpp +++ b/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]) ); + 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)); - 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]) ); + 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) + BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER), + "glCheckFramebufferStatus failed 0x%08x", + 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;