Added ability to read occlusion query result on main thread.

This commit is contained in:
Branimir Karadžić 2015-11-03 16:00:14 -08:00
parent a5bbb18a25
commit ecf7eba043
11 changed files with 111 additions and 39 deletions

View file

@ -212,6 +212,8 @@ class Occlusion : public entry::AppI
bgfx::touch(0);
bgfx::touch(2);
uint8_t img[CUBES_DIM*CUBES_DIM*2];
for (uint32_t yy = 0; yy < CUBES_DIM; ++yy)
{
for (uint32_t xx = 0; xx < CUBES_DIM; ++xx)
@ -246,9 +248,14 @@ class Occlusion : public entry::AppI
bgfx::setCondition(occlusionQuery, true);
bgfx::setState(BGFX_STATE_DEFAULT);
bgfx::submit(2, m_program);
img[(yy*CUBES_DIM+xx)*2+0] = " \xfex"[bgfx::getResult(occlusionQuery)];
img[(yy*CUBES_DIM+xx)*2+1] = 0xf;
}
}
bgfx::dbgTextImage(5, 5, CUBES_DIM, CUBES_DIM, img, CUBES_DIM*2);
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx::frame();

View file

@ -275,6 +275,18 @@ namespace bgfx
};
};
struct OcclusionQueryResult
{
enum Enum
{
Invisible,
Visible,
NoResult,
Count
};
};
static const uint16_t invalidHandle = UINT16_MAX;
BGFX_HANDLE(DynamicIndexBufferHandle);
@ -1538,6 +1550,14 @@ namespace bgfx
///
OcclusionQueryHandle createOcclusionQuery();
/// Retrieve occlusion query result.
///
/// @param[in] _handle Handle to occlusion query object.
///
/// @attention C99 equivalent is `bgfx_get_result`.
///
OcclusionQueryResult::Enum getResult(OcclusionQueryHandle _handle);
/// Destroy occlusion query.
///
/// @param[in] _handle Handle to occlusion query object.

View file

@ -184,6 +184,16 @@ typedef enum bgfx_backbuffer_ratio
} bgfx_backbuffer_ratio_t;
typedef enum bgfx_occlusion_query_result
{
BGFX_OCCLUSION_QUERY_RESULT_INVISIBLE,
BGFX_OCCLUSION_QUERY_RESULT_VISIBLE,
BGFX_OCCLUSION_QUERY_RESULT_NORESULT,
BGFX_OCCLUSION_QUERY_RESULT_COUNT
} bgfx_occlusion_query_result_t;
#define BGFX_HANDLE_T(_name) \
typedef struct _name { uint16_t idx; } _name##_t
@ -642,6 +652,9 @@ BGFX_C_API void bgfx_destroy_uniform(bgfx_uniform_handle_t _handle);
/**/
BGFX_C_API bgfx_occlusion_query_handle_t bgfx_create_occlusion_query();
/**/
BGFX_C_API bgfx_occlusion_query_result_t bgfx_get_result(bgfx_occlusion_query_handle_t _handle);
/**/
BGFX_C_API void bgfx_destroy_occlusion_query(bgfx_occlusion_query_handle_t _handle);

View file

@ -1372,6 +1372,8 @@ namespace bgfx
bx::xchg(m_render, m_submit);
memcpy(m_render->m_occlusion, m_submit->m_occlusion, sizeof(m_submit->m_occlusion) );
if (!BX_ENABLED(BGFX_CONFIG_MULTITHREADED)
|| m_singleThreaded)
{
@ -3026,6 +3028,13 @@ again:
return s_ctx->createOcclusionQuery();
}
OcclusionQueryResult::Enum getResult(OcclusionQueryHandle _handle)
{
BGFX_CHECK_MAIN_THREAD();
BGFX_CHECK_CAPS(BGFX_CAPS_OCCLUSION_QUERY, "Occlusion query is not supported!");
return s_ctx->getResult(_handle);
}
void destroyOcclusionQuery(OcclusionQueryHandle _handle)
{
BGFX_CHECK_MAIN_THREAD();
@ -3991,6 +4000,12 @@ BGFX_C_API bgfx_occlusion_query_handle_t bgfx_create_occlusion_query()
return handle.c;
}
BGFX_C_API bgfx_occlusion_query_result_t bgfx_get_result(bgfx_occlusion_query_handle_t _handle)
{
union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } handle = { _handle };
return bgfx_occlusion_query_result_t(bgfx::getResult(handle.cpp) );
}
BGFX_C_API void bgfx_destroy_occlusion_query(bgfx_occlusion_query_handle_t _handle)
{
union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } handle = { _handle };

View file

