Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 83 additions & 120 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,120 +1,83 @@
cmake_minimum_required(VERSION 3.19)
include(FetchContent)
include(ExternalProject)

project("haio" LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(xxd scripts/xxd.cpp)
add_executable(replace scripts/replace.cpp)
find_package(Python REQUIRED COMPONENTS Interpreter)

file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/shaders")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/shaders")
file(GLOB_RECURSE HAIO_LIB_SOURCES "${CMAKE_CURRENT_LIST_DIR}/library/*/*.cpp")
#TODO: file(GLOB_RECURSE HAIO_BIN_SOURCES "${CMAKE_CURRENT_LIST_DIR}/source/*/*.cpp")
add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_LIST_DIR}/source/main.cpp;${HAIO_LIB_SOURCES};${HAIO_BIN_SOURCES}")
target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include;${CMAKE_BINARY_DIR}/include")
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")

if (WIN32)
file(GLOB_RECURSE HAIO_WINDOWS_SOURCES "${CMAKE_CURRENT_LIST_DIR}/source/platform/microslop/*.cpp")
target_sources(${PROJECT_NAME} PRIVATE "${HAIO_WINDOWS_SOURCES}")
endif()

set(WUFFS_VERSION "v0.3.4")
set(WUFFS_DIR "${CMAKE_SOURCE_DIR}/vendor/wuffs")
set(WUFFS_DOWNLOAD "https://github.com/google/wuffs-mirror-release-c/archive/refs/tags/${WUFFS_VERSION}.tar.gz")
FetchContent_Populate(wuffs URL "${WUFFS_DOWNLOAD}" SOURCE_DIR "${WUFFS_DIR}")
set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/library/codecs/png.cpp" PROPERTIES INCLUDE_DIRECTORIES "${WUFFS_DIR}/release/c")

set(VULKAN_VERSION "v1.3.290")
set(VULKAN_DIR "${CMAKE_SOURCE_DIR}/vendor/vulkan/vulkan")
set(VULKAN_DOWNLOAD "https://github.com/KhronosGroup/Vulkan-Headers/archive/refs/tags/${VULKAN_VERSION}.tar.gz")
FetchContent_Populate(vulkan URL ${VULKAN_DOWNLOAD} SOURCE_DIR ${VULKAN_DIR})

set(VOLK_VERSION "1.4.350")
set(VOLK_DIR "${CMAKE_SOURCE_DIR}/vendor/vulkan/volk")
set(VOLK_DOWNLOAD "https://github.com/zeux/volk/archive/refs/tags/${VOLK_VERSION}.tar.gz")
FetchContent_Populate(volk URL "${VOLK_DOWNLOAD}" SOURCE_DIR "${VOLK_DIR}")
file(GLOB HAIO_VULKAN_SOURCES "${CMAKE_CURRENT_LIST_DIR}/library/vulkan/*.cpp")
set_source_files_properties(${HAIO_VULKAN_SOURCES} PROPERTIES INCLUDE_DIRECTORIES "${VOLK_DIR};${VULKAN_DIR}/include")
add_library(volk STATIC ${VOLK_DIR}/volk.c)
target_link_libraries(${PROJECT_NAME} PRIVATE volk)
target_include_directories(volk SYSTEM PRIVATE "${VULKAN_DIR}/include")

