diff options
Diffstat (limited to '3rdparty/bgfx/src/renderer_gl.cpp')
-rw-r--r-- | 3rdparty/bgfx/src/renderer_gl.cpp | 698 |
1 files changed, 525 insertions, 173 deletions
diff --git a/3rdparty/bgfx/src/renderer_gl.cpp b/3rdparty/bgfx/src/renderer_gl.cpp index 38875bbd2d7..4545f55756a 100644 --- a/3rdparty/bgfx/src/renderer_gl.cpp +++ b/3rdparty/bgfx/src/renderer_gl.cpp @@ -178,6 +178,7 @@ namespace bgfx { namespace gl struct TextureFormatInfo { GLenum m_internalFmt; + GLenum m_internalFmtSrgb; GLenum m_fmt; GLenum m_type; bool m_supported; @@ -185,55 +186,55 @@ namespace bgfx { namespace gl static TextureFormatInfo s_textureFormat[] = { - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, false }, // BC1 - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, false }, // BC2 - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, false }, // BC3 - { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, false }, // BC4 - { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, false }, // BC5 - { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_ZERO, false }, // BC6H - { GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_ZERO, false }, // BC7 - { GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, GL_ZERO, false }, // ETC1 - { GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_ZERO, false }, // ETC2 - { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_ZERO, false }, // ETC2A - { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO, false }, // ETC2A1 - { GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12 - { GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14 - { GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12A - { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14A - { GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_ZERO, false }, // PTC22 - { GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_ZERO, false }, // PTC24 - { GL_ZERO, GL_ZERO, GL_ZERO, false }, // Unknown - { GL_ZERO, GL_ZERO, GL_ZERO, false }, // R1 - { GL_R8, GL_RED, GL_UNSIGNED_BYTE, false }, // R8 - { GL_R16, GL_RED, GL_UNSIGNED_SHORT, false }, // R16 - { GL_R16F, GL_RED, GL_HALF_FLOAT, false }, // R16F - { GL_R32UI, GL_RED, GL_UNSIGNED_INT, false }, // R32 - { GL_R32F, GL_RED, GL_FLOAT, false }, // R32F - { GL_RG8, GL_RG, GL_UNSIGNED_BYTE, false }, // RG8 - { GL_RG16, GL_RG, GL_UNSIGNED_SHORT, false }, // RG16 - { GL_RG16F, GL_RG, GL_FLOAT, false }, // RG16F - { GL_RG32UI, GL_RG, GL_UNSIGNED_INT, false }, // RG32 - { GL_RG32F, GL_RG, GL_FLOAT, false }, // RG32F - { GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, false }, // BGRA8 - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false }, // RGBA8 - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, false }, // RGBA16 - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false }, // RGBA16F - { GL_RGBA32UI, GL_RGBA, GL_UNSIGNED_INT, false }, // RGBA32 - { GL_RGBA32F, GL_RGBA, GL_FLOAT, false }, // RGBA32F - { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false }, // R5G6B5 - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false }, // RGBA4 - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, false }, // RGB5A1 - { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false }, // RGB10A2 - { GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false }, // R11G11B10F - { GL_ZERO, GL_ZERO, GL_ZERO, false }, // UnknownDepth - { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false }, // D16 - { GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false }, // D24 - { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false }, // D24S8 - { GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false }, // D32 - { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D16F - { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D24F - { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D32F - { GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, false }, // D0S8 + { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, false }, // BC1 + { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, false }, // BC2 + { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, false }, // BC3 + { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, false }, // BC4 + { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, false }, // BC5 + { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_ZERO, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_ZERO, false }, // BC6H + { GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_ZERO, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_ZERO, false }, // BC7 + { GL_ETC1_RGB8_OES, GL_ZERO, GL_ETC1_RGB8_OES, GL_ZERO, false }, // ETC1 + { GL_COMPRESSED_RGB8_ETC2, GL_ZERO, GL_COMPRESSED_RGB8_ETC2, GL_ZERO, false }, // ETC2 + { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_ZERO, false }, // ETC2A + { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO, false }, // ETC2A1 + { GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12 + { GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14 + { GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12A + { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14A + { GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_ZERO, GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_ZERO, false }, // PTC22 + { GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_ZERO, GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_ZERO, false }, // PTC24 + { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO, false }, // Unknown + { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO, false }, // R1 + { GL_R8, GL_ZERO, GL_RED, GL_UNSIGNED_BYTE, false }, // R8 + { GL_R16, GL_ZERO, GL_RED, GL_UNSIGNED_SHORT, false }, // R16 + { GL_R16F, GL_ZERO, GL_RED, GL_HALF_FLOAT, false }, // R16F + { GL_R32UI, GL_ZERO, GL_RED, GL_UNSIGNED_INT, false }, // R32 + { GL_R32F, GL_ZERO, GL_RED, GL_FLOAT, false }, // R32F + { GL_RG8, GL_ZERO, GL_RG, GL_UNSIGNED_BYTE, false }, // RG8 + { GL_RG16, GL_ZERO, GL_RG, GL_UNSIGNED_SHORT, false }, // RG16 + { GL_RG16F, GL_ZERO, GL_RG, GL_FLOAT, false }, // RG16F + { GL_RG32UI, GL_ZERO, GL_RG, GL_UNSIGNED_INT, false }, // RG32 + { GL_RG32F, GL_ZERO, GL_RG, GL_FLOAT, false }, // RG32F + { GL_RGBA8, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE, false }, // BGRA8 + { GL_RGBA8, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, false }, // RGBA8 + { GL_RGBA16, GL_ZERO, GL_RGBA, GL_UNSIGNED_BYTE, false }, // RGBA16 + { GL_RGBA16F, GL_ZERO, GL_RGBA, GL_HALF_FLOAT, false }, // RGBA16F + { GL_RGBA32UI, GL_ZERO, GL_RGBA, GL_UNSIGNED_INT, false }, // RGBA32 + { GL_RGBA32F, GL_ZERO, GL_RGBA, GL_FLOAT, false }, // RGBA32F + { GL_RGB565, GL_ZERO, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false }, // R5G6B5 + { GL_RGBA4, GL_ZERO, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false }, // RGBA4 + { GL_RGB5_A1, GL_ZERO, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, false }, // RGB5A1 + { GL_RGB10_A2, GL_ZERO, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false }, // RGB10A2 + { GL_R11F_G11F_B10F, GL_ZERO, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, false }, // R11G11B10F + { GL_ZERO, GL_ZERO, GL_ZERO, GL_ZERO, false }, // UnknownDepth + { GL_DEPTH_COMPONENT16, GL_ZERO, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, false }, // D16 + { GL_DEPTH_COMPONENT24, GL_ZERO, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false }, // D24 + { GL_DEPTH24_STENCIL8, GL_ZERO, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, false }, // D24S8 + { GL_DEPTH_COMPONENT32, GL_ZERO, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, false }, // D32 + { GL_DEPTH_COMPONENT32F, GL_ZERO, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D16F + { GL_DEPTH_COMPONENT32F, GL_ZERO, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D24F + { GL_DEPTH_COMPONENT32F, GL_ZERO, GL_DEPTH_COMPONENT, GL_FLOAT, false }, // D32F + { GL_STENCIL_INDEX8, GL_ZERO, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, false }, // D0S8 }; BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) ); @@ -352,6 +353,7 @@ namespace bgfx { namespace gl enum Enum { AMD_conservative_depth, + AMD_multi_draw_indirect, ANGLE_depth_texture, ANGLE_framebuffer_blit, @@ -373,6 +375,7 @@ namespace bgfx { namespace gl ARB_depth_buffer_float, ARB_depth_clamp, ARB_draw_buffers_blend, + ARB_draw_indirect, ARB_draw_instanced, ARB_ES3_compatibility, ARB_framebuffer_object, @@ -383,6 +386,7 @@ namespace bgfx { namespace gl ARB_instanced_arrays, ARB_invalidate_subdata, ARB_map_buffer_range, + ARB_multi_draw_indirect, ARB_multisample, ARB_occlusion_query, ARB_occlusion_query2, @@ -425,6 +429,7 @@ namespace bgfx { namespace gl EXT_compressed_ETC1_RGB8_sub_texture, EXT_debug_label, EXT_debug_marker, + EXT_debug_tool, EXT_discard_framebuffer, EXT_disjoint_timer_query, EXT_draw_buffers, @@ -432,6 +437,7 @@ namespace bgfx { namespace gl EXT_framebuffer_blit, EXT_framebuffer_object, EXT_framebuffer_sRGB, + EXT_multi_draw_indirect, EXT_occlusion_query_boolean, EXT_packed_float, EXT_read_format_bgra, @@ -468,6 +474,7 @@ namespace bgfx { namespace gl INTEL_fragment_shader_ordering, KHR_debug, + KHR_no_error, MOZ_WEBGL_compressed_texture_s3tc, MOZ_WEBGL_depth_texture, @@ -540,6 +547,7 @@ namespace bgfx { namespace gl static Extension s_extension[] = { { "AMD_conservative_depth", false, true }, + { "AMD_multi_draw_indirect", false, true }, { "ANGLE_depth_texture", false, true }, { "ANGLE_framebuffer_blit", false, true }, @@ -561,6 +569,7 @@ namespace bgfx { namespace gl { "ARB_depth_buffer_float", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "ARB_depth_clamp", BGFX_CONFIG_RENDERER_OPENGL >= 32, true }, { "ARB_draw_buffers_blend", BGFX_CONFIG_RENDERER_OPENGL >= 40, true }, + { "ARB_draw_indirect", BGFX_CONFIG_RENDERER_OPENGL >= 40, true }, { "ARB_draw_instanced", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "ARB_ES3_compatibility", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_framebuffer_object", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, @@ -571,6 +580,7 @@ namespace bgfx { namespace gl { "ARB_instanced_arrays", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "ARB_invalidate_subdata", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_map_buffer_range", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, + { "ARB_multi_draw_indirect", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "ARB_multisample", false, true }, { "ARB_occlusion_query", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "ARB_occlusion_query2", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, @@ -613,6 +623,7 @@ namespace bgfx { namespace gl { "EXT_compressed_ETC1_RGB8_sub_texture", false, true }, // GLES2 extension. { "EXT_debug_label", false, true }, { "EXT_debug_marker", false, true }, + { "EXT_debug_tool", false, true }, // RenderDoc extension. { "EXT_discard_framebuffer", false, true }, // GLES2 extension. { "EXT_disjoint_timer_query", false, true }, // GLES2 extension. { "EXT_draw_buffers", false, true }, // GLES2 extension. @@ -620,6 +631,7 @@ namespace bgfx { namespace gl { "EXT_framebuffer_blit", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, { "EXT_framebuffer_object", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, { "EXT_framebuffer_sRGB", BGFX_CONFIG_RENDERER_OPENGL >= 30, true }, + { "EXT_multi_draw_indirect", false, true }, // GLES3.1 extension. { "EXT_occlusion_query_boolean", false, true }, { "EXT_packed_float", BGFX_CONFIG_RENDERER_OPENGL >= 33, true }, { "EXT_read_format_bgra", false, true }, @@ -656,6 +668,7 @@ namespace bgfx { namespace gl { "INTEL_fragment_shader_ordering", false, true }, { "KHR_debug", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, + { "KHR_no_error", false, true }, { "MOZ_WEBGL_compressed_texture_s3tc", false, true }, { "MOZ_WEBGL_depth_texture", false, true }, @@ -805,6 +818,26 @@ namespace bgfx { namespace gl { } + static void GL_APIENTRY stubMultiDrawArraysIndirect(GLenum _mode, const void* _indirect, GLsizei _drawcount, GLsizei _stride) + { + const uint8_t* args = (const uint8_t*)_indirect; + for (GLsizei ii = 0; ii < _drawcount; ++ii) + { + GL_CHECK(glDrawArraysIndirect(_mode, (void*)args) ); + args += _stride; + } + } + + static void GL_APIENTRY stubMultiDrawElementsIndirect(GLenum _mode, GLenum _type, const void* _indirect, GLsizei _drawcount, GLsizei _stride) + { + const uint8_t* args = (const uint8_t*)_indirect; + for (GLsizei ii = 0; ii < _drawcount; ++ii) + { + GL_CHECK(glDrawElementsIndirect(_mode, _type, (void*)args) ); + args += _stride; + } + } + typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height); static const char* getGLString(GLenum _name) @@ -863,30 +896,26 @@ namespace bgfx { namespace gl const char* toString(GLenum _enum) { -#if defined(GL_DEBUG_SOURCE_API_ARB) switch (_enum) { - case GL_DEBUG_SOURCE_API_ARB: return "API"; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "WinSys"; - case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "Shader"; - case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "3rdparty"; - case GL_DEBUG_SOURCE_APPLICATION_ARB: return "Application"; - case GL_DEBUG_SOURCE_OTHER_ARB: return "Other"; - case GL_DEBUG_TYPE_ERROR_ARB: return "Error"; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "Deprecated behavior"; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "Undefined behavior"; - case GL_DEBUG_TYPE_PORTABILITY_ARB: return "Portability"; - case GL_DEBUG_TYPE_PERFORMANCE_ARB: return "Performance"; - case GL_DEBUG_TYPE_OTHER_ARB: return "Other"; - case GL_DEBUG_SEVERITY_HIGH_ARB: return "High"; - case GL_DEBUG_SEVERITY_MEDIUM_ARB: return "Medium"; - case GL_DEBUG_SEVERITY_LOW_ARB: return "Low"; + case GL_DEBUG_SOURCE_API: return "API"; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "WinSys"; + case GL_DEBUG_SOURCE_SHADER_COMPILER: return "Shader"; + case GL_DEBUG_SOURCE_THIRD_PARTY: return "3rdparty"; + case GL_DEBUG_SOURCE_APPLICATION: return "Application"; + case GL_DEBUG_SOURCE_OTHER: return "Other"; + case GL_DEBUG_TYPE_ERROR: return "Error"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "Deprecated behavior"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "Undefined behavior"; + case GL_DEBUG_TYPE_PORTABILITY: return "Portability"; + case GL_DEBUG_TYPE_PERFORMANCE: return "Performance"; + case GL_DEBUG_TYPE_OTHER: return "Other"; + case GL_DEBUG_SEVERITY_HIGH: return "High"; + case GL_DEBUG_SEVERITY_MEDIUM: return "Medium"; + case GL_DEBUG_SEVERITY_LOW: return "Low"; default: break; } -#else - BX_UNUSED(_enum); -#endif // defined(GL_DEBUG_SOURCE_API_ARB) return "<unknown>"; } @@ -920,10 +949,35 @@ namespace bgfx { namespace gl tfi.m_type = _type; } - bool isTextureFormatValid(TextureFormat::Enum _format) + void initTestTexture(TextureFormat::Enum _format, bool srgb = false) { const TextureFormatInfo& tfi = s_textureFormat[_format]; - if (GL_ZERO == tfi.m_internalFmt) + GLenum internalFmt = srgb + ? tfi.m_internalFmtSrgb + : tfi.m_internalFmt + ; + + GLsizei size = (16*16*getBitsPerPixel(_format) )/8; + void* data = alloca(size); + + if (isCompressed(_format) ) + { + glCompressedTexImage2D(GL_TEXTURE_2D, 0, internalFmt, 16, 16, 0, size, data); + } + else + { + glTexImage2D(GL_TEXTURE_2D, 0, internalFmt, 16, 16, 0, tfi.m_fmt, tfi.m_type, data); + } + } + + static bool isTextureFormatValid(TextureFormat::Enum _format, bool srgb = false) + { + const TextureFormatInfo& tfi = s_textureFormat[_format]; + GLenum internalFmt = srgb + ? tfi.m_internalFmtSrgb + : tfi.m_internalFmt + ; + if (GL_ZERO == internalFmt) { return false; } @@ -931,25 +985,109 @@ namespace bgfx { namespace gl GLuint id; GL_CHECK(glGenTextures(1, &id) ); GL_CHECK(glBindTexture(GL_TEXTURE_2D, id) ); + initTestTexture(_format); - GLsizei size = (16*16*getBitsPerPixel(_format) )/8; - void* data = alloca(size); + GLenum err = glGetError(); + BX_WARN(0 == err, "TextureFormat::%s is not supported (%x: %s).", getName(_format), err, glEnumName(err) ); - if (isCompressed(_format) ) + GL_CHECK(glDeleteTextures(1, &id) ); + + return 0 == err; + } + + static bool isImageFormatValid(TextureFormat::Enum _format) + { + if (GL_ZERO == s_imageFormat[_format]) { - glCompressedTexImage2D(GL_TEXTURE_2D, 0, tfi.m_internalFmt, 16, 16, 0, size, data); + return false; } - else + + GLuint id; + GL_CHECK(glGenTextures(1, &id) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, id) ); + GL_CHECK(glTexStorage2D(GL_TEXTURE_2D, 1, s_imageFormat[_format], 16, 16) ); + + glBindImageTexture(0 + , id + , 0 + , GL_FALSE + , 0 + , GL_READ_WRITE + , s_imageFormat[_format] + ); + GLenum err = glGetError(); + + GL_CHECK(glDeleteTextures(1, &id) ); + + return 0 == err; + } + + static bool isFramebufferFormatValid(TextureFormat::Enum _format, bool srgb = false) + { + const TextureFormatInfo& tfi = s_textureFormat[_format]; + GLenum internalFmt = srgb + ? tfi.m_internalFmtSrgb + : tfi.m_internalFmt + ; + if (GL_ZERO == internalFmt + || !tfi.m_supported) { - glTexImage2D(GL_TEXTURE_2D, 0, tfi.m_internalFmt, 16, 16, 0, tfi.m_fmt, tfi.m_type, data); + return false; } + GLuint fbo; + GL_CHECK(glGenFramebuffers(1, &fbo) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fbo) ); + + GLuint id; + GL_CHECK(glGenTextures(1, &id) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, id) ); + + initTestTexture(_format); + GLenum err = glGetError(); - BX_WARN(0 == err, "TextureFormat::%s is not supported (%x: %s).", getName(_format), err, glEnumName(err) ); + + GLenum attachment; + if (isDepth(_format) ) + { + const ImageBlockInfo& info = getBlockInfo(_format); + if (0 < info.stencilBits) + { + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + } + else if (0 == info.depthBits) + { + attachment = GL_STENCIL_ATTACHMENT; + } + else + { + attachment = GL_DEPTH_ATTACHMENT; + } + } + else + { + attachment = GL_COLOR_ATTACHMENT0; + } + + glFramebufferTexture2D(GL_FRAMEBUFFER + , attachment + , GL_TEXTURE_2D + , id + , 0 + ); + err = glGetError(); + + if (0 == err) + { + err = glCheckFramebufferStatus(GL_FRAMEBUFFER); + } + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + GL_CHECK(glDeleteFramebuffers(1, &fbo) ); GL_CHECK(glDeleteTextures(1, &id) ); - return 0 == err; + return GL_FRAMEBUFFER_COMPLETE == err; } static void getFilters(uint32_t _flags, bool _hasMips, GLenum& _magFilter, GLenum& _minFilter) @@ -1235,6 +1373,12 @@ namespace bgfx { namespace gl if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES < 30) ) { setTextureFormat(TextureFormat::RGBA16F, GL_RGBA, GL_RGBA, GL_HALF_FLOAT); + // internalFormat and format must match: + // https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml + setTextureFormat(TextureFormat::RGBA8, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE); + setTextureFormat(TextureFormat::R5G6B5, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5); + setTextureFormat(TextureFormat::RGBA4, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4); + setTextureFormat(TextureFormat::RGB5A1, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1); if (s_extension[Extension::OES_texture_half_float].m_supported || s_extension[Extension::OES_texture_float ].m_supported) @@ -1313,21 +1457,54 @@ namespace bgfx { namespace gl s_textureFormat[TextureFormat::R8].m_fmt = GL_LUMINANCE; } - if (!BX_ENABLED(BX_PLATFORM_EMSCRIPTEN) ) + for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) { - for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) + if (TextureFormat::Unknown != ii + && TextureFormat::UnknownDepth != ii) { - if (TextureFormat::Unknown != ii - && TextureFormat::UnknownDepth != ii) - { - s_textureFormat[ii].m_supported = isTextureFormatValid( (TextureFormat::Enum)ii); - } + s_textureFormat[ii].m_supported = isTextureFormatValid(TextureFormat::Enum(ii) ); } } + if (BX_ENABLED(0) ) + { + // Disable all compressed texture formats. For testing only. + for (uint32_t ii = 0; ii < TextureFormat::Unknown; ++ii) + { + s_textureFormat[ii].m_supported = false; + } + } + + const bool computeSupport = false + || !!(BGFX_CONFIG_RENDERER_OPENGLES >= 31) + || s_extension[Extension::ARB_compute_shader].m_supported + ; + for (uint32_t ii = 0; ii < TextureFormat::Count; ++ii) { - g_caps.formats[ii] = s_textureFormat[ii].m_supported ? 1 : 0; + uint8_t supported = 0; + supported |= s_textureFormat[ii].m_supported + ? BGFX_CAPS_FORMAT_TEXTURE_COLOR + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + supported |= isTextureFormatValid(TextureFormat::Enum(ii), true) + ? BGFX_CAPS_FORMAT_TEXTURE_COLOR_SRGB + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + supported |= computeSupport + && isImageFormatValid(TextureFormat::Enum(ii) ) + ? BGFX_CAPS_FORMAT_TEXTURE_IMAGE + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + supported |= isFramebufferFormatValid(TextureFormat::Enum(ii) ) + ? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER + : BGFX_CAPS_FORMAT_TEXTURE_NONE + ; + + g_caps.formats[ii] = supported; } g_caps.supported |= !!(BGFX_CONFIG_RENDERER_OPENGL || BGFX_CONFIG_RENDERER_OPENGLES >= 30) @@ -1364,6 +1541,28 @@ namespace bgfx { namespace gl : 0 ; + const bool drawIndirectSupported = false + || s_extension[Extension::AMD_multi_draw_indirect].m_supported + || s_extension[Extension::ARB_draw_indirect ].m_supported + || s_extension[Extension::ARB_multi_draw_indirect].m_supported + || s_extension[Extension::EXT_multi_draw_indirect].m_supported + ; + + if (drawIndirectSupported) + { + if (NULL == glMultiDrawArraysIndirect + || NULL == glMultiDrawElementsIndirect) + { + glMultiDrawArraysIndirect = stubMultiDrawArraysIndirect; + glMultiDrawElementsIndirect = stubMultiDrawElementsIndirect; + } + } + + g_caps.supported |= drawIndirectSupported + ? BGFX_CAPS_DRAW_INDIRECT + : 0 + ; + g_caps.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) ); if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) @@ -1436,8 +1635,7 @@ namespace bgfx { namespace gl : 0 ; - g_caps.supported |= !!(BGFX_CONFIG_RENDERER_OPENGLES >= 31) - || s_extension[Extension::ARB_compute_shader].m_supported + g_caps.supported |= computeSupport ? BGFX_CAPS_COMPUTE : 0 ; @@ -1496,12 +1694,23 @@ namespace bgfx { namespace gl } } -#if BGFX_CONFIG_RENDERER_OPENGL if (s_extension[Extension::ARB_debug_output].m_supported || s_extension[Extension::KHR_debug].m_supported) { - GL_CHECK(glDebugMessageCallback(debugProcCb, NULL) ); - GL_CHECK(glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM_ARB, 0, NULL, GL_TRUE) ); + if (NULL != glDebugMessageControl + && NULL != glDebugMessageInsert + && NULL != glDebugMessageCallback + && NULL != glGetDebugMessageLog) + { + GL_CHECK(glDebugMessageCallback(debugProcCb, NULL) ); + GL_CHECK(glDebugMessageControl(GL_DONT_CARE + , GL_DONT_CARE + , GL_DEBUG_SEVERITY_MEDIUM + , 0 + , NULL + , GL_TRUE + ) ); + } } if (s_extension[Extension::ARB_seamless_cube_map].m_supported) @@ -1513,7 +1722,6 @@ namespace bgfx { namespace gl { GL_CHECK(glEnable(GL_DEPTH_CLAMP) ); } -#endif // BGFX_CONFIG_RENDERER_OPENGL if (NULL == glFrameTerminatorGREMEDY || !s_extension[Extension::GREMEDY_frame_terminator].m_supported) @@ -1530,6 +1738,8 @@ namespace bgfx { namespace gl ; } + setGraphicsDebuggerPresent(s_extension[Extension::EXT_debug_tool].m_supported); + if (NULL == glObjectLabel) { glObjectLabel = stubObjectLabel; @@ -1616,7 +1826,7 @@ namespace bgfx { namespace gl } } - void createIndexBuffer(IndexBufferHandle _handle, Memory* _mem, uint8_t _flags) BX_OVERRIDE + void createIndexBuffer(IndexBufferHandle _handle, Memory* _mem, uint16_t _flags) BX_OVERRIDE { m_indexBuffers[_handle.idx].create(_mem->size, _mem->data, _flags); } @@ -1637,9 +1847,9 @@ namespace bgfx { namespace gl { } - void createVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle, uint8_t /*_flags*/) BX_OVERRIDE + void createVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle, uint16_t _flags) BX_OVERRIDE { - m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle); + m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle, _flags); } void destroyVertexBuffer(VertexBufferHandle _handle) BX_OVERRIDE @@ -1647,7 +1857,7 @@ namespace bgfx { namespace gl m_vertexBuffers[_handle.idx].destroy(); } - void createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint8_t _flags) BX_OVERRIDE + void createDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size, uint16_t _flags) BX_OVERRIDE { m_indexBuffers[_handle.idx].create(_size, NULL, _flags); } @@ -1662,10 +1872,10 @@ namespace bgfx { namespace gl m_indexBuffers[_handle.idx].destroy(); } - void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint8_t /*_flags*/) BX_OVERRIDE + void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint16_t _flags) BX_OVERRIDE { VertexDeclHandle decl = BGFX_INVALID_HANDLE; - m_vertexBuffers[_handle.idx].create(_size, NULL, decl); + m_vertexBuffers[_handle.idx].create(_size, NULL, decl, _flags); } void updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) BX_OVERRIDE @@ -2239,9 +2449,9 @@ namespace bgfx { namespace gl config.OGL.Header.RTSize.h = m_resolution.m_height; # endif // OVR_VERSION > OVR_VERSION_043 config.OGL.Header.Multisample = 0; - config.OGL.Window = g_bgfxHwnd; - config.OGL.DC = GetDC(g_bgfxHwnd); - if (m_ovr.postReset(g_bgfxHwnd, &config.Config, !!(m_resolution.m_flags & BGFX_RESET_HMD_DEBUG) ) ) + config.OGL.Window = (HWND)g_platformData.nwh; + config.OGL.DC = GetDC(config.OGL.Window); + if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_resolution.m_flags & BGFX_RESET_HMD_DEBUG) ) ) { uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate); const Memory* mem = alloc(size); @@ -3066,8 +3276,11 @@ namespace bgfx { namespace gl *array = '\0'; array++; char* end = strchr(array, ']'); - *end = '\0'; - offset = atoi(array); + if (NULL != end) + { // Some devices (Amazon Fire) might not return terminating brace. + *end = '\0'; + offset = atoi(array); + } } switch (gltype) @@ -3329,18 +3542,20 @@ namespace bgfx { namespace gl } } - bool TextureGL::init(GLenum _target, uint32_t _width, uint32_t _height, uint8_t _format, uint8_t _numMips, uint32_t _flags) + bool TextureGL::init(GLenum _target, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _format, uint8_t _numMips, uint32_t _flags) { - m_target = _target; + m_target = _target; m_numMips = _numMips; - m_flags = _flags; - m_currentFlags = UINT32_MAX; - m_width = _width; - m_height = _height; + m_flags = _flags; + m_width = _width; + m_height = _height; + m_depth = _depth; + m_currentFlags = UINT32_MAX; m_requestedFormat = _format; m_textureFormat = _format; - const bool bufferOnly = 0 != (m_flags&BGFX_TEXTURE_RT_BUFFER_ONLY); + const bool bufferOnly = 0 != (m_flags&BGFX_TEXTURE_RT_BUFFER_ONLY); + const bool computeWrite = 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE ); if (!bufferOnly) { @@ -3361,6 +3576,7 @@ namespace bgfx { namespace gl const bool convert = false || (compressed && m_textureFormat != m_requestedFormat) || swizzle + || !s_textureFormat[m_requestedFormat].m_supported ; if (convert) @@ -3371,6 +3587,29 @@ namespace bgfx { namespace gl m_type = tfiRgba8.m_type; } + if (computeWrite) + { + if (_target == GL_TEXTURE_3D) + { + GL_CHECK(glTexStorage3D(_target + , _numMips + , s_textureFormat[m_textureFormat].m_internalFmt + , m_width + , m_height + , _depth + ) ); + } + else + { + GL_CHECK(glTexStorage2D(_target + , _numMips + , s_textureFormat[m_textureFormat].m_internalFmt + , m_width + , m_height + ) ); + } + } + setSamplerState(_flags); if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) @@ -3439,9 +3678,15 @@ namespace bgfx { namespace gl uint8_t numMips = imageContainer.m_numMips; const uint8_t startLod = uint8_t(bx::uint32_min(_skip, numMips-1) ); numMips -= startLod; - const ImageBlockInfo& blockInfo = getBlockInfo(TextureFormat::Enum(imageContainer.m_format) ); - const uint32_t textureWidth = bx::uint32_max(blockInfo.blockWidth, imageContainer.m_width >>startLod); - const uint32_t textureHeight = bx::uint32_max(blockInfo.blockHeight, imageContainer.m_height>>startLod); + uint32_t textureWidth; + uint32_t textureHeight; + uint32_t textureDepth; + { + const ImageBlockInfo& ibi = getBlockInfo(TextureFormat::Enum(imageContainer.m_format) ); + textureWidth = bx::uint32_max(ibi.blockWidth, imageContainer.m_width >>startLod); + textureHeight = bx::uint32_max(ibi.blockHeight, imageContainer.m_height>>startLod); + textureDepth = imageContainer.m_depth; + } GLenum target = GL_TEXTURE_2D; if (imageContainer.m_cubeMap) @@ -3456,6 +3701,7 @@ namespace bgfx { namespace gl if (!init(target , textureWidth , textureHeight + , textureDepth , imageContainer.m_format , numMips , _flags @@ -3464,9 +3710,15 @@ namespace bgfx { namespace gl return; } + const bool computeWrite = 0 != (m_flags&BGFX_TEXTURE_COMPUTE_WRITE); + const bool srgb = 0 != (m_flags&BGFX_TEXTURE_SRGB); + target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target; - const GLenum internalFmt = s_textureFormat[m_textureFormat].m_internalFmt; + const GLenum internalFmt = srgb + ? s_textureFormat[m_textureFormat].m_internalFmtSrgb + : s_textureFormat[m_textureFormat].m_internalFmt + ; const bool swizzle = true && TextureFormat::BGRA8 == m_requestedFormat @@ -3475,17 +3727,9 @@ namespace bgfx { namespace gl ; const bool compressed = isCompressed(TextureFormat::Enum(m_requestedFormat) ); const bool convert = false - || (compressed && m_textureFormat != m_requestedFormat) + || m_textureFormat != m_requestedFormat || swizzle ; - uint32_t blockWidth = 1; - uint32_t blockHeight = 1; - - if (convert && compressed) - { - blockWidth = blockInfo.blockWidth; - blockHeight = blockInfo.blockHeight; - } BX_TRACE("Texture%-4s %3d: %s (requested: %s), %dx%dx%d%s." , imageContainer.m_cubeMap ? "Cube" : (1 < imageContainer.m_depth ? "3D" : "2D") @@ -3520,14 +3764,15 @@ namespace bgfx { namespace gl for (uint8_t lod = 0, num = numMips; lod < num; ++lod) { - width = bx::uint32_max(blockWidth, width); - height = bx::uint32_max(blockHeight, height); + width = bx::uint32_max(1, width); + height = bx::uint32_max(1, height); depth = bx::uint32_max(1, depth); ImageMip mip; if (imageGetRawData(imageContainer, side, lod+startLod, _mem->data, _mem->size, mip) ) { - if (compressed) + if (compressed + && !convert) { compressedTexImage(target+side , lod @@ -3546,7 +3791,13 @@ namespace bgfx { namespace gl if (convert) { - imageDecodeToRgba8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_width*4, mip.m_format); + imageDecodeToRgba8(temp + , mip.m_data + , mip.m_width + , mip.m_height + , mip.m_width*4 + , mip.m_format + ); data = temp; } @@ -3563,7 +3814,7 @@ namespace bgfx { namespace gl ); } } - else + else if (!computeWrite) { if (compressed) { @@ -3724,6 +3975,12 @@ namespace bgfx { namespace gl ) ); } + if (!convert + && unpackRowLength) + { + GL_CHECK(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0) ); + } + if (NULL != temp) { BX_FREE(g_allocator, temp); @@ -4133,11 +4390,14 @@ namespace bgfx { namespace gl writeString(&writer, "#version 140\n"); } + writeString(&writer, "#define texture2DLod textureLod\n"); + writeString(&writer, "#define texture3DLod textureLod\n"); + writeString(&writer, "#define textureCubeLod textureLod\n"); + if (m_type == GL_FRAGMENT_SHADER) { writeString(&writer, "#define varying in\n"); writeString(&writer, "#define texture2D texture\n"); - writeString(&writer, "#define texture2DLod textureLod\n"); writeString(&writer, "#define texture2DProj textureProj\n"); if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) ) @@ -4152,9 +4412,7 @@ namespace bgfx { namespace gl } writeString(&writer, "#define texture3D texture\n"); - writeString(&writer, "#define texture3DLod textureLod\n"); writeString(&writer, "#define textureCube texture\n"); - writeString(&writer, "#define textureCubeLod textureLod\n"); uint32_t fragData = 0; @@ -4782,7 +5040,38 @@ namespace bgfx { namespace gl viewState.setPredefined<1>(this, view, eye, program, _render, compute); - GL_CHECK(glDispatchCompute(compute.m_numX, compute.m_numY, compute.m_numZ) ); + if (isValid(compute.m_indirectBuffer) ) + { + const VertexBufferGL& vb = m_vertexBuffers[compute.m_indirectBuffer.idx]; + if (currentState.m_indirectBuffer.idx != compute.m_indirectBuffer.idx) + { + currentState.m_indirectBuffer = compute.m_indirectBuffer; + GL_CHECK(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, vb.m_id) ); + } + + uint32_t numDrawIndirect = UINT16_MAX == compute.m_numIndirect + ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE + : compute.m_numIndirect + ; + + uintptr_t args = compute.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE; + for (uint32_t ii = 0; ii < numDrawIndirect; ++ii) + { + GL_CHECK(glDispatchComputeIndirect(args) ); + args += BGFX_CONFIG_DRAW_INDIRECT_STRIDE; + } + } + else + { + if (isValid(currentState.m_indirectBuffer) ) + { + currentState.m_indirectBuffer.idx = invalidHandle; + GL_CHECK(glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, 0) ); + } + + GL_CHECK(glDispatchCompute(compute.m_numX, compute.m_numY, compute.m_numZ) ); + } + GL_CHECK(glMemoryBarrier(barrier) ); } } @@ -4790,6 +5079,8 @@ namespace bgfx { namespace gl continue; } + bool resetState = viewChanged || wasCompute; + if (wasCompute) { wasCompute = false; @@ -4812,7 +5103,7 @@ namespace bgfx { namespace gl uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil; currentState.m_stencil = newStencil; - if (viewChanged) + if (resetState) { currentState.clear(); currentState.m_scissor = !draw.m_scissor; @@ -5310,61 +5601,116 @@ namespace bgfx { namespace gl numVertices = vb.m_size/vertexDecl.m_stride; } - uint32_t numIndices = 0; + uint32_t numIndices = 0; uint32_t numPrimsSubmitted = 0; - uint32_t numInstances = 0; - uint32_t numPrimsRendered = 0; + uint32_t numInstances = 0; + uint32_t numPrimsRendered = 0; + uint32_t numDrawIndirect = 0; - if (isValid(draw.m_indexBuffer) ) + if (isValid(draw.m_indirectBuffer) ) { - const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx]; - const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32); - const GLenum indexFormat = hasIndex16 - ? GL_UNSIGNED_SHORT - : GL_UNSIGNED_INT - ; + const VertexBufferGL& vb = m_vertexBuffers[draw.m_indirectBuffer.idx]; + if (currentState.m_indirectBuffer.idx != draw.m_indirectBuffer.idx) + { + currentState.m_indirectBuffer = draw.m_indirectBuffer; + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, vb.m_id) ); + } - if (UINT32_MAX == draw.m_numIndices) + if (isValid(draw.m_indexBuffer) ) { - const uint32_t indexSize = hasIndex16 ? 2 : 4; - numIndices = ib.m_size/indexSize; - numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; - - GL_CHECK(glDrawElementsInstanced(prim.m_type - , numIndices - , indexFormat - , (void*)0 - , draw.m_numInstances + const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx]; + const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32); + const GLenum indexFormat = hasIndex16 + ? GL_UNSIGNED_SHORT + : GL_UNSIGNED_INT + ; + + numDrawIndirect = UINT16_MAX == draw.m_numIndirect + ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE + : draw.m_numIndirect + ; + + uintptr_t args = draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE; + GL_CHECK(glMultiDrawElementsIndirect(prim.m_type, indexFormat + , (void*)args + , numDrawIndirect + , BGFX_CONFIG_DRAW_INDIRECT_STRIDE ) ); } - else if (prim.m_min <= draw.m_numIndices) + else { - numIndices = draw.m_numIndices; - numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; + numDrawIndirect = UINT16_MAX == draw.m_numIndirect + ? vb.m_size/BGFX_CONFIG_DRAW_INDIRECT_STRIDE + : draw.m_numIndirect + ; - GL_CHECK(glDrawElementsInstanced(prim.m_type - , numIndices - , indexFormat - , (void*)(uintptr_t)(draw.m_startIndex*2) - , draw.m_numInstances + uintptr_t args = draw.m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE; + GL_CHECK(glMultiDrawArraysIndirect(prim.m_type + , (void*)args + , numDrawIndirect + , BGFX_CONFIG_DRAW_INDIRECT_STRIDE ) ); } } else { - numPrimsSubmitted = numVertices/prim.m_div - prim.m_sub; - numInstances = draw.m_numInstances; - numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; + if (isValid(currentState.m_indirectBuffer) ) + { + currentState.m_indirectBuffer.idx = invalidHandle; + GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0) ); + } - GL_CHECK(glDrawArraysInstanced(prim.m_type - , 0 - , numVertices - , draw.m_numInstances - ) ); + if (isValid(draw.m_indexBuffer) ) + { + const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx]; + const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32); + const GLenum indexFormat = hasIndex16 + ? GL_UNSIGNED_SHORT + : GL_UNSIGNED_INT + ; + + if (UINT32_MAX == draw.m_numIndices) + { + const uint32_t indexSize = hasIndex16 ? 2 : 4; + numIndices = ib.m_size/indexSize; + numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; + numInstances = draw.m_numInstances; + numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; + + GL_CHECK(glDrawElementsInstanced(prim.m_type + , numIndices + , indexFormat + , (void*)0 + , draw.m_numInstances + ) ); + } + else if (prim.m_min <= draw.m_numIndices) + { + numIndices = draw.m_numIndices; + numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub; + numInstances = draw.m_numInstances; + numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; + + GL_CHECK(glDrawElementsInstanced(prim.m_type + , numIndices + , indexFormat + , (void*)(uintptr_t)(draw.m_startIndex*2) + , draw.m_numInstances + ) ); + } + } + else + { + numPrimsSubmitted = numVertices/prim.m_div - prim.m_sub; + numInstances = draw.m_numInstances; + numPrimsRendered = numPrimsSubmitted*draw.m_numInstances; + + GL_CHECK(glDrawArraysInstanced(prim.m_type + , 0 + , numVertices + , draw.m_numInstances + ) ); + } } statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted; @@ -5379,6 +5725,11 @@ namespace bgfx { namespace gl if (0 < _render->m_num) { + if (0 != (m_resolution.m_flags & BGFX_RESET_FLUSH_AFTER_RENDER) ) + { + GL_CHECK(glFlush() ); + } + captureElapsed = -bx::getHPCounter(); capture(); captureElapsed += bx::getHPCounter(); @@ -5459,6 +5810,7 @@ namespace bgfx { namespace gl , elapsedCpuMs > elapsedGpuMs ? '>' : '<' , elapsedGpuMs ); + for (uint32_t ii = 0; ii < BX_COUNTOF(s_primInfo); ++ii) { tvm.printf(10, pos++, 0x8e, " %9s: %7d (#inst: %5d), submitted: %7d" |