diff --git a/examples/13-stencil/stencil.cpp b/examples/13-stencil/stencil.cpp index 168c19ba5..8045e431b 100644 --- a/examples/13-stencil/stencil.cpp +++ b/examples/13-stencil/stencil.cpp @@ -9,11 +9,7 @@ #include "common.h" #include "bgfx_utils.h" -#include -#include #include -#include -#include "entry/entry.h" #include "camera.h" #include "imgui/imgui.h" @@ -1002,7 +998,7 @@ int _main_(int _argc, char** _argv) last = now; const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; - float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); + const float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); const float deltaTime = float(frameTime/freq); s_uniforms.m_time = time; diff --git a/examples/26-occlusion/occlusion.cpp b/examples/26-occlusion/occlusion.cpp new file mode 100644 index 000000000..ff9ffdf24 --- /dev/null +++ b/examples/26-occlusion/occlusion.cpp @@ -0,0 +1,272 @@ +/* + * Copyright 2011-2015 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "common.h" +#include "bgfx_utils.h" +#include "camera.h" + +#define CUBES_DIM 10 + +struct PosColorVertex +{ + float m_x; + float m_y; + float m_z; + uint32_t m_abgr; + + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .end(); + }; + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorVertex::ms_decl; + +static PosColorVertex s_cubeVertices[8] = +{ + {-1.0f, 1.0f, 1.0f, 0xff000000 }, + { 1.0f, 1.0f, 1.0f, 0xff0000ff }, + {-1.0f, -1.0f, 1.0f, 0xff00ff00 }, + { 1.0f, -1.0f, 1.0f, 0xff00ffff }, + {-1.0f, 1.0f, -1.0f, 0xffff0000 }, + { 1.0f, 1.0f, -1.0f, 0xffff00ff }, + {-1.0f, -1.0f, -1.0f, 0xffffff00 }, + { 1.0f, -1.0f, -1.0f, 0xffffffff }, +}; + +static const uint16_t s_cubeIndices[36] = +{ + 0, 1, 2, // 0 + 1, 3, 2, + 4, 6, 5, // 2 + 5, 6, 7, + 0, 2, 4, // 4 + 4, 2, 6, + 1, 5, 3, // 6 + 5, 7, 3, + 0, 4, 1, // 8 + 4, 5, 1, + 2, 3, 6, // 10 + 6, 3, 7, +}; + +class Occlusion : public entry::AppI +{ + void init(int _argc, char** _argv) BX_OVERRIDE + { + Args args(_argc, _argv); + + m_state.m_width = 1280; + m_state.m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_VSYNC; + + bgfx::init(args.m_type, args.m_pciId); + bgfx::reset(m_state.m_width, m_state.m_height, m_reset); + + // Enable debug text. + bgfx::setDebug(m_debug); + + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); + + bgfx::setViewClear(2 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x202020ff + , 1.0f + , 0 + ); + + // Create vertex stream declaration. + PosColorVertex::init(); + + // Create static vertex buffer. + m_vbh = bgfx::createVertexBuffer( + // Static data can be passed with bgfx::makeRef + bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ) + , PosColorVertex::ms_decl + ); + + // Create static index buffer. + m_ibh = bgfx::createIndexBuffer( + // Static data can be passed with bgfx::makeRef + bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) + ); + + // Create program from shaders. + m_program = loadProgram("vs_cubes", "fs_cubes"); + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii) + { + m_occlusionQueries[ii] = bgfx::createOcclusionQuery(); + } + + cameraCreate(); + + const float initialPos[3] = { 15.5f, 0.0f, -15.5f }; + cameraSetPosition(initialPos); + cameraSetHorizontalAngle(bx::toRad(-45.0f) ); + + m_timeOffset = bx::getHPCounter(); + } + + virtual int shutdown() BX_OVERRIDE + { + // Cleanup. + cameraDestroy(); + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_occlusionQueries); ++ii) + { + bgfx::destroyOcclusionQuery(m_occlusionQueries[ii]); + } + + bgfx::destroyIndexBuffer(m_ibh); + bgfx::destroyVertexBuffer(m_vbh); + bgfx::destroyProgram(m_program); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; + } + + bool update() BX_OVERRIDE + { + if (!entry::processWindowEvents(m_state, m_debug, m_reset) ) + { + int64_t now = bx::getHPCounter(); + static int64_t last = now; + const int64_t frameTime = now - last; + last = now; + const double freq = double(bx::getHPFrequency() ); + const double toMs = 1000.0/freq; + const float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) ); + const float deltaTime = float(frameTime/freq); + + // Use debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/26-occlusion"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Using occlusion query to do conditional rendering."); + bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); + + uint32_t width = m_state.m_width; + uint32_t height = m_state.m_height; + + // Update camera. + float view[16]; + cameraUpdate(deltaTime, m_state.m_mouse); + cameraGetViewMtx(view); + + // Set view and projection matrix for view 0. + const bgfx::HMD* hmd = bgfx::getHMD(); + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) + { + float viewHead[16]; + float eye[3] = {}; + bx::mtxQuatTranslationHMD(viewHead, hmd->eye[0].rotation, eye); + + float tmp[16]; + bx::mtxMul(tmp, view, viewHead); + + float proj[16]; + bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f); + + bgfx::setViewTransform(0, tmp, proj); + bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); + + bgfx::setViewTransform(1, tmp, proj); + bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height); + } + else + { + float proj[16]; + bx::mtxProj(proj, 90.0f, float(width)/float(height), 0.1f, 10000.0f); + + bgfx::setViewTransform(0, view, proj); + bgfx::setViewRect(0, 0, 0, width, height); + + bgfx::setViewTransform(1, view, proj); + bgfx::setViewRect(1, 0, 0, width, height); + + float at[3] = { 0.0f, 0.0f, 0.0f }; + float eye[3] = { 17.5f, 10.0f, -17.5f }; + bx::mtxLookAt(view, eye, at); + + bgfx::setViewTransform(2, view, proj); + bgfx::setViewRect(2, 10, height - height/4 - 10, width/4, height/4); + } + + for (uint32_t yy = 0; yy < CUBES_DIM; ++yy) + { + for (uint32_t xx = 0; xx < CUBES_DIM; ++xx) + { + float mtx[16]; + bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f); + mtx[12] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(xx)*3.0f; + mtx[13] = 0.0f; + mtx[14] = -(CUBES_DIM-1) * 3.0f / 2.0f + float(yy)*3.0f; + + bgfx::OcclusionQueryHandle occlusionQuery = m_occlusionQueries[yy*CUBES_DIM+xx]; + + bgfx::setTransform(mtx); + bgfx::setVertexBuffer(m_vbh); + bgfx::setIndexBuffer(m_ibh); + bgfx::setCondition(occlusionQuery, true); + bgfx::setState(BGFX_STATE_DEFAULT); + bgfx::submit(0, m_program); + + bgfx::setTransform(mtx); + bgfx::setVertexBuffer(m_vbh); + bgfx::setIndexBuffer(m_ibh); + bgfx::setState(0 + | BGFX_STATE_DEPTH_TEST_LEQUAL + | BGFX_STATE_CULL_CW + ); + bgfx::submit(1, m_program, occlusionQuery); + + bgfx::setTransform(mtx); + bgfx::setVertexBuffer(m_vbh); + bgfx::setIndexBuffer(m_ibh); + bgfx::setCondition(occlusionQuery, true); + bgfx::setState(BGFX_STATE_DEFAULT); + bgfx::submit(2, m_program); + } + } + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + + return true; + } + + return false; + } + + uint32_t m_reset; + uint32_t m_debug; + + bgfx::VertexBufferHandle m_vbh; + bgfx::IndexBufferHandle m_ibh; + bgfx::ProgramHandle m_program; + int64_t m_timeOffset; + + bgfx::OcclusionQueryHandle m_occlusionQueries[CUBES_DIM*CUBES_DIM]; + + entry::WindowState m_state; +}; + +ENTRY_IMPLEMENT_MAIN(Occlusion); diff --git a/examples/common/camera.cpp b/examples/common/camera.cpp index 4d0a47166..7c1d01458 100644 --- a/examples/common/camera.cpp +++ b/examples/common/camera.cpp @@ -6,8 +6,10 @@ #include #include #include "camera.h" +#include "entry/entry.h" #include "entry/cmd.h" #include "entry/input.h" +#include int cmdMove(CmdContext* /*_context*/, void* /*_userData*/, int _argc, char const* const* _argv) { @@ -63,7 +65,9 @@ static const InputBinding s_camBindings[] = { entry::Key::GamepadDown, entry::Modifier::None, 0, cmd, "move backward" }, { entry::Key::KeyD, entry::Modifier::None, 0, cmd, "move right" }, { entry::Key::GamepadRight, entry::Modifier::None, 0, cmd, "move right" }, + { entry::Key::KeyQ, entry::Modifier::None, 0, cmd, "move down" }, { entry::Key::GamepadShoulderL, entry::Modifier::None, 0, cmd, "move down" }, + { entry::Key::KeyE, entry::Modifier::None, 0, cmd, "move up" }, { entry::Key::GamepadShoulderR, entry::Modifier::None, 0, cmd, "move up" }, INPUT_BINDING_END @@ -294,12 +298,12 @@ static Camera* s_camera = NULL; void cameraCreate() { - s_camera = new Camera; + s_camera = BX_NEW(entry::getAllocator(), Camera); } void cameraDestroy() { - delete s_camera; + BX_DELETE(entry::getAllocator(), s_camera); s_camera = NULL; } diff --git a/examples/makefile b/examples/makefile index 56ad944b7..117f994e2 100644 --- a/examples/makefile +++ b/examples/makefile @@ -27,6 +27,8 @@ rebuild: @make -s --no-print-directory rebuild -C 21-deferred @make -s --no-print-directory rebuild -C 23-vectordisplay @make -s --no-print-directory rebuild -C 24-nbody +# @make -s --no-print-directory rebuild -C 25-c99 +# @make -s --no-print-directory rebuild -C 26-occlusion @make -s --no-print-directory rebuild -C common/font @make -s --no-print-directory rebuild -C common/imgui @make -s --no-print-directory rebuild -C common/nanovg diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 64cd158c4..f4a39f474 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -282,6 +282,7 @@ namespace bgfx BGFX_HANDLE(FrameBufferHandle); BGFX_HANDLE(IndexBufferHandle); BGFX_HANDLE(IndirectBufferHandle); + BGFX_HANDLE(OcclusionQueryHandle); BGFX_HANDLE(ProgramHandle); BGFX_HANDLE(ShaderHandle); BGFX_HANDLE(TextureHandle); @@ -1529,6 +1530,12 @@ namespace bgfx /// void destroyUniform(UniformHandle _handle); + /// + OcclusionQueryHandle createOcclusionQuery(); + + /// + void destroyOcclusionQuery(OcclusionQueryHandle _handle); + /// Set palette color value. /// /// @param[in] _index Index into palette. @@ -1729,6 +1736,15 @@ namespace bgfx /// void setState(uint64_t _state, uint32_t _rgba = 0); + /// Set condition for rendering. + /// + /// @param[in] _handle Occlusion query handle. + /// @param[in] _visible Render if occlusion query is visible. + /// + /// @attention C99 equivalent is `bgfx_set_condition`. + /// + void setCondition(OcclusionQueryHandle _handle, bool _visible); + /// Set stencil test state. /// /// @param[in] _fstencil Front stencil state. @@ -1946,19 +1962,31 @@ namespace bgfx /// Submit primitive for rendering. /// /// @param[in] _id View id. - /// @param[in] _handle Program. + /// @param[in] _program Program. /// @param[in] _depth Depth for sorting. /// @returns Number of draw calls. /// /// @attention C99 equivalent is `bgfx_submit`. /// - uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth = 0); + uint32_t submit(uint8_t _id, ProgramHandle _program, int32_t _depth = 0); + + /// Submit primitive with occlusion query for rendering. + /// + /// @param[in] _id View id. + /// @param[in] _program Program. + /// @param[in] _occlusionQuery Occlusion query. + /// @param[in] _depth Depth for sorting. + /// @returns Number of draw calls. + /// + /// @attention C99 equivalent is `bgfx_submit_occlusion_query. + /// + uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth = 0); /// Submit primitive for rendering with index and instance data info from /// indirect buffer. /// /// @param[in] _id View id. - /// @param[in] _handle Program. + /// @param[in] _program Program. /// @param[in] _indirectHandle Indirect buffer. /// @param[in] _start First element in indirect buffer. /// @param[in] _num Number of dispatches. @@ -1966,7 +1994,7 @@ namespace bgfx /// /// @attention C99 equivalent is `bgfx_submit_indirect`. /// - uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0); + uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start = 0, uint16_t _num = 1, int32_t _depth = 0); /// Set compute index buffer. /// diff --git a/include/bgfx/bgfxdefines.h b/include/bgfx/bgfxdefines.h index 5ca5e7d02..3945d94d0 100644 --- a/include/bgfx/bgfxdefines.h +++ b/include/bgfx/bgfxdefines.h @@ -71,7 +71,9 @@ /// MSAA frame buffer. #define BGFX_STATE_MSAA UINT64_C(0x1000000000000000) //!< Enable MSAA rasterization. -#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!< Internal bits, do not use! +/// Do not use! +#define BGFX_STATE_RESERVED_SHIFT 61 //!< Internal bits shift. +#define BGFX_STATE_RESERVED_MASK UINT64_C(0xe000000000000000) //!< Internal bits mask. /// See BGFX_STATE_POINT_SIZE(_size) helper macro. #define BGFX_STATE_NONE UINT64_C(0x0000000000000000) //!< No state. @@ -370,6 +372,7 @@ #define BGFX_CAPS_HIDPI UINT64_C(0x0000000000008000) //!< HiDPI rendering is supported. #define BGFX_CAPS_TEXTURE_BLIT UINT64_C(0x0000000000010000) //!< Texture blit is supported. #define BGFX_CAPS_TEXTURE_READ_BACK UINT64_C(0x0000000000020000) //!< Read-back texture is supported. +#define BGFX_CAPS_OCCLUSION_QUERY UINT64_C(0x0000000000040000) //!< Occlusion query is supported. /// #define BGFX_CAPS_FORMAT_TEXTURE_NONE UINT16_C(0x0000) //!< Texture format is not supported. diff --git a/include/bgfx/c99/bgfx.h b/include/bgfx/c99/bgfx.h index 534c13f1f..f0bd44136 100644 --- a/include/bgfx/c99/bgfx.h +++ b/include/bgfx/c99/bgfx.h @@ -192,6 +192,7 @@ BGFX_HANDLE_T(bgfx_dynamic_index_buffer_handle); BGFX_HANDLE_T(bgfx_dynamic_vertex_buffer_handle); BGFX_HANDLE_T(bgfx_frame_buffer_handle); BGFX_HANDLE_T(bgfx_index_buffer_handle); +BGFX_HANDLE_T(bgfx_occlusion_query_handle); BGFX_HANDLE_T(bgfx_program_handle); BGFX_HANDLE_T(bgfx_shader_handle); BGFX_HANDLE_T(bgfx_texture_handle); @@ -677,6 +678,9 @@ BGFX_C_API void bgfx_set_marker(const char* _marker); /**/ BGFX_C_API void bgfx_set_state(uint64_t _state, uint32_t _rgba); +/**/ +BGFX_C_API void bgfx_set_condition(bgfx_occlusion_query_handle_t _handle, bool _visible); + /**/ BGFX_C_API void bgfx_set_stencil(uint32_t _fstencil, uint32_t _bstencil); @@ -737,6 +741,9 @@ BGFX_C_API uint32_t bgfx_touch(uint8_t _id); /**/ BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int32_t _depth); +/**/ +BGFX_C_API uint32_t bgfx_submit_occlusion_query(uint8_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, int32_t _depth); + /**/ BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth); diff --git a/scripts/genie.lua b/scripts/genie.lua index ce3e8d8e6..d6887faf6 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -381,6 +381,7 @@ exampleProject("21-deferred") exampleProject("22-windows") exampleProject("23-vectordisplay") exampleProject("24-nbody") +exampleProject("26-occlusion") -- C99 source doesn't compile under WinRT settings if not premake.vstudio.iswinrt() then diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 51b52b037..6e1edef8b 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -762,7 +762,7 @@ namespace bgfx return PredefinedUniform::Count; } - uint32_t Frame::submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) + uint32_t Frame::submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth) { if (m_discard) { @@ -779,9 +779,9 @@ namespace bgfx m_uniformEnd = m_uniformBuffer->getPos(); - m_key.m_program = invalidHandle == _handle.idx + m_key.m_program = invalidHandle == _program.idx ? 0 - : _handle.idx + : _program.idx ; m_key.m_depth = (uint32_t)_depth; @@ -796,13 +796,22 @@ namespace bgfx m_draw.m_constBegin = m_uniformBegin; m_draw.m_constEnd = m_uniformEnd; - m_draw.m_flags |= m_flags; + m_draw.m_stateFlags |= m_stateFlags; + + if (isValid(_occlusionQuery) ) + { + BX_CHECK(!isValid(m_draw.m_occlusionQuery), ""); + + m_draw.m_stateFlags |= BGFX_STATE_INTERNAL_OCCLUSION_QUERY; + m_draw.m_occlusionQuery = _occlusionQuery; + } + m_renderItem[m_numRenderItems].draw = m_draw; ++m_numRenderItems; m_draw.clear(); m_uniformBegin = m_uniformEnd; - m_flags = BGFX_STATE_NONE; + m_stateFlags = BGFX_STATE_NONE; return m_num; } @@ -979,6 +988,7 @@ namespace bgfx CAPS_FLAGS(BGFX_CAPS_HIDPI), CAPS_FLAGS(BGFX_CAPS_TEXTURE_BLIT), CAPS_FLAGS(BGFX_CAPS_TEXTURE_READ_BACK), + CAPS_FLAGS(BGFX_CAPS_OCCLUSION_QUERY), #undef CAPS_FLAGS }; @@ -1331,7 +1341,7 @@ namespace bgfx { freeDynamicBuffers(); m_submit->m_resolution = m_resolution; - m_resolution.m_flags &= ~BGFX_RESET_FORCE; + m_resolution.m_flags &= ~BGFX_RESET_INTERNAL_FORCE; m_submit->m_debug = m_debug; memcpy(m_submit->m_viewRemap, m_viewRemap, sizeof(m_viewRemap) ); @@ -2608,7 +2618,9 @@ again: const InstanceDataBuffer* allocInstanceDataBuffer(uint32_t _num, uint16_t _stride) { BGFX_CHECK_MAIN_THREAD(); - BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_INSTANCING), "Instancing is not supported! Use bgfx::getCaps to check backend renderer capabilities."); + BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_INSTANCING) + , "Instancing is not supported! Use bgfx::getCaps to check backend renderer capabilities." + ); BX_CHECK(0 < _num, "Requesting 0 instanced data vertices."); return s_ctx->allocInstanceDataBuffer(_num, _stride); } @@ -2905,6 +2917,7 @@ again: BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_TEXTURE_3D) , "Texture3D is not supported! Use bgfx::getCaps to check BGFX_CAPS_TEXTURE_3D backend renderer capabilities." ); + if (_width == 0 || _height == 0 || _depth == 0) @@ -3004,6 +3017,24 @@ again: s_ctx->destroyUniform(_handle); } + OcclusionQueryHandle createOcclusionQuery() + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY) + , "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability" + ); + return s_ctx->createOcclusionQuery(); + } + + void destroyOcclusionQuery(OcclusionQueryHandle _handle) + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY) + , "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability" + ); + s_ctx->destroyOcclusionQuery(_handle); + } + void setPaletteColor(uint8_t _index, uint32_t _rgba) { BGFX_CHECK_MAIN_THREAD(); @@ -3133,9 +3164,19 @@ again: void setState(uint64_t _state, uint32_t _rgba) { BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(0 == (_state&BGFX_STATE_RESERVED_MASK), "Do not set state reserved flags!"); s_ctx->setState(_state, _rgba); } + void setCondition(OcclusionQueryHandle _handle, bool _visible) + { + BGFX_CHECK_MAIN_THREAD(); + BX_CHECK(0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY) + , "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability" + ); + s_ctx->setCondition(_handle, _visible); + } + void setStencil(uint32_t _fstencil, uint32_t _bstencil) { BGFX_CHECK_MAIN_THREAD(); @@ -3269,16 +3310,27 @@ again: return submit(_id, handle); } - uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) + uint32_t submit(uint8_t _id, ProgramHandle _program, int32_t _depth) { - BGFX_CHECK_MAIN_THREAD(); - return s_ctx->submit(_id, _handle, _depth); + OcclusionQueryHandle handle = BGFX_INVALID_HANDLE; + return submit(_id, _program, handle, _depth); } - uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) + uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth) { BGFX_CHECK_MAIN_THREAD(); - return s_ctx->submit(_id, _handle, _indirectHandle, _start, _num, _depth); + BX_CHECK(false + || !isValid(_occlusionQuery) + || 0 != (g_caps.supported & BGFX_CAPS_OCCLUSION_QUERY) + , "Occlusion query is not supported, use bgfx::getCaps to test BGFX_CAPS_OCCLUSION_QUERY feature availability" + ); + return s_ctx->submit(_id, _program, _occlusionQuery, _depth); + } + + uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) + { + BGFX_CHECK_MAIN_THREAD(); + return s_ctx->submit(_id, _program, _indirectHandle, _start, _num, _depth); } void setBuffer(uint8_t _stage, IndexBufferHandle _handle, Access::Enum _access) @@ -4011,6 +4063,12 @@ BGFX_C_API void bgfx_set_state(uint64_t _state, uint32_t _rgba) bgfx::setState(_state, _rgba); } +BGFX_C_API void bgfx_set_condition(bgfx_occlusion_query_handle_t _handle, bool _visible) +{ + union { bgfx_occlusion_query_handle_t c; bgfx::OcclusionQueryHandle cpp; } handle = { _handle }; + bgfx::setCondition(handle.cpp, _visible); +} + BGFX_C_API void bgfx_set_stencil(uint32_t _fstencil, uint32_t _bstencil) { bgfx::setStencil(_fstencil, _bstencil); @@ -4123,6 +4181,13 @@ BGFX_C_API uint32_t bgfx_submit(uint8_t _id, bgfx_program_handle_t _handle, int3 return bgfx::submit(_id, handle.cpp, _depth); } +BGFX_C_API uint32_t bgfx_submit_occlusion_query(uint8_t _id, bgfx_program_handle_t _program, bgfx_occlusion_query_handle_t _occlusionQuery, int32_t _depth) +{ + union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } program = { _program }; + union { bgfx_occlusion_query_handle c; bgfx::OcclusionQueryHandle cpp; } occlusionQuery = { _occlusionQuery }; + return bgfx::submit(_id, program.cpp, occlusionQuery.cpp, _depth); +} + BGFX_C_API uint32_t bgfx_submit_indirect(uint8_t _id, bgfx_program_handle_t _handle, bgfx_indirect_buffer_handle_t _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) { union { bgfx_program_handle_t c; bgfx::ProgramHandle cpp; } handle = { _handle }; diff --git a/src/bgfx_p.h b/src/bgfx_p.h index fe9f89d91..4fe13dca1 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -173,8 +173,12 @@ namespace stl #define BGFX_MAX_COMPUTE_BINDINGS 8 -#define BGFX_SAMPLER_DEFAULT_FLAGS UINT32_C(0x10000000) -#define BGFX_RESET_FORCE UINT32_C(0x80000000) +#define BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER UINT32_C(0x10000000) + +#define BGFX_RESET_INTERNAL_FORCE UINT32_C(0x80000000) + +#define BGFX_STATE_INTERNAL_SCISSOR UINT64_C(0x2000000000000000) +#define BGFX_STATE_INTERNAL_OCCLUSION_QUERY UINT64_C(0x4000000000000000) #define BGFX_RENDERER_DIRECT3D9_NAME "Direct3D 9" #define BGFX_RENDERER_DIRECT3D11_NAME "Direct3D 11" @@ -1093,7 +1097,7 @@ namespace bgfx { struct { - uint32_t m_flags; + uint32_t m_textureFlags; } m_draw; struct @@ -1112,7 +1116,7 @@ namespace bgfx { m_constBegin = 0; m_constEnd = 0; - m_flags = BGFX_STATE_DEFAULT; + m_stateFlags = BGFX_STATE_DEFAULT; m_stencil = packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT); m_rgba = 0; m_matrix = 0; @@ -1123,28 +1127,29 @@ namespace bgfx m_instanceDataOffset = 0; m_instanceDataStride = 0; m_numInstances = 1; - m_startIndirect = 0; - m_numIndirect = UINT16_MAX; - m_num = 1; - m_flags = BGFX_SUBMIT_EYE_FIRST; - m_scissor = UINT16_MAX; + m_startIndirect = 0; + m_numIndirect = UINT16_MAX; + m_num = 1; + m_submitFlags = BGFX_SUBMIT_EYE_FIRST; + m_scissor = UINT16_MAX; m_vertexBuffer.idx = invalidHandle; m_vertexDecl.idx = invalidHandle; m_indexBuffer.idx = invalidHandle; m_instanceDataBuffer.idx = invalidHandle; - m_indirectBuffer.idx = invalidHandle; + m_indirectBuffer.idx = invalidHandle; + m_occlusionQuery.idx = invalidHandle; for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS; ++ii) { Binding& bind = m_bind[ii]; bind.m_idx = invalidHandle; bind.m_type = 0; - bind.m_un.m_draw.m_flags = 0; + bind.m_un.m_draw.m_textureFlags = 0; } } Binding m_bind[BGFX_CONFIG_MAX_TEXTURE_SAMPLERS]; - uint64_t m_flags; + uint64_t m_stateFlags; uint64_t m_stencil; uint32_t m_rgba; uint32_t m_constBegin; @@ -1163,11 +1168,12 @@ namespace bgfx uint16_t m_scissor; uint8_t m_submitFlags; - VertexBufferHandle m_vertexBuffer; - VertexDeclHandle m_vertexDecl; - IndexBufferHandle m_indexBuffer; - VertexBufferHandle m_instanceDataBuffer; + VertexBufferHandle m_vertexBuffer; + VertexDeclHandle m_vertexDecl; + IndexBufferHandle m_indexBuffer; + VertexBufferHandle m_instanceDataBuffer; IndirectBufferHandle m_indirectBuffer; + OcclusionQueryHandle m_occlusionQuery; }; struct RenderCompute @@ -1313,7 +1319,7 @@ namespace bgfx void start() { - m_flags = BGFX_STATE_NONE; + m_stateFlags = BGFX_STATE_NONE; m_uniformBegin = 0; m_uniformEnd = 0; m_draw.clear(); @@ -1361,10 +1367,16 @@ namespace bgfx uint8_t blend = ( (_state&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT)&0xff; // transparency sort order table m_key.m_trans = "\x0\x1\x1\x2\x2\x1\x2\x1\x2\x1\x1\x1\x1\x1\x1\x1\x1\x1\x1"[( (blend)&0xf) + (!!blend)]; - m_draw.m_flags = _state; + m_draw.m_stateFlags = _state; m_draw.m_rgba = _rgba; } + void setCondition(OcclusionQueryHandle _handle, bool _visible) + { + m_draw.m_occlusionQuery = _handle; + BX_UNUSED(_visible); + } + void setStencil(uint32_t _fstencil, uint32_t _bstencil) { m_draw.m_stencil = packStencil(_fstencil, _bstencil); @@ -1473,8 +1485,8 @@ namespace bgfx Binding& bind = m_draw.m_bind[_stage]; bind.m_idx = _handle.idx; bind.m_type = uint8_t(Binding::Texture); - bind.m_un.m_draw.m_flags = (_flags&BGFX_SAMPLER_DEFAULT_FLAGS) - ? BGFX_SAMPLER_DEFAULT_FLAGS + bind.m_un.m_draw.m_textureFlags = (_flags&BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER) + ? BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER : _flags ; @@ -1526,17 +1538,18 @@ namespace bgfx m_discard = false; m_draw.clear(); m_compute.clear(); - m_flags = BGFX_STATE_NONE; + m_stateFlags = BGFX_STATE_NONE; } - uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth); + uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth); - uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) + uint32_t submit(uint8_t _id, ProgramHandle _program, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) { m_draw.m_startIndirect = _start; m_draw.m_numIndirect = _num; m_draw.m_indirectBuffer = _indirectHandle; - return submit(_id, _handle, _depth); + OcclusionQueryHandle handle = BGFX_INVALID_HANDLE; + return submit(_id, _program, handle, _depth); } uint32_t dispatch(uint8_t _id, ProgramHandle _handle, uint16_t _ngx, uint16_t _ngy, uint16_t _ngz, uint8_t _flags); @@ -1674,7 +1687,7 @@ namespace bgfx RenderCompute m_compute; uint32_t m_blitKeys[BGFX_CONFIG_MAX_BLIT_ITEMS+1]; BlitItem m_blitItem[BGFX_CONFIG_MAX_BLIT_ITEMS+1]; - uint64_t m_flags; + uint64_t m_stateFlags; uint32_t m_uniformBegin; uint32_t m_uniformEnd; uint32_t m_uniformMax; @@ -2037,7 +2050,7 @@ namespace bgfx , uint16_t(m_resolution.m_width) , uint16_t(m_resolution.m_height) ); - m_resolution.m_flags |= BGFX_RESET_FORCE; + m_resolution.m_flags |= BGFX_RESET_INTERNAL_FORCE; } } } @@ -3279,6 +3292,18 @@ namespace bgfx } } + BGFX_API_FUNC(OcclusionQueryHandle createOcclusionQuery() ) + { + OcclusionQueryHandle handle = { m_occlusionQueryHandle.alloc() }; + return handle; + } + + BGFX_API_FUNC(void destroyOcclusionQuery(OcclusionQueryHandle _handle) ) + { + BGFX_CHECK_HANDLE("destroyOcclusionQuery", m_occlusionQueryHandle, _handle); + m_occlusionQueryHandle.free(_handle.idx); + } + BGFX_API_FUNC(void saveScreenShot(const char* _filePath) ) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::SaveScreenShot); @@ -3435,6 +3460,11 @@ namespace bgfx m_submit->setState(_state, _rgba); } + BGFX_API_FUNC(void setCondition(OcclusionQueryHandle _handle, bool _visible) ) + { + m_submit->setCondition(_handle, _visible); + } + BGFX_API_FUNC(void setStencil(uint32_t _fstencil, uint32_t _bstencil) ) { m_submit->setStencil(_fstencil, _bstencil); @@ -3565,14 +3595,15 @@ namespace bgfx m_submit->setTexture(_stage, _sampler, textureHandle, _flags); } - BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, int32_t _depth) ) + BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _program, OcclusionQueryHandle _occlusionQuery, int32_t _depth) ) { - BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _handle); + BGFX_CHECK_HANDLE_INVALID_OK("submit", m_programHandle, _program); + BGFX_CHECK_HANDLE_INVALID_OK("submit", m_occlusionQueryHandle, _occlusionQuery); if (BX_ENABLED(BGFX_CONFIG_DEBUG_UNIFORM) ) { m_uniformSet.clear(); } - return m_submit->submit(_id, _handle, _depth); + return m_submit->submit(_id, _program, _occlusionQuery, _depth); } BGFX_API_FUNC(uint32_t submit(uint8_t _id, ProgramHandle _handle, IndirectBufferHandle _indirectHandle, uint16_t _start, uint16_t _num, int32_t _depth) ) @@ -3797,6 +3828,7 @@ namespace bgfx bx::HandleAllocT m_textureHandle; bx::HandleAllocT m_frameBufferHandle; bx::HandleAllocT m_uniformHandle; + bx::HandleAllocT m_occlusionQueryHandle; struct ShaderRef { diff --git a/src/config.h b/src/config.h index a150861a2..1237b93ee 100644 --- a/src/config.h +++ b/src/config.h @@ -269,6 +269,10 @@ # define BGFX_CONFIG_MAX_UNIFORMS 512 #endif // BGFX_CONFIG_MAX_UNIFORMS +#ifndef BGFX_CONFIG_MAX_OCCUSION_QUERIES +# define BGFX_CONFIG_MAX_OCCUSION_QUERIES 256 +#endif // BGFX_CONFIG_MAX_OCCUSION_QUERIES + #ifndef BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE # define BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE (64<<10) #endif // BGFX_CONFIG_MAX_COMMAND_BUFFER_SIZE diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index e2ec495a3..bb60ea84e 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -1158,6 +1158,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); | BGFX_CAPS_DRAW_INDIRECT | BGFX_CAPS_TEXTURE_BLIT | BGFX_CAPS_TEXTURE_READ_BACK + | BGFX_CAPS_OCCLUSION_QUERY ); if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2) @@ -1940,7 +1941,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); setShaderUniform(flags, predefined.m_loc, proj, 4); commitShaderConstants(); - m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL); + m_textures[_blitter.m_texture.idx].commit(0, BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER, NULL); commitTextureStage(); } @@ -1964,6 +1965,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); ovrPreReset(); m_gpuTimer.preReset(); + m_occlusionQuery.preReset(); if (NULL == g_platformData.backBufferDS) { @@ -2008,6 +2010,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); } m_gpuTimer.postReset(); + m_occlusionQuery.postReset(); ovrPostReset(); @@ -2159,7 +2162,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); || m_resolution.m_height != _resolution.m_height || m_resolution.m_flags != flags) { - flags &= ~BGFX_RESET_FORCE; + flags &= ~BGFX_RESET_INTERNAL_FORCE; bool resize = true && !BX_ENABLED(BX_PLATFORM_WINRT) // can't use ResizeBuffers on Windows Phone @@ -2726,6 +2729,12 @@ BX_PRAGMA_DIAGNOSTIC_POP(); return sampler; } + bool isVisible(OcclusionQueryHandle _handle) + { + m_occlusionQuery.resolve(); + return m_occlusion[_handle.idx]; + } + DXGI_FORMAT getBufferFormat() { #if BX_PLATFORM_WINRT @@ -3296,6 +3305,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); ID3D11DeviceContext* m_deviceCtx; ID3D11InfoQueue* m_infoQueue; TimerQueryD3D11 m_gpuTimer; + OcclusionQueryD3D11 m_occlusionQuery; ID3D11RenderTargetView* m_backBufferColor; ID3D11DepthStencilView* m_backBufferDepthStencil; @@ -3324,6 +3334,7 @@ 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; @@ -4149,7 +4160,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { TextureStage& ts = s_renderD3D11->m_textureStage; ts.m_srv[_stage] = m_srv; - uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) + uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ? _flags : m_flags ; @@ -4516,7 +4527,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); Frame& frame = m_frame[m_control.m_read]; uint64_t finish; - HRESULT hr = deviceCtx->GetData(frame.m_end, &finish, sizeof(finish), 0); + HRESULT hr = deviceCtx->GetData(frame.m_end, &finish, sizeof(finish), D3D11_ASYNC_GETDATA_DONOTFLUSH); if (S_OK == hr) { m_control.consume(1); @@ -4543,6 +4554,70 @@ BX_PRAGMA_DIAGNOSTIC_POP(); return false; } + void OcclusionQueryD3D11::postReset() + { + ID3D11Device* device = s_renderD3D11->m_device; + + D3D11_QUERY_DESC desc; + desc.Query = D3D11_QUERY_OCCLUSION; + desc.MiscFlags = 0; + for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii) + { + Query& query = m_query[ii]; + DX_CHECK(device->CreateQuery(&desc, &query.m_ptr) ); + } + } + + void OcclusionQueryD3D11::preReset() + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii) + { + Query& query = m_query[ii]; + DX_RELEASE(query.m_ptr, 0); + } + } + + void OcclusionQueryD3D11::begin(OcclusionQueryHandle _handle) + { + while (0 == m_control.reserve(1) ) + { + resolve(true); + } + + ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; + Query& query = m_query[m_control.m_current]; + deviceCtx->Begin(query.m_ptr); + query.m_handle = _handle; + } + + void OcclusionQueryD3D11::end() + { + ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; + Query& query = m_query[m_control.m_current]; + deviceCtx->End(query.m_ptr); + m_control.commit(1); + } + + void OcclusionQueryD3D11::resolve(bool _wait) + { + ID3D11DeviceContext* deviceCtx = s_renderD3D11->m_deviceCtx; + + while (0 != m_control.available() ) + { + Query& query = m_query[m_control.m_read]; + + uint64_t result = 0; + HRESULT hr = deviceCtx->GetData(query.m_ptr, &result, sizeof(result), _wait ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); + if (S_FALSE == hr) + { + break; + } + + s_renderD3D11->m_occlusion[query.m_handle.idx] = 0 < result; + m_control.consume(1); + } + } + void RendererContextD3D11::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) { PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), L"rendererSubmit"); @@ -4572,7 +4647,7 @@ BX_PRAGMA_DIAGNOSTIC_POP(); RenderDraw currentState; currentState.clear(); - currentState.m_flags = BGFX_STATE_NONE; + currentState.m_stateFlags = BGFX_STATE_NONE; currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); _render->m_hmdInitialized = m_ovr.isInitialized(); @@ -4612,6 +4687,8 @@ BX_PRAGMA_DIAGNOSTIC_POP(); uint32_t statsNumIndices = 0; uint32_t statsKeyType[2] = {}; + m_occlusionQuery.resolve(); + if (0 == (_render->m_debug&BGFX_DEBUG_IFH) ) { // reset the framebuffer to be the backbuffer; depending on the swap effect, @@ -4965,8 +5042,6 @@ BX_PRAGMA_DIAGNOSTIC_POP(); PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), viewNameW); } - wasCompute = false; - programIdx = invalidHandle; m_currentProgram = NULL; @@ -4975,10 +5050,18 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const RenderDraw& draw = renderItem.draw; - const uint64_t newFlags = draw.m_flags; - uint64_t changedFlags = currentState.m_flags ^ draw.m_flags; + 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; changedFlags |= currentState.m_rgba != draw.m_rgba ? BGFX_D3D11_BLEND_STATE_MASK : 0; - currentState.m_flags = newFlags; + currentState.m_stateFlags = newFlags; const uint64_t newStencil = draw.m_stencil; uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil; @@ -4987,12 +5070,14 @@ BX_PRAGMA_DIAGNOSTIC_POP(); if (resetState) { + wasCompute = false; + currentState.clear(); currentState.m_scissor = !draw.m_scissor; changedFlags = BGFX_STATE_MASK; changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK); - currentState.m_flags = newFlags; - currentState.m_stencil = newStencil; + currentState.m_stateFlags = newFlags; + currentState.m_stencil = newStencil; setBlendState(newFlags); setDepthStencilState(newFlags, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) ); @@ -5156,13 +5241,13 @@ BX_PRAGMA_DIAGNOSTIC_POP(); const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; if (current.m_idx != bind.m_idx - || current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags + || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) { if (invalidHandle != bind.m_idx) { TextureD3D11& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette); + texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); } else { @@ -5261,6 +5346,11 @@ BX_PRAGMA_DIAGNOSTIC_POP(); uint32_t numPrimsRendered = 0; uint32_t numDrawIndirect = 0; + if (hasOcclusionQuery) + { + m_occlusionQuery.begin(draw.m_occlusionQuery); + } + if (isValid(draw.m_indirectBuffer) ) { const VertexBufferD3D11& vb = m_vertexBuffers[draw.m_indirectBuffer.idx]; @@ -5369,6 +5459,11 @@ BX_PRAGMA_DIAGNOSTIC_POP(); ); } } + + if (hasOcclusionQuery) + { + m_occlusionQuery.end(); + } } statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted; @@ -5540,6 +5635,9 @@ BX_PRAGMA_DIAGNOSTIC_POP(); tvm.printf(10, pos++, 0x8e, " DVB size: %7d ", _render->m_vboffset); tvm.printf(10, pos++, 0x8e, " DIB size: %7d ", _render->m_iboffset); + pos++; + tvm.printf(10, pos++, 0x8e, " Occlusion queries: %3d ", m_occlusionQuery.m_control.available() ); + pos++; tvm.printf(10, pos++, 0x8e, " State cache: "); tvm.printf(10, pos++, 0x8e, " Blend | DepthS | Input | Raster | Sampler "); diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 958e3d8c8..bdac87f58 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -307,6 +307,29 @@ namespace bgfx { namespace d3d11 bx::RingBufferControl m_control; }; + struct OcclusionQueryD3D11 + { + OcclusionQueryD3D11() + : m_control(BX_COUNTOF(m_query) ) + { + } + + void postReset(); + void preReset(); + void begin(OcclusionQueryHandle _handle); + void end(); + void resolve(bool _wait = false); + + struct Query + { + ID3D11Query* m_ptr; + OcclusionQueryHandle m_handle; + }; + + Query m_query[BGFX_CONFIG_MAX_OCCUSION_QUERIES]; + bx::RingBufferControl m_control; + }; + } /* namespace d3d11 */ } // namespace bgfx #endif // BGFX_RENDERER_D3D11_H_HEADER_GUARD diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index ce3d71bac..be4d3a01e 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -1728,7 +1728,7 @@ data.NumQualityLevels = 0; || m_resolution.m_height != _resolution.m_height || m_resolution.m_flags != flags) { - flags &= ~BGFX_RESET_FORCE; + flags &= ~BGFX_RESET_INTERNAL_FORCE; bool resize = (m_resolution.m_flags&BGFX_RESET_MSAA_MASK) == (_resolution.m_flags&BGFX_RESET_MSAA_MASK); @@ -4349,8 +4349,8 @@ data.NumQualityLevels = 0; RenderDraw currentState; currentState.clear(); - currentState.m_flags = BGFX_STATE_NONE; - currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); + currentState.m_stateFlags = BGFX_STATE_NONE; + currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); _render->m_hmdInitialized = false; @@ -4718,9 +4718,9 @@ data.NumQualityLevels = 0; const RenderDraw& draw = renderItem.draw; - const uint64_t newFlags = draw.m_flags; - uint64_t changedFlags = currentState.m_flags ^ draw.m_flags; - currentState.m_flags = newFlags; + const uint64_t newFlags = draw.m_stateFlags; + uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags; + currentState.m_stateFlags = newFlags; const uint64_t newStencil = draw.m_stencil; uint64_t changedStencil = (currentState.m_stencil ^ draw.m_stencil) & BGFX_STENCIL_FUNC_REF_MASK; @@ -4765,8 +4765,8 @@ data.NumQualityLevels = 0; currentState.m_scissor = !draw.m_scissor; changedFlags = BGFX_STATE_MASK; changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK); - currentState.m_flags = newFlags; - currentState.m_stencil = newStencil; + currentState.m_stateFlags = newFlags; + currentState.m_stencil = newStencil; const uint64_t pt = newFlags&BGFX_STATE_PT_MASK; primIndex = uint8_t(pt>>BGFX_STATE_PT_SHIFT); @@ -4776,7 +4776,7 @@ data.NumQualityLevels = 0; if (isValid(draw.m_vertexBuffer) ) { - const uint64_t state = draw.m_flags; + const uint64_t state = draw.m_stateFlags; bool hasFactor = 0 || f0 == (state & f0) || f1 == (state & f1) @@ -4825,8 +4825,8 @@ data.NumQualityLevels = 0; TextureD3D12& texture = m_textures[bind.m_idx]; texture.setState(m_commandList, D3D12_RESOURCE_STATE_GENERIC_READ); scratchBuffer.allocSrv(srvHandle[stage], texture); - samplerFlags[stage] = (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & bind.m_un.m_draw.m_flags) - ? bind.m_un.m_draw.m_flags + samplerFlags[stage] = (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & bind.m_un.m_draw.m_textureFlags) + ? bind.m_un.m_draw.m_textureFlags : texture.m_flags ) & (BGFX_TEXTURE_SAMPLER_BITS_MASK|BGFX_TEXTURE_BORDER_COLOR_MASK) ; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 63423aa6a..f8e10833f 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -285,6 +285,7 @@ namespace bgfx { namespace d3d9 , m_nvidia(false) , m_instancingSupport(false) , m_timerQuerySupport(false) + , m_occlusionQuerySupport(false) , m_rtMsaa(false) { } @@ -501,6 +502,26 @@ namespace bgfx { namespace d3d9 DX_CHECK(m_device->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&m_deviceEx) ); } + { + IDirect3DQuery9* timerQueryTest[3] = {}; + m_timerQuerySupport = true + && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &timerQueryTest[0]) ) + && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &timerQueryTest[1]) ) + && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &timerQueryTest[2]) ) + ; + DX_RELEASE(timerQueryTest[0], 0); + DX_RELEASE(timerQueryTest[1], 0); + DX_RELEASE(timerQueryTest[2], 0); + } + + { + IDirect3DQuery9* occlusionQueryTest; + m_occlusionQuerySupport = true + && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQueryTest) ) + ; + DX_RELEASE(occlusionQueryTest, 0); + } + DX_CHECK(m_device->GetDeviceCaps(&m_caps) ); // For shit GPUs that can create DX9 device but can't do simple stuff. GTFO! @@ -538,6 +559,7 @@ namespace bgfx { namespace d3d9 | ( (UINT16_MAX < m_caps.MaxVertexIndex) ? BGFX_CAPS_INDEX32 : 0) | ( (m_caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) ? BGFX_CAPS_TEXTURE_BLIT : 0) | BGFX_CAPS_TEXTURE_READ_BACK + | (m_occlusionQuerySupport ? BGFX_CAPS_OCCLUSION_QUERY : 0) ); g_caps.maxTextureSize = uint16_t(bx::uint32_min(m_caps.MaxTextureWidth, m_caps.MaxTextureHeight) ); // g_caps.maxVertexIndex = m_caps.MaxVertexIndex; @@ -694,18 +716,6 @@ namespace bgfx { namespace d3d9 m_fmtDepth = D3DFMT_D24FS8; #endif // BX_PLATFORM_WINDOWS - { - IDirect3DQuery9* timerQueryTest[3] = {}; - m_timerQuerySupport = true - && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPDISJOINT, &timerQueryTest[0]) ) - && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMP, &timerQueryTest[1]) ) - && SUCCEEDED(m_device->CreateQuery(D3DQUERYTYPE_TIMESTAMPFREQ, &timerQueryTest[2]) ) - ; - DX_RELEASE(timerQueryTest[0], 0); - DX_RELEASE(timerQueryTest[1], 0); - DX_RELEASE(timerQueryTest[2], 0); - } - { IDirect3DSwapChain9* swapChain; DX_CHECK(m_device->GetSwapChain(0, &swapChain) ); @@ -1162,7 +1172,7 @@ namespace bgfx { namespace d3d9 uint8_t flags = predefined.m_type; setShaderUniform(flags, predefined.m_loc, proj, 4); - m_textures[_blitter.m_texture.idx].commit(0, BGFX_SAMPLER_DEFAULT_FLAGS, NULL); + m_textures[_blitter.m_texture.idx].commit(0, BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER, NULL); } void blitRender(TextVideoMemBlitter& _blitter, uint32_t _numIndices) BX_OVERRIDE @@ -1223,7 +1233,7 @@ namespace bgfx { namespace d3d9 || m_resolution.m_height != _resolution.m_height || m_resolution.m_flags != flags) { - flags &= ~BGFX_RESET_FORCE; + flags &= ~BGFX_RESET_INTERNAL_FORCE; m_resolution = _resolution; m_resolution.m_flags = flags; @@ -1434,6 +1444,11 @@ namespace bgfx { namespace d3d9 m_gpuTimer.preReset(); } + if (m_occlusionQuerySupport) + { + m_occlusionQuery.preReset(); + } + for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii) { m_indexBuffers[ii].preReset(); @@ -1467,6 +1482,11 @@ namespace bgfx { namespace d3d9 m_gpuTimer.postReset(); } + if (m_occlusionQuerySupport) + { + m_occlusionQuery.postReset(); + } + capturePostReset(); for (uint32_t ii = 0; ii < BX_COUNTOF(m_indexBuffers); ++ii) @@ -1545,6 +1565,12 @@ namespace bgfx { namespace d3d9 } } + bool isVisible(OcclusionQueryHandle _handle) + { + m_occlusionQuery.resolve(); + return m_occlusion[_handle.idx]; + } + void capturePreReset() { if (NULL != m_captureSurface) @@ -1937,10 +1963,11 @@ namespace bgfx { namespace d3d9 IDirect3D9Ex* m_d3d9ex; IDirect3DDevice9Ex* m_deviceEx; - IDirect3D9* m_d3d9; - IDirect3DDevice9* m_device; - IDirect3DQuery9* m_flushQuery; - TimerQueryD3D9 m_gpuTimer; + IDirect3D9* m_d3d9; + IDirect3DDevice9* m_device; + IDirect3DQuery9* m_flushQuery; + TimerQueryD3D9 m_gpuTimer; + OcclusionQueryD3D9 m_occlusionQuery; D3DPOOL m_pool; IDirect3DSwapChain9* m_swapChain; @@ -1969,6 +1996,7 @@ namespace bgfx { namespace d3d9 bool m_nvidia; bool m_instancingSupport; bool m_timerQuerySupport; + bool m_occlusionQuerySupport; D3DFORMAT m_fmtDepth; @@ -1979,6 +2007,7 @@ 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]; @@ -2950,7 +2979,7 @@ namespace bgfx { namespace d3d9 void TextureD3D9::commit(uint8_t _stage, uint32_t _flags, const float _palette[][4]) { - uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) + uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ? _flags : m_flags ; @@ -3361,6 +3390,63 @@ namespace bgfx { namespace d3d9 return false; } + void OcclusionQueryD3D9::postReset() + { + IDirect3DDevice9* device = s_renderD3D9->m_device; + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii) + { + Query& query = m_query[ii]; + DX_CHECK(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &query.m_ptr) ); + } + } + + void OcclusionQueryD3D9::preReset() + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_query); ++ii) + { + Query& query = m_query[ii]; + DX_RELEASE(query.m_ptr, 0); + } + } + + void OcclusionQueryD3D9::begin(OcclusionQueryHandle _handle) + { + while (0 == m_control.reserve(1) ) + { + resolve(true); + } + + Query& query = m_query[m_control.m_current]; + query.m_ptr->Issue(D3DISSUE_BEGIN); + query.m_handle = _handle; + } + + void OcclusionQueryD3D9::end() + { + Query& query = m_query[m_control.m_current]; + query.m_ptr->Issue(D3DISSUE_END); + m_control.commit(1); + } + + void OcclusionQueryD3D9::resolve(bool) + { + while (0 != m_control.available() ) + { + Query& query = m_query[m_control.m_read]; + + uint64_t result; + HRESULT hr = query.m_ptr->GetData(&result, sizeof(result), 0); + if (S_FALSE == hr) + { + break; + } + + s_renderD3D9->m_occlusion[query.m_handle.idx] = 0 < result; + m_control.consume(1); + } + } + void RendererContextD3D9::submit(Frame* _render, ClearQuad& _clearQuad, TextVideoMemBlitter& _textVideoMemBlitter) { IDirect3DDevice9* device = m_device; @@ -3394,8 +3480,8 @@ namespace bgfx { namespace d3d9 RenderDraw currentState; currentState.clear(); - currentState.m_flags = BGFX_STATE_NONE; - currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); + currentState.m_stateFlags = BGFX_STATE_NONE; + currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); ViewState viewState(_render, false); @@ -3445,9 +3531,17 @@ namespace bgfx { namespace d3d9 const RenderDraw& draw = _render->m_renderItem[_render->m_sortValues[item] ].draw; - const uint64_t newFlags = draw.m_flags; - uint64_t changedFlags = currentState.m_flags ^ draw.m_flags; - currentState.m_flags = newFlags; + 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; const uint64_t newStencil = draw.m_stencil; uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil; @@ -3459,8 +3553,8 @@ namespace bgfx { namespace d3d9 currentState.m_scissor = !draw.m_scissor; changedFlags = BGFX_STATE_MASK; changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK); - currentState.m_flags = newFlags; - currentState.m_stencil = newStencil; + currentState.m_stateFlags = newFlags; + currentState.m_stencil = newStencil; PIX_ENDEVENT(); PIX_BEGINEVENT(D3DCOLOR_RGBA(0xff, 0x00, 0x00, 0xff), s_viewNameW[key.m_view]); @@ -3807,12 +3901,12 @@ namespace bgfx { namespace d3d9 const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; if (current.m_idx != bind.m_idx - || current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags + || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) { if (invalidHandle != bind.m_idx) { - m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette); + m_textures[bind.m_idx].commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); } else { @@ -3902,6 +3996,11 @@ namespace bgfx { namespace d3d9 uint32_t numInstances = 0; uint32_t numPrimsRendered = 0; + if (hasOcclusionQuery) + { + m_occlusionQuery.begin(draw.m_occlusionQuery); + } + if (isValid(draw.m_indexBuffer) ) { if (UINT32_MAX == draw.m_numIndices) @@ -3949,6 +4048,11 @@ namespace bgfx { namespace d3d9 ) ); } + if (hasOcclusionQuery) + { + m_occlusionQuery.end(); + } + statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted; statsNumPrimsRendered[primIndex] += numPrimsRendered; statsNumInstances[primIndex] += numInstances; diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index ea649dd8f..2a3706484 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -357,6 +357,7 @@ namespace bgfx { namespace d3d9 IDirect3DVolumeTexture9* m_staging3d; IDirect3DCubeTexture9* m_stagingCube; }; + uint32_t m_flags; uint32_t m_width; uint32_t m_height; @@ -429,6 +430,29 @@ namespace bgfx { namespace d3d9 bx::RingBufferControl m_control; }; + struct OcclusionQueryD3D9 + { + OcclusionQueryD3D9() + : m_control(BX_COUNTOF(m_query) ) + { + } + + void postReset(); + void preReset(); + void begin(OcclusionQueryHandle _handle); + void end(); + void resolve(bool _wait = false); + + struct Query + { + IDirect3DQuery9* m_ptr; + OcclusionQueryHandle m_handle; + }; + + Query m_query[BGFX_CONFIG_MAX_OCCUSION_QUERIES]; + bx::RingBufferControl m_control; + }; + } /* namespace d3d9 */ } // namespace bgfx #endif // BGFX_RENDERER_D3D9_H_HEADER_GUARD diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 0a684f57c..568c3a563 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2350,7 +2350,7 @@ namespace bgfx { namespace gl || m_resolution.m_height != _resolution.m_height || m_resolution.m_flags != flags) { - flags &= ~BGFX_RESET_FORCE; + flags &= ~BGFX_RESET_INTERNAL_FORCE; m_resolution = _resolution; m_resolution.m_flags = flags; @@ -2587,7 +2587,7 @@ namespace bgfx { namespace gl if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL) || BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGLES >= 30) ) { - if (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ) + if (0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ) { const uint32_t index = (_flags & BGFX_TEXTURE_BORDER_COLOR_MASK) >> BGFX_TEXTURE_BORDER_COLOR_SHIFT; @@ -4282,7 +4282,7 @@ namespace bgfx { namespace gl ; } - const uint32_t flags = (0 != (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) ? m_flags : _flags) & BGFX_TEXTURE_SAMPLER_BITS_MASK; + const uint32_t flags = (0 != (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ? m_flags : _flags) & BGFX_TEXTURE_SAMPLER_BITS_MASK; bool hasBorderColor = false; bx::HashMurmur2A murmur; @@ -4361,7 +4361,7 @@ namespace bgfx { namespace gl void TextureGL::commit(uint32_t _stage, uint32_t _flags, const float _palette[][4]) { - const uint32_t flags = 0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) + const uint32_t flags = 0 == (BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags) ? _flags : m_flags ; @@ -5163,8 +5163,8 @@ namespace bgfx { namespace gl RenderDraw currentState; currentState.clear(); - currentState.m_flags = BGFX_STATE_NONE; - currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); + currentState.m_stateFlags = BGFX_STATE_NONE; + currentState.m_stencil = packStencil(BGFX_STENCIL_NONE, BGFX_STENCIL_NONE); _render->m_hmdInitialized = m_ovr.isInitialized(); @@ -5505,9 +5505,9 @@ namespace bgfx { namespace gl const RenderDraw& draw = renderItem.draw; - const uint64_t newFlags = draw.m_flags; - uint64_t changedFlags = currentState.m_flags ^ draw.m_flags; - currentState.m_flags = newFlags; + const uint64_t newFlags = draw.m_stateFlags; + uint64_t changedFlags = currentState.m_stateFlags ^ draw.m_stateFlags; + currentState.m_stateFlags = newFlags; const uint64_t newStencil = draw.m_stencil; uint64_t changedStencil = currentState.m_stencil ^ draw.m_stencil; @@ -5519,8 +5519,8 @@ namespace bgfx { namespace gl currentState.m_scissor = !draw.m_scissor; changedFlags = BGFX_STATE_MASK; changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK); - currentState.m_flags = newFlags; - currentState.m_stencil = newStencil; + currentState.m_stateFlags = newFlags; + currentState.m_stencil = newStencil; } uint16_t scissor = draw.m_scissor; @@ -5830,13 +5830,13 @@ namespace bgfx { namespace gl const Binding& bind = draw.m_bind[stage]; Binding& current = currentState.m_bind[stage]; if (current.m_idx != bind.m_idx - || current.m_un.m_draw.m_flags != bind.m_un.m_draw.m_flags + || current.m_un.m_draw.m_textureFlags != bind.m_un.m_draw.m_textureFlags || programChanged) { if (invalidHandle != bind.m_idx) { TextureGL& texture = m_textures[bind.m_idx]; - texture.commit(stage, bind.m_un.m_draw.m_flags, _render->m_colorPalette); + texture.commit(stage, bind.m_un.m_draw.m_textureFlags, _render->m_colorPalette); } }