diff options
Diffstat (limited to '3rdparty/bgfx/examples/17-drawstress/drawstress.cpp')
-rw-r--r-- | 3rdparty/bgfx/examples/17-drawstress/drawstress.cpp | 316 |
1 files changed, 214 insertions, 102 deletions
diff --git a/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp b/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp index 18a7a8fee1a..d84b1502290 100644 --- a/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp +++ b/3rdparty/bgfx/examples/17-drawstress/drawstress.cpp @@ -7,6 +7,8 @@ #include "bgfx_utils.h" #include <bx/uint32_t.h> +#include <bx/thread.h> +#include <bx/os.h> #include "imgui/imgui.h" #include <bgfx/embedded_shader.h> @@ -15,6 +17,9 @@ #include "vs_drawstress.bin.h" #include "fs_drawstress.bin.h" +namespace +{ + static const bgfx::EmbeddedShader s_embeddedShaders[] = { BGFX_EMBEDDED_SHADER(vs_drawstress), @@ -72,23 +77,41 @@ static const uint16_t s_cubeIndices[36] = 6, 3, 7, }; -#if BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_NACL +static const float s_mod[6][3] = +{ + { 1.0f, 1.0f, 1.0f }, + { 1.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f }, + { 1.0f, 1.0f, 0.0f }, + { 0.0f, 1.0f, 1.0f }, +}; + +#if BX_PLATFORM_EMSCRIPTEN static const int64_t highwm = 1000000/35; static const int64_t lowwm = 1000000/27; #else static const int64_t highwm = 1000000/65; static const int64_t lowwm = 1000000/57; -#endif // BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_NACL +#endif // BX_PLATFORM_EMSCRIPTEN + +int32_t threadFunc(bx::Thread* _thread, void* _userData); class ExampleDrawStress : public entry::AppI { - void init(int _argc, char** _argv) BX_OVERRIDE +public: + ExampleDrawStress(const char* _name, const char* _description) + : entry::AppI(_name, _description) + { + } + + void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override { Args args(_argc, _argv); - m_width = 1280; - m_height = 720; - m_debug = BGFX_DEBUG_TEXT; + m_width = _width; + m_height = _height; + m_debug = BGFX_DEBUG_NONE; m_reset = BGFX_RESET_NONE; m_autoAdjust = true; @@ -114,11 +137,11 @@ class ExampleDrawStress : public entry::AppI // Set view 0 clear state. bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH - , 0x303030ff - , 1.0f - , 0 - ); + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); // Create vertex stream declaration. PosColorVertex::init(); @@ -127,31 +150,45 @@ class ExampleDrawStress : public entry::AppI // Create program from shaders. m_program = bgfx::createProgram( - bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress") - , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress") - , true /* destroy shaders when program is destroyed */ - ); + bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_drawstress") + , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_drawstress") + , true /* destroy shaders when program is destroyed */ + ); // Create static vertex buffer. m_vbh = bgfx::createVertexBuffer( - bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ) - , PosColorVertex::ms_decl - ); + bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ) + , PosColorVertex::ms_decl + ); // Create static index buffer. m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) ); // Imgui. imguiCreate(); + + m_maxThreads = bx::min<int32_t>(caps->limits.maxEncoders, BX_COUNTOF(m_thread) ); + m_numThreads = (m_maxThreads+1)/2; + + for (int32_t ii = 0; ii < m_maxThreads; ++ii) + { + m_thread[ii].init(threadFunc, this); + } } - int shutdown() BX_OVERRIDE + int shutdown() override { + for (int32_t ii = 0; ii < m_maxThreads; ++ii) + { + m_thread[ii].push(reinterpret_cast<void*>(UINTPTR_MAX) ); + m_thread[ii].shutdown(); + } + // Cleanup. imguiDestroy(); - bgfx::destroyIndexBuffer(m_ibh); - bgfx::destroyVertexBuffer(m_vbh); - bgfx::destroyProgram(m_program); + bgfx::destroy(m_ibh); + bgfx::destroy(m_vbh); + bgfx::destroy(m_program); // Shutdown bgfx. bgfx::shutdown(); @@ -159,7 +196,94 @@ class ExampleDrawStress : public entry::AppI return 0; } - bool update() BX_OVERRIDE + int32_t thread(bx::Thread* _thread) + { + for (;;) + { + union + { + void* ptr; + uintptr_t id; + + } cast; + + cast.ptr = _thread->pop(); + if (UINTPTR_MAX == cast.id) + { + break; + } + + const uint32_t numThreads = uint32_t(cast.id); + const uint32_t idx = uint32_t(_thread - m_thread); + const uint32_t num = uint32_t(m_dim)/numThreads; + const uint32_t rem = idx == numThreads-1 ? uint32_t(m_dim)%numThreads : 0; + const uint32_t xx = idx*num; + submit(idx+1, xx, num + rem); + } + + return bx::kExitSuccess; + } + + void submit(uint32_t _tid, uint32_t _xstart, uint32_t _num) + { + bgfx::Encoder* encoder = bgfx::begin(); + if (0 != _tid) + { + m_sync.post(); + } + + if (NULL != encoder) + { + const int64_t now = bx::getHPCounter(); + const double freq = double(bx::getHPFrequency() ); + float time = (float)( (now-m_timeOffset)/freq); + + const float* mod = s_mod[_tid%BX_COUNTOF(s_mod)]; + + float mtxS[16]; + const float scale = 0 == m_transform ? 0.25f : 0.0f; + bx::mtxScale(mtxS, scale, scale, scale); + + const float step = 0.6f; + float pos[3]; + pos[0] = -step*m_dim / 2.0f; + pos[1] = -step*m_dim / 2.0f; + pos[2] = -15.0; + + for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz) + { + for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy) + { + for (uint32_t xx = _xstart, xend = _xstart+_num; xx < xend; ++xx) + { + float mtxR[16]; + bx::mtxRotateXYZ(mtxR + , (time + xx*0.21f)*mod[0] + , (time + yy*0.37f)*mod[1] + , (time + zz*0.13f)*mod[2] + ); + + float mtx[16]; + bx::mtxMul(mtx, mtxS, mtxR); + + mtx[12] = pos[0] + float(xx)*step; + mtx[13] = pos[1] + float(yy)*step; + mtx[14] = pos[2] + float(zz)*step; + + encoder->setTransform(mtx); + encoder->setVertexBuffer(0, m_vbh); + encoder->setIndexBuffer(m_ibh); + encoder->setState(BGFX_STATE_DEFAULT); + encoder->submit(0, m_program); + } + } + } + + bgfx::end(encoder); + } + } + + bool update() override { if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) ) { @@ -197,53 +321,59 @@ class ExampleDrawStress : public entry::AppI ++m_numFrames; } - float time = (float)( (now-m_timeOffset)/freq); - imguiBeginFrame(m_mouseState.m_mx - , m_mouseState.m_my - , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) - | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) - | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0) - , m_mouseState.m_mz - , uint16_t(m_width) - , uint16_t(m_height) - ); - - imguiBeginScrollArea("Settings", m_width - m_width / 4 - 10, 10, m_width / 4, m_height / 2, &m_scrollArea); - imguiSeparatorLine(); - - m_transform = imguiChoose(m_transform - , "Rotate" - , "No fragments" - ); - imguiSeparatorLine(); - - if (imguiCheck("Auto adjust", m_autoAdjust) ) - { - m_autoAdjust ^= true; - } + , m_mouseState.m_my + , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0) + , m_mouseState.m_mz + , uint16_t(m_width) + , uint16_t(m_height) + ); + + showExampleDialog(this); - imguiSlider("Dim", m_dim, 5, m_maxDim); - imguiLabel("Draw calls: %d", m_dim*m_dim*m_dim); - imguiLabel("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f); + ImGui::SetNextWindowPos(ImVec2((float)m_width - (float)m_width / 4.0f - 10.0f, 10.0f) ); + ImGui::SetNextWindowSize(ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) ); + ImGui::Begin("Settings" + , NULL + , ImVec2((float)m_width / 4.0f, (float)m_height / 2.0f) + , ImGuiWindowFlags_AlwaysAutoResize + ); + + ImGui::RadioButton("Rotate",&m_transform,0); + ImGui::RadioButton("No fragments",&m_transform,1); + ImGui::Separator(); + + ImGui::Checkbox("Auto adjust", &m_autoAdjust); + + ImGui::SliderInt("Num threads", &m_numThreads, 1, m_maxThreads); + const uint32_t numThreads = m_numThreads; - imguiSeparatorLine(); + ImGui::SliderInt("Dim", &m_dim, 5, m_maxDim); + ImGui::Text("Draw calls: %d", m_dim*m_dim*m_dim); + ImGui::Text("Avg Delta Time (1 second) [ms]: %0.4f", m_deltaTimeAvgNs/1000.0f); + + ImGui::Separator(); const bgfx::Stats* stats = bgfx::getStats(); - imguiLabel("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq); - imguiLabel("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq); - imguiLabel("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs); - imguiLabel("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs); + ImGui::Text("GPU %0.6f [ms]", double(stats->gpuTimeEnd - stats->gpuTimeBegin)*1000.0/stats->gpuTimerFreq); + ImGui::Text("CPU %0.6f [ms]", double(stats->cpuTimeEnd - stats->cpuTimeBegin)*1000.0/stats->cpuTimerFreq); + ImGui::Text("Waiting for render thread %0.6f [ms]", double(stats->waitRender) * toMs); + ImGui::Text("Waiting for submit thread %0.6f [ms]", double(stats->waitSubmit) * toMs); + + ImGui::End(); - imguiEndScrollArea(); imguiEndFrame(); float at[3] = { 0.0f, 0.0f, 0.0f }; float eye[3] = { 0.0f, 0.0f, -35.0f }; float view[16]; - float proj[16]; bx::mtxLookAt(view, eye, at); - bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f); + + const bgfx::Caps* caps = bgfx::getCaps(); + float proj[16]; + bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth); // Set view and projection matrix for view 0. bgfx::setViewTransform(0, view, proj); @@ -255,53 +385,22 @@ class ExampleDrawStress : public entry::AppI // if no other draw calls are submitted to view 0. bgfx::touch(0); - // Use debug font to print information about this example. - bgfx::dbgTextClear(); - bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/17-drawstress"); - bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Draw stress, maximizing number of draw calls."); - bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: %7.3f[ms]", double(frameTime)*toMs); - - float mtxS[16]; - const float scale = 0 == m_transform ? 0.25f : 0.0f; - bx::mtxScale(mtxS, scale, scale, scale); - - const float step = 0.6f; - float pos[3]; - pos[0] = -step*m_dim / 2.0f; - pos[1] = -step*m_dim / 2.0f; - pos[2] = -15.0; - - for (uint32_t zz = 0; zz < uint32_t(m_dim); ++zz) + if (1 < numThreads) { - for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy) + for (uint32_t ii = 0; ii < numThreads; ++ii) { - for (uint32_t xx = 0; xx < uint32_t(m_dim); ++xx) - { - float mtxR[16]; - bx::mtxRotateXYZ(mtxR, time + xx*0.21f, time + yy*0.37f, time + yy*0.13f); - - float mtx[16]; - bx::mtxMul(mtx, mtxS, mtxR); - - mtx[12] = pos[0] + float(xx)*step; - mtx[13] = pos[1] + float(yy)*step; - mtx[14] = pos[2] + float(zz)*step; - - // Set model matrix for rendering. - bgfx::setTransform(mtx); - - // Set vertex and index buffer. - bgfx::setVertexBuffer(m_vbh); - bgfx::setIndexBuffer(m_ibh); - - // Set render states. - bgfx::setState(BGFX_STATE_DEFAULT); + m_thread[ii].push(reinterpret_cast<void*>(uintptr_t(numThreads) ) ); + } - // Submit primitive for rendering to view 0. - bgfx::submit(0, m_program); - } + for (uint32_t ii = 0; ii < numThreads; ++ii) + { + m_sync.wait(); } } + else + { + submit(0, 0, uint32_t(m_dim) ); + } // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. @@ -324,7 +423,9 @@ class ExampleDrawStress : public entry::AppI int32_t m_scrollArea; int32_t m_dim; int32_t m_maxDim; - uint32_t m_transform; + int32_t m_transform; + int32_t m_numThreads; + int32_t m_maxThreads; int64_t m_timeOffset; @@ -332,9 +433,20 @@ class ExampleDrawStress : public entry::AppI int64_t m_deltaTimeAvgNs; int64_t m_numFrames; + bx::Thread m_thread[5]; + bx::Semaphore m_sync; + bgfx::ProgramHandle m_program; bgfx::VertexBufferHandle m_vbh; bgfx::IndexBufferHandle m_ibh; }; -ENTRY_IMPLEMENT_MAIN(ExampleDrawStress); +int32_t threadFunc(bx::Thread* _thread, void* _userData) +{ + ExampleDrawStress* self = static_cast<ExampleDrawStress*>(_userData); + return self->thread(_thread); +} + +} // namespace + +ENTRY_IMPLEMENT_MAIN(ExampleDrawStress, "17-drawstress", "Draw stress, maximizing number of draw calls."); |