set(SHADERC_VERSION "v2026.2")
set(SHADERC_DIR "${CMAKE_SOURCE_DIR}/vendor/vulkan/shaderc")
set(SHADERC_DOWNLOAD "https://github.com/google/shaderc/archive/refs/tags/${SHADERC_VERSION}.tar.gz")
ExternalProject_Add(shaderc
URL ${SHADERC_DOWNLOAD}
PREFIX ${CMAKE_BINARY_DIR}/shaderc
SOURCE_DIR ${SHADERC_DIR}
UPDATE_COMMAND cd ${SHADERC_DIR} && $<TARGET_FILE:Python::Interpreter> utils/git-sync-deps
PATCH_COMMAND $<TARGET_FILE:replace>
"${SHADERC_DIR}/third_party/glslang/CMakeLists.txt"
"if \\(GLSLANG_ENABLE_INSTALL\\)"
"if(FALSE)"
CMAKE_ARGS
-DSHADERC_SKIP_TESTS=ON
-DSHADERC_SKIP_INSTALL=ON
-DSHADERC_SKIP_EXAMPLES=ON
-DCMAKE_BUILD_TYPE=Release
-G "${CMAKE_GENERATOR}"
BUILD_COMMAND $(MAKE) -C <BINARY_DIR> glslc_exe
INSTALL_COMMAND ""
)
ExternalProject_Add_StepDependencies(shaderc patch replace)
ExternalProject_Get_Property(shaderc BINARY_DIR)

add_executable(glslc IMPORTED)
set_target_properties(glslc PROPERTIES IMPORTED_LOCATION "${BINARY_DIR}/glslc/glslc${CMAKE_EXECUTABLE_SUFFIX}")
add_dependencies(glslc shaderc)

file(GLOB_RECURSE GLSL_SOURCES "${CMAKE_SOURCE_DIR}/shaders/*.glsl")
set(GENERATED_HEADERS "")
foreach(GLSL ${GLSL_SOURCES})
get_filename_component(GLSL_NAME ${GLSL} NAME_WE)

set(SPIRV_OUT ${CMAKE_BINARY_DIR}/shaders/${GLSL_NAME}.spirv)
set(HEADER_OUT ${CMAKE_BINARY_DIR}/include/shaders/${GLSL_NAME}.h)

add_custom_command(
OUTPUT ${SPIRV_OUT}
COMMAND $<TARGET_FILE:glslc> -fshader-stage=comp ${GLSL} -o ${SPIRV_OUT}
DEPENDS ${GLSL}
COMMENT "Compiling shader: ${GLSL_NAME}"
)

add_custom_command(
OUTPUT ${HEADER_OUT}
COMMAND $<TARGET_FILE:xxd> ${SPIRV_OUT} > ${HEADER_OUT}
DEPENDS ${SPIRV_OUT} xxd
COMMENT "Embedding shader: ${GLSL_NAME}"
)

list(APPEND GENERATED_HEADERS ${HEADER_OUT})
endforeach()
add_custom_target(haio_shaders DEPENDS ${GENERATED_HEADERS} shaderc)
add_dependencies(${PROJECT_NAME} haio_shaders)

option(HAIO_TESTS "Unit Tests" OFF)
if(HAIO_TESTS)
include(CTest)
set(tests
"test_image_convert_png_to_ppm,library/codecs/png.cpp"
)
foreach(deps IN LISTS tests)
string(REPLACE "," ";${CMAKE_SOURCE_DIR}/" deps "${deps}")
list(GET deps 0 tests_name)
list(REMOVE_AT deps 0)
add_executable("${tests_name}" "${CMAKE_SOURCE_DIR}/tests/${tests_name}.cpp;${deps};${HAIO_LIB_SOURCES}")
target_link_libraries(${tests_name} PRIVATE volk)
add_dependencies(${tests_name} haio_shaders)
target_include_directories(${tests_name} PRIVATE "${CMAKE_SOURCE_DIR}/include;${CMAKE_BINARY_DIR}/include")
add_test(NAME "${tests_name}" COMMAND "${tests_name}")
endforeach()
endif()
cmake_minimum_required(VERSION 3.19)
include(FetchContent)
include(CheckCXXCompilerFlag)

project("haio" LANGUAGES C CXX)
if(POLICY CMP0167)
cmake_policy(SET CMP0167 NEW)
endif()
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Threads REQUIRED)
find_package(PNG REQUIRED)
find_package(Boost REQUIRED COMPONENTS url)
find_package(PkgConfig REQUIRED)
pkg_check_modules(WEBP REQUIRED IMPORTED_TARGET libwebp)

