From 10f7d185a6ddc154145a271ad892934d0189a22a Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 6 Sep 2013 17:38:34 +0200 Subject: [PATCH] Added conditional rendering Former-commit-id: 30c062a469ad5f534b95a33c07c92c89036aacf7 --- include/Nazara/Renderer/Enums.hpp | 11 +++++ include/Nazara/Renderer/OpenGL.hpp | 8 +++- include/Nazara/Renderer/Renderer.hpp | 5 ++ src/Nazara/Renderer/OpenGL.cpp | 69 ++++++++++++++++++++++------ src/Nazara/Renderer/Renderer.cpp | 43 +++++++++++++++++ 5 files changed, 121 insertions(+), 15 deletions(-) diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 4968ff76b..77f1d667b 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -51,6 +51,16 @@ enum nzFaceFilling nzFaceFilling_Max = nzFaceFilling_Fill }; +enum nzGpuQueryCondition +{ + nzGpuQueryCondition_Region_NoWait, + nzGpuQueryCondition_Region_Wait, + nzGpuQueryCondition_NoWait, + nzGpuQueryCondition_Wait, + + nzGpuQueryCondition_Max = nzGpuQueryCondition_Wait +}; + enum nzGpuQueryMode { nzGpuQueryMode_AnySamplesPassed, @@ -97,6 +107,7 @@ enum nzPixelBufferType enum nzRendererCap { nzRendererCap_AnisotropicFilter, + nzRendererCap_ConditionalRendering, nzRendererCap_FP64, nzRendererCap_HardwareBuffer, nzRendererCap_Instancing, diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index 6bb216a89..afa5974d4 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -29,6 +29,7 @@ enum nzOpenGLExtension { nzOpenGLExtension_AnisotropicFilter, + nzOpenGLExtension_ConditionalRender, nzOpenGLExtension_DebugOutput, nzOpenGLExtension_DrawInstanced, nzOpenGLExtension_FP64, @@ -90,8 +91,8 @@ class NAZARA_API NzOpenGL static GLuint GetCurrentBuffer(nzBufferType type); static GLuint GetCurrentProgram(); - static const NzRenderTarget* GetCurrentTarget(); static NzRecti GetCurrentScissorBox(); + static const NzRenderTarget* GetCurrentTarget(); static GLuint GetCurrentTexture(); static GLuint GetCurrentTexture(unsigned int textureUnit); static unsigned int GetCurrentTextureUnit(); @@ -110,8 +111,8 @@ class NAZARA_API NzOpenGL static bool IsSupported(const NzString& string); static void SetBuffer(nzBufferType type, GLuint id); - static void SetScissorBox(const NzRecti& scissorBox); static void SetProgram(GLuint id); + static void SetScissorBox(const NzRecti& scissorBox); static void SetTarget(const NzRenderTarget* renderTarget); static void SetTexture(GLuint id); static void SetTexture(unsigned int textureUnit, GLuint id); @@ -135,6 +136,7 @@ class NAZARA_API NzOpenGL static GLenum FaceCulling[nzFaceCulling_Max+1]; static GLenum FaceFilling[nzFaceFilling_Max+1]; static GLenum PrimitiveMode[nzPrimitiveMode_Max+1]; + static GLenum QueryCondition[nzGpuQueryCondition_Max+1]; static GLenum QueryMode[nzGpuQueryMode_Max+1]; static GLenum RendererComparison[nzRendererComparison_Max+1]; static GLenum RendererParameter[nzRendererParameter_Max+1]; @@ -152,6 +154,7 @@ class NAZARA_API NzOpenGL NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture; NAZARA_API extern PFNGLATTACHSHADERPROC glAttachShader; +NAZARA_API extern PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender; NAZARA_API extern PFNGLBEGINQUERYPROC glBeginQuery; NAZARA_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer; @@ -201,6 +204,7 @@ NAZARA_API extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced; NAZARA_API extern PFNGLDRAWTEXTURENVPROC glDrawTexture; NAZARA_API extern PFNGLENABLEPROC glEnable; NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; +NAZARA_API extern PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender; NAZARA_API extern PFNGLENDQUERYPROC glEndQuery; NAZARA_API extern PFNGLFLUSHPROC glFlush; NAZARA_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index c7295c899..b7f040d9a 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ class NAZARA_API NzRenderer NzRenderer() = delete; ~NzRenderer() = delete; + static void BeginCondition(const NzGpuQuery& query, nzGpuQueryCondition condition); + static void Clear(nzUInt32 flags = nzRendererClear_Color | nzRendererClear_Depth); static void DrawFullscreenQuad(); @@ -45,6 +48,8 @@ class NAZARA_API NzRenderer static void Enable(nzRendererParameter parameter, bool enable); + static void EndCondition(); + static void Flush(); static NzVertexBuffer* GetInstanceBuffer(); diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index a7c3e366f..3cb23d0e7 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -923,6 +923,37 @@ bool NzOpenGL::Initialize() // AnisotropicFilter s_openGLextensions[nzOpenGLExtension_AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic"); + // ConditionalRender + if (s_openglVersion >= 300) + { + try + { + glBeginConditionalRender = reinterpret_cast(LoadEntry("glBeginConditionalRender")); + glEndConditionalRender = reinterpret_cast(LoadEntry("glEndConditionalRender")); + + s_openGLextensions[nzOpenGLExtension_ConditionalRender] = true; + } + catch (const std::exception& e) + { + NazaraWarning("Failed to load Conditional Render: " + NzString(e.what())); + } + } + + if (!s_openGLextensions[nzOpenGLExtension_ConditionalRender] && IsSupported("GL_NV_conditional_render")) + { + try + { + glBeginConditionalRender = reinterpret_cast(LoadEntry("glBeginConditionalRenderNV")); + glEndConditionalRender = reinterpret_cast(LoadEntry("glEndConditionalRenderNV")); + + s_openGLextensions[nzOpenGLExtension_ConditionalRender] = true; + } + catch (const std::exception& e) + { + NazaraWarning("Failed to load GL_NV_conditional_render: " + NzString(e.what())); + } + } + // DebugOutput if (s_openglVersion >= 430 || IsSupported("GL_KHR_debug")) { @@ -1228,19 +1259,6 @@ void NzOpenGL::SetBuffer(nzBufferType type, GLuint id) s_contextStates->buffersBinding[type] = id; } -void NzOpenGL::SetScissorBox(const NzRecti& scissorBox) -{ - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->currentScissorBox = scissorBox; -} - void NzOpenGL::SetProgram(GLuint id) { #ifdef NAZARA_DEBUG @@ -1254,6 +1272,19 @@ void NzOpenGL::SetProgram(GLuint id) s_contextStates->currentProgram = id; } +void NzOpenGL::SetScissorBox(const NzRecti& scissorBox) +{ + #ifdef NAZARA_DEBUG + if (!s_contextStates) + { + NazaraError("No context activated"); + return; + } + #endif + + s_contextStates->currentScissorBox = scissorBox; +} + void NzOpenGL::SetTarget(const NzRenderTarget* renderTarget) { #ifdef NAZARA_DEBUG @@ -1855,6 +1886,16 @@ GLenum NzOpenGL::PrimitiveMode[nzPrimitiveMode_Max+1] = static_assert(sizeof(NzOpenGL::PrimitiveMode)/sizeof(GLenum) == nzPrimitiveMode_Max+1, "Primitive mode array is incomplete"); +GLenum NzOpenGL::QueryCondition[nzGpuQueryCondition_Max+1] = +{ + GL_QUERY_WAIT, // nzGpuQueryCondition_NoWait + GL_QUERY_BY_REGION_NO_WAIT, // nzGpuQueryCondition_Region_NoWait + GL_QUERY_BY_REGION_WAIT, // nzGpuQueryCondition_Region_Wait + GL_QUERY_WAIT // nzGpuQueryCondition_Wait +}; + +static_assert(sizeof(NzOpenGL::QueryCondition)/sizeof(GLenum) == nzGpuQueryCondition_Max+1, "Query condition array is incomplete"); + GLenum NzOpenGL::QueryMode[nzGpuQueryMode_Max+1] = { GL_ANY_SAMPLES_PASSED, // nzGpuQueryMode_AnySamplesPassed @@ -1963,6 +2004,7 @@ static_assert(sizeof(NzOpenGL::TextureTargetProxy)/sizeof(GLenum) == nzImageType PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr; PFNGLATTACHSHADERPROC glAttachShader = nullptr; +PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender = nullptr; PFNGLBEGINQUERYPROC glBeginQuery = nullptr; PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr; PFNGLBINDBUFFERPROC glBindBuffer = nullptr; @@ -2012,6 +2054,7 @@ PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = nullptr; PFNGLDRAWTEXTURENVPROC glDrawTexture = nullptr; PFNGLENABLEPROC glEnable = nullptr; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; +PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender = nullptr; PFNGLENDQUERYPROC glEndQuery = nullptr; PFNGLFLUSHPROC glFlush = nullptr; PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr; diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 39d1e4347..8c8ec834b 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -184,6 +184,27 @@ namespace ResourceListener s_listener; } +void NzRenderer::BeginCondition(const NzGpuQuery& query, nzGpuQueryCondition condition) +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + #if NAZARA_RENDERER_SAFE + if (!s_capabilities[nzRendererCap_ConditionalRendering]) + { + NazaraError("Conditional rendering is not supported"); + return; + } + #endif + + glBeginConditionalRender(query.GetOpenGLID(), NzOpenGL::QueryCondition[condition]); +} + void NzRenderer::Clear(nzUInt32 flags) { #ifdef NAZARA_DEBUG @@ -463,6 +484,27 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable) s_states.parameters[parameter] = enable; } +void NzRenderer::EndCondition() +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + #if NAZARA_RENDERER_SAFE + if (!s_capabilities[nzRendererCap_ConditionalRendering]) + { + NazaraError("Conditional rendering is not supported"); + return; + } + #endif + + glEndConditionalRender(); +} + void NzRenderer::Flush() { #ifdef NAZARA_DEBUG @@ -617,6 +659,7 @@ bool NzRenderer::Initialize() // Récupération des capacités d'OpenGL s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter); + s_capabilities[nzRendererCap_ConditionalRendering] = NzOpenGL::IsSupported(nzOpenGLExtension_ConditionalRender); s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64); s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);