@ -1292,6 +1292,7 @@ namespace bgfx
term.m_program = invalidHandle;
m_sortKeys[BGFX_CONFIG_MAX_DRAW_CALLS] = term.encodeDraw();
m_sortValues[BGFX_CONFIG_MAX_DRAW_CALLS] = BGFX_CONFIG_MAX_DRAW_CALLS;
memset(m_occlusion, 0xff, sizeof(m_occlusion) );
}
~Frame()
@ -1681,6 +1682,7 @@ namespace bgfx
Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_proj[2][BGFX_CONFIG_MAX_VIEWS];
uint8_t m_viewFlags[BGFX_CONFIG_MAX_VIEWS];
uint8_t m_occlusion[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
uint64_t m_sortKeys[BGFX_CONFIG_MAX_DRAW_CALLS+1];
RenderItemCount m_sortValues[BGFX_CONFIG_MAX_DRAW_CALLS+1];
@ -3297,9 +3299,27 @@ namespace bgfx
BGFX_API_FUNC(OcclusionQueryHandle createOcclusionQuery() )
{
OcclusionQueryHandle handle = { m_occlusionQueryHandle.alloc() };
if (isValid(handle) )
{
m_submit->m_occlusion[handle.idx] = UINT8_MAX;
}
return handle;
}
BGFX_API_FUNC(OcclusionQueryResult::Enum getResult(OcclusionQueryHandle _handle) )
{
BGFX_CHECK_HANDLE("destroyOcclusionQuery", m_occlusionQueryHandle, _handle);
switch (m_submit->m_occlusion[_handle.idx])
{
case 0: return OcclusionQueryResult::Invisible;
case UINT8_MAX: return OcclusionQueryResult::NoResult;
default:;
}
return OcclusionQueryResult::Visible;
}
BGFX_API_FUNC(void destroyOcclusionQuery(OcclusionQueryHandle _handle) )
{
BGFX_CHECK_HANDLE("destroyOcclusionQuery", m_occlusionQueryHandle, _handle);

View file

@ -2729,10 +2729,10 @@ BX_PRAGMA_DIAGNOSTIC_POP();
return sampler;
}
bool isVisible(OcclusionQueryHandle _handle, bool _visible)
bool isVisible(Frame* _render, OcclusionQueryHandle _handle, bool _visible)
{
m_occlusionQuery.resolve();
return _visible == m_occlusion[_handle.idx];
m_occlusionQuery.resolve(_render);
return _visible == 0 != _render->m_occlusion[_handle.idx];
}
DXGI_FORMAT getBufferFormat()
@ -3334,7 +3334,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
TextureD3D11 m_textures[BGFX_CONFIG_MAX_TEXTURES];
VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
FrameBufferD3D11 m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
bool m_occlusion[BGFX_CONFIG_MAX_OCCUSION_QUERIES];
void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS];
Matrix4 m_predefinedUniforms[PredefinedUniform::Count];
UniformRegistry m_uniformReg;
@ -4577,11 +4576,11 @@ BX_PRAGMA_DIAGNOSTIC_POP();
}
}
void OcclusionQueryD3D11::begin(OcclusionQueryHandle _handle)
void OcclusionQueryD3D11::begin(Frame* _render, OcclusionQueryHandle _handle)
{
while (0 == m_control.reserve(1) )
{
resolve(true);
resolve(_render, true);
}
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
@ -4598,7 +4597,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
m_control.commit(1);
}
void OcclusionQueryD3D11::resolve(bool _wait)
void OcclusionQueryD3D11::resolve(Frame* _render, bool _wait)
{
ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx;
@ -4613,7 +4612,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
break;
}
s_renderD3D11->m_occlusion[query.m_handle.idx] = 0 < result;
_render->m_occlusion[query.m_handle.idx] = 0 < result;
m_control.consume(1);
}
}
@ -4687,7 +4686,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t statsNumIndices = 0;
uint32_t statsKeyType[2] = {};
m_occlusionQuery.resolve();
m_occlusionQuery.resolve(_render);
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
{
@ -5053,7 +5052,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
if (isValid(draw.m_occlusionQuery)
&& !hasOcclusionQuery
&& !isVisible(draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
&& !isVisible(_render, draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
{
continue;
}
@ -5348,7 +5347,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (hasOcclusionQuery)
{
m_occlusionQuery.begin(draw.m_occlusionQuery);
m_occlusionQuery.begin(_render, draw.m_occlusionQuery);
}
if (isValid(draw.m_indirectBuffer) )

View file

@ -316,9 +316,9 @@ namespace bgfx { namespace d3d11
void postReset();
void preReset();
void begin(OcclusionQueryHandle _handle);
void begin(Frame* _render, OcclusionQueryHandle _handle);
void end();
void resolve(bool _wait = false);
void resolve(Frame* _render, bool _wait = false);
struct Query
{

View file

@ -1565,10 +1565,10 @@ namespace bgfx { namespace d3d9
}
}
bool isVisible(OcclusionQueryHandle _handle, bool _visible)
bool isVisible(Frame* _render, OcclusionQueryHandle _handle, bool _visible)
{
m_occlusionQuery.resolve();
return _visible == m_occlusion[_handle.idx];
m_occlusionQuery.resolve(_render);
return _visible == 0 != _render->m_occlusion[_handle.idx];
}
void capturePreReset()
@ -2007,7 +2007,6 @@ namespace bgfx { namespace d3d9
TextureD3D9 m_textures[BGFX_CONFIG_MAX_TEXTURES];
VertexDeclD3D9 m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
FrameBufferD3D9 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];
@ -3410,11 +3409,11 @@ namespace bgfx { namespace d3d9
}
}
void OcclusionQueryD3D9::begin(OcclusionQueryHandle _handle)
void OcclusionQueryD3D9::begin(Frame* _render, OcclusionQueryHandle _handle)
{
while (0 == m_control.reserve(1) )
{
resolve(true);
resolve(_render, true);
}
Query& query = m_query[m_control.m_current];
@ -3429,7 +3428,7 @@ namespace bgfx { namespace d3d9
m_control.commit(1);
}
void OcclusionQueryD3D9::resolve(bool)
void OcclusionQueryD3D9::resolve(Frame* _render, bool)
{
while (0 != m_control.available() )
{
@ -3442,7 +3441,7 @@ namespace bgfx { namespace d3d9
break;
}
s_renderD3D9->m_occlusion[query.m_handle.idx] = 0 < result;
_render->m_occlusion[query.m_handle.idx] = 0 < result;
m_control.consume(1);
}
}
@ -3518,7 +3517,7 @@ namespace bgfx { namespace d3d9
if (m_occlusionQuerySupport)
{
m_occlusionQuery.resolve();
m_occlusionQuery.resolve(_render);
}
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
@ -3539,7 +3538,7 @@ namespace bgfx { namespace d3d9
const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
if (isValid(draw.m_occlusionQuery)
&& !hasOcclusionQuery
&& !isVisible(draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
&& !isVisible(_render, draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
{
continue;
}
@ -4003,7 +4002,7 @@ namespace bgfx { namespace d3d9
if (hasOcclusionQuery)
{
m_occlusionQuery.begin(draw.m_occlusionQuery);
m_occlusionQuery.begin(_render, draw.m_occlusionQuery);
}
if (isValid(draw.m_indexBuffer) )

View file

@ -439,9 +439,9 @@ namespace bgfx { namespace d3d9
void postReset();
void preReset();
void begin(OcclusionQueryHandle _handle);
void begin(Frame* _render, OcclusionQueryHandle _handle);
void end();
void resolve(bool _wait = false);
void resolve(Frame* _render, bool _wait = false);
struct Query
{

View file

@ -2712,10 +2712,10 @@ namespace bgfx { namespace gl
}
}
bool isVisible(OcclusionQueryHandle _handle, bool _visible)
bool isVisible(Frame* _render, OcclusionQueryHandle _handle, bool _visible)
{
m_occlusionQuery.resolve();
return _visible == m_occlusion[_handle.idx];
m_occlusionQuery.resolve(_render);
return _visible == 0 != _render->m_occlusion[_handle.idx];
}
void ovrPostReset()
@ -3156,7 +3156,6 @@ 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];
@ -5166,11 +5165,11 @@ namespace bgfx { namespace gl
}
}
void OcclusionQueryGL::begin(OcclusionQueryHandle _handle)
void OcclusionQueryGL::begin(Frame* _render, OcclusionQueryHandle _handle)
{
while (0 == m_control.reserve(1) )
{
resolve(true);
resolve(_render, true);
}
Query& query = m_query[m_control.m_current];
@ -5184,7 +5183,7 @@ namespace bgfx { namespace gl
m_control.commit(1);
}
void OcclusionQueryGL::resolve(bool _wait)
void OcclusionQueryGL::resolve(Frame* _render, bool _wait)
{
while (0 != m_control.available() )
{
@ -5202,7 +5201,7 @@ namespace bgfx { namespace gl
}
GL_CHECK(glGetQueryObjectiv(query.m_id, GL_QUERY_RESULT, &result) );
s_renderGL->m_occlusion[query.m_handle.idx] = 0 < result;
_render->m_occlusion[query.m_handle.idx] = 0 < result;
m_control.consume(1);
}
}
@ -5307,7 +5306,7 @@ namespace bgfx { namespace gl
if (m_occlusionQuerySupport)
{
m_occlusionQuery.resolve();
m_occlusionQuery.resolve(_render);
}
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
@ -5605,7 +5604,7 @@ namespace bgfx { namespace gl
const bool hasOcclusionQuery = 0 != (draw.m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY);
if (isValid(draw.m_occlusionQuery)
&& !hasOcclusionQuery
&& !isVisible(draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
&& !isVisible(_render, draw.m_occlusionQuery, 0 != (draw.m_submitFlags&BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE) ) )
{
continue;
}
@ -6124,7 +6123,7 @@ namespace bgfx { namespace gl
if (hasOcclusionQuery)
{
m_occlusionQuery.begin(draw.m_occlusionQuery);
m_occlusionQuery.begin(_render, draw.m_occlusionQuery);
}
if (isValid(draw.m_indirectBuffer) )

View file

@ -1270,9 +1270,9 @@ namespace bgfx { namespace gl
void create();
void destroy();
void begin(OcclusionQueryHandle _handle);
void begin(Frame* _render, OcclusionQueryHandle _handle);
void end();
void resolve(bool _wait = false);
void resolve(Frame* _render, bool _wait = false);
struct Query
{