file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
file(GLOB_RECURSE HAIO_LIB_SOURCES "${CMAKE_CURRENT_LIST_DIR}/library/*/*.cpp")

set(ETCPAK_VERSION "2.1")
set(ETCPAK_DIR "${CMAKE_SOURCE_DIR}/vendor/etcpak")
set(ETCPAK_DOWNLOAD "https://github.com/wolfpld/etcpak/archive/refs/tags/${ETCPAK_VERSION}.tar.gz")
FetchContent_Populate(etcpak URL "${ETCPAK_DOWNLOAD}" SOURCE_DIR "${ETCPAK_DIR}")
set(ETCPAK_SOURCES
"${ETCPAK_DIR}/bcdec.c"
"${ETCPAK_DIR}/Decode.cpp"
"${ETCPAK_DIR}/Dither.cpp"
"${ETCPAK_DIR}/ProcessRGB.cpp"
"${ETCPAK_DIR}/Tables.cpp"
)

if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64|i[3-6]86)$")
check_cxx_compiler_flag("-msse4.1" HAIO_HAS_SSE41)
if(HAIO_HAS_SSE41)
set_source_files_properties(${ETCPAK_SOURCES} PROPERTIES COMPILE_OPTIONS "-msse4.1")
endif()
endif()

set(WUFFS_VERSION "v0.3.4")
set(WUFFS_DIR "${CMAKE_SOURCE_DIR}/vendor/wuffs")
set(WUFFS_DOWNLOAD "https://github.com/google/wuffs-mirror-release-c/archive/refs/tags/${WUFFS_VERSION}.tar.gz")
FetchContent_Populate(wuffs URL "${WUFFS_DOWNLOAD}" SOURCE_DIR "${WUFFS_DIR}")

add_library(haio_core STATIC ${HAIO_LIB_SOURCES} ${ETCPAK_SOURCES})
target_include_directories(haio_core
PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include"
PRIVATE "${ETCPAK_DIR}" "${WUFFS_DIR}/release/c"
)
target_link_libraries(haio_core PUBLIC PNG::PNG PkgConfig::WEBP Boost::headers Boost::url Threads::Threads)

if(WIN32)
file(GLOB_RECURSE HAIO_WINDOWS_SOURCES "${CMAKE_CURRENT_LIST_DIR}/source/platform/microslop/*.cpp")
target_sources(haio_core PRIVATE ${HAIO_WINDOWS_SOURCES})
endif()

add_executable(${PROJECT_NAME} "${CMAKE_CURRENT_LIST_DIR}/source/main.cpp")
target_link_libraries(${PROJECT_NAME} PRIVATE haio_core)
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")

option(HAIO_TESTS "Unit Tests" OFF)
if(HAIO_TESTS)
include(CTest)
set(tests
"test_image_convert_png_to_ppm"
"test_image_etc1_roundtrip"
"test_image_convert_png_to_etc1_ppm"
"test_gpu_formats_roundtrip"
"test_url_parsing"
)
foreach(test_name IN LISTS tests)
add_executable("${test_name}" "${CMAKE_SOURCE_DIR}/tests/${test_name}.cpp")
target_link_libraries("${test_name}" PRIVATE haio_core)
if(test_name STREQUAL "test_image_convert_png_to_ppm")
add_test(NAME "${test_name}" COMMAND "${test_name}" "${CMAKE_SOURCE_DIR}/assets/logo8x8.png" "${CMAKE_BINARY_DIR}/logo8x8_direct.ppm")
elseif(test_name STREQUAL "test_image_convert_png_to_etc1_ppm")
add_test(NAME "${test_name}" COMMAND "${test_name}" "${CMAKE_SOURCE_DIR}/assets/logo8x8.png" "${CMAKE_BINARY_DIR}/logo8x8_etc1.ppm")
else()
add_test(NAME "${test_name}" COMMAND "${test_name}")
endif()
endforeach()
endif()
91 changes: 46 additions & 45 deletions include/haio.hpp
Original file line number Diff line number Diff line change
@@ -1,45 +1,46 @@
#include "haio_common.hpp"
#include "haio_formats.hpp"
#include "haio_iwindow.hpp"
#include "haio_vulkan.hpp"

