Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yas jpeg benchmark #161

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
27 changes: 27 additions & 0 deletions 68_JpegLoading/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
include(common RESULT_VARIABLE RES)
if(NOT RES)
message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory")
endif()

nbl_create_executable_project("" "" "" "" "${NBL_EXECUTABLE_PROJECT_CREATION_PCH_TARGET}")

if(NBL_EMBED_BUILTIN_RESOURCES)
set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData)
set(RESOURCE_DIR "app_resources")

get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)

file(GLOB_RECURSE BUILTIN_RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}" CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}/*")
foreach(RES_FILE ${BUILTIN_RESOURCE_FILES})
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "${RES_FILE}")
endforeach()

ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}")

LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_})
endif()

add_dependencies(${EXECUTABLE_NAME} argparse)
target_include_directories(${EXECUTABLE_NAME} PUBLIC $<TARGET_PROPERTY:argparse,INTERFACE_INCLUDE_DIRECTORIES>)
193 changes: 193 additions & 0 deletions 68_JpegLoading/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Copyright (C) 2018-2024 - DevSH GrapMonoAssetManagerAndBuiltinResourceApplicationhics Programming Sp. z O.O.
// This file is part of the "Nabla Engine".
// For conditions of distribution and use, see copyright notice in nabla.h
#include "nbl/application_templates/MonoAssetManagerAndBuiltinResourceApplication.hpp"

#include <future>

#include "nlohmann/json.hpp"
#include "argparse/argparse.hpp"

using json = nlohmann::json;

using namespace nbl;
using namespace core;
using namespace hlsl;
using namespace system;
using namespace asset;
using namespace ui;
using namespace video;

class ThreadPool
{
using task_t = std::function<void()>;
public:
ThreadPool(size_t workers = std::thread::hardware_concurrency())
{
for (size_t i = 0; i < workers; i++)
{
m_workers.emplace_back([this] {
task_t task;

while (1)
{
{
std::unique_lock<std::mutex> lock(m_queueLock);
m_taskAvailable.wait(lock, [this] { return !m_tasks.empty() || m_shouldStop; });

if (m_shouldStop && m_tasks.empty()) {
return;
}

task = std::move(m_tasks.front());
m_tasks.pop();
}

task();
}
});
}
}

~ThreadPool()
{
m_shouldStop = true;
m_taskAvailable.notify_all();

for (auto& worker : m_workers)
{
worker.join();
}
}

void enqueue(task_t task)
{
{
std::lock_guard<std::mutex> lock(m_queueLock);
m_tasks.emplace(std::move(task));
}
m_taskAvailable.notify_one();
}
private:
std::mutex m_queueLock;
std::condition_variable m_taskAvailable;
std::vector<std::thread> m_workers;
std::queue<task_t> m_tasks;
std::atomic<bool> m_shouldStop = false;
};

