diff --git a/CMakeLists.txt b/CMakeLists.txt index d4033ca0a..276234a92 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_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DRELEASE=1") - - set(CMAKE_VERBOSE_MAKEFILE on) -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) +# 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") + +if(KOMPUTE_OPT_ENABLE_SPDLOG) + set(KOMPUTE_EXTRA_CXX_FLAGS "${KOMPUTE_EXTRA_CXX_FLAGS} -DKOMPUTE_ENABLE_SPDLOG=1") +endif() + +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 de52676e7..849ecfd01 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 76660f1c6..8b5d9fab4 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 8d41f50cf..3f2a6d1b5 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 238e79083..b7fd244ef 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 4a91112ae..d3df76d85 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 0f4b2a8ae..dad8d3d30 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 a803b5a93..bdeef5763 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 dee949527..e46b697c0 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 3d196b05c..e2aca74c7 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 466af2e46..6e4a4ab4f 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 6c7ab10db..9242d766d 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 1cadbf125..d4543cb4c 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 107f34509..07a14467a 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 27474ec8d..5661a7c63 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 08c98e8af..a5dca3a4e 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 372b4f070..367a64ac3 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 a9d6d02dc..56a5a971e 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 44dfe0805..c60efeeb8 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") {