diff --git a/CMakeLists.txt b/CMakeLists.txt index d4033ca0..276234a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,16 +4,22 @@ project(kompute VERSION 0.1.0) set(CMAKE_CXX_STANDARD 17) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_VERBOSE_MAKEFILE on) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DRELEASE=1") +# Enable or disable targets +option(KOMPUTE_OPT_BUILD_TESTS "Enable if you want to build tests" 1) +option(KOMPUTE_OPT_BUILD_DOCS "Enable if you want to build documentation" 1) +option(KOMPUTE_OPT_DEBUG_SYMBOLS "Enable if you want to build debug with symbols" 0) +option(KOMPUTE_OPT_ENABLE_SPDLOG "Extra compile flags for Kompute, see docs for full list" 1) +set(KOMPUTE_EXTRA_CXX_FLAGS "" CACHE STRING "Extra compile flags for Kompute, see docs for full list") -set(CMAKE_VERBOSE_MAKEFILE on) +if(KOMPUTE_OPT_ENABLE_SPDLOG) + set(KOMPUTE_EXTRA_CXX_FLAGS "${KOMPUTE_EXTRA_CXX_FLAGS} -DKOMPUTE_ENABLE_SPDLOG=1") +endif() -option(KOMPUTE_OPT_BUILD_TESTS "Enable if you want to build tests" ON) -option(KOMPUTE_OPT_BUILD_DOCS "Enable if you want to build documentation" ON) -option(KOMPUTE_OPT_DEBUG_SYMBOLS "Enable if you want to build debug with symbols" 0) +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1 ${KOMPUTE_EXTRA_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DRELEASE=1 ${KOMPUTE_EXTRA_CXX_FLAGS}") # Allow scripts to call main kompute Makefile function(kompute_make KOMPUTE_MAKE_TARGET) diff --git a/Makefile b/Makefile index de52676e..849ecfd0 100755 --- a/Makefile +++ b/Makefile @@ -73,12 +73,14 @@ mk_run_tests: mk_build_tests ####### Visual studio build shortcut commands ####### VS_BUILD_TYPE ?= "Debug" +VS_CMAKE_EXTRA_FLAGS ?= "" vs_cmake: $(CMAKE_BIN) \ -Bbuild \ -DCMAKE_TOOLCHAIN_FILE=$(VCPKG_WIN_PATH) \ -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ + $(VS_CMAKE_EXTRA_FLAGS) \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ -G "Visual Studio 16 2019" diff --git a/README.md b/README.md index 76660f1c..8b5d9fab 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ * Explicit relationships for GPU and host memory ownership and memory management * Providing [simple usecases]() as well as [advanced machine learning & data processing](https://axsaucedo.github.io/vulkan-kompute/overview/advanced-examples.html) examples + +![](https://raw.githubusercontent.com/axsaucedo/vulkan-kompute/master/docs/images/komputer-2.gif) + + ## Getting Started ### Setup @@ -177,6 +181,32 @@ We cover more advanced examples and applications of Vulkan Kompute, such as mach You can find these in the advanced examples documentation section, such as the [logistic regression example](https://axsaucedo.github.io/vulkan-kompute/overview/advanced-examples.html). +## Build Overview + +### Dependencies + +Given Kompute is expected to be used across a broad range of architectures and hardware, it will be important to make sure we are able to minimise dependencies. + +#### Required dependencies + +The only required dependency in the build is Vulkan (vulkan.h and vulkan.hpp which are both part of the Vulkan SDK). + +#### Optional dependencies + +SPDLOG is the preferred logging library, however by default Vulkan Kompute runs without SPDLOG by overriding the macros. It also provides an easy way to override the macros if you prefer to bring your own logging framework. The macro override is the following: + +```c++ +#ifndef KOMPUTE_LOG_OVERRIDE // Use this if you want to define custom macro overrides +#if KOMPUTE_SPDLOG_ENABLED // Use this if you want to enable SPDLOG +#include +#endif //KOMPUTE_SPDLOG_ENABLED +// ... Otherwise it adds macros that use std::cout (and only print first element) +#endif // KOMPUTE_LOG_OVERRIDE +``` + +You can choose to build with or without SPDLOG by using the cmake flag `KOMPUTE_OPT_ENABLE_SPDLOG`. + + ## Motivations Vulkan Kompute was created after identifying the challenge most GPU processing projects with Vulkan undergo - namely having to build extensive boilerplate for Vulkan and create abstractions and interfaces that expose the core compute capabilities. It is only after a few thousand lines of code that it's possible to start building the application-specific logic. @@ -275,8 +305,3 @@ make mk_cmake MK_BUILD_TYPE="Release" make mk_run_tests ``` - -# The Komputer is waiting for instructions... - -![](https://raw.githubusercontent.com/axsaucedo/vulkan-kompute/master/docs/images/komputer-2.gif) - diff --git a/single_include/kompute/Kompute.hpp b/single_include/kompute/Kompute.hpp index 8d41f50c..3f2a6d1b 100755 --- a/single_include/kompute/Kompute.hpp +++ b/single_include/kompute/Kompute.hpp @@ -4,10 +4,38 @@ // SPDLOG_ACTIVE_LEVEL must be defined before spdlog.h import #if DEBUG +#ifndef SPDLOG_ACTIVE_LEVEL #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG +#endif #endif +#ifndef KOMPUTE_LOG_OVERRIDE +#if KOMPUTE_ENABLE_SPDLOG #include +#else +#include +#if SPDLOG_ACTIVE_LEVEL > 1 +#define SPDLOG_DEBUG(message, ...) +#else +#define SPDLOG_DEBUG(message, ...) std::cout << "DEBUG: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 1 +#if SPDLOG_ACTIVE_LEVEL > 2 +#define SPDLOG_INFO(message, ...) +#else +#define SPDLOG_INFO(message, ...) std::cout << "INFO: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 2 +#if SPDLOG_ACTIVE_LEVEL > 3 +#define SPDLOG_WARN(message, ...) +#else +#define SPDLOG_WARN(message, ...) std::cout << "WARNING: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 3 +#if SPDLOG_ACTIVE_LEVEL > 4 +#define SPDLOG_ERROR(message, ...) +#else +#define SPDLOG_ERROR(message, ...) std::cout << "ERROR: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 4 +#endif //KOMPUTE_SPDLOG_ENABLED +#endif // KOMPUTE_LOG_OVERRIDE /* THIS FILE HAS BEEN AUTOMATICALLY GENERATED - DO NOT EDIT @@ -407,7 +435,7 @@ class OpBase SPDLOG_DEBUG("Kompute OpBase destructor started"); if (!this->mDevice) { - spdlog::warn("Kompute OpBase destructor called with empty device"); + SPDLOG_WARN("Kompute OpBase destructor called with empty device"); return; } @@ -417,7 +445,7 @@ class OpBase if (tensor && tensor->isInit()) { tensor->freeMemoryDestroyGPUResources(); } else { - spdlog::error("Kompute OpBase expected to free " + SPDLOG_ERROR("Kompute OpBase expected to free " "tensor but has already been freed."); } } @@ -550,7 +578,7 @@ class Sequence SPDLOG_DEBUG("Kompute Sequence record function started"); if (!this->isRecording()) { - spdlog::error( + SPDLOG_ERROR( "Kompute sequence record attempted when not record BEGIN"); return false; } @@ -999,7 +1027,7 @@ OpAlgoBase::OpAlgoBase(std::shared_ptr physicalD this->mY = 1; this->mZ = 1; } - spdlog::info("Kompute OpAlgoBase dispatch size X: {}, Y: {}, Z: {}", + SPDLOG_INFO("Kompute OpAlgoBase dispatch size X: {}, Y: {}, Z: {}", this->mX, this->mY, this->mZ); diff --git a/src/Algorithm.cpp b/src/Algorithm.cpp index 238e7908..b7fd244e 100644 --- a/src/Algorithm.cpp +++ b/src/Algorithm.cpp @@ -23,7 +23,7 @@ Algorithm::~Algorithm() SPDLOG_DEBUG("Kompute Algorithm Destructor started"); if (!this->mDevice) { - spdlog::error( + SPDLOG_ERROR( "Kompute Algorithm destructor reached with null Device pointer"); return; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4a91112a..d3df76d8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,4 @@ -find_package(fmt REQUIRED) find_package(spdlog REQUIRED) find_package(Vulkan REQUIRED) @@ -25,11 +24,16 @@ target_include_directories( target_link_libraries( kompute - fmt::fmt - spdlog::spdlog Vulkan::Vulkan ) +if(KOMPUTE_OPT_ENABLE_SPDLOG) + target_link_libraries( + kompute + spdlog::spdlog + ) +endif() + add_dependencies(kompute build_shaders build_single_header) diff --git a/src/Manager.cpp b/src/Manager.cpp index 0f4b2a8a..dad8d3d3 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -50,7 +50,7 @@ Manager::~Manager() SPDLOG_DEBUG("Kompute Manager Destructor started"); if (this->mDevice == nullptr) { - spdlog::error( + SPDLOG_ERROR( "Kompute Manager destructor reached with null Device pointer"); return; } @@ -61,13 +61,13 @@ Manager::~Manager() } if (this->mFreeDevice) { - spdlog::info("Destroying device"); + SPDLOG_INFO("Destroying device"); this->mDevice->destroy(); SPDLOG_DEBUG("Kompute Manager Destroyed Device"); } if (this->mInstance == nullptr) { - spdlog::error( + SPDLOG_ERROR( "Kompute Manager destructor reached with null Instance pointer"); return; } @@ -214,7 +214,7 @@ Manager::createDevice() vk::PhysicalDeviceProperties physicalDeviceProperties = physicalDevice.getProperties(); - spdlog::info("Using physical device index {} found {}", + SPDLOG_INFO("Using physical device index {} found {}", this->mPhysicalDeviceIndex, physicalDeviceProperties.deviceName); @@ -234,7 +234,7 @@ Manager::createDevice() } if (this->mComputeQueueFamilyIndex < 0) { - spdlog::critical("Compute queue is not supported"); + throw std::runtime_error("Compute queue is not supported"); } const float defaultQueuePriority(0.0f); diff --git a/src/Sequence.cpp b/src/Sequence.cpp index a803b5a9..bdeef576 100644 --- a/src/Sequence.cpp +++ b/src/Sequence.cpp @@ -28,15 +28,15 @@ Sequence::~Sequence() SPDLOG_DEBUG("Kompute Sequence Destructor started"); if (!this->mDevice) { - spdlog::error( + SPDLOG_ERROR( "Kompute Sequence destructor reached with null Device pointer"); return; } if (this->mFreeCommandBuffer) { - spdlog::info("Freeing CommandBuffer"); + SPDLOG_INFO("Freeing CommandBuffer"); if (!this->mCommandBuffer) { - spdlog::error("Kompute Sequence destructor reached with null " + SPDLOG_ERROR("Kompute Sequence destructor reached with null " "CommandPool pointer"); return; } @@ -46,9 +46,9 @@ Sequence::~Sequence() } if (this->mFreeCommandPool) { - spdlog::info("Destroying CommandPool"); + SPDLOG_INFO("Destroying CommandPool"); if (this->mCommandPool == nullptr) { - spdlog::error("Kompute Sequence destructor reached with null " + SPDLOG_ERROR("Kompute Sequence destructor reached with null " "CommandPool pointer"); return; } @@ -71,7 +71,7 @@ Sequence::begin() SPDLOG_DEBUG("Kompute sequence called BEGIN"); if (this->isRecording()) { - spdlog::warn("Kompute Sequence begin called when already recording"); + SPDLOG_WARN("Kompute Sequence begin called when already recording"); return false; } @@ -80,11 +80,11 @@ Sequence::begin() } if (!this->mRecording) { - spdlog::info("Kompute Sequence command recording BEGIN"); + SPDLOG_INFO("Kompute Sequence command recording BEGIN"); this->mCommandBuffer->begin(vk::CommandBufferBeginInfo()); this->mRecording = true; } else { - spdlog::warn("Kompute Sequence attempted to start command recording " + SPDLOG_WARN("Kompute Sequence attempted to start command recording " "but recording already started"); } return true; @@ -96,7 +96,7 @@ Sequence::end() SPDLOG_DEBUG("Kompute Sequence calling END"); if (!this->isRecording()) { - spdlog::warn("Kompute Sequence end called when not recording"); + SPDLOG_WARN("Kompute Sequence end called when not recording"); return false; } @@ -105,11 +105,11 @@ Sequence::end() } if (this->mRecording) { - spdlog::info("Kompute Sequence command recording END"); + SPDLOG_INFO("Kompute Sequence command recording END"); this->mCommandBuffer->end(); this->mRecording = false; } else { - spdlog::warn("Kompute Sequence attempted to end command recording but " + SPDLOG_WARN("Kompute Sequence attempted to end command recording but " "recording not started"); } return true; @@ -121,7 +121,7 @@ Sequence::eval() SPDLOG_DEBUG("Kompute sequence compute recording EVAL"); if (this->isRecording()) { - spdlog::warn("Kompute Sequence eval called when still recording"); + SPDLOG_WARN("Kompute Sequence eval called when still recording"); return false; } diff --git a/src/Tensor.cpp b/src/Tensor.cpp index dee94952..e46b697c 100644 --- a/src/Tensor.cpp +++ b/src/Tensor.cpp @@ -1,6 +1,9 @@ #if DEBUG -#include +#if KOMPUTE_SPDLOG_ENABLED +// Only enabled if spdlog is enabled +#include +#endif #endif #include "kompute/Tensor.hpp" @@ -169,7 +172,7 @@ Tensor::mapDataFromHostMemory() SPDLOG_DEBUG("Kompute Tensor mapping data from host buffer"); if (this->mTensorType != TensorTypes::eStaging) { - spdlog::error( + SPDLOG_ERROR( "Mapping tensor data manually from DEVICE buffer instead of " "using record GPU command with staging buffer"); return; @@ -191,7 +194,7 @@ Tensor::mapDataIntoHostMemory() SPDLOG_DEBUG("Kompute Tensor local mapping tensor data to host buffer"); if (this->mTensorType != TensorTypes::eStaging) { - spdlog::error( + SPDLOG_ERROR( "Mapping tensor data manually to DEVICE memory instead of " "using record GPU command with staging buffer"); return; @@ -335,14 +338,14 @@ Tensor::freeMemoryDestroyGPUResources() this->mIsInit = false; if (!this->mDevice) { - spdlog::error( + SPDLOG_ERROR( "Kompute Tensor destructor reached with null Device pointer"); return; } if (this->mFreeBuffer) { if (!this->mBuffer) { - spdlog::error( + SPDLOG_ERROR( "Kompose Tensor expected to free buffer but got null buffer"); } else { SPDLOG_DEBUG("Kompose Tensor destroying buffer"); @@ -353,7 +356,7 @@ Tensor::freeMemoryDestroyGPUResources() if (this->mFreeMemory) { if (!this->mMemory) { - spdlog::error( + SPDLOG_ERROR( "Kompose Tensor expected to free buffer but got null memory"); } else { SPDLOG_DEBUG("Kompose Tensor freeing memory"); diff --git a/src/include/kompute/Core.hpp b/src/include/kompute/Core.hpp index 3d196b05..e2aca74c 100644 --- a/src/include/kompute/Core.hpp +++ b/src/include/kompute/Core.hpp @@ -4,7 +4,36 @@ // SPDLOG_ACTIVE_LEVEL must be defined before spdlog.h import #if DEBUG +#ifndef SPDLOG_ACTIVE_LEVEL #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG +#endif #endif +#ifndef KOMPUTE_LOG_OVERRIDE +#if KOMPUTE_ENABLE_SPDLOG #include +#else +#include +#if SPDLOG_ACTIVE_LEVEL > 1 +#define SPDLOG_DEBUG(message, ...) +#else +#define SPDLOG_DEBUG(message, ...) std::cout << "DEBUG: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 1 +#if SPDLOG_ACTIVE_LEVEL > 2 +#define SPDLOG_INFO(message, ...) +#else +#define SPDLOG_INFO(message, ...) std::cout << "INFO: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 2 +#if SPDLOG_ACTIVE_LEVEL > 3 +#define SPDLOG_WARN(message, ...) +#else +#define SPDLOG_WARN(message, ...) std::cout << "WARNING: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 3 +#if SPDLOG_ACTIVE_LEVEL > 4 +#define SPDLOG_ERROR(message, ...) +#else +#define SPDLOG_ERROR(message, ...) std::cout << "ERROR: " << message << std::endl +#endif // SPDLOG_ACTIVE_LEVEL > 4 +#endif //KOMPUTE_SPDLOG_ENABLED +#endif // KOMPUTE_LOG_OVERRIDE + diff --git a/src/include/kompute/Sequence.hpp b/src/include/kompute/Sequence.hpp index 466af2e4..6e4a4ab4 100644 --- a/src/include/kompute/Sequence.hpp +++ b/src/include/kompute/Sequence.hpp @@ -92,7 +92,7 @@ class Sequence SPDLOG_DEBUG("Kompute Sequence record function started"); if (!this->isRecording()) { - spdlog::error( + SPDLOG_ERROR( "Kompute sequence record attempted when not record BEGIN"); return false; } diff --git a/src/include/kompute/operations/OpAlgoBase.hpp b/src/include/kompute/operations/OpAlgoBase.hpp index 6c7ab10d..9242d766 100644 --- a/src/include/kompute/operations/OpAlgoBase.hpp +++ b/src/include/kompute/operations/OpAlgoBase.hpp @@ -185,7 +185,7 @@ OpAlgoBase::OpAlgoBase(std::shared_ptr physicalD this->mY = 1; this->mZ = 1; } - spdlog::info("Kompute OpAlgoBase dispatch size X: {}, Y: {}, Z: {}", + SPDLOG_INFO("Kompute OpAlgoBase dispatch size X: {}, Y: {}, Z: {}", this->mX, this->mY, this->mZ); diff --git a/src/include/kompute/operations/OpBase.hpp b/src/include/kompute/operations/OpBase.hpp index 1cadbf12..d4543cb4 100644 --- a/src/include/kompute/operations/OpBase.hpp +++ b/src/include/kompute/operations/OpBase.hpp @@ -59,7 +59,7 @@ class OpBase SPDLOG_DEBUG("Kompute OpBase destructor started"); if (!this->mDevice) { - spdlog::warn("Kompute OpBase destructor called with empty device"); + SPDLOG_WARN("Kompute OpBase destructor called with empty device"); return; } @@ -69,7 +69,7 @@ class OpBase if (tensor && tensor->isInit()) { tensor->freeMemoryDestroyGPUResources(); } else { - spdlog::error("Kompute OpBase expected to free " + SPDLOG_ERROR("Kompute OpBase expected to free " "tensor but has already been freed."); } } diff --git a/test/TestLogisticRegression.cpp b/test/TestLogisticRegression.cpp index 107f3450..07a14467 100644 --- a/test/TestLogisticRegression.cpp +++ b/test/TestLogisticRegression.cpp @@ -3,8 +3,6 @@ #include "kompute/Kompute.hpp" -#include - TEST_CASE("test_logistic_regression") { uint32_t ITERATIONS = 100; @@ -77,6 +75,6 @@ TEST_CASE("test_logistic_regression") { REQUIRE(wIn->data()[1] > 1.0); REQUIRE(bIn->data()[0] < 0.0); - SPDLOG_DEBUG("Result wIn: {}, bIn: {}", - wIn->data(), bIn->data()); + //SPDLOG_DEBUG("Result wIn: {}, bIn: {}", + // wIn->data(), bIn->data()); } diff --git a/test/TestMain.cpp b/test/TestMain.cpp index 27474ec8..5661a7c6 100644 --- a/test/TestMain.cpp +++ b/test/TestMain.cpp @@ -2,23 +2,19 @@ // clang-format: SPDLOG_ACTIVE_LEVEL must be defined before spdlog.h import #if DEBUG +#ifndef SPDLOG_ACTIVE_LEVEL #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #endif +#endif -#include -// clang-format: ranges.h must come after spdlog.h -#include +//#include +//// clang-format: ranges.h must come after spdlog.h +//#include #include "catch2/catch.hpp" int main( int argc, char* argv[] ) { -#if DEBUG - spdlog::set_level(spdlog::level::debug); -#else - spdlog::set_level(spdlog::level::info); -#endif - int result = Catch::Session().run( argc, argv ); // global clean-up... diff --git a/test/TestManager.cpp b/test/TestManager.cpp index 08c98e8a..a5dca3a4 100755 --- a/test/TestManager.cpp +++ b/test/TestManager.cpp @@ -3,8 +3,6 @@ #include "kompute/Kompute.hpp" -#include - TEST_CASE("End to end OpMult Flow should execute correctly from manager") { kp::Manager mgr; @@ -20,17 +18,8 @@ TEST_CASE("End to end OpMult Flow should execute correctly from manager") { 0, 0, 0 }) }; mgr.evalOp({ tensorOutput }); - spdlog::info("OpCreateTensor success for tensors"); - spdlog::info("Tensor one: {}", tensorLHS->data()); - spdlog::info("Tensor two: {}", tensorRHS->data()); - spdlog::info("Tensor output: {}", tensorOutput->data()); - - spdlog::info("Calling op mult"); mgr.evalOp>({ tensorLHS, tensorRHS, tensorOutput }); - spdlog::info("OpMult call success"); - spdlog::info("Tensor output: {}", tensorOutput->data()); - REQUIRE(tensorOutput->data() == std::vector{0, 4, 12}); } diff --git a/test/TestMultipleAlgoExecutions.cpp b/test/TestMultipleAlgoExecutions.cpp index 372b4f07..367a64ac 100644 --- a/test/TestMultipleAlgoExecutions.cpp +++ b/test/TestMultipleAlgoExecutions.cpp @@ -3,8 +3,6 @@ #include "kompute/Kompute.hpp" -#include - TEST_CASE("test_multiple_algo_exec_single_cmd_buf_record") { kp::Manager mgr; diff --git a/test/TestOpCreateTensor.cpp b/test/TestOpCreateTensor.cpp index a9d6d02d..56a5a971 100644 --- a/test/TestOpCreateTensor.cpp +++ b/test/TestOpCreateTensor.cpp @@ -3,8 +3,6 @@ #include "kompute/Kompute.hpp" -#include - TEST_CASE("test_opcreatetensor_create_single_tensor") { kp::Manager mgr; diff --git a/test/TestOpShadersFromStringAndFile.cpp b/test/TestOpShadersFromStringAndFile.cpp index 44dfe080..c60efeeb 100644 --- a/test/TestOpShadersFromStringAndFile.cpp +++ b/test/TestOpShadersFromStringAndFile.cpp @@ -3,8 +3,6 @@ #include "kompute/Kompute.hpp" -#include - #include "kompute_test/shaders/shadertest_op_custom_shader.hpp" TEST_CASE("test_op_shader_raw_data_from_constructor") {