class JpegLoaderApp final : public application_templates::MonoAssetManagerAndBuiltinResourceApplication
{
using clock_t = std::chrono::steady_clock;
using clock_resolution_t = std::chrono::milliseconds;
using base_t = application_templates::MonoAssetManagerAndBuiltinResourceApplication;
public:
using base_t::base_t;

inline bool onAppInitialized(smart_refctd_ptr<ISystem>&& system) override
{
argparse::ArgumentParser program("Color Space");

program.add_argument<std::string>("--directory")
.required()
.help("Path to a directory where all JPEG files are stored (not recursive)");

program.add_argument<std::string>("--output")
.default_value("output.json")
.help("Path to the file where the benchmark result will be stored");

try
{
program.parse_args({ argv.data(), argv.data() + argv.size() });
}
catch (const std::exception& err)
{
std::cerr << err.what() << std::endl << program; // NOTE: std::cerr because logger isn't initialized yet
return false;
}

if (!base_t::onAppInitialized(std::move(system)))
return false;

options.directory = program.get<std::string>("--directory");
options.outputFile = program.get<std::string>("--output");

// check if directory exists
if (!std::filesystem::exists(options.directory))
{
logFail("Provided directory doesn't exist");
return false;
}

auto start = clock_t::now();
std::vector<std::string> files;

{
ThreadPool tp;

constexpr auto cachingFlags = static_cast<IAssetLoader::E_CACHING_FLAGS>(IAssetLoader::ECF_DONT_CACHE_REFERENCES & IAssetLoader::ECF_DONT_CACHE_TOP_LEVEL);
const IAssetLoader::SAssetLoadParams loadParams(0ull, nullptr, cachingFlags, IAssetLoader::ELPF_NONE, m_logger.get());

for (auto& item : std::filesystem::directory_iterator(options.directory))
{
auto& path = item.path();
if (path.has_extension() && path.extension() == ".jpg")
{
files.emplace_back(std::move(path.generic_string()));

ISystem::future_t<smart_refctd_ptr<system::IFile>> future;
m_system->createFile(future, path, IFile::ECF_READ | IFile::ECF_MAPPABLE);

if (auto pFile = future.acquire(); pFile && pFile->get())
{
auto& file = *pFile;
tp.enqueue([=] {
m_logger->log("Loading %S", ILogger::ELL_INFO, path.c_str());
m_assetMgr->getAsset(file.get(), path.generic_string(), loadParams);
});
}
}
}
}

auto stop = clock_t::now();
auto time = std::chrono::duration_cast<clock_resolution_t>(stop - start).count();

m_logger->log("Process took %llu ms", ILogger::ELL_INFO, time);

// Dump data to JSON
json j;
j["loaded_files"] = files;
j["duration_ms"] = time;

std::ofstream output(options.outputFile);
if (!output.good())
{
logFail("Failed to open %S", options.outputFile);
return false;
}

output << j;

return true;
}

inline bool keepRunning() override
{
return false;
}

inline void workLoopBody() override
{

}

private:
struct NBL_APP_OPTIONS
{
std::string directory;
std::string outputFile;
} options;
};

NBL_MAIN_FUNC(JpegLoaderApp)
50 changes: 50 additions & 0 deletions 68_JpegLoading/pipeline.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import org.DevshGraphicsProgramming.Agent
import org.DevshGraphicsProgramming.BuilderInfo
import org.DevshGraphicsProgramming.IBuilder

class CJpegLoading extends IBuilder
{
public CJpegLoading(Agent _agent, _info)
{
super(_agent, _info)
}

@Override
public boolean prepare(Map axisMapping)
{
return true
}

@Override
public boolean build(Map axisMapping)
{
IBuilder.CONFIGURATION config = axisMapping.get("CONFIGURATION")
IBuilder.BUILD_TYPE buildType = axisMapping.get("BUILD_TYPE")

def nameOfBuildDirectory = getNameOfBuildDirectory(buildType)
def nameOfConfig = getNameOfConfig(config)

agent.execute("cmake --build ${info.rootProjectPath}/${nameOfBuildDirectory}/${info.targetProjectPathRelativeToRoot} --target ${info.targetBaseName} --config ${nameOfConfig} -j12 -v")

return true
}

@Override
public boolean test(Map axisMapping)
{
return true
}

@Override
public boolean install(Map axisMapping)
{
return true
}
}

def create(Agent _agent, _info)
{
return new CJpegLoading(_agent, _info)
}

return this
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ if(NBL_BUILD_EXAMPLES)
add_subdirectory(0_ImportanceSamplingEnvMaps EXCLUDE_FROM_ALL) #TODO: integrate back into 42

add_subdirectory(67_RayQueryGeometry EXCLUDE_FROM_ALL)
add_subdirectory(68_JpegLoading EXCLUDE_FROM_ALL)

NBL_HOOK_COMMON_API("${NBL_COMMON_API_TARGETS}")
endif()