GL: Occlusion query.

This commit is contained in:
Branimir Karadžić 2015-11-01 19:12:42 -08:00
parent 4eac3f398e
commit 7a8b3632b9
4 changed files with 151 additions and 37 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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;

View file

@ -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