Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jamylak committed May 4, 2024
1 parent a820f03 commit 1d9279a
Show file tree
Hide file tree
Showing 35 changed files with 2,605 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Never
41 changes: 41 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Continuous Integration

on:
pull_request:
branches:
- main

jobs:
build-and-test-linux:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Build Docker image
run: docker build -t linux-tests -f linux-tests.Dockerfile .

- name: Test with Docker
run: docker run linux-tests

build-and-test-macos:
name: Build and Test on macOS
runs-on: macos-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install dependencies
run: |
brew install glfw glslang spdlog glm vulkan-tools googletest
- name: Configure
run: cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTS=ON -B build

- name: Build
run: cmake --build build

- name: Run tests
run: build/tests/vsdf_tests && build/tests/filewatcher/filewatcher_tests
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
a.out
.cache/clangd/index
build
testshaders
shaders/fullscreenquad.spv
42 changes: 42 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.6)

set(CMAKE_CXX_STANDARD 20)
project(vsdf)

find_package(glfw3 REQUIRED)
find_package(Vulkan REQUIRED)
find_package(glslang REQUIRED)
find_package(spdlog REQUIRED)
find_package(glm REQUIRED)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()

add_executable(${PROJECT_NAME} src/main.cpp src/shader_utils.cpp src/sdf_renderer.cpp)

