From ecf7eba04385debfd9d2a67e908193424692481b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 3 Nov 2015 16:00:14 -0800 Subject: [PATCH] Added ability to read occlusion query result on main thread. --- examples/26-occlusion/occlusion.cpp | 7 +++++++ include/bgfx/bgfx.h | 20 ++++++++++++++++++++ include/bgfx/c99/bgfx.h | 13 +++++++++++++ src/bgfx.cpp | 15 +++++++++++++++ src/bgfx_p.h | 20 ++++++++++++++++++++ src/renderer_d3d11.cpp | 21 ++++++++++----------- src/renderer_d3d11.h | 4 ++-- src/renderer_d3d9.cpp | 21 ++++++++++----------- src/renderer_d3d9.h | 4 ++-- src/renderer_gl.cpp | 21 ++++++++++----------- src/renderer_gl.h | 4 ++-- 11 files changed, 111 insertions(+), 39 deletions(-) diff --git a/examples/26-occlusion/occlusion.cpp b/examples/26-occlusion/occlusion.cpp index dac3973d..afe7c780 100644 --- a/examples/26-occlusion/occlusion.cpp +++ b/examples/26-occlusion/occlusion.cpp @@ -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(); diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 17cc45d9..06dab1cc 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -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. diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 08c14eb9..c333333a 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -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); diff --git a/src/bgfx.cpp b/src/bgfx.cpp index f7b88db4..8fef39bf 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -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 }; diff --git a/src/bgfx_p.h b/src/bgfx_p.h index b6f806f2..7cade4fc 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -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); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 8c5d9c5f..98bd2fe8 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -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) ) diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index bdac87f5..4408f193 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -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 { diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 33362481..1697989c 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -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) ) diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 2a370648..aca8b260 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -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 { diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 2c82497e..4c38c2cc 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -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) ) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 1f5570d5..3d0c9dee 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -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 {