Branimir Karadžić пре 10 година
родитељ
комит
7a8b3632b9
4 измењених фајлова са 151 додато и 37 уклоњено
  1. 3 0
      examples/26-occlusion/occlusion.cpp
  2. 5 0
      src/renderer_d3d9.cpp
  3. 120 5
      src/renderer_gl.cpp
  4. 23 32
      src/renderer_gl.h

+ 3 - 0
examples/26-occlusion/occlusion.cpp

@@ -209,6 +209,9 @@ class Occlusion : public entry::AppI
 				bgfx::setViewRect(2, 10, height - height/4 - 10, width/4, height/4);
 			}
 
+			bgfx::touch(0);
+			bgfx::touch(2);
+
 			for (uint32_t yy = 0; yy < CUBES_DIM; ++yy)
 			{
 				for (uint32_t xx = 0; xx < CUBES_DIM; ++xx)

+ 5 - 0
src/renderer_d3d9.cpp

@@ -3516,6 +3516,11 @@ namespace bgfx { namespace d3d9
 
 		invalidateSamplerState();
 
+		if (m_occlusionQuerySupport)
+		{
+			m_occlusionQuery.resolve();
+		}
+
 		if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
 		{
 			for (uint32_t item = 0, numItems = _render->m_num; item < numItems; ++item)

+ 120 - 5
src/renderer_gl.cpp

@@ -558,6 +558,7 @@ namespace bgfx { namespace gl
 
 			NV_copy_image,
 			NV_draw_buffers,
+			NV_occlusion_query,
 			NV_texture_border_clamp,
 			NVX_gpu_memory_info,
 
@@ -716,7 +717,7 @@ namespace bgfx { namespace gl
 		{ "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_occlusion_query_boolean",           false,                             true  }, // GLES2 extension.
 		{ "EXT_packed_float",                      BGFX_CONFIG_RENDERER_OPENGL >= 33, true  },
 		{ "EXT_read_format_bgra",                  false,                             true  },
 		{ "EXT_shader_image_load_store",           false,                             true  },
@@ -761,6 +762,7 @@ namespace bgfx { namespace gl
 
 		{ "NV_copy_image",                         false,                             true  },
 		{ "NV_draw_buffers",                       false,                             true  }, // GLES2 extension.
+		{ "NV_occlusion_query",                    false,                             true  },
 		{ "NV_texture_border_clamp",               false,                             true  }, // GLES2 extension.
 		{ "NVX_gpu_memory_info",                   false,                             true  },
 
@@ -1213,6 +1215,7 @@ namespace bgfx { namespace gl
 			, m_textureSwizzleSupport(false)
 			, m_depthTextureSupport(false)
 			, m_timerQuerySupport(false)
+			, m_occlusionQuerySupport(false)
 			, m_flip(false)
 			, m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT)
 			, m_backBufferFbo(0)
@@ -1800,6 +1803,18 @@ namespace bgfx { namespace gl
 				&& NULL != glGetQueryObjectui64v
 				;
 
+			m_occlusionQuerySupport = false
+				|| s_extension[Extension::ARB_occlusion_query        ].m_supported
+				|| s_extension[Extension::ARB_occlusion_query2       ].m_supported
+				|| s_extension[Extension::EXT_occlusion_query_boolean].m_supported
+				|| s_extension[Extension::NV_occlusion_query         ].m_supported
+				;
+
+			g_caps.supported |= m_occlusionQuerySupport
+				? BGFX_CAPS_OCCLUSION_QUERY
+				: 0
+				;
+
 			g_caps.supported |= m_depthTextureSupport
 				? BGFX_CAPS_TEXTURE_COMPARE_LEQUAL
 				: 0
@@ -1926,12 +1941,16 @@ namespace bgfx { namespace gl
 				glInvalidateFramebuffer = stubInvalidateFramebuffer;
 			}
 
-			if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
-			&&  m_timerQuerySupport)
+			if (m_timerQuerySupport)
 			{
 				m_gpuTimer.create();
 			}
 
+			if (m_occlusionQuerySupport)
+			{
+				m_occlusionQuery.create();
+			}
+
 			// Init reserved part of view name.
 			for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii)
 			{
@@ -1957,12 +1976,16 @@ namespace bgfx { namespace gl
 
 			invalidateCache();
 
-			if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
-			&&  m_timerQuerySupport)
+			if (m_timerQuerySupport)
 			{
 				m_gpuTimer.destroy();
 			}
 
+			if (m_occlusionQuerySupport)
+			{
+				m_occlusionQuery.destroy();
+			}
+
 			destroyMsaaFbo();
 			m_glctx.destroy();
 
@@ -2689,6 +2712,12 @@ namespace bgfx { namespace gl
 			}
 		}
 
+		bool isVisible(OcclusionQueryHandle _handle)
+		{
+			m_occlusionQuery.resolve();
+			return m_occlusion[_handle.idx];
+		}
+
 		void ovrPostReset()
 		{
 #if BGFX_CONFIG_USE_OVR
@@ -3127,9 +3156,12 @@ namespace bgfx { namespace gl
 		TextureGL m_textures[BGFX_CONFIG_MAX_TEXTURES];
 		VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
 		FrameBufferGL m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
+		bool m_occlusion[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
 		UniformRegistry m_uniformReg;
 		void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];
+
 		TimerQueryGL m_gpuTimer;
+		OcclusionQueryGL m_occlusionQuery;
 
 		VaoStateCache m_vaoStateCache;
 		SamplerStateCache m_samplerStateCache;
@@ -3157,6 +3189,7 @@ namespace bgfx { namespace gl
 		bool m_textureSwizzleSupport;
 		bool m_depthTextureSupport;
 		bool m_timerQuerySupport;
+		bool m_occlusionQuerySupport;
 		bool m_flip;
 
 		uint64_t m_hash;
@@ -5115,6 +5148,65 @@ namespace bgfx { namespace gl
 		GL_CHECK(glInvalidateFramebuffer(GL_FRAMEBUFFER, idx, buffers) );
 	}
 
+	void OcclusionQueryGL::create()
+	{
+		for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
+		{
+			Query& query = m_query[ii];
+			GL_CHECK(glGenQueries(1, &query.m_id) );
+		}
+	}
+
+	void OcclusionQueryGL::destroy()
+	{
+		for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii)
+		{
+			Query& query = m_query[ii];
+			GL_CHECK(glDeleteQueries(1, &query.m_id) );
+		}
+	}
+
+	void OcclusionQueryGL::begin(OcclusionQueryHandle _handle)
+	{
+		while (0 == m_control.reserve(1) )
+		{
+			resolve(true);
+		}
+
+		Query& query = m_query[m_control.m_current];
+		GL_CHECK(glBeginQuery(GL_SAMPLES_PASSED, query.m_id) );
+		query.m_handle = _handle;
+	}
+
+	void OcclusionQueryGL::end()
+	{
+		GL_CHECK(glEndQuery(GL_SAMPLES_PASSED) );
+		m_control.commit(1);
+	}
+
+	void OcclusionQueryGL::resolve(bool _wait)
+	{
+		while (0 != m_control.available() )
+		{
+			Query& query = m_query[m_control.m_read];
+			int32_t result;
+
+			if (!_wait)
+			{
+				GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT_AVAILABLE, &result) );
+
+				if (!result)
+				{
+					break;
+				}
+			}
+
+			GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT, &result) );
+			s_renderGL->m_occlusion[query.m_handle.idx] = 0 < result;
+			m_control.consume(1);
+		}
+	}
+
 	void RendererContextGL::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter)
 	{
 		if (1 < m_numWindows
@@ -5213,6 +5305,11 @@ namespace bgfx { namespace gl
 		uint32_t statsNumIndices = 0;
 		uint32_t statsKeyType[2] = {};
 
+		if (m_occlusionQuerySupport)
+		{
+			m_occlusionQuery.resolve();
+		}
+
 		if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
 		{
 			GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
@@ -5505,6 +5602,14 @@ namespace bgfx { namespace gl
 
 				const RenderDraw& draw = renderItem.draw;
 
+				const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
+				if (isValid(draw.m_occlusionQuery)
+				&&  !hasOcclusionQuery
+				&&  !isVisible(draw.m_occlusionQuery) )
+				{
+					continue;
+				}
+
 				const uint64_t newFlags = draw.m_stateFlags;
 				uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags;
 				currentState.m_stateFlags = newFlags;
@@ -6017,6 +6122,11 @@ namespace bgfx { namespace gl
 						uint32_t numPrimsRendered  = 0;
 						uint32_t numDrawIndirect   = 0;
 
+						if (hasOcclusionQuery)
+						{
+							m_occlusionQuery.begin(draw.m_occlusionQuery);
+						}
+
 						if (isValid(draw.m_indirectBuffer) )
 						{
 							const VertexBufferGL& vb = m_vertexBuffers[draw.m_indirectBuffer.idx];
@@ -6123,6 +6233,11 @@ namespace bgfx { namespace gl
 							}
 						}
 
+						if (hasOcclusionQuery)
+						{
+							m_occlusionQuery.end();
+						}
+
 						statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
 						statsNumPrimsRendered[primIndex]  += numPrimsRendered;
 						statsNumInstances[primIndex]      += numInstances;

+ 23 - 32
src/renderer_gl.h

@@ -1188,38 +1188,6 @@ namespace bgfx { namespace gl
 		VaoCacheRef m_vcref;
 	};
 
-	struct QueriesGL
-	{
-		void create()
-		{
-			GL_CHECK(glGenQueries(BX_COUNTOF(m_queries), m_queries) );
-		}
-
-		void destroy()
-		{
-			GL_CHECK(glDeleteQueries(BX_COUNTOF(m_queries), m_queries) );
-		}
-
-		void begin(uint16_t _id, GLenum _target) const
-		{
-			GL_CHECK(glBeginQuery(_target, m_queries[_id]) );
-		}
-
-		void end(GLenum _target) const
-		{
-			GL_CHECK(glEndQuery(_target) );
-		}
-
-		uint64_t getResult(uint16_t _id) const
-		{
-			uint64_t result;
-			GL_CHECK(glGetQueryObjectui64v(m_queries[_id], GL_QUERY_RESULT, &result) );
-			return result;
-		}
-
-		GLuint m_queries[64];
-	};
-
 	struct TimerQueryGL
 	{
 		TimerQueryGL()
@@ -1285,6 +1253,29 @@ namespace bgfx { namespace gl
 		bx::RingBufferControl m_control;
 	};
 
+	struct OcclusionQueryGL
+	{
+		OcclusionQueryGL()
+			: m_control(BX_COUNTOF(m_query) )
+		{
+		}
+
+		void create();
+		void destroy();
+		void begin(OcclusionQueryHandle _handle);
+		void end();
+		void resolve(bool _wait = false);
+
+		struct Query
+		{
+			GLuint m_id;
+			OcclusionQueryHandle m_handle;
+		};
+
+		Query m_query[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
+		bx::RingBufferControl m_control;
+	};
+
 } /* namespace gl */ } // namespace bgfx
 
 #endif // BGFX_RENDERER_GL_H_HEADER_GUARD