From 56a850f9ad24f9db23f54fb080b5fbfc68a390d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 4 Mar 2023 00:28:28 +0100 Subject: [PATCH] GL: implement NV_depth_buffer_float. The GL::Renderer::setClearDepth() and setDepthRange() APIs now use the non-clamping NV entrypoints if available. The float overloads do that too, to avoid differences in behavior depending on whether these functions are called with a float or a double type. --- doc/changelog.dox | 6 ++- doc/opengl-mapping.dox | 4 +- doc/opengl-support.dox | 4 +- .../GL/Implementation/RendererState.cpp | 45 ++++++++++++++----- src/Magnum/GL/Implementation/RendererState.h | 4 ++ src/Magnum/GL/Renderer.cpp | 12 ++++- src/Magnum/GL/Renderer.h | 41 ++++++++++++----- src/MagnumExternal/OpenGL/GL/extensions.txt | 8 ++++ src/MagnumExternal/OpenGL/GL/flextGL.cpp | 4 ++ src/MagnumExternal/OpenGL/GL/flextGL.h | 17 +++++++ .../OpenGL/GL/flextGLPlatform.cpp | 4 ++ 11 files changed, 117 insertions(+), 32 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ebcb52e84..8951a6b57 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -153,7 +153,11 @@ See also: @relativeref{GL::Renderer,Feature::SampleAlphaToOne}, @relativeref{GL::Renderer,Feature::SampleCoverage} and @ref GL::Renderer::setSampleCoverage() GL 1.3 APIs -- Exposed missing @ref GL::Renderer::setDepthRange() GL 1.0 API +- Using the non-clamping @gl_extension{NV,depth_buffer_float} entrypoints in + @ref GL::Renderer::setClearDepth() and a newly exposed + @ref GL::Renderer::setDepthRange() if the extension is available. See also + [mosra/magnum#543](https://github.com/mosra/magnum/issues/543) and + [mosra/magnum#558](https://github.com/mosra/magnum/issues/558). - A new @cpp "nv-egl-crashy-query-device-attrib" @ce workaround for a crash happening during EGL initialization in recent NVidia drivers. See @ref opengl-workarounds and [mosra/magnum#491](https://github.com/mosra/magnum/pull/491) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 48a73ec54..2c77a4feb 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -101,7 +101,7 @@ OpenGL function | Matching API @fn_gl{ClearBufferData}, \n `glClearNamedBufferData()` | | @fn_gl{ClearBufferSubData}, \n `glClearNamedBufferSubData()` | | @fn_gl{ClearColor} | @ref GL::Renderer::setClearColor() -@fn_gl{ClearDepth} | @ref GL::Renderer::setClearDepth() +@fn_gl{ClearDepth}, \n @fn_gl_extension{ClearDepthd,NV,depth_buffer_float} | @ref GL::Renderer::setClearDepth() @fn_gl{ClearStencil} | @ref GL::Renderer::setClearStencil() @fn_gl{ClearTexImage} | | @fn_gl{ClearTexSubImage} | | @@ -131,7 +131,7 @@ OpenGL function | Matching API @fn_gl{DebugMessageInsert}, \n @fn_gl_extension{InsertEventMarker,EXT,debug_marker}, \n @fn_gl_extension{StringMarker,GREMEDY,string_marker} | @ref GL::DebugMessage::insert() @fn_gl{DepthFunc} | @ref GL::Renderer::setDepthFunction() @fn_gl{DepthMask} | @ref GL::Renderer::setDepthMask() -@fn_gl{DepthRange} | @ref GL::Renderer::setDepthRange() +@fn_gl{DepthRange}, \n @fn_gl_extension_keyword{DepthRanged,NV,depth_buffer_float} | @ref GL::Renderer::setDepthRange() @fn_gl{DepthRangeArray} | | @fn_gl{DepthRangeIndexed} | | @fn_gl{DetachShader} | | diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 1ee2f713d..256aae77f 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -52,8 +52,6 @@ following: @subsection opengl-support-30 OpenGL 3.0 -@todo Add @gl_extension{ARB,depth_buffer_float} and implement the missing @fn_gl{DepthRange} function, but keep (and implement) @gl_extension{NV,depth_buffer_float} for non-linear depth buffer - @m_class{m-fullwidth} Extension | Status @@ -79,7 +77,7 @@ GLSL 1.30 | done @gl_extension{EXT,texture_integer} | done (GL 3.0 subset) @gl_extension{EXT,transform_feedback} | done `MAGNUM_shader_vertex_id` \n @m_span{m-text m-dim} Pseudo-extension denoting support for the @glsl gl_VertexID @ce GLSL builtin. @m_endspan | done -@gl_extension{NV,depth_buffer_float} | | +@gl_extension{NV,depth_buffer_float} | done @gl_extension{NV,conditional_render} | done @subsection opengl-support-31 OpenGL 3.1 diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index 56f12f6ff..68b22ac15 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -40,25 +40,46 @@ RendererState::RendererState(Context& context, ContextState& contextState, Conta : resetNotificationStrategy() #endif { - /* Float depth clear value / range implementation */ + /* Depth clear value / range implementation. If the NV_depth_buffer_float + extension is present, prefer it for both the float and double overloads + to avoid accidents. Otherwise use the float variant if available, and + fall back to the double variant otherwise. */ #ifndef MAGNUM_TARGET_GLES - if(context.isExtensionSupported()) + if(context.isExtensionSupported()) { + extensions[Extensions::NV::depth_buffer_float::Index] = + Extensions::NV::depth_buffer_float::string(); + + clearDepthImplementation = glClearDepthdNV; + depthRangeImplementation = glDepthRangedNV; + clearDepthfImplementation = &Renderer::clearDepthfImplementationNV; + depthRangefImplementation = &Renderer::depthRangefImplementationNV; + } else #endif { #ifndef MAGNUM_TARGET_GLES - extensions[Extensions::ARB::ES2_compatibility::Index] = - Extensions::ARB::ES2_compatibility::string(); + clearDepthImplementation = glClearDepth; + depthRangeImplementation = glDepthRange; #endif - clearDepthfImplementation = glClearDepthf; - depthRangefImplementation = glDepthRangef; - } - #ifndef MAGNUM_TARGET_GLES - else { - clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault; - depthRangefImplementation = &Renderer::depthRangefImplementationDefault; + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + extensions[Extensions::ARB::ES2_compatibility::Index] = + Extensions::ARB::ES2_compatibility::string(); + #endif + + clearDepthfImplementation = glClearDepthf; + depthRangefImplementation = glDepthRangef; + } + #ifndef MAGNUM_TARGET_GLES + else { + clearDepthfImplementation = &Renderer::clearDepthfImplementationDefault; + depthRangefImplementation = &Renderer::depthRangefImplementationDefault; + } + #endif } - #endif #ifndef MAGNUM_TARGET_WEBGL /* Graphics reset status implementation */ diff --git a/src/Magnum/GL/Implementation/RendererState.h b/src/Magnum/GL/Implementation/RendererState.h index 6f573a64d..cda385147 100644 --- a/src/Magnum/GL/Implementation/RendererState.h +++ b/src/Magnum/GL/Implementation/RendererState.h @@ -38,6 +38,10 @@ struct RendererState { Range1D(*lineWidthRangeImplementation)(); /* These are direct pointers to the GL functions, so need a __stdcall on Windows to compile properly on 32 bits */ + #ifndef MAGNUM_TARGET_GLES + void(APIENTRY *clearDepthImplementation)(GLdouble); + void(APIENTRY *depthRangeImplementation)(GLdouble, GLdouble); + #endif void(APIENTRY *clearDepthfImplementation)(GLfloat); void(APIENTRY *depthRangefImplementation)(GLfloat, GLfloat); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) diff --git a/src/Magnum/GL/Renderer.cpp b/src/Magnum/GL/Renderer.cpp index 0ac3087c1..f7c3a175d 100644 --- a/src/Magnum/GL/Renderer.cpp +++ b/src/Magnum/GL/Renderer.cpp @@ -96,7 +96,7 @@ void Renderer::setClearColor(const Color4& color) { #ifndef MAGNUM_TARGET_GLES void Renderer::setClearDepth(const Double depth) { - glClearDepth(depth); + Context::current().state().renderer.clearDepthImplementation(depth); } #endif @@ -105,6 +105,10 @@ void Renderer::setClearDepth(const Float depth) { } #ifndef MAGNUM_TARGET_GLES +void Renderer::clearDepthfImplementationNV(const GLfloat depth) { + glClearDepthdNV(GLdouble(depth)); +} + void Renderer::clearDepthfImplementationDefault(const GLfloat depth) { glClearDepth(GLdouble(depth)); } @@ -304,7 +308,7 @@ void Renderer::setDepthFunction(const DepthFunction function) { #ifndef MAGNUM_TARGET_GLES void Renderer::setDepthRange(const Double near, const Double far) { - glDepthRange(near, far); + Context::current().state().renderer.depthRangeImplementation(near, far); } #endif @@ -313,6 +317,10 @@ void Renderer::setDepthRange(const Float near, const Float far) { } #ifndef MAGNUM_TARGET_GLES +void Renderer::depthRangefImplementationNV(const Float near, const Float far) { + glDepthRangedNV(GLdouble(near), GLdouble(far)); +} + void Renderer::depthRangefImplementationDefault(const Float near, const Float far) { glDepthRange(GLdouble(near), GLdouble(far)); } diff --git a/src/Magnum/GL/Renderer.h b/src/Magnum/GL/Renderer.h index 35b9ae942..7e272f31e 100644 --- a/src/Magnum/GL/Renderer.h +++ b/src/Magnum/GL/Renderer.h @@ -690,7 +690,11 @@ class MAGNUM_GL_EXPORT Renderer { /** * @brief Set clear depth * - * Initial value is @cpp 1.0 @ce. + * Initial value is @cpp 1.0 @ce. If the + * @gl_extension{NV,depth_buffer_float} desktop extension is available, + * the function uses the + * @fn_gl_extension_keyword{ClearDepthd,NV,depth_buffer_float} API + * which doesn't clamp the input to the @f$ [0, 1] @f$ range. * @see @ref Feature::DepthTest, @ref AbstractFramebuffer::clearDepth(), * @ref AbstractFramebuffer::clearDepthStencil(), * @ref setDepthRange(), @fn_gl_keyword{ClearDepth} @@ -707,13 +711,17 @@ class MAGNUM_GL_EXPORT Renderer { /** * @overload * - * Initial value is @cpp 1.0f @ce. If OpenGL ES, OpenGL 4.1 or - * extension @gl_extension{ARB,ES2_compatibility} is not available, - * this function behaves exactly as - * @ref setClearDepth(Double). + * Initial value is @cpp 1.0f @ce. If the + * @gl_extension{NV,depth_buffer_float} desktop extension is available, + * the function behaves exactly as @ref setClearDepth(Double) for + * consistent clamping behavior between the two overloads. Otherwise, + * if OpenGL ES, OpenGL 4.1 or extension + * @gl_extension{ARB,ES2_compatibility} is available, this function + * uses the @fn_gl2_keyword{ClearDepthf,ClearDepth} API. Otherwise it + * behaves exactly as @ref setClearDepth(Double). * @see @ref Feature::DepthTest, @ref AbstractFramebuffer::clearDepth(), * @ref AbstractFramebuffer::clearDepthStencil(), - * @ref setDepthRange(), @fn_gl2_keyword{ClearDepthf,ClearDepth} + * @ref setDepthRange() * @deprecated_gl Prefer to use @ref AbstractFramebuffer::clearDepth() * / @ref AbstractFramebuffer::clearDepthStencil() instead of * @ref setClearDepth() and @ref AbstractFramebuffer::clear() as @@ -1197,7 +1205,11 @@ class MAGNUM_GL_EXPORT Renderer { * @brief Set depth range * @m_since_latest * - * Initial value is @cpp 0.0 @ce and @cpp 1.0 @ce. + * Initial value is @cpp 0.0 @ce and @cpp 1.0 @ce. If the + * @gl_extension{NV,depth_buffer_float} desktop extension is available, + * the function uses the + * @fn_gl_extension_keyword{DepthRanged,NV,depth_buffer_float} API + * which doesn't clamp the input to the @f$ [0, 1] @f$ range. * @see @fn_gl_keyword{DepthRange} * @requires_gl See @ref setClearDepth(Float), which is available in * OpenGL ES and WebGL. @@ -1209,11 +1221,14 @@ class MAGNUM_GL_EXPORT Renderer { * @overload * @m_since_latest * - * Initial value is @cpp 0.0 @ce and @cpp 1.0 @ce. If OpenGL ES, OpenGL - * 4.1 or extension @gl_extension{ARB,ES2_compatibility} is not - * available, this function behaves exactly as - * @ref setDepthRange(Double, Double). - * @see @fn_gl2_keyword{DepthRangef,DepthRange} + * Initial value is @cpp 0.0 @ce and @cpp 1.0 @ce. If the + * @gl_extension{NV,depth_buffer_float} desktop extension is available, + * the function behaves exactly as @ref setDepthRange(Double, Double) + * for consistent clamping behavior between the two overloads. + * Otherwise, if OpenGL ES, OpenGL 4.1 or extension + * @gl_extension{ARB,ES2_compatibility} is available, this function + * uses the @fn_gl2_keyword{DepthRangef,DepthRange} API. Otherwise it + * behaves exactly as @ref setDepthRange(Double, Double). */ static void setDepthRange(Float near, Float far); @@ -2263,7 +2278,9 @@ class MAGNUM_GL_EXPORT Renderer { /* These have to be compatible with direct pointers to the GL functions which need a __stdcall on Windows to compile properly on 32 bits */ #ifndef MAGNUM_TARGET_GLES + static void APIENTRY MAGNUM_GL_LOCAL clearDepthfImplementationNV(GLfloat depth); static void APIENTRY MAGNUM_GL_LOCAL clearDepthfImplementationDefault(GLfloat depth); + static void APIENTRY MAGNUM_GL_LOCAL depthRangefImplementationNV(GLfloat near, GLfloat far); static void APIENTRY MAGNUM_GL_LOCAL depthRangefImplementationDefault(GLfloat near, GLfloat far); #endif #ifndef MAGNUM_TARGET_WEBGL diff --git a/src/MagnumExternal/OpenGL/GL/extensions.txt b/src/MagnumExternal/OpenGL/GL/extensions.txt index b48691380..497e7bbad 100644 --- a/src/MagnumExternal/OpenGL/GL/extensions.txt +++ b/src/MagnumExternal/OpenGL/GL/extensions.txt @@ -42,9 +42,17 @@ extension KHR_blend_equation_advanced optional extension KHR_blend_equation_advanced_coherent optional # extension KHR_texture_compression_astc_sliced_3d optional extension KHR_parallel_shader_compile optional +extension NV_depth_buffer_float optional extension NV_sample_locations optional extension NV_fragment_shader_barycentric optional extension OVR_multiview optional extension OVR_multiview2 optional +begin functions blacklist + # Part of NV_depth_buffer_float, according to the spec file should be + # present only if EXT_depth_bounds_test is also present (which we don't + # use) + DepthBoundsdNV +end functions blacklist + # kate: hl python diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.cpp b/src/MagnumExternal/OpenGL/GL/flextGL.cpp index d289c4428..8be86e7a8 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.cpp +++ b/src/MagnumExternal/OpenGL/GL/flextGL.cpp @@ -225,6 +225,10 @@ FlextGL flextGL{ /* GL_KHR_parallel_shader_compile */ nullptr, + /* GL_NV_depth_buffer_float */ + nullptr, + nullptr, + /* GL_NV_sample_locations */ nullptr, nullptr, diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.h b/src/MagnumExternal/OpenGL/GL/flextGL.h index d11cc1880..e04874a63 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.h +++ b/src/MagnumExternal/OpenGL/GL/flextGL.h @@ -1778,6 +1778,13 @@ typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum #define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0 #define GL_COMPLETION_STATUS_KHR 0x91B1 +/* GL_NV_depth_buffer_float */ + +#define GL_DEPTH_COMPONENT32F_NV 0x8DAB +#define GL_DEPTH32F_STENCIL8_NV 0x8DAC +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD +#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF + /* GL_NV_sample_locations */ #define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D @@ -1885,6 +1892,11 @@ struct FlextGL { void(APIENTRY *MaxShaderCompilerThreadsKHR)(GLuint); + /* GL_NV_depth_buffer_float */ + + void(APIENTRY *ClearDepthdNV)(GLdouble); + void(APIENTRY *DepthRangedNV)(GLdouble, GLdouble); + /* GL_NV_sample_locations */ void(APIENTRY *FramebufferSampleLocationsfvNV)(GLenum, GLuint, GLsizei, const GLfloat *); @@ -2693,6 +2705,11 @@ extern FLEXTGL_EXPORT FlextGL flextGL; #define glMaxShaderCompilerThreadsKHR flextGL.MaxShaderCompilerThreadsKHR +/* GL_NV_depth_buffer_float */ + +#define glClearDepthdNV flextGL.ClearDepthdNV +#define glDepthRangedNV flextGL.DepthRangedNV + /* GL_NV_sample_locations */ #define glFramebufferSampleLocationsfvNV flextGL.FramebufferSampleLocationsfvNV diff --git a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp index 46da39b00..d31043877 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp +++ b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp @@ -189,6 +189,10 @@ void flextGLInit(Magnum::GL::Context& context) { /* GL_KHR_parallel_shader_compile */ flextGL.MaxShaderCompilerThreadsKHR = reinterpret_cast(loader.load("glMaxShaderCompilerThreadsKHR")); + /* GL_NV_depth_buffer_float */ + flextGL.ClearDepthdNV = reinterpret_cast(loader.load("glClearDepthdNV")); + flextGL.DepthRangedNV = reinterpret_cast(loader.load("glDepthRangedNV")); + /* GL_NV_sample_locations */ flextGL.FramebufferSampleLocationsfvNV = reinterpret_cast(loader.load("glFramebufferSampleLocationsfvNV")); flextGL.NamedFramebufferSampleLocationsfvNV = reinterpret_cast(loader.load("glNamedFramebufferSampleLocationsfvNV"));