WValidator::Result WTimeValidator::validate(const WT_USTRING& input) const { if (input.empty()) return WValidator::validate(input); for (unsigned i = 0; i < formats_.size(); ++i) { try { WTime d = WTime::fromString(input, formats_[i]); if (d.isValid()) { if (!bottom_.isNull()) if (d < bottom_) return Result(Invalid, invalidTooEarlyText()); if (!top_.isNull()) if (d > top_) return Result(Invalid, invalidTooLateText()); return Result(Valid); } } catch (std::exception& e) { LOG_WARN("validate(): " << e.what()); } } return Result(Invalid, invalidNotATimeText()); }
bool WTime::operator<= (const WTime& other) const { if (!isValid() && !other.isValid()) return true; if (!isValid() || !other.isValid()) throw InvalidTimeException(); return time_ <= other.time_; }
int WTime::msecsTo(const WTime& t) const { if (!isValid() || !t.isValid()) throw InvalidTimeException(); return t.time_ - time_; }
void WTimePicker::setTime(const WTime& time) { if (!time.isValid()) { LOG_ERROR("Time is invalid!"); return; } int hours = 0; if (formatAp()) { hours = time.pmhour(); if (time.hour() < 12) cbAP_->setCurrentIndex(0); else cbAP_->setCurrentIndex(1); } else hours = time.hour(); int minutes = time.minute(); int seconds = time.second(); int millisecond = time.msec(); sbhour_->setValue(hours); sbminute_->setValue(minutes); sbsecond_->setValue(seconds); if (formatMs()) { sbmillisecond_->setValue(millisecond); } }
void WTimePicker::setTime(const WTime& time) { if(!time.isValid()) { LOG_ERROR("Time is invalid!"); return; } std::string hoursStr("0"), minutesStr("00"), secondsStr("00"); try { hoursStr = time.toString("hh").toUTF8(); minutesStr = time.toString("mm").toUTF8(); secondsStr = time.toString("ss").toUTF8(); } catch(const boost::bad_lexical_cast& ex) { LOG_ERROR("boost::bad_lexical_cast caught in WTimePicker::time()"); } hourText_->setText(hoursStr); minuteText_->setText(minutesStr); secondText_->setText(secondsStr); }
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(); }