namespace Haio {

struct Image {
Format type;
int width;
int height;
std::vector<uint8_t> data;
};

using Stage = std::function<Image(const Image&)>;

template<Format F>
Stage Encode();

template<Format F>
Stage Decode();

inline Stage operator|(Stage a, Stage b) {
return [=](const Image& img) {
return b(a(img));
};
}

inline Image operator>>(std::istream& in, Stage decode) {
std::vector<uint8_t> buffer(
(std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>()
);
Image raw{Format::RAW, 0, 0, std::move(buffer)};
return decode(raw);
}

inline std::ostream& operator>>(const Image& img, std::ostream& out) {
out.write(reinterpret_cast<const char*>(img.data.data()), img.data.size());
return out;
}

std::unique_ptr<IWindow> CreateWindow(const char* title, int width, int height);

}
#include "haio_common.hpp"
#include "haio_formats.hpp"
#include "haio_buffer.hpp"
#include "haio_iwindow.hpp"
#include "haio_pipeline.hpp"

namespace Haio {

struct Image {
Format type;
int width;
int height;
std::vector<uint8_t> data;
};

using Stage = std::function<Image(const Image&)>;

template<Format F>
Stage Encode();

template<Format F>
Stage Decode();

inline Stage operator|(Stage a, Stage b) {
return [=](const Image& img) {
return b(a(img));
};
}

inline Image operator>>(std::istream& in, Stage decode) {
std::vector<uint8_t> buffer(
(std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>()
);
Image raw{Format::RAW, 0, 0, std::move(buffer)};
return decode(raw);
}

inline std::ostream& operator>>(const Image& img, std::ostream& out) {
out.write(reinterpret_cast<const char*>(img.data.data()), img.data.size());
return out;
}

std::unique_ptr<IWindow> CreateWindow(const char* title, int width, int height);

}
11 changes: 11 additions & 0 deletions include/haio_buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include "haio_common.hpp"
#include "haio_formats.hpp"

namespace Haio::Buffer {

template<Format From, Format To>
void Copy(const std::vector<uint8_t>& input, std::vector<uint8_t>& output);

}
32 changes: 32 additions & 0 deletions include/haio_cdn.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once

#include "haio.hpp"

#include <boost/asio/awaitable.hpp>

#include <filesystem>
#include <map>

namespace Haio::Cdn {

struct BucketConfig {
std::string name;
std::string type = "file";
std::filesystem::path root = ".";
std::string host;
std::string prefix;
std::string endpoint;
std::map<std::string, std::string> values;
};

struct Config {
std::string host = "0.0.0.0";
unsigned short port = 8080;
std::map<std::string, BucketConfig> buckets;
};

Config loadConfig(const std::filesystem::path& path, std::filesystem::path defaultRoot = ".");
boost::asio::awaitable<Blob> fetchBucket(const Config& config, std::string bucket, std::string path);
boost::asio::awaitable<void> runServer(Config config);

}
35 changes: 21 additions & 14 deletions include/haio_formats.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
#pragma once

namespace Haio {

enum class Format {
RAW,
PNG,
PPM,
RGBA8888,
RGB888,
YUV420
};

}
#pragma once

namespace Haio {

enum class Format {
RAW,
PNG,
PPM,
WEBP,
RGBA8888,
RGB888,
YUV420,
ETC1,
RGB565,
PVR,
DDS,
KTX,
KTX2
};

}
9 changes: 4 additions & 5 deletions include/haio_iwindow.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once
#include "haio_iwindow.hpp"

namespace Haio {
#pragma once

namespace Haio {

class IWindow {
public:
Expand All @@ -13,4 +12,4 @@ class IWindow {
virtual bool shouldClose() const = 0;
};

}
}
Loading