if(APPLE)
message("Building filewatcher for macOS")
target_sources(${PROJECT_NAME} PRIVATE src/filewatcher/mac_filewatcher.cpp)
find_library(CORE_SERVICES_LIBRARY CoreServices)
target_link_libraries(${PROJECT_NAME} PRIVATE ${CORE_SERVICES_LIBRARY})
elseif(UNIX AND NOT APPLE)
# Print building linux
message("Building filewatcher for Linux")
find_package(Threads REQUIRED)
target_sources(${PROJECT_NAME} PRIVATE src/filewatcher/linux_filewatcher.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
endif()

target_link_libraries(${PROJECT_NAME} PRIVATE glfw Vulkan::Vulkan spdlog::spdlog glslang::glslang glslang::glslang-default-resource-limits glslang::SPIRV)
include_directories(${PROJECT_NAME} PRIVATE include ${GLM_INCLUDE_DIRS})

# Option to enable or disable the building of tests
option(BUILD_TESTS "Build the tests" OFF)

if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# I mainly just use this to do quick :make
# See README.md for real build instructions
all:
@./scripts/build_quiet.sh
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# VSDF
Vulkan SDF Renderer + Hot Reloader

![Preview](https://i.imgur.com/88KG4NL.gif)

Render an SDF like ShaderToy using Vulkan and hot reload based on frag shader changes.
That way you can use your favourite editor / LSP and also utilise git.

## Platforms
Supports Mac & Linux currently because it contains filewatcher implementations for those platforms so far but could add Windows and then the rest of the code should work on there...

## Build
```sh
cmake -B build .
cmake --build build
./build/vsdf {filepath}.frag
```

## Usage
### With shader toy shaders (most seem to work)
```sh
./vsdf --toy path/to/shader.frag
```

Note: That if you use `--toy` we will prepend a template in
`shaders/toytemplate.frag` which sets up the push constants
like `iTime` and we will also follow this logic.

```cpp
if (useToyTemplate) {
Client = glslang::EShClientOpenGL;
ClientVersion = glslang::EShTargetOpenGL_450;
} else {
Client = glslang::EShClientVulkan;
ClientVersion = glslang::EShTargetVulkan_1_0;
}
```

### Manually create your own vulkan compatible shader
If you don't want any template prepended or you have issues
loading that way, I recommend copying `shaders/vulktemplate.frag`
and adjusting it to your liking

- See `shaders/vulktemplate.frag` to see how push constants
are passed in
```sh
./vsdf path/to/shader.frag
```

## Test Build
```sh
cmake -B build -DBUILD_TESTS=ON -DDEBUG=ON
./build/tests/vsdf_tests
./build/tests/filewatcher/filewatcher_tests
```

## Nix Develop Shell
```sh
nix develop
```

### Credits:
- https://shadertoy.com
- https://iquilezles.org/
- https://www.youtube.com/playlist?list=PL0JVLUVCkk-l7CWCn3-cdftR0oajugYvd (zeux)

### CPP Guidelines
(I should try follow this but haven't gotten through it all yet)
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 68 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Based on
# https://github.com/nixvital/nix-based-cpp-starterkit/tree/main
{
description = "vsdf";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/23.11";
utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, ... }@inputs: inputs.utils.lib.eachSystem [
"x86_64-linux"
"i686-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
]
(system:
let
pkgs = import nixpkgs {
inherit system;

# Add overlays here if you need to override the nixpkgs
# official packages.
overlays = [ ];

# Uncomment this if you need unfree software (e.g. cuda) for
# your project.
#
# config.allowUnfree = true;
};
in
{
devShells.default = pkgs.mkShell rec {
name = "vsdf";

packages = with pkgs; [
# Development Tools
llvmPackages_14.clang
cmake
cmakeCurses

# Development time dependencies
gtest

# Dependencies
glfw
glm
spdlog
boost
vulkan-loader
vulkan-headers
];

# Setting up the environment variables you need during
# development.
shellHook =
let
icon = "f121";
in
''
export PS1="$(echo -e '\u${icon}') {\[$(tput sgr0)\]\[\033[38;5;228m\]\w\[$(tput sgr0)\]\[\033[38;5;15m\]} (${name}) \\$ \[$(tput sgr0)\]"
'';
};

packages.default = pkgs.callPackage ./default.nix { };
});
}
32 changes: 32 additions & 0 deletions include/fileutils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef FILEUTILS_H
#define FILEUTILS_H

#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

[[nodiscard]] static std::vector<char>
loadBinaryFile(const std::string &filename) {
std::ifstream file(filename, std::ios::ate | std::ios::binary);

if (!file.is_open()) {
throw std::runtime_error("Failed to open file: " + filename);
}

size_t fileSize = static_cast<size_t>(file.tellg());
std::vector<char> buffer(fileSize);

file.seekg(0);
file.read(buffer.data(), fileSize);

if (file.gcount() != fileSize) {
throw std::runtime_error("Failed to read the complete file: " +
filename);
}

return buffer;
};

#endif // FILEUTILS_H
34 changes: 34 additions & 0 deletions include/filewatcher/filewatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef FILE_WATCHER_H
#define FILE_WATCHER_H

#include <functional>
#include <string>

// Abstract class for file watching
class FileWatcher {
public:
FileWatcher() = default;
using FileChangeCallback = std::function<void()>;

virtual ~FileWatcher() = default;

// Delete copy constructor and copy assignment operator
FileWatcher(const FileWatcher &) = delete;
FileWatcher &operator=(const FileWatcher &) = delete;

// Delete move constructor and move assignment operator
FileWatcher(FileWatcher &&) = delete;
FileWatcher &operator=(FileWatcher &&) = delete;

// Starts a thread to watch the file
virtual void startWatching(const std::string &filepath,
FileChangeCallback callback) = 0;

// Allows the thread watching the file to instantly stop
virtual void stopWatching() = 0;

protected:
FileChangeCallback callback;
};

#endif // FILE_WATCHER_H
23 changes: 23 additions & 0 deletions include/filewatcher/filewatcher_factory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef FILEWATCHERFACTORY_H
#define FILEWATCHERFACTORY_H

#ifdef __APPLE__
#include "mac_filewatcher.h"
#elif __linux__
#include "linux_filewatcher.h"
#else
#error "Unsupported platform."
#endif

namespace filewatcher_factory {
static std::unique_ptr<FileWatcher> createFileWatcher() {
#ifdef __APPLE__
return std::make_unique<MacFileWatcher>();
#elif __linux__
return std::make_unique<LinuxFileWatcher>();
#else
return nullptr; // Handle unsupported platforms gracefully
#endif
}
} // namespace filewatcher_factory
#endif // FILEWATCHERFACTORY_H
Loading

0 comments on commit 1d9279a

Please sign in to comment.