From 8107522629bcb14a9b5558b7ecda5f9010c427ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Fri, 21 Aug 2015 20:08:03 -0700 Subject: [PATCH] Refactored a few examples to work with Emscripten. --- examples/01-cubes/cubes.cpp | 272 +++++++------ examples/02-metaballs/metaballs.cpp | 563 ++++++++++++++------------ examples/17-drawstress/drawstress.cpp | 482 +++++++++++----------- examples/common/bgfx_utils.cpp | 2 +- examples/common/entry/entry.cpp | 26 ++ examples/common/entry/entry.h | 24 +- 6 files changed, 738 insertions(+), 631 deletions(-) diff --git a/examples/01-cubes/cubes.cpp b/examples/01-cubes/cubes.cpp index 62ab6b9a4..d3679d1ea 100644 --- a/examples/01-cubes/cubes.cpp +++ b/examples/01-cubes/cubes.cpp @@ -55,141 +55,165 @@ static const uint16_t s_cubeIndices[36] = 6, 3, 7, }; -int _main_(int /*_argc*/, char** /*_argv*/) +class Cubes : public entry::AppI { - uint32_t width = 1280; - uint32_t height = 720; - uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_VSYNC; - - bgfx::init(); - bgfx::reset(width, height, reset); - - // Enable debug text. - bgfx::setDebug(debug); - - // Set view 0 clear state. - bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH - , 0x303030ff - , 1.0f - , 0 - ); - - // Create vertex stream declaration. - PosColorVertex::init(); - - // Create static vertex buffer. - bgfx::VertexBufferHandle 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. - bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer( - // Static data can be passed with bgfx::makeRef - bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) - ); - - // Create program from shaders. - bgfx::ProgramHandle program = loadProgram("vs_cubes", "fs_cubes"); - - int64_t timeOffset = bx::getHPCounter(); - - while (!entry::processEvents(width, height, debug, reset) ) + void init(int /*_argc*/, char** /*_argv*/) BX_OVERRIDE { - 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; + m_width = 1280; + m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_VSYNC; - float time = (float)( (now-timeOffset)/double(bx::getHPFrequency() ) ); + bgfx::init(); + bgfx::reset(m_width, m_height, m_reset); - // Use debug font to print information about this example. - bgfx::dbgTextClear(); - bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/01-cube"); - bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering simple static mesh."); - bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); + // Enable debug text. + bgfx::setDebug(m_debug); - float at[3] = { 0.0f, 0.0f, 0.0f }; - float eye[3] = { 0.0f, 0.0f, -35.0f }; + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); - // Set view and projection matrix for view 0. - const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) - { - float view[16]; - bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); + // Create vertex stream declaration. + PosColorVertex::init(); - float proj[16]; - bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); + // 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 + ); - bgfx::setViewTransform(0, view, proj); + // Create static index buffer. + m_ibh = bgfx::createIndexBuffer( + // Static data can be passed with bgfx::makeRef + bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) + ); - // Set view 0 default viewport. - // - // Use HMD's width/height since HMD's internal frame buffer size - // might be much larger than window size. - bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); - } - else - { - float view[16]; - bx::mtxLookAt(view, eye, at); + // Create program from shaders. + m_program = loadProgram("vs_cubes", "fs_cubes"); - float proj[16]; - bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); - bgfx::setViewTransform(0, view, proj); - - // Set view 0 default viewport. - bgfx::setViewRect(0, 0, 0, width, height); - } - - // This dummy draw call is here to make sure that view 0 is cleared - // if no other draw calls are submitted to view 0. - bgfx::touch(0); - - // Submit 11x11 cubes. - for (uint32_t yy = 0; yy < 11; ++yy) - { - for (uint32_t xx = 0; xx < 11; ++xx) - { - float mtx[16]; - bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f); - mtx[12] = -15.0f + float(xx)*3.0f; - mtx[13] = -15.0f + float(yy)*3.0f; - mtx[14] = 0.0f; - - // Set model matrix for rendering. - bgfx::setTransform(mtx); - - // Set vertex and index buffer. - bgfx::setVertexBuffer(vbh); - bgfx::setIndexBuffer(ibh); - - // Set render states. - bgfx::setState(BGFX_STATE_DEFAULT); - - // Submit primitive for rendering to view 0. - bgfx::submit(0, program); - } - } - - // Advance to next frame. Rendering thread will be kicked to - // process submitted rendering primitives. - bgfx::frame(); + m_timeOffset = bx::getHPCounter(); } - // Cleanup. - bgfx::destroyIndexBuffer(ibh); - bgfx::destroyVertexBuffer(vbh); - bgfx::destroyProgram(program); + virtual int shutdown() BX_OVERRIDE + { + // Cleanup. + bgfx::destroyIndexBuffer(m_ibh); + bgfx::destroyVertexBuffer(m_vbh); + bgfx::destroyProgram(m_program); - // Shutdown bgfx. - bgfx::shutdown(); + // Shutdown bgfx. + bgfx::shutdown(); - return 0; -} + return 0; + } + + bool update() BX_OVERRIDE + { + if (!entry::processEvents(m_width, m_height, 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; + + float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) ); + + // Use debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/01-cube"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering simple static mesh."); + bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); + + float at[3] = { 0.0f, 0.0f, 0.0f }; + float eye[3] = { 0.0f, 0.0f, -35.0f }; + + // Set view and projection matrix for view 0. + const bgfx::HMD* hmd = bgfx::getHMD(); + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) + { + float view[16]; + bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); + + float proj[16]; + bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); + + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + // + // Use HMD's width/height since HMD's internal frame buffer size + // might be much larger than window size. + bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); + } + else + { + float view[16]; + bx::mtxLookAt(view, eye, at); + + float proj[16]; + bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f); + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, m_width, m_height); + } + + // This dummy draw call is here to make sure that view 0 is cleared + // if no other draw calls are submitted to view 0. + bgfx::touch(0); + + // Submit 11x11 cubes. + for (uint32_t yy = 0; yy < 11; ++yy) + { + for (uint32_t xx = 0; xx < 11; ++xx) + { + float mtx[16]; + bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f); + mtx[12] = -15.0f + float(xx)*3.0f; + mtx[13] = -15.0f + float(yy)*3.0f; + mtx[14] = 0.0f; + + // 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); + + // Submit primitive for rendering to view 0. + bgfx::submit(0, 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_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; + bgfx::VertexBufferHandle m_vbh; + bgfx::IndexBufferHandle m_ibh; + bgfx::ProgramHandle m_program; + int64_t m_timeOffset; +}; + +ENTRY_IMPLEMENT_MAIN(Cubes); diff --git a/examples/02-metaballs/metaballs.cpp b/examples/02-metaballs/metaballs.cpp index 59c8bf1af..b7dc4654d 100644 --- a/examples/02-metaballs/metaballs.cpp +++ b/examples/02-metaballs/metaballs.cpp @@ -460,291 +460,318 @@ uint32_t triangulate(uint8_t* _result, uint32_t _stride, const float* __restrict return num; } -int _main_(int /*_argc*/, char** /*_argv*/) -{ - uint32_t width = 1280; - uint32_t height = 720; - uint32_t debug = BGFX_DEBUG_TEXT; - uint32_t reset = BGFX_RESET_VSYNC; - - bgfx::init(); - bgfx::reset(width, height, reset); - - // Enable debug text. - bgfx::setDebug(debug); - - // Set view 0 clear state. - bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH - , 0x303030ff - , 1.0f - , 0 - ); - - // Create vertex stream declaration. - PosNormalColorVertex::init(); - - const bgfx::Memory* vs_metaballs; - const bgfx::Memory* fs_metaballs; - - switch (bgfx::getRendererType() ) - { - case bgfx::RendererType::Direct3D9: - vs_metaballs = bgfx::makeRef(vs_metaballs_dx9, sizeof(vs_metaballs_dx9) ); - fs_metaballs = bgfx::makeRef(fs_metaballs_dx9, sizeof(fs_metaballs_dx9) ); - break; - - case bgfx::RendererType::Direct3D11: - case bgfx::RendererType::Direct3D12: - vs_metaballs = bgfx::makeRef(vs_metaballs_dx11, sizeof(vs_metaballs_dx11) ); - fs_metaballs = bgfx::makeRef(fs_metaballs_dx11, sizeof(fs_metaballs_dx11) ); - break; - - default: - vs_metaballs = bgfx::makeRef(vs_metaballs_glsl, sizeof(vs_metaballs_glsl) ); - fs_metaballs = bgfx::makeRef(fs_metaballs_glsl, sizeof(fs_metaballs_glsl) ); - break; - } - - bgfx::ShaderHandle vsh = bgfx::createShader(vs_metaballs); - bgfx::ShaderHandle fsh = bgfx::createShader(fs_metaballs); - - // Create program from shaders. - bgfx::ProgramHandle program = bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */); - #define DIMS 32 - Grid* grid = new Grid[DIMS*DIMS*DIMS]; - const uint32_t ypitch = DIMS; - const uint32_t zpitch = DIMS*DIMS; - const float invdim = 1.0f/float(DIMS-1); - - int64_t timeOffset = bx::getHPCounter(); - - while (!entry::processEvents(width, height, debug, reset) ) +class Metaballs : public entry::AppI +{ + void init(int /*_argc*/, char** /*_argv*/) BX_OVERRIDE { - // Set view 0 default viewport. - bgfx::setViewRect(0, 0, 0, width, height); + m_width = 1280; + m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_VSYNC; - // This dummy draw call is here to make sure that view 0 is cleared - // if no other draw calls are submitted to view 0. - bgfx::touch(0); + bgfx::init(); + bgfx::reset(m_width, m_height, 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; - float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); + // Enable debug text. + bgfx::setDebug(m_debug); - // Use debug font to print information about this example. - bgfx::dbgTextClear(); - bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/02-metaball"); - bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering with transient buffers and embedding shaders."); + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x303030ff + , 1.0f + , 0 + ); - float at[3] = { 0.0f, 0.0f, 0.0f }; - float eye[3] = { 0.0f, 0.0f, -50.0f }; + // Create vertex stream declaration. + PosNormalColorVertex::init(); - // Set view and projection matrix for view 0. - const bgfx::HMD* hmd = bgfx::getHMD(); - if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) + const bgfx::Memory* vs_metaballs; + const bgfx::Memory* fs_metaballs; + + switch (bgfx::getRendererType() ) { - float view[16]; - bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); + case bgfx::RendererType::Direct3D9: + vs_metaballs = bgfx::makeRef(vs_metaballs_dx9, sizeof(vs_metaballs_dx9) ); + fs_metaballs = bgfx::makeRef(fs_metaballs_dx9, sizeof(fs_metaballs_dx9) ); + break; - float proj[16]; - bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); + case bgfx::RendererType::Direct3D11: + case bgfx::RendererType::Direct3D12: + vs_metaballs = bgfx::makeRef(vs_metaballs_dx11, sizeof(vs_metaballs_dx11) ); + fs_metaballs = bgfx::makeRef(fs_metaballs_dx11, sizeof(fs_metaballs_dx11) ); + break; - bgfx::setViewTransform(0, view, proj); - - // Set view 0 default viewport. - // - // Use HMD's width/height since HMD's internal frame buffer size - // might be much larger than window size. - bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); - } - else - { - float view[16]; - bx::mtxLookAt(view, eye, at); - - float proj[16]; - bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); - bgfx::setViewTransform(0, view, proj); - - // Set view 0 default viewport. - bgfx::setViewRect(0, 0, 0, width, height); + default: + vs_metaballs = bgfx::makeRef(vs_metaballs_glsl, sizeof(vs_metaballs_glsl) ); + fs_metaballs = bgfx::makeRef(fs_metaballs_glsl, sizeof(fs_metaballs_glsl) ); + break; } - // Stats. - uint32_t numVertices = 0; - int64_t profUpdate = 0; - int64_t profNormal = 0; - int64_t profTriangulate = 0; + bgfx::ShaderHandle vsh = bgfx::createShader(vs_metaballs); + bgfx::ShaderHandle fsh = bgfx::createShader(fs_metaballs); - // Allocate 32K vertices in transient vertex buffer. - uint32_t maxVertices = (32<<10); - bgfx::TransientVertexBuffer tvb; - bgfx::allocTransientVertexBuffer(&tvb, maxVertices, PosNormalColorVertex::ms_decl); + // Create program from shaders. + m_program = bgfx::createProgram(vsh, fsh, true /* destroy shaders when program is destroyed */); - const uint32_t numSpheres = 16; - float sphere[numSpheres][4]; - for (uint32_t ii = 0; ii < numSpheres; ++ii) - { - sphere[ii][0] = sinf(time*(ii*0.21f)+ii*0.37f) * (DIMS * 0.5f - 8.0f); - sphere[ii][1] = sinf(time*(ii*0.37f)+ii*0.67f) * (DIMS * 0.5f - 8.0f); - sphere[ii][2] = cosf(time*(ii*0.11f)+ii*0.13f) * (DIMS * 0.5f - 8.0f); - sphere[ii][3] = 1.0f/(2.0f + (sinf(time*(ii*0.13f) )*0.5f+0.5f)*2.0f); - } - - profUpdate = bx::getHPCounter(); - - for (uint32_t zz = 0; zz < DIMS; ++zz) - { - for (uint32_t yy = 0; yy < DIMS; ++yy) - { - uint32_t offset = (zz*DIMS+yy)*DIMS; - - for (uint32_t xx = 0; xx < DIMS; ++xx) - { - uint32_t xoffset = offset + xx; - - float dist = 0.0f; - float prod = 1.0f; - for (uint32_t ii = 0; ii < numSpheres; ++ii) - { - const float* pos = sphere[ii]; - float dx = pos[0] - (-DIMS*0.5f + float(xx) ); - float dy = pos[1] - (-DIMS*0.5f + float(yy) ); - float dz = pos[2] - (-DIMS*0.5f + float(zz) ); - float invr = pos[3]; - float dot = dx*dx + dy*dy + dz*dz; - dot *= invr*invr; - - dist *= dot; - dist += prod; - prod *= dot; - } - - grid[xoffset].m_val = dist / prod - 1.0f; - } - } - } - - profUpdate = bx::getHPCounter() - profUpdate; - - profNormal = bx::getHPCounter(); - - for (uint32_t zz = 1; zz < DIMS-1; ++zz) - { - for (uint32_t yy = 1; yy < DIMS-1; ++yy) - { - uint32_t offset = (zz*DIMS+yy)*DIMS; - - for (uint32_t xx = 1; xx < DIMS-1; ++xx) - { - uint32_t xoffset = offset + xx; - - float normal[3] = - { - grid[xoffset-1 ].m_val - grid[xoffset+1 ].m_val, - grid[xoffset-ypitch].m_val - grid[xoffset+ypitch].m_val, - grid[xoffset-zpitch].m_val - grid[xoffset+zpitch].m_val, - }; - - bx::vec3Norm(grid[xoffset].m_normal, normal); - } - } - } - - profNormal = bx::getHPCounter() - profNormal; - - profTriangulate = bx::getHPCounter(); - - PosNormalColorVertex* vertex = (PosNormalColorVertex*)tvb.data; - - for (uint32_t zz = 0; zz < DIMS-1 && numVertices+12 < maxVertices; ++zz) - { - float rgb[6]; - rgb[2] = zz*invdim; - rgb[5] = (zz+1)*invdim; - - for (uint32_t yy = 0; yy < DIMS-1 && numVertices+12 < maxVertices; ++yy) - { - uint32_t offset = (zz*DIMS+yy)*DIMS; - - rgb[1] = yy*invdim; - rgb[4] = (yy+1)*invdim; - - for (uint32_t xx = 0; xx < DIMS-1 && numVertices+12 < maxVertices; ++xx) - { - uint32_t xoffset = offset + xx; - - rgb[0] = xx*invdim; - rgb[3] = (xx+1)*invdim; - - float pos[3] = - { - -DIMS*0.5f + float(xx), - -DIMS*0.5f + float(yy), - -DIMS*0.5f + float(zz) - }; - - const Grid* val[8] = { - &grid[xoffset+zpitch+ypitch ], - &grid[xoffset+zpitch+ypitch+1], - &grid[xoffset+ypitch+1 ], - &grid[xoffset+ypitch ], - &grid[xoffset+zpitch ], - &grid[xoffset+zpitch+1 ], - &grid[xoffset+1 ], - &grid[xoffset ], - }; - - uint32_t num = triangulate( (uint8_t*)vertex, PosNormalColorVertex::ms_decl.getStride(), rgb, pos, val, 0.5f); - vertex += num; - numVertices += num; - } - } - } - - profTriangulate = bx::getHPCounter() - profTriangulate; - - float mtx[16]; - bx::mtxRotateXY(mtx, time*0.67f, time); - - // Set model matrix for rendering. - bgfx::setTransform(mtx); - - // Set vertex and index buffer. - bgfx::setVertexBuffer(&tvb, 0, numVertices); - - // Set render states. - bgfx::setState(BGFX_STATE_DEFAULT); - - // Submit primitive for rendering to view 0. - bgfx::submit(0, program); - - // Display stats. - bgfx::dbgTextPrintf(1, 4, 0x0f, "Num vertices: %5d (%6.4f%%)", numVertices, float(numVertices)/maxVertices * 100); - bgfx::dbgTextPrintf(1, 5, 0x0f, " Update: % 7.3f[ms]", double(profUpdate)*toMs); - bgfx::dbgTextPrintf(1, 6, 0x0f, "Calc normals: % 7.3f[ms]", double(profNormal)*toMs); - bgfx::dbgTextPrintf(1, 7, 0x0f, " Triangulate: % 7.3f[ms]", double(profTriangulate)*toMs); - bgfx::dbgTextPrintf(1, 8, 0x0f, " Frame: % 7.3f[ms]", double(frameTime)*toMs); - - // Advance to next frame. Rendering thread will be kicked to - // process submitted rendering primitives. - bgfx::frame(); + m_grid = new Grid[DIMS*DIMS*DIMS]; + m_timeOffset = bx::getHPCounter(); } - delete [] grid; + int shutdown() BX_OVERRIDE + { + delete [] m_grid; - // Cleanup. - bgfx::destroyProgram(program); + // Cleanup. + bgfx::destroyProgram(m_program); - // Shutdown bgfx. - bgfx::shutdown(); + // Shutdown bgfx. + bgfx::shutdown(); - return 0; -} + return 0; + } + + bool update() BX_OVERRIDE + { + const uint32_t ypitch = DIMS; + const uint32_t zpitch = DIMS*DIMS; + const float invdim = 1.0f/float(DIMS-1); + + if (!entry::processEvents(m_width, m_height, m_debug, m_reset) ) + { + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, m_width, m_height); + + // This dummy draw call is here to make sure that view 0 is cleared + // if no other draw calls are submitted to view 0. + bgfx::touch(0); + + 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; + float time = (float)( (now - m_timeOffset)/double(bx::getHPFrequency() ) ); + + // Use debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/02-metaball"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering with transient buffers and embedding shaders."); + + float at[3] = { 0.0f, 0.0f, 0.0f }; + float eye[3] = { 0.0f, 0.0f, -50.0f }; + + // Set view and projection matrix for view 0. + const bgfx::HMD* hmd = bgfx::getHMD(); + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) + { + float view[16]; + bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); + + float proj[16]; + bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f); + + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + // + // Use HMD's width/height since HMD's internal frame buffer size + // might be much larger than window size. + bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); + } + else + { + float view[16]; + bx::mtxLookAt(view, eye, at); + + float proj[16]; + bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f); + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, m_width, m_height); + } + + // Stats. + uint32_t numVertices = 0; + int64_t profUpdate = 0; + int64_t profNormal = 0; + int64_t profTriangulate = 0; + + // Allocate 32K vertices in transient vertex buffer. + uint32_t maxVertices = (32<<10); + bgfx::TransientVertexBuffer tvb; + bgfx::allocTransientVertexBuffer(&tvb, maxVertices, PosNormalColorVertex::ms_decl); + + const uint32_t numSpheres = 16; + float sphere[numSpheres][4]; + for (uint32_t ii = 0; ii < numSpheres; ++ii) + { + sphere[ii][0] = sinf(time*(ii*0.21f)+ii*0.37f) * (DIMS * 0.5f - 8.0f); + sphere[ii][1] = sinf(time*(ii*0.37f)+ii*0.67f) * (DIMS * 0.5f - 8.0f); + sphere[ii][2] = cosf(time*(ii*0.11f)+ii*0.13f) * (DIMS * 0.5f - 8.0f); + sphere[ii][3] = 1.0f/(2.0f + (sinf(time*(ii*0.13f) )*0.5f+0.5f)*2.0f); + } + + profUpdate = bx::getHPCounter(); + + for (uint32_t zz = 0; zz < DIMS; ++zz) + { + for (uint32_t yy = 0; yy < DIMS; ++yy) + { + uint32_t offset = (zz*DIMS+yy)*DIMS; + + for (uint32_t xx = 0; xx < DIMS; ++xx) + { + uint32_t xoffset = offset + xx; + + float dist = 0.0f; + float prod = 1.0f; + for (uint32_t ii = 0; ii < numSpheres; ++ii) + { + const float* pos = sphere[ii]; + float dx = pos[0] - (-DIMS*0.5f + float(xx) ); + float dy = pos[1] - (-DIMS*0.5f + float(yy) ); + float dz = pos[2] - (-DIMS*0.5f + float(zz) ); + float invr = pos[3]; + float dot = dx*dx + dy*dy + dz*dz; + dot *= invr*invr; + + dist *= dot; + dist += prod; + prod *= dot; + } + + m_grid[xoffset].m_val = dist / prod - 1.0f; + } + } + } + + profUpdate = bx::getHPCounter() - profUpdate; + + profNormal = bx::getHPCounter(); + + for (uint32_t zz = 1; zz < DIMS-1; ++zz) + { + for (uint32_t yy = 1; yy < DIMS-1; ++yy) + { + uint32_t offset = (zz*DIMS+yy)*DIMS; + + for (uint32_t xx = 1; xx < DIMS-1; ++xx) + { + uint32_t xoffset = offset + xx; + + Grid* grid = m_grid; + float normal[3] = + { + grid[xoffset-1 ].m_val - grid[xoffset+1 ].m_val, + grid[xoffset-ypitch].m_val - grid[xoffset+ypitch].m_val, + grid[xoffset-zpitch].m_val - grid[xoffset+zpitch].m_val, + }; + + bx::vec3Norm(grid[xoffset].m_normal, normal); + } + } + } + + profNormal = bx::getHPCounter() - profNormal; + + profTriangulate = bx::getHPCounter(); + + PosNormalColorVertex* vertex = (PosNormalColorVertex*)tvb.data; + + for (uint32_t zz = 0; zz < DIMS-1 && numVertices+12 < maxVertices; ++zz) + { + float rgb[6]; + rgb[2] = zz*invdim; + rgb[5] = (zz+1)*invdim; + + for (uint32_t yy = 0; yy < DIMS-1 && numVertices+12 < maxVertices; ++yy) + { + uint32_t offset = (zz*DIMS+yy)*DIMS; + + rgb[1] = yy*invdim; + rgb[4] = (yy+1)*invdim; + + for (uint32_t xx = 0; xx < DIMS-1 && numVertices+12 < maxVertices; ++xx) + { + uint32_t xoffset = offset + xx; + + rgb[0] = xx*invdim; + rgb[3] = (xx+1)*invdim; + + float pos[3] = + { + -DIMS*0.5f + float(xx), + -DIMS*0.5f + float(yy), + -DIMS*0.5f + float(zz) + }; + + const Grid* grid = m_grid; + const Grid* val[8] = { + &grid[xoffset+zpitch+ypitch ], + &grid[xoffset+zpitch+ypitch+1], + &grid[xoffset+ypitch+1 ], + &grid[xoffset+ypitch ], + &grid[xoffset+zpitch ], + &grid[xoffset+zpitch+1 ], + &grid[xoffset+1 ], + &grid[xoffset ], + }; + + uint32_t num = triangulate( (uint8_t*)vertex, PosNormalColorVertex::ms_decl.getStride(), rgb, pos, val, 0.5f); + vertex += num; + numVertices += num; + } + } + } + + profTriangulate = bx::getHPCounter() - profTriangulate; + + float mtx[16]; + bx::mtxRotateXY(mtx, time*0.67f, time); + + // Set model matrix for rendering. + bgfx::setTransform(mtx); + + // Set vertex and index buffer. + bgfx::setVertexBuffer(&tvb, 0, numVertices); + + // Set render states. + bgfx::setState(BGFX_STATE_DEFAULT); + + // Submit primitive for rendering to view 0. + bgfx::submit(0, m_program); + + // Display stats. + bgfx::dbgTextPrintf(1, 4, 0x0f, "Num vertices: %5d (%6.4f%%)", numVertices, float(numVertices)/maxVertices * 100); + bgfx::dbgTextPrintf(1, 5, 0x0f, " Update: % 7.3f[ms]", double(profUpdate)*toMs); + bgfx::dbgTextPrintf(1, 6, 0x0f, "Calc normals: % 7.3f[ms]", double(profNormal)*toMs); + bgfx::dbgTextPrintf(1, 7, 0x0f, " Triangulate: % 7.3f[ms]", double(profTriangulate)*toMs); + bgfx::dbgTextPrintf(1, 8, 0x0f, " Frame: % 7.3f[ms]", double(frameTime)*toMs); + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + + return true; + } + + return false; + } + + uint32_t m_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; + bgfx::ProgramHandle m_program; + + Grid* m_grid; + int64_t m_timeOffset; + +}; + +ENTRY_IMPLEMENT_MAIN(Metaballs); diff --git a/examples/17-drawstress/drawstress.cpp b/examples/17-drawstress/drawstress.cpp index c969b8c73..a442e885b 100644 --- a/examples/17-drawstress/drawstress.cpp +++ b/examples/17-drawstress/drawstress.cpp @@ -13,10 +13,6 @@ #include "vs_drawstress.bin.h" #include "fs_drawstress.bin.h" -#if BX_PLATFORM_EMSCRIPTEN -# include -#endif // BX_PLATFORM_EMSCRIPTEN - struct PosColorVertex { float m_x; @@ -66,25 +62,6 @@ static const uint16_t s_cubeIndices[36] = 6, 3, 7, }; -uint32_t width = 1280; -uint32_t height = 720; -uint32_t debug = BGFX_DEBUG_TEXT; -uint32_t reset = BGFX_RESET_NONE; - -bool autoAdjust = true; -int32_t scrollArea = 0; -int32_t dim = 16; -int32_t maxDim = 40; -uint32_t transform = 0; - -entry::MouseState mouseState; - -int64_t timeOffset = bx::getHPCounter(); - -int64_t deltaTimeNs = 0; -int64_t deltaTimeAvgNs = 0; -int64_t numFrames = 0; - #if BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_NACL static const int64_t highwm = 1000000/35; static const int64_t lowwm = 1000000/27; @@ -93,239 +70,272 @@ static const int64_t highwm = 1000000/65; static const int64_t lowwm = 1000000/57; #endif // BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_NACL -bgfx::ProgramHandle program; -bgfx::VertexBufferHandle vbh; -bgfx::IndexBufferHandle ibh; - -BX_NO_INLINE bool mainloop() +class DrawStress : public entry::AppI { - if (!entry::processEvents(width, height, debug, reset, &mouseState) ) + void init(int /*_argc*/, char** /*_argv*/) BX_OVERRIDE { - int64_t now = bx::getHPCounter(); - static int64_t last = now; - const int64_t hpFreq = bx::getHPFrequency(); - const int64_t frameTime = now - last; - last = now; - const double freq = double(hpFreq); - const double toMs = 1000.0/freq; + BX_UNUSED(_argc, _argv); - deltaTimeNs += frameTime*1000000/hpFreq; + m_width = 1280; + m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_NONE; - if (deltaTimeNs > 1000000) + m_autoAdjust = true; + m_scrollArea = 0; + m_dim = 16; + m_maxDim = 40; + m_transform = 0; + + m_timeOffset = bx::getHPCounter(); + + m_deltaTimeNs = 0; + m_deltaTimeAvgNs = 0; + m_numFrames = 0; + + bgfx::init(); + bgfx::reset(m_width, m_height, m_reset); + + const bgfx::Caps* caps = bgfx::getCaps(); + m_maxDim = (int32_t)powf(float(caps->maxDrawCalls), 1.0f/3.0f); + + // 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 + ); + + // Create vertex stream declaration. + PosColorVertex::init(); + + const bgfx::Memory* vs_drawstress; + const bgfx::Memory* fs_drawstress; + + switch (bgfx::getRendererType() ) { - deltaTimeAvgNs = deltaTimeNs / bx::int64_max(1, numFrames); + case bgfx::RendererType::Direct3D9: + vs_drawstress = bgfx::makeRef(vs_drawstress_dx9, sizeof(vs_drawstress_dx9) ); + fs_drawstress = bgfx::makeRef(fs_drawstress_dx9, sizeof(fs_drawstress_dx9) ); + break; - if (autoAdjust) + case bgfx::RendererType::Direct3D11: + case bgfx::RendererType::Direct3D12: + vs_drawstress = bgfx::makeRef(vs_drawstress_dx11, sizeof(vs_drawstress_dx11) ); + fs_drawstress = bgfx::makeRef(fs_drawstress_dx11, sizeof(fs_drawstress_dx11) ); + break; + + default: + vs_drawstress = bgfx::makeRef(vs_drawstress_glsl, sizeof(vs_drawstress_glsl) ); + fs_drawstress = bgfx::makeRef(fs_drawstress_glsl, sizeof(fs_drawstress_glsl) ); + break; + } + + // Create program from shaders. + m_program = bgfx::createProgram( + bgfx::createShader(vs_drawstress) + , bgfx::createShader(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 + ); + + // Create static index buffer. + m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) ); + + // Imgui. + imguiCreate(); + } + + int shutdown() BX_OVERRIDE + { + // Cleanup. + imguiDestroy(); + bgfx::destroyIndexBuffer(m_ibh); + bgfx::destroyVertexBuffer(m_vbh); + bgfx::destroyProgram(m_program); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; + } + + bool update() BX_OVERRIDE + { + entry::MouseState mouseState; + if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &mouseState) ) + { + int64_t now = bx::getHPCounter(); + static int64_t last = now; + const int64_t hpFreq = bx::getHPFrequency(); + const int64_t frameTime = now - last; + last = now; + const double freq = double(hpFreq); + const double toMs = 1000.0/freq; + + m_deltaTimeNs += frameTime*1000000/hpFreq; + + if (m_deltaTimeNs > 1000000) { - if (deltaTimeAvgNs < highwm) + m_deltaTimeAvgNs = m_deltaTimeNs / bx::int64_max(1, m_numFrames); + + if (m_autoAdjust) { - dim = bx::uint32_min(dim + 2, maxDim); + if (m_deltaTimeAvgNs < highwm) + { + m_dim = bx::uint32_min(m_dim + 2, m_maxDim); + } + else if (m_deltaTimeAvgNs > lowwm) + { + m_dim = bx::uint32_max(m_dim - 1, 2); + } } - else if (deltaTimeAvgNs > lowwm) + + m_deltaTimeNs = 0; + m_numFrames = 0; + } + else + { + ++m_numFrames; + } + + float time = (float)( (now-m_timeOffset)/freq); + + imguiBeginFrame(mouseState.m_mx + , mouseState.m_my + , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) + | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) + , mouseState.m_mz + , m_width + , m_height + ); + + imguiBeginScrollArea("Settings", m_width - m_width / 4 - 10, 10, m_width / 4, m_height / 3, &m_scrollArea); + imguiSeparatorLine(); + + m_transform = imguiChoose(m_transform + , "Rotate" + , "No fragments" + ); + imguiSeparatorLine(); + + if (imguiCheck("Auto adjust", m_autoAdjust) ) + { + m_autoAdjust ^= true; + } + + 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); + + 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); + + // Set view and projection matrix for view 0. + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, m_width, m_height); + + // This dummy draw call is here to make sure that view 0 is cleared + // 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) + { + for (uint32_t yy = 0; yy < uint32_t(m_dim); ++yy) { - dim = bx::uint32_max(dim - 1, 2); + 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); + + // Submit primitive for rendering to view 0. + bgfx::submit(0, m_program); + } } } - deltaTimeNs = 0; - numFrames = 0; + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + + return true; } - else - { - ++numFrames; - } - - float time = (float)( (now-timeOffset)/freq); - - imguiBeginFrame(mouseState.m_mx - , mouseState.m_my - , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) - | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) - , mouseState.m_mz - , width - , height - ); - - imguiBeginScrollArea("Settings", width - width / 4 - 10, 10, width / 4, height / 3, &scrollArea); - imguiSeparatorLine(); - - transform = imguiChoose(transform - , "Rotate" - , "No fragments" - ); - imguiSeparatorLine(); - - if (imguiCheck("Auto adjust", autoAdjust) ) - { - autoAdjust ^= true; - } - - imguiSlider("Dim", dim, 5, maxDim); - imguiLabel("Draw calls: %d", dim*dim*dim); - imguiLabel("Avg Delta Time (1 second) [ms]: %0.4f", deltaTimeAvgNs/1000.0f); - - 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(width)/float(height), 0.1f, 100.0f); - - // Set view and projection matrix for view 0. - bgfx::setViewTransform(0, view, proj); - - // Set view 0 default viewport. - bgfx::setViewRect(0, 0, 0, width, height); - - // This dummy draw call is here to make sure that view 0 is cleared - // 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 == transform ? 0.25f : 0.0f; - bx::mtxScale(mtxS, scale, scale, scale); - - const float step = 0.6f; - float pos[3]; - pos[0] = -step*dim / 2.0f; - pos[1] = -step*dim / 2.0f; - pos[2] = -15.0; - - for (uint32_t zz = 0; zz < uint32_t(dim); ++zz) - { - for (uint32_t yy = 0; yy < uint32_t(dim); ++yy) - { - for (uint32_t xx = 0; xx < uint32_t(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(vbh); - bgfx::setIndexBuffer(ibh); - - // Set render states. - bgfx::setState(BGFX_STATE_DEFAULT); - - // Submit primitive for rendering to view 0. - bgfx::submit(0, program); - } - } - } - - // Advance to next frame. Rendering thread will be kicked to - // process submitted rendering primitives. - bgfx::frame(); return false; } - return true; -} + uint32_t m_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; -void loop() -{ - mainloop(); -} + bool m_autoAdjust; + int32_t m_scrollArea; + int32_t m_dim; + int32_t m_maxDim; + uint32_t m_transform; -int _main_(int /*_argc*/, char** /*_argv*/) -{ - bgfx::init(); - bgfx::reset(width, height, reset); + int64_t m_timeOffset; - const bgfx::Caps* caps = bgfx::getCaps(); - maxDim = (int32_t)powf(float(caps->maxDrawCalls), 1.0f/3.0f); + int64_t m_deltaTimeNs; + int64_t m_deltaTimeAvgNs; + int64_t m_numFrames; - // Enable debug text. - bgfx::setDebug(debug); + bgfx::ProgramHandle m_program; + bgfx::VertexBufferHandle m_vbh; + bgfx::IndexBufferHandle m_ibh; +}; - // Set view 0 clear state. - bgfx::setViewClear(0 - , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH - , 0x303030ff - , 1.0f - , 0 - ); - - // Create vertex stream declaration. - PosColorVertex::init(); - - const bgfx::Memory* vs_drawstress; - const bgfx::Memory* fs_drawstress; - - switch (bgfx::getRendererType() ) - { - case bgfx::RendererType::Direct3D9: - vs_drawstress = bgfx::makeRef(vs_drawstress_dx9, sizeof(vs_drawstress_dx9) ); - fs_drawstress = bgfx::makeRef(fs_drawstress_dx9, sizeof(fs_drawstress_dx9) ); - break; - - case bgfx::RendererType::Direct3D11: - case bgfx::RendererType::Direct3D12: - vs_drawstress = bgfx::makeRef(vs_drawstress_dx11, sizeof(vs_drawstress_dx11) ); - fs_drawstress = bgfx::makeRef(fs_drawstress_dx11, sizeof(fs_drawstress_dx11) ); - break; - - default: - vs_drawstress = bgfx::makeRef(vs_drawstress_glsl, sizeof(vs_drawstress_glsl) ); - fs_drawstress = bgfx::makeRef(fs_drawstress_glsl, sizeof(fs_drawstress_glsl) ); - break; - } - - // Create program from shaders. - program = bgfx::createProgram( - bgfx::createShader(vs_drawstress) - , bgfx::createShader(fs_drawstress) - , true /* destroy shaders when program is destroyed */ - ); - - const bgfx::Memory* mem; - - // Create static vertex buffer. - mem = bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ); - vbh = bgfx::createVertexBuffer(mem, PosColorVertex::ms_decl); - - // Create static index buffer. - mem = bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ); - ibh = bgfx::createIndexBuffer(mem); - - // Imgui. - imguiCreate(); - -#if BX_PLATFORM_EMSCRIPTEN - emscripten_set_main_loop(&loop, -1, 1); -#else - while (!mainloop() ); -#endif // BX_PLATFORM_EMSCRIPTEN - - // Cleanup. - imguiDestroy(); - bgfx::destroyIndexBuffer(ibh); - bgfx::destroyVertexBuffer(vbh); - bgfx::destroyProgram(program); - - // Shutdown bgfx. - bgfx::shutdown(); - - return 0; -} +ENTRY_IMPLEMENT_MAIN(DrawStress); diff --git a/examples/common/bgfx_utils.cpp b/examples/common/bgfx_utils.cpp index e9c56ea5e..ad1ca9fc4 100644 --- a/examples/common/bgfx_utils.cpp +++ b/examples/common/bgfx_utils.cpp @@ -107,7 +107,7 @@ static bgfx::ShaderHandle loadShader(bx::FileReaderI* _reader, const char* _name case bgfx::RendererType::Metal: shaderPath = "shaders/metal/"; break; - + case bgfx::RendererType::OpenGLES: shaderPath = "shaders/gles/"; break; diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index 45cebf1ec..94f8e4ded 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -9,6 +9,10 @@ #include +#if BX_PLATFORM_EMSCRIPTEN +# include +#endif // BX_PLATFORM_EMSCRIPTEN + #include "entry_p.h" #include "cmd.h" #include "input.h" @@ -304,6 +308,28 @@ BX_PRAGMA_DIAGNOSTIC_POP(); INPUT_BINDING_END }; +#if BX_PLATFORM_EMSCRIPTEN + static AppI* s_app; + static void updateApp() + { + s_app->update(); + } +#endif // BX_PLATFORM_EMSCRIPTEN + + int runApp(AppI* _app, int _argc, char** _argv) + { + _app->init(_argc, _argv); + +#if BX_PLATFORM_EMSCRIPTEN + s_app = _app; + emscripten_set_main_loop(&updateApp, -1, 1); +#else + while (_app->update() ); +#endif // BX_PLATFORM_EMSCRIPTEN + + return _app->shutdown(); + } + int main(int _argc, char** _argv) { //DBG(BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME); diff --git a/examples/common/entry/entry.h b/examples/common/entry/entry.h index a583abfc3..373808b67 100644 --- a/examples/common/entry/entry.h +++ b/examples/common/entry/entry.h @@ -18,6 +18,13 @@ extern "C" int _main_(int _argc, char** _argv); #define ENTRY_WINDOW_FLAG_ASPECT_RATIO UINT32_C(0x00000001) #define ENTRY_WINDOW_FLAG_FRAME UINT32_C(0x00000002) +#define ENTRY_IMPLEMENT_MAIN(_app) \ + int _main_(int _argc, char** _argv) \ + { \ + _app app; \ + return entry::runApp(&app, _argc, _argv); \ + } + namespace entry { struct WindowHandle { uint16_t idx; }; @@ -55,8 +62,7 @@ namespace entry }; struct Modifier - { - enum Enum + { enum Enum { None = 0, LeftAlt = 0x01, @@ -244,6 +250,20 @@ namespace entry bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset); + struct BX_NO_VTABLE AppI + { + virtual ~AppI() = 0; + virtual void init(int _argc, char** _argv) = 0; + virtual int shutdown() = 0; + virtual bool update() = 0; + }; + + inline AppI::~AppI() + { + } + + int runApp(AppI* _app, int _argc, char** _argv); + } // namespace entry #endif // ENTRY_H_HEADER_GUARD