DWORD __stdcall GameThreadMain(void* args) { HWND hWnd = (HWND) args; Render::Init(); SwapChain swapChain; swapChain.Create(hWnd, OUTPUT_SIZE_X, OUTPUT_SIZE_Y); Core::Load(); Core::SetSwapChain(&swapChain); for (;;) { Core::Update(); swapChain.Present(); } return 0; }
void Queue::present( Semaphore& signalSemaphore, SwapChain& swapChain, unsigned int chainIndex) { auto transitionCmd = m_device.createCommandList(); transitionCmd.transition(swapChain.renderTarget(chainIndex), ResourceState::Present); submit(transitionCmd); m_impl->present(signalSemaphore, swapChain, chainIndex); }
// --------------------------------------------------------------------------------------------------------- LVEDRENDERINGENGINE_API void __stdcall LvEd_End() { RenderContext* rc = RenderContext::Inst(); RenderSurface* surface = s_engineData->pRenderSurface; s_engineData->basicRenderer->End(); LineRenderer::Inst()->RenderAll(rc); ErrorHandler::ClearError(); LvEdFonts::FontRenderer::Inst()->FlushPrintRequests( rc ); if(surface->GetType() == RenderSurface::kSwapChain) { RenderWorldAxis(); SwapChain* swapchain = static_cast<SwapChain*>(surface); HRESULT hr = swapchain->GetDXGISwapChain()->Present(0,0); Logger::IsFailureLog(hr, L"presenting swapchain"); } s_engineData->renderableSorter.ClearLists(); s_engineData->pRenderSurface = NULL; RenderContext::Inst()->LightEnvDirty = false; }
void mainLoop(double deltaTime) override { auto cmd = device.graphicsCommandList(); auto backbuffer = swapChain.backbuffer(); cmd.imguiBeginFrame(swapChain, deltaTime); ImGui::ShowTestWindow(); cmd.clearRTV(backbuffer, float4(0, 0, .25f, 1)); cmd.setRenderTargets({backbuffer}); cmd.bind(hello); cube.setForRendering(cmd); float objectPhase = frac(time.secondsF() / ObjectPeriod) * 2 * Pi; float cameraPhase = frac(time.secondsF() / CameraPeriod) * 2 * Pi; Hello::Constants c; float3 cameraPos; cameraPos.x = cos(cameraPhase) * CameraDistance; cameraPos.z = sin(cameraPhase) * CameraDistance; cameraPos.y = 2; Matrix view = Matrix::lookAt(cameraPos, 0); Matrix proj = Matrix::projectionPerspective(size()); c.viewProj = proj * view; c.model = Matrix::axisAngle({1, 0, 0}, Angle(objectPhase)); cmd.setConstants(c); cmd.setShaderView(Hello::tex, lena); cmd.drawIndexed(cube.numIndices()); cmd.setRenderTargets(); cmd.imguiEndFrame(swapChain); device.execute(cmd); device.present(swapChain); }
static void runTestsForDevice(GpuDevice& dev, GraphicsQueue& queue, Window& window, SwapChain& sc, ViewPort& port, GfxCommandList& gfx, faze::Logger& log) { faze::TestWorks t("advtests"); t.setAfterTest([&]() { // clean up auto fence = dev.createFence(); queue.insertFence(fence); fence.wait(); if (!gfx.isClosed()) { gfx.closeList(); } gfx.resetList(); }); t.addTest("Lots of drawcalls bench, (single thread), rough baseline", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 1000000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; while (cpuTime > 14.f) //while(true) { if (window.simpleReadMessages()) break; // Rendertarget b.start(false); gfx.setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); gfx.ClearRenderTargetView(sc[backBufferIndex], vec); gfx.setRenderTarget(sc[backBufferIndex]); // graphics begin { auto bind = gfx.bind(pipeline); bind.SRV(0, dstdataSrv); gfx.drawInstanced(bind, 3, 1, 0, 0); for (int i = 1; i < currentTriangleCount; ++i) { gfx.drawInstancedRaw(3, 1, 0, i); // this is the cheat. } } // submit all gfx.closeList(); queue.submit(gfx); cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); gfx.resetList(); t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; if (cpuTime > 16.f) { currentTriangleCount -= currentTriangleCount/100; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); //fence.wait(); return true; }); t.addTest("Lots of drawcalls bench, (single thread), myapi", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 200000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; while (cpuTime > 14.f) //while (true) { if (window.simpleReadMessages()) break; // Rendertarget b.start(false); gfx.setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); gfx.ClearRenderTargetView(sc[backBufferIndex], vec); gfx.setRenderTarget(sc[backBufferIndex]); // graphics begin { for (int i = 0; i < currentTriangleCount; ++i) { auto bind = gfx.bind(pipeline); bind.SRV(0, dstdataSrv); gfx.drawInstanced(bind, 3, 1, 0, i); } } // submit all gfx.closeList(); queue.submit(gfx); cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); gfx.resetList(); t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; frameTime = t.analyzeFrames().x(); if (cpuTime > 16.f) { currentTriangleCount -= currentTriangleCount / 100; } } //fence.wait(); F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.addTest("Lots of drawcalls bench, (Multithread), baseline", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 4000000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; std::vector<GfxCommandList> m_cmds; for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds.push_back(dev.createUniversalCommandList()); } //while (true) while (cpuTime > 14.f) { if (window.simpleReadMessages()) break; // Rendertarget b.start(false); m_cmds[0].setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); m_cmds[0].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[0].setRenderTarget(sc[backBufferIndex]); for (size_t i = 1; i < lbs.threadCount(); ++i) { m_cmds[i].setViewPort(port); //m_cmds[i].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[i].setRenderTarget(sc[backBufferIndex]); } // graphics begin lbs.addParallelFor<1>("fillCommands", {}, {}, 0, 100, [&](size_t id, size_t threadIndex) { auto& gfx2 = m_cmds[threadIndex]; unsigned workAmount = currentTriangleCount / 100; unsigned startIndex = static_cast<unsigned>(workAmount * id); auto bind = gfx2.bind(pipeline); bind.SRV(0, dstdataSrv); gfx2.drawInstanced(bind, 3, 1, 0, startIndex); for (unsigned i = startIndex+1; i < startIndex + workAmount; ++i) { gfx2.drawInstancedRaw(3, 1, 0, i); } }); lbs.sleepTillKeywords({ "fillCommands" }); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].closeList(); queue.submit(m_cmds[i]); } cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].resetList(); } t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; frameTime = t.analyzeFrames().x(); if (cpuTime > 16.f) { currentTriangleCount -= currentTriangleCount / 100; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.addTest("Lots of drawcalls bench, (Multithread), myapi", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 2000000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; std::vector<GfxCommandList> m_cmds; for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds.push_back(dev.createUniversalCommandList()); } //while (true) while (cpuTime > 14.f) { if (window.simpleReadMessages()) break; // Rendertarget b.start(false); m_cmds[0].setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); m_cmds[0].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[0].setRenderTarget(sc[backBufferIndex]); for (size_t i = 1; i < lbs.threadCount(); ++i) { m_cmds[i].setViewPort(port); //m_cmds[i].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[i].setRenderTarget(sc[backBufferIndex]); } // graphics begin lbs.addParallelFor<1>("fillCommands", {}, {}, 0, 100, [&](size_t id, size_t threadIndex) { auto& gfx2 = m_cmds[threadIndex]; unsigned workAmount = currentTriangleCount / 100; unsigned startIndex = static_cast<unsigned>(workAmount * id); for (unsigned i = startIndex; i < startIndex + workAmount; ++i) { auto bind = gfx2.bind(pipeline); bind.SRV(0, dstdataSrv); gfx2.drawInstanced(bind, 3, 1, 0, i); } }); lbs.sleepTillKeywords({ "fillCommands" }); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].closeList(); queue.submit(m_cmds[i]); } cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].resetList(); } t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; frameTime = t.analyzeFrames().x(); if (cpuTime > 16.f) { currentTriangleCount -= currentTriangleCount / 40; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.addTest("Lots of drawcalls bench, (single thread), rough baseline, frametime 20ms", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 800000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); fence.wait(); gfx.resetList(); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; int beenUnderLimit = 0; while (beenUnderLimit < 10) { if (frameTime < 20.f) beenUnderLimit++; if (window.simpleReadMessages()) break; // Rendertarget b.start(false); gfx.setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); gfx.ClearRenderTargetView(sc[backBufferIndex], vec); gfx.setRenderTarget(sc[backBufferIndex]); // graphics begin { auto bind = gfx.bind(pipeline); bind.SRV(0, dstdataSrv); gfx.drawInstanced(bind, 3, 1, 0, 0); for (int i = 1; i < currentTriangleCount; ++i) { gfx.drawInstancedRaw(3, 1, 0, i); // this is the cheat. } } // submit all gfx.closeList(); queue.submit(gfx); cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); gfx.resetList(); t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; if (frameTime > 20.f) { currentTriangleCount -= currentTriangleCount / 100; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); //fence.wait(); return true; }); t.addTest("Lots of drawcalls bench, (single thread), myapi, frametime 20ms", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 100000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; int beenUnderLimit = 0; while (beenUnderLimit < 10) { if (frameTime < 20.f) beenUnderLimit++; if (window.simpleReadMessages()) break; // Rendertarget b.start(false); gfx.setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); gfx.ClearRenderTargetView(sc[backBufferIndex], vec); gfx.setRenderTarget(sc[backBufferIndex]); // graphics begin { for (int i = 0; i < currentTriangleCount; ++i) { auto bind = gfx.bind(pipeline); bind.SRV(0, dstdataSrv); gfx.drawInstanced(bind, 3, 1, 0, i); } } // submit all gfx.closeList(); queue.submit(gfx); cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); gfx.resetList(); t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; //frameTime = t.analyzeFrames().x(); if (frameTime > 20.f) { currentTriangleCount -= currentTriangleCount / 100; } } //fence.wait(); F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.addTest("Lots of drawcalls bench, (Multithread), baseline, frametime 20ms", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 1000000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; std::vector<GfxCommandList> m_cmds; for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds.push_back(dev.createUniversalCommandList()); } //while (true) int beenUnderLimit = 0; while (beenUnderLimit < 10) { if (frameTime < 20.f) beenUnderLimit++; if (window.simpleReadMessages()) break; // Rendertarget b.start(false); m_cmds[0].setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); m_cmds[0].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[0].setRenderTarget(sc[backBufferIndex]); for (size_t i = 1; i < lbs.threadCount(); ++i) { m_cmds[i].setViewPort(port); //m_cmds[i].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[i].setRenderTarget(sc[backBufferIndex]); } // graphics begin lbs.addParallelFor<1>("fillCommands", {}, {}, 0, 100, [&](size_t id, size_t threadIndex) { auto& gfx2 = m_cmds[threadIndex]; unsigned workAmount = static_cast<unsigned>(currentTriangleCount / 100); unsigned startIndex = static_cast<unsigned>(workAmount * id); auto bind = gfx2.bind(pipeline); bind.SRV(0, dstdataSrv); gfx2.drawInstanced(bind, 3, 1, 0, startIndex); for (unsigned i = startIndex + 1; i < startIndex + workAmount; ++i) { gfx2.drawInstancedRaw(3, 1, 0, i); } }); lbs.sleepTillKeywords({ "fillCommands" }); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].closeList(); queue.submit(m_cmds[i]); } cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].resetList(); } t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; //frameTime = t.analyzeFrames().x(); if (frameTime > 20.f) { currentTriangleCount -= currentTriangleCount / 120; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.addTest("Lots of drawcalls bench, (Multithread), myapi, frametime 20ms", [&]() { using namespace faze; struct buf { float pos[4]; }; auto triangleCount = 400000; auto currentTriangleCount = triangleCount; auto srcdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>() .Usage(ResourceUsage::UploadHeap)); auto dstdata = dev.createBuffer(ResourceDescriptor() .Width(triangleCount) .Format<buf>()); auto dstdataSrv = dev.createBufferSRV(dstdata); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<> dis(-0.8f, 0.8f); std::uniform_real_distribution<> dis2(0.f, 1.f); { auto tmp = srcdata.Map<buf>(); for (int i = 0;i < triangleCount; ++i) { auto& it = tmp[i].pos; it[0] = static_cast<float>(dis(gen)); it[1] = static_cast<float>(dis(gen)); it[2] = static_cast<float>(dis2(gen)); } } gfx.CopyResource(dstdata, srcdata); GpuFence fence = dev.createFence(); gfx.closeList(); queue.submit(gfx); queue.insertFence(fence); auto pipeline = dev.createGraphicsPipeline(GraphicsPipelineDescriptor() .PixelShader("tests/stress/pixel") .VertexShader("tests/stress/vertex_triangle") .setRenderTargetCount(1) .RTVFormat(0, FormatType::R8G8B8A8_UNORM_SRGB) .DepthStencil(DepthStencilDescriptor().DepthEnable(false))); auto vec = faze::vec4({ 0.2f, 0.2f, 0.2f, 1.0f }); fence.wait(); gfx.resetList(); WTime t; t.firstTick(); float frameTime = 30.f; float cpuTime = 30.f; Bentsumaakaa b; LBS lbs; std::vector<GfxCommandList> m_cmds; for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds.push_back(dev.createUniversalCommandList()); } //while (true) int beenUnderLimit = 0; while (beenUnderLimit < 10) { if (frameTime < 20.f) beenUnderLimit++; if (window.simpleReadMessages()) break; // Rendertarget b.start(false); m_cmds[0].setViewPort(port); auto backBufferIndex = sc->GetCurrentBackBufferIndex(); m_cmds[0].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[0].setRenderTarget(sc[backBufferIndex]); for (size_t i = 1; i < lbs.threadCount(); ++i) { m_cmds[i].setViewPort(port); //m_cmds[i].ClearRenderTargetView(sc[backBufferIndex], vec); m_cmds[i].setRenderTarget(sc[backBufferIndex]); } // graphics begin lbs.addParallelFor<1>("fillCommands", {}, {}, 0, 100, [&](size_t id, size_t threadIndex) { auto& gfx2 = m_cmds[threadIndex]; size_t workAmount = currentTriangleCount / 100; size_t startIndex = workAmount * id; for (unsigned i = static_cast<unsigned>(startIndex); i < static_cast<unsigned>(startIndex + workAmount); ++i) { auto bind = gfx2.bind(pipeline); bind.SRV(0, dstdataSrv); gfx2.drawInstanced(bind, 3, 1, 0, i); } }); lbs.sleepTillKeywords({ "fillCommands" }); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].closeList(); queue.submit(m_cmds[i]); } cpuTime = b.stop(false) / 1000000.f; // present sc->Present(1, 0); queue.insertFence(fence); fence.wait(); for (size_t i = 0; i < lbs.threadCount(); ++i) { m_cmds[i].resetList(); } t.tick(); frameTime = static_cast<float>(t.getCurrentNano())*0.000001f; //frameTime = t.analyzeFrames().x(); if (frameTime > 20.f) { currentTriangleCount -= currentTriangleCount / 120; } } F_LOG("frametime: %.3fms CpuTime: %.3fms TriangleCount: %d\n", frameTime, cpuTime, currentTriangleCount); log.update(); return true; }); t.runTests(); }
std::unique_ptr<SwapChain> SwapChain_<>::Create( const Config &config ) { SwapChain* retval = nullptr; #if defined(LUDI_PLATFORM_XENON) retval = nullptr; #elif defined(LUDI_PLATFORM_PS3) retval = nullptr; #elif defined(LUDI_PLATFORM_WII) retval = nullptr; #elif LUDI_PLATFORM_ID == LUDI_PLATFORM_WINDOWS // Attempt to get the DXGI Factory. Device* device = Device::Get(); Driver* driver = device->driver(); // Attempt to create the swap chain. IDXGISwapChain* chain = nullptr; // Create the swap chain DXGI_SWAP_CHAIN_DESC desc; desc = ConversionDx11::To(config); HRESULT hresult = driver->factory()->CreateSwapChain(device->device(), &desc, &chain); if (FAILED(hresult)) { //Log::Get().Write( L"Failed to create swap chain!" ); ASSERT(false); return nullptr; } // Retrieve the texture buffer (render-texture) ID3D11Texture2D* texture = nullptr; hresult = chain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &texture ) ); if (FAILED(hresult)) { //Log::Get().Write( L"Failed to get swap chain texture resource!" ); ASSERT(false); return nullptr; } // Create the swap chain render target view ID3D11RenderTargetView* view; hresult = (*device)->CreateRenderTargetView(texture, nullptr, &view); if (FAILED(hresult)) { //Log::Get().Write( L"Failed to create render target view for swap chain!" ); ASSERT(false); return nullptr; } // Create the swap chain, set the render texture and render target view retval = new SwapChain_<LUDI_PLATFORM_WINDOWS>(chain); retval->set_render_texture(new Texture(texture)); retval->set_render_target_view(new RenderTargetView(view)); #elif LUDI_PLATFORM_ID == LUDI_PLATFORM_OSX retval = new SwapChain_<LUDI_PLATFORM_OSX>(nullptr); retval->set_render_texture(new Texture()); retval->set_render_target_view(new RenderTargetView()); #else // NO VALID PLATFORM retval = nullptr; #endif return std::unique_ptr<SwapChain>(retval); }