diff --git a/.github/linux.yml b/.github/linux.yml deleted file mode 100644 index a0be0b0..0000000 --- a/.github/linux.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Linux Build Tests - -on: [pull_request] - -jobs: - linux-build: - name: "Linux-Build" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install LLVM - run: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh - - - name: Install LLVM's C++ Standard Library - run: sudo apt install libc++-17-dev libc++abi-17-dev - - - name: Installing pipx - run: sudo apt install pipx - - - name: Installing Prerequisites for Linux - run: | - sudo apt-get update - sudo apt install lsb-release wget software-properties-common gnupg libgtk2.0-dev libgl1-mesa-dev -y - # sudo apt install libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxt-dev libxtst-dev libxrender-dev libxrandr-dev libxi-dev -y - sudo apt-get install -y libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxt-dev libxtst-dev libxrender-dev libxrandr-dev libxi-dev - sudo apt install software-properties-common -y - sudo add-apt-repository ppa:deadsnakes/ppa - - - name: Installing Conan - run: pipx install "conan>=2.10.1" - - - name: Setting up Conan Profiles - # run: conan config install -sf profiles/x86_64/linux/ -tf profiles https://github.com/engine3d-dev/conan-config.git - run: conan config install -sf profiles/x86_64/linux/ -tf profiles https://github.com/engine3d-dev/conan-config.git --args "profiles_update" - - - name: Installing project dependencies - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan - - - name: Cloning Atlas repository - run: git clone https://github.com/engine3d-dev/TheAtlasEngine - - - name: Building Atlas - run: conan build . -b missing -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install - diff --git a/.github/mac.yml b/.github/mac.yml deleted file mode 100644 index c8d17e0..0000000 --- a/.github/mac.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Macos Build Tests - -on: [pull_request] - -jobs: - macos-build: - name: "M1 Mac Build" - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: Install Homebrew - run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - - - name: Install LLVM - run: | - brew install python pipx llvm@17 - - - name: Installing conan - run: pipx install "conan>=2.10.2" - - - name: Installing clang-tidy - run: sudo ln -s $(brew --prefix llvm)/bin/clang-tidy /usr/local/bin/ - - - name: Install Rosetta - run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license - - - name: Setting up Conan profile - run: conan config install -sf profiles/armv8/mac/ -tf profiles https://github.com/engine3d-dev/conan-config.git - - - name: Installing Atlas repositories - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan - - - name: Cloning Atlas repository - run: git clone https://github.com/engine3d-dev/TheAtlasEngine - - - name: Building the project - run: conan build . -b missing diff --git a/.github/windows.yml b/.github/windows.yml deleted file mode 100644 index f2024a4..0000000 --- a/.github/windows.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Windows Build Tests - -on: [pull_request, workflow_dispatch] - -jobs: - windows-build: - name: "Windows-Build" - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - # - name: Setting up C++ on Windows - # shell: pwsh - # run: winget install Microsoft.VisualStudio.2022.BuildTools --override "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended -p --installWhileDownloading" - - - name: Installing Choco - shell: pwsh - run: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) - - - name: Install tooling with Choco - shell: pwsh - run: | - choco install cmake.install --version=3.31.6 - cmake --version - choco install llvm --version=20.1.4 - clang++ --version - choco install git make mingw - - # - name: Installing python - # run: choco install python --version=3.12.2 - - - name: Pip installing conan - shell: pwsh - run: pip install conan - - # - name: Installing vulkan - # shell: pwsh - # run: winget install --id=KhronosGroup.VulkanSDK -e - - - name: Setting up conan profiles - shell: pwsh - run: conan config install -sf profiles/x86_64/Windows/ -tf profiles https://github.com/engine3d-dev/conan-config.git --args "profiles_update" - - - name: Setting up packages - shell: pwsh - run: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan - - - name: Running Test Cases - shell: pwsh - run: conan build . -b missing - diff --git a/.github/clang-format-deploy.yml b/.github/workflows/clang-format-deploy.yml similarity index 100% rename from .github/clang-format-deploy.yml rename to .github/workflows/clang-format-deploy.yml diff --git a/.github/clang-tidy.yml b/.github/workflows/clang-tidy.yml similarity index 100% rename from .github/clang-tidy.yml rename to .github/workflows/clang-tidy.yml diff --git a/.github/deploy.yml b/.github/workflows/deploy.yml similarity index 100% rename from .github/deploy.yml rename to .github/workflows/deploy.yml diff --git a/.github/workflows/deploy_linux.yml b/.github/workflows/deploy_linux.yml new file mode 100644 index 0000000..e777847 --- /dev/null +++ b/.github/workflows/deploy_linux.yml @@ -0,0 +1,66 @@ +name: Deploy to Linux + +on: + pull_request: + types: [closed] + branches: + - main # Only trigger for PRs merged into main + +jobs: + linux_x86_64: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install LLVM's C++ Standard Library + run: sudo apt-get install libc++-20-dev libc++abi-20-dev + + - name: Installing pipx + run: sudo apt install pipx + + - name: Installing Prerequisites for Linux + run: | + sudo apt-get update + sudo apt install software-properties-common -y + sudo add-apt-repository ppa:deadsnakes/ppa + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + + - name: Pip installing conan + shell: pwsh + run: pipx install conan + + - name: Setting up conan profiles + shell: pwsh + run: conan config install -sf profiles/x86_64/linux/ -tf profiles https://github.com/engine3d-dev/conan-config.git + + - name: Setting up Remote Repositories + shell: pwsh + run: | + conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan + + - name: Creating Release build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Release -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + + - name: Creating Debug build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Debug -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + + - name: Creating MinSizeRel build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=MinSizeRel -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + + - name: Login to JFrog + run: conan remote login -p ${{ secrets.JFROG_USER_TOKEN_ID }} engine3d-conan ${{ secrets.JFROG_USERNAME }} + + - name: Uploading vulkan-cpp to engine3d-conan remote repositories + shell: pwsh + run: conan upload vulkan-cpp/4.0 --r=engine3d-conan --confirm \ No newline at end of file diff --git a/.github/workflows/deploy_mac.yml b/.github/workflows/deploy_mac.yml new file mode 100644 index 0000000..50c0f08 --- /dev/null +++ b/.github/workflows/deploy_mac.yml @@ -0,0 +1,62 @@ +name: Deploy to MacOS Armv8 + +on: + pull_request: + types: [closed] + branches: + - main # Only trigger for PRs merged into main + +jobs: + macos_armv8: + if: github.event.pull_request.merged == true + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Homebrew + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + - name: Install LLVM + run: brew install python pipx llvm@20 + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + + - name: Pipx installing conan + shell: pwsh + run: | + pipx install "conan>=2.18.2" + pipx upgrade conan + + - name: Setting up conan profiles + shell: pwsh + run: conan config install -sf profiles/armv8/mac/ -tf profiles https://github.com/engine3d-dev/conan-config.git + + - name: Setting up Remote Repositories + shell: pwsh + run: | + conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan + + - name: Creating Release build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Release -pr mac_armv8 + + - name: Creating Debug build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Debug -pr mac_armv8 + + - name: Creating MinSizeRel build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=MinSizeRel -pr mac_armv8 + + - name: Login to JFrog + run: conan remote login -p ${{ secrets.JFROG_USER_TOKEN_ID }} engine3d-conan ${{ secrets.JFROG_USERNAME }} + + - name: Uploading vulkan-cpp to engine3d-conan remote repositories + shell: pwsh + run: conan upload vulkan-cpp/4.0 --r=engine3d-conan --confirm \ No newline at end of file diff --git a/.github/workflows/deploy_windows.yml b/.github/workflows/deploy_windows.yml new file mode 100644 index 0000000..1ab9830 --- /dev/null +++ b/.github/workflows/deploy_windows.yml @@ -0,0 +1,67 @@ +name: Deploy to Windows + +on: + pull_request: + types: [closed] + branches: + - main # Only trigger for PRs merged into main + +jobs: + windows_x86_64: + if: github.event.pull_request.merged == true + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: Installing Choco + shell: pwsh + run: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + + - name: Install tooling with Choco + shell: pwsh + run: | + choco install cmake.install --version=3.31.6 + cmake --version + choco install llvm --version=20.1.4 + clang++ --version + choco install git make mingw + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + + + - name: Pip installing conan + shell: pwsh + run: pip install conan + + - name: Setting up conan profiles + shell: pwsh + run: conan config install -sf profiles/x86_64/Windows/ -tf profiles https://github.com/engine3d-dev/conan-config.git + + - name: Setting up Remote Repositories + shell: pwsh + run: | + conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan + + - name: Creating Release build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Release -pr windows_x86_64 + + - name: Creating Debug build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Debug -pr windows_x86_64 + + - name: Creating MinSizeRel build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=MinSizeRel -pr windows_x86_64 + + - name: Login to JFrog + run: conan remote login -p ${{ secrets.JFROG_USER_TOKEN_ID }} engine3d-conan ${{ secrets.JFROG_USERNAME }} + + - name: Uploading vulkan-cpp to engine3d-conan remote repositories + shell: pwsh + run: conan upload vulkan-cpp/4.0 --r=engine3d-conan --confirm \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..eb1a7bd --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,56 @@ +name: Linux Platform Build + +on: [pull_request] + +jobs: + linux-build: + name: "Linux-Build" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # - name: Install LLVM + # run: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh + + - name: Install LLVM's C++ Standard Library + run: sudo apt-get install libc++-20-dev libc++abi-20-dev + + - name: Installing pipx + run: sudo apt install pipx + + - name: Installing Prerequisites for Linux + run: | + sudo apt-get update + sudo apt install software-properties-common -y + sudo add-apt-repository ppa:deadsnakes/ppa + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + + - name: Installing Conan + run: pipx install "conan>=2.18.1" + + - name: Setting up Conan Profiles + run: conan config install -sf profiles/x86_64/linux/ -tf profiles https://github.com/engine3d-dev/conan-config.git + + - name: Adding Conan remote dependencies + run: | + conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan + + - name: Creating Release build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Release -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + + - name: Creating Debug build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=Debug -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + + - name: Creating MinSizeRel build for vulkan-cpp + shell: pwsh + run: conan create . -b missing -s build_type=MinSizeRel -pr linux_x86_64 -c tools.system.package_manager:sudo=True -c tools.system.package_manager:mode=install + diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 0000000..46dfba8 --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,50 @@ +name: Macos Platform Build + +on: [pull_request] + +jobs: + macos-build: + name: "M1 Mac Build" + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Homebrew + run: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + - name: Install LLVM + run: | + brew install python pipx llvm@20 + + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + + + - name: Installing conan + run: | + pipx install "conan>=2.18.2" + pipx upgrade conan + + - name: Installing clang-tidy + run: sudo ln -s $(brew --prefix llvm)/bin/clang-tidy /usr/local/bin/ + + - name: Install Rosetta + run: /usr/sbin/softwareupdate --install-rosetta --agree-to-license + + - name: Setting up Conan profile + run: conan config install -sf profiles/armv8/mac/ -tf profiles https://github.com/engine3d-dev/conan-config.git + + - name: Installing Atlas repositories + run: | + conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan + conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan + + - name: Building vulkan-cpp + run: | + conan create . -b missing -s build_type=Release -pr mac_armv8 + conan create . -b missing -s build_type=Debug -pr mac_armv8 + conan create . -b missing -s build_type=MinSizeRel -pr mac_armv8 \ No newline at end of file diff --git a/.github/workflows/windows_build.yml b/.github/workflows/windows.yml similarity index 71% rename from .github/workflows/windows_build.yml rename to .github/workflows/windows.yml index b787159..269443a 100644 --- a/.github/workflows/windows_build.yml +++ b/.github/workflows/windows.yml @@ -1,4 +1,4 @@ -name: Windows Build Tests +name: Windows Platform Build on: [pull_request, workflow_dispatch] @@ -21,6 +21,19 @@ jobs: choco install llvm --version=20.1.4 clang++ --version choco install git make mingw + + # - name: Installing Vulkan SDK + # shell: pwsh + # # run: winget install --id=KhronosGroup.VulkanSDK -e --accept-licenses --default-answer --confirm-command install + # run: | + # winget install --id=KhronosGroup.VulkanSDK -e --force --silent --accept-package-agreements --accept-source-agreements + - name: Install Vulkan SDK + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + vulkan-use-cache: true + - name: Pip installing conan shell: pwsh @@ -36,9 +49,9 @@ jobs: conan remote add engine3d-conan https://libhal.jfrog.io/artifactory/api/conan/engine3d-conan conan remote add libhal-trunk https://libhal.jfrog.io/artifactory/api/conan/trunk-conan - - name: Building audio-cpp + - name: Building vulkan-cpp shell: pwsh run: | conan create . -b missing -s build_type=Release -pr windows_x86_64 conan create . -b missing -s build_type=Debug -pr windows_x86_64 - conan create . -b missing -s build_type=MinSizeRel -pr windows_x86_64 + conan create . -b missing -s build_type=MinSizeRel -pr windows_x86_64 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 612c1bb..8debc50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,42 +1,80 @@ -cmake_minimum_required(VERSION 3.27) -project(vulkan-cpp CXX) - -build_library( - DIRECTORIES - src - # demos/1-instance - # demos/2-physical-device - # demos/3-logical-device - # demos/4-surface - # demos/5-swapchain - # demos/6-graphics-pipeline - # demos/7-vertex-buffer - # demos/8-index-uniform-buffers - # demos/9-uniforms - # demos/10-textures - # demos/11-depth-buffering - # demos/12-loading-models - # demos/13-skybox - # demos/sandbox +cmake_minimum_required(VERSION 4.0) + +# Generate compile commands for anyone using our libraries. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_COLOR_DIAGNOSTICS ON) + +project(vulkan-cpp LANGUAGES CXX) + +static_library( ENABLE_TESTS OFF + INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR} + PACKAGES glfw3 Vulkan - VulkanHeaders glm stb - tinyobjloader LINK_PACKAGES glfw Vulkan::Vulkan - vulkan-headers::vulkan-headers glm::glm stb::stb - tinyobjloader::tinyobjloader ) -generate_compile_commands() +target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) + +target_sources(${PROJECT_NAME} PUBLIC + FILE_SET CXX_MODULES + TYPE CXX_MODULES + FILES + vulkan-cpp/vk.cppm + vulkan-cpp/types.cppm + vulkan-cpp/utilities.cppm + vulkan-cpp/instance.cppm + vulkan-cpp/physical_device.cppm + vulkan-cpp/device.cppm + vulkan-cpp/device_queue.cppm + vulkan-cpp/surface.cppm + vulkan-cpp/swapchain.cppm + vulkan-cpp/device_present_queue.cppm + vulkan-cpp/command_buffer.cppm + vulkan-cpp/renderpass.cppm + vulkan-cpp/framebuffer.cppm + vulkan-cpp/sample_image.cppm + vulkan-cpp/shader_resource.cppm + vulkan-cpp/pipeline.cppm + vulkan-cpp/buffer_streams.cppm + vulkan-cpp/vertex_buffer.cppm + vulkan-cpp/buffer_streams16.cppm + vulkan-cpp/buffer_streams32.cppm + vulkan-cpp/index_buffer.cppm + vulkan-cpp/uniform_buffer.cppm + vulkan-cpp/descriptor_resource.cppm + vulkan-cpp/texture.cppm +) + +install( + TARGETS ${PROJECT_NAME} + EXPORT vulkan-cpp_targets + FILE_SET CXX_MODULES DESTINATION "." + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + CXX_MODULES_BMI DESTINATION "bmi" +) + +install( + EXPORT vulkan-cpp_targets + FILE "vulkan-cpp-config.cmake" + DESTINATION "lib/cmake" + CXX_MODULES_DIRECTORY "cxx-modules" +) -target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +# Always run this custom target by making it depend on ALL +add_custom_target(copy_compile_commands ALL + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${CMAKE_BINARY_DIR}/compile_commands.json + ${CMAKE_SOURCE_DIR}/compile_commands.json + DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json) diff --git a/conanfile.py b/conanfile.py index a808c81..a286703 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,39 +1,44 @@ -import os from conan import ConanFile -from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps -from conan.tools.system.package_manager import Apt, Yum, PacMan, Zypper -from conan.tools.scm import Git +from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeDeps from conan.tools.files import copy -import os +from pathlib import Path -class VulkanCpp(ConanFile): + +required_conan_version = ">=2.2.0" + + +class VulkanCppRecipe(ConanFile): name = "vulkan-cpp" - version = "3.0" - settings = "os", "compiler", "build_type", "arch" - generators = "CMakeDeps", "CMakeToolchain" + version = "4.0" + license = "Apache-2.0" + url = "https://github.com/engine3d-dev/vulkan-cpp" + homepage = "https://github.com/engine3d-dev/vulkan-cpp" + settings = "compiler", "build_type", "os", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + default_options = {"shared": False, "fPIC": True} + exports_sources = "vulkan-cpp/*", "tests/*", "CMakeLists.txt", "LICENSE" - # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") + self.test_requires("boost-ext-ut/2.3.1") self.tool_requires("engine3d-cmake-utils/4.0") - # Putting all of your packages here def requirements(self): self.requires("glfw/3.4") - self.requires("vulkan-headers/1.3.290.0") - self.requires("imguidocking/2.0") self.requires("glm/1.0.1") self.requires("stb/cci.20230920") - self.requires("tinyobjloader/2.0.0-rc10") - self.requires("boost-ext-ut/2.3.1") + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.generator = "Ninja" + tc.generate() - def export_sources(self): - copy(self,"CMakeLists.txt", self.recipe_folder, self.export_sources_folder) - copy(self,"src/CMakeLists.txt", self.recipe_folder, self.export_sources_folder) - copy(self,"*.hpp", self.recipe_folder, self.export_sources_folder) - copy(self,"*.cpp", self.recipe_folder, self.export_sources_folder) + deps = CMakeDeps(self) + deps.generate() def build(self): cmake = CMake(self) @@ -41,21 +46,15 @@ def build(self): cmake.build() def package(self): - copy(self, "LICENSE", src=self.source_folder, dst=os.path.join(self.package_folder, "licenses")) - copy(self, pattern="*.h", src=os.path.join(self.source_folder, "vulkan-cpp"), dst=os.path.join(self.package_folder, "vulkan-cpp")) - copy(self, pattern="*.hpp", src=os.path.join(self.source_folder, "vulkan-cpp"), dst=os.path.join(self.package_folder, "vulkan-cpp")) - copy(self, pattern="*.a", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.so", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.lib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) - copy(self, pattern="*.dll", src=self.build_folder, dst=os.path.join(self.package_folder, "bin"), keep_path=False) - copy(self, pattern="*.dylib", src=self.build_folder, dst=os.path.join(self.package_folder, "lib"), keep_path=False) cmake = CMake(self) cmake.install() - - def layout(self): - cmake_layout(self) - + + copy(self, "LICENSE", + dst=Path(self.package_folder) / "licenses", + src=self.source_folder) + def package_info(self): - self.cpp_info.set_property("cmake_target_name", "vulkan-cpp::vulkan-cpp") - self.cpp_info.libs = ["vulkan-cpp"] - self.cpp_info.includedirs = ['./', './vulkan-cpp'] + # DISABLE Conan's config file generation + self.cpp_info.set_property("cmake_find_mode", "none") + # Tell CMake to include this directory in its search path + self.cpp_info.builddirs.append("lib/cmake") \ No newline at end of file diff --git a/demos/1-instance/CMakeLists.txt b/demos/1-instance/CMakeLists.txt index e2a7413..6b5b93b 100644 --- a/demos/1-instance/CMakeLists.txt +++ b/demos/1-instance/CMakeLists.txt @@ -6,12 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/1-instance/application.cpp b/demos/1-instance/application.cpp index cfe7235..164a766 100644 --- a/demos/1-instance/application.cpp +++ b/demos/1-instance/application.cpp @@ -1,9 +1,19 @@ -#define FMT_HEADER_ONLY -#include +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR #include -#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -55,7 +65,7 @@ int main() { //! @note Just added the some test code to test the conan-starter setup code if (!glfwInit()) { - fmt::print("glfwInit could not be initialized!\n"); + std::print("glfwInit could not be initialized!\n"); return -1; } @@ -72,7 +82,7 @@ main() { std::string title = "Hello Window"; GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); - + glfwMakeContextCurrent(window); std::array validation_layers = { @@ -84,29 +94,33 @@ main() { initialize_instance_extensions(); vk::debug_message_utility debug_callback_info = { - .severity = vk::message::verbose | vk::message::warning | vk::message::error, - .message_type = vk::debug::general | vk::debug::validation | vk::debug::performance, + .severity = + vk::message::verbose | vk::message::warning | vk::message::error, + .message_type = + vk::debug::general | vk::debug::validation | vk::debug::performance, .callback = debug_callback }; vk::application_params config = { .name = "vulkan instance", .version = vk::api_version::vk_1_3, // specify to using vulkan 1.3 - .validations = validation_layers, // .validation takes in a std::span - .extensions = global_extensions // .extensions also takes in std::span + .validations = + validation_layers, // .validation takes in a std::span + .extensions = + global_extensions // .extensions also takes in std::span }; vk::instance api_instance(config, debug_callback_info); - std::span properties = api_instance.validation(); - for(vk::layer_properties property : properties) { + std::span properties = + api_instance.validation(); + for (vk::layer_properties property : properties) { std::println("Validation Layer Name:\t\t{}", property.name); std::println("Validation Layer Description: {}", property.description); } while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - } glfwDestroyWindow(window); diff --git a/demos/1-instance/conanfile.py b/demos/1-instance/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/1-instance/conanfile.py +++ b/demos/1-instance/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/10-textures/CMakeLists.txt b/demos/10-textures/CMakeLists.txt index f2c909c..c0d93d5 100644 --- a/demos/10-textures/CMakeLists.txt +++ b/demos/10-textures/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/10-textures/application.cpp b/demos/10-textures/application.cpp index 2ab2886..3857116 100644 --- a/demos/10-textures/application.cpp +++ b/demos/10-textures/application.cpp @@ -1,29 +1,20 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include +#include +#include +import vk; #include #define GLM_FORCE_RADIANS @@ -45,7 +36,7 @@ initialize_instance_extensions() { std::vector extension_names; extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); - + extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); // An additional surface extension needs to be loaded. This extension is @@ -419,9 +410,9 @@ main() { }; // uint32_t image_count = image_count; vk::descriptor_layout set0_layout = { - .slot = 0, // indicate that this is descriptor set 0 + .slot = 0, // indicate that this is descriptor set 0 .max_sets = image_count, // max of descriptor sets able to allocate - .entries = entries, // specifies pool sizes and descriptor layout + .entries = entries, // specifies pool sizes and descriptor layout }; vk::descriptor_resource set0_resource(logical_device, set0_layout); std::array layouts = { set0_resource.layout() }; @@ -483,26 +474,17 @@ main() { std::println("index_buffer.alive() = {}", test_ibo.alive()); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) - }; - vk::uniform_buffer test_ubo = vk::uniform_buffer(logical_device, test_ubo_info); - + vk::uniform_params test_ubo_info = { .phsyical_memory_properties = + physical_device.memory_properties(), + .size_bytes = sizeof(global_uniform) }; + vk::uniform_buffer test_ubo = + vk::uniform_buffer(logical_device, test_ubo_info); - std::array uniforms0 = { - vk::write_buffer{ - .buffer = test_ubo, - .offset = 0, - .range = test_ubo.size_bytes() - } - }; + std::array uniforms0 = { vk::write_buffer{ + .buffer = test_ubo, .offset = 0, .range = test_ubo.size_bytes() } }; std::array uniforms = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = uniforms0 - } + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = uniforms0 } }; // Loading a texture -- for testing @@ -520,37 +502,28 @@ main() { .phsyical_memory_properties = physical_device.memory_properties(), .size_bytes = sizeof(material_uniform) }; - vk::uniform_buffer material_ubo = vk::uniform_buffer(logical_device, material_ubfo_info); - + vk::uniform_buffer material_ubo = + vk::uniform_buffer(logical_device, material_ubfo_info); - std::array set1_uniforms0 = { - vk::write_buffer{ - .buffer = material_ubo, - .offset = 0, - .range = material_ubo.size_bytes() - } - }; + std::array set1_uniforms0 = { vk::write_buffer{ + .buffer = material_ubo, + .offset = 0, + .range = material_ubo.size_bytes() } }; std::array uniforms_set1 = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = set1_uniforms0 - } + vk::write_buffer_descriptor{ .dst_binding = 0, + .uniforms = set1_uniforms0 } }; - std::array set1_samplers = { - vk::write_image{ - .sampler = texture1.image().sampler(), - .view = texture1.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - } - }; + std::array set1_samplers = { vk::write_image{ + .sampler = texture1.image().sampler(), + .view = texture1.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + } }; std::array sample_images = { - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = set1_samplers - } + vk::write_image_descriptor{ .dst_binding = 1, + .sample_images = set1_samplers } }; set0_resource.update(uniforms, sample_images); @@ -610,8 +583,7 @@ main() { // before making any of the draw calls Something to note: You cannot // update descriptor sets in the process of a current-recording command // buffers or else that becomes undefined behavior - set0_resource.bind( - current, main_graphics_pipeline.layout()); + set0_resource.bind(current, main_graphics_pipeline.layout()); // Drawing-call to render actual triangle to the screen // vkCmdDraw(current, 3, 1, 0, 0); vkCmdDrawIndexed( diff --git a/demos/10-textures/conanfile.py b/demos/10-textures/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/10-textures/conanfile.py +++ b/demos/10-textures/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/11-depth-buffering/CMakeLists.txt b/demos/11-depth-buffering/CMakeLists.txt index 5c56efd..be80e23 100644 --- a/demos/11-depth-buffering/CMakeLists.txt +++ b/demos/11-depth-buffering/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp - + glfw3 + glm + stb + LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/11-depth-buffering/application.cpp b/demos/11-depth-buffering/application.cpp index b8c147b..7655fcd 100644 --- a/demos/11-depth-buffering/application.cpp +++ b/demos/11-depth-buffering/application.cpp @@ -1,29 +1,20 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +import vk; #include #define GLM_FORCE_RADIANS @@ -417,9 +408,9 @@ main() { }; // uint32_t image_count = image_count; vk::descriptor_layout set0_layout = { - .slot = 0, // indicate that this is descriptor set 0 + .slot = 0, // indicate that this is descriptor set 0 .max_sets = image_count, // max of descriptor sets able to allocate - .entries = entries, // specifies pool sizes and descriptor layout + .entries = entries, // specifies pool sizes and descriptor layout }; vk::descriptor_resource set0_resource(logical_device, set0_layout); @@ -495,27 +486,23 @@ main() { // data camera_ubo global_ubo = {}; test_ubo.update(&global_ubo); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) - }; + vk::uniform_params test_ubo_info = { .phsyical_memory_properties = + physical_device.memory_properties(), + .size_bytes = sizeof(global_uniform) }; vk::uniform_buffer test_ubo = vk::uniform_buffer(logical_device, test_ubo_info); std::println("uniform_buffer.alive() = {}", test_ubo.alive()); - std::array uniforms0 = { - vk::write_buffer{ - .buffer = test_ubo, - .offset = 0, - .range = test_ubo.size_bytes(), - } - }; - + std::array uniforms0 = { vk::write_buffer{ + .buffer = test_ubo, + .offset = 0, + .range = test_ubo.size_bytes(), + } }; std::array uniforms = { vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = uniforms0, + .dst_binding = 0, + .uniforms = uniforms0, } }; @@ -529,20 +516,16 @@ main() { std::println("texture1.valid = {}", texture1.loaded()); - std::array samplers = { - vk::write_image{ - .sampler = texture1.image().sampler(), - .view = texture1.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - } - }; + std::array samplers = { vk::write_image{ + .sampler = texture1.image().sampler(), + .view = texture1.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + } }; // Moving update call here because now we add textures to set0 std::array sample_images = { - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = samplers - } + vk::write_image_descriptor{ .dst_binding = 1, + .sample_images = samplers } }; set0_resource.update(uniforms, sample_images); @@ -601,8 +584,7 @@ main() { // before making any of the draw calls Something to note: You cannot // update descriptor sets in the process of a current-recording command // buffers or else that becomes undefined behavior - set0_resource.bind( - current, main_graphics_pipeline.layout()); + set0_resource.bind(current, main_graphics_pipeline.layout()); // Drawing-call to render actual triangle to the screen // vkCmdDraw(current, 3, 1, 0, 0); diff --git a/demos/11-depth-buffering/conanfile.py b/demos/11-depth-buffering/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/11-depth-buffering/conanfile.py +++ b/demos/11-depth-buffering/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/12-loading-models/CMakeLists.txt b/demos/12-loading-models/CMakeLists.txt index 565c38e..a0f1d47 100644 --- a/demos/12-loading-models/CMakeLists.txt +++ b/demos/12-loading-models/CMakeLists.txt @@ -6,13 +6,15 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb + tinyobjloader LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + tinyobjloader + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/12-loading-models/application.cpp b/demos/12-loading-models/application.cpp index 42f9ebf..9b46ba7 100644 --- a/demos/12-loading-models/application.cpp +++ b/demos/12-loading-models/application.cpp @@ -1,29 +1,20 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include +#include +#include +import vk; #include #define GLM_FORCE_RADIANS @@ -192,15 +183,13 @@ class obj_model { indices.push_back(unique_vertices[vertex]); } } - vk::vertex_params vertex_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .vertices = vertices - }; + vk::vertex_params vertex_info = { .phsyical_memory_properties = + p_physical.memory_properties(), + .vertices = vertices }; - vk::index_params index_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .indices = indices - }; + vk::index_params index_info = { .phsyical_memory_properties = + p_physical.memory_properties(), + .indices = indices }; m_vertex_buffer = vk::vertex_buffer(p_device, vertex_info); m_index_buffer = vk::index_buffer(p_device, index_info); m_is_loaded = true; @@ -240,9 +229,11 @@ class obj_model { vk::index_buffer m_index_buffer{}; }; -VkDeviceSize get_alignment(VkDeviceSize p_original_size, VkDeviceSize p_min_ubo_alignment) { +VkDeviceSize +get_alignment(VkDeviceSize p_original_size, VkDeviceSize p_min_ubo_alignment) { // Round up originalSize to the nearest multiple of min_ubo_alignment - VkDeviceSize aligned_size = (p_original_size + p_min_ubo_alignment - 1) & ~(p_min_ubo_alignment - 1); + VkDeviceSize aligned_size = + (p_original_size + p_min_ubo_alignment - 1) & ~(p_min_ubo_alignment - 1); return aligned_size; } @@ -306,7 +297,6 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - // setting up physical device // TODO: Probably enforce the use of // vk::enumerate_physical_device({.device_type = vk::physical::discrete}) @@ -584,11 +574,11 @@ main() { } }; vk::descriptor_layout set0_layout = { - .slot = 0, // indicate that this is descriptor set 0 - // set layout able to be allocated + .slot = 0, // indicate that this is descriptor set 0 + // set layout able to be allocated .max_sets = image_count, // max of descriptor sets able to allocate - // this descriptor sets - .entries = entries, // specifies pool sizes and descriptor layout + // this descriptor sets + .entries = entries, // specifies pool sizes and descriptor layout }; vk::descriptor_resource set0_resource(logical_device, set0_layout); @@ -609,26 +599,17 @@ main() { physical_device); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) - }; + vk::uniform_params test_ubo_info = { .phsyical_memory_properties = + physical_device.memory_properties(), + .size_bytes = sizeof(global_uniform) }; vk::uniform_buffer test_ubo = vk::uniform_buffer(logical_device, test_ubo_info); std::println("uniform_buffer.alive() = {}", test_ubo.alive()); - std::array uniforms0 = { - vk::write_buffer{ - .buffer = test_ubo, - .offset = 0, - .range = test_ubo.size_bytes() - } - }; + std::array uniforms0 = { vk::write_buffer{ + .buffer = test_ubo, .offset = 0, .range = test_ubo.size_bytes() } }; std::array uniforms = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = uniforms0 - } + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = uniforms0 } }; // Loading a texture -- for testing @@ -640,17 +621,17 @@ main() { std::array samplers = { vk::write_image{ - .sampler = texture1.image().sampler(), - .view = texture1.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, + .sampler = texture1.image().sampler(), + .view = texture1.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, }, }; // Moving update call here because now we add textures to set0 std::array sample_images = { vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = samplers, + .dst_binding = 1, + .sample_images = samplers, } }; set0_resource.update(uniforms, sample_images); diff --git a/demos/12-loading-models/conanfile.py b/demos/12-loading-models/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/12-loading-models/conanfile.py +++ b/demos/12-loading-models/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/13-skybox/application.cpp b/demos/13-skybox/application.cpp index dabe01b..51c7680 100644 --- a/demos/13-skybox/application.cpp +++ b/demos/13-skybox/application.cpp @@ -94,12 +94,12 @@ struct skybox_camera_data { }; template -void hash_combine(size_t& seed, const T& v, const Rest&... rest) { +void +hash_combine(size_t& seed, const T& v, const Rest&... rest) { seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); (hash_combine(seed, rest), ...); } - namespace std { template<> @@ -114,11 +114,14 @@ namespace std { } // This is how we are going to load a .obj model for this demo -// Example of how you might want to have your own classes for loading geometry-meshes +// Example of how you might want to have your own classes for loading +// geometry-meshes class obj_model { public: obj_model() = default; - obj_model(const std::filesystem::path& p_filename, const VkDevice& p_device, const vk::physical_device& p_physical) { + obj_model(const std::filesystem::path& p_filename, + const VkDevice& p_device, + const vk::physical_device& p_physical) { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; @@ -136,7 +139,8 @@ class obj_model { &warn, &err, p_filename.string().c_str())) { - std::println("Could not load model from path {}", p_filename.string()); + std::println("Could not load model from path {}", + p_filename.string()); m_is_loaded = false; return; } @@ -194,15 +198,13 @@ class obj_model { indices.push_back(unique_vertices[vertex]); } } - vk::vertex_params vertex_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .vertices = vertices - }; + vk::vertex_params vertex_info = { .phsyical_memory_properties = + p_physical.memory_properties(), + .vertices = vertices }; - vk::index_params index_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .indices = indices - }; + vk::index_params index_info = { .phsyical_memory_properties = + p_physical.memory_properties(), + .indices = indices }; m_vertex_buffer = vk::vertex_buffer(p_device, vertex_info); m_index_buffer = vk::index_buffer(p_device, index_info); m_is_loaded = true; @@ -212,14 +214,19 @@ class obj_model { void bind(const VkCommandBuffer& p_command) { m_vertex_buffer.bind(p_command); - if(m_index_buffer.size() > 0) { + if (m_index_buffer.size() > 0) { m_index_buffer.bind(p_command); } } void draw(const VkCommandBuffer& p_command) { - if(m_index_buffer.size() > 0) { - vkCmdDrawIndexed(p_command, static_cast(m_index_buffer.size()), 1, 0, 0, 0); + if (m_index_buffer.size() > 0) { + vkCmdDrawIndexed(p_command, + static_cast(m_index_buffer.size()), + 1, + 0, + 0, + 0); } else { vkCmdDraw(p_command, m_vertex_buffer.size(), 1, 0, 0); @@ -232,17 +239,18 @@ class obj_model { } private: - bool m_is_loaded=false; + bool m_is_loaded = false; vk::vertex_buffer m_vertex_buffer{}; vk::index_buffer m_index_buffer{}; }; // template -// void write(const VkDevice& p_device, const vk::buffer_handle& p_buffer, const std::array& p_in_buffer) { +// void write(const VkDevice& p_device, const vk::buffer_handle& p_buffer, const +// std::array& p_in_buffer) { // } - -// void write_array(const VkDevice& p_device, const vk::buffer_handle& p_buffer) { +// void write_array(const VkDevice& p_device, const vk::buffer_handle& p_buffer) +// { // std::array buffer_to_write; // write<256>(p_device, p_buffer, buffer_to_write); // } @@ -312,7 +320,8 @@ main() { // std::span // setting up physical device - // TODO: Probably enforce the use of vk::enumerate_physical_device({.device_type = vk::physical::discrete}) + // TODO: Probably enforce the use of + // vk::enumerate_physical_device({.device_type = vk::physical::discrete}) vk::physical_enumeration enumerate_devices{ .device_type = vk::physical::discrete }; vk::physical_device physical_device(api_instance, enumerate_devices); @@ -371,8 +380,9 @@ main() { surface_properties); // querying swapchain images - // TODO: Make the images and framebuffers contained within the vk::swapchain - // Considering if you have two display they will prob have their own set of images to display to the two separate screens + // TODO: Make the images and framebuffers contained within the vk::swapchain + // Considering if you have two display they will prob have their own set of + // images to display to the two separate screens uint32_t image_count = 0; vkGetSwapchainImagesKHR(logical_device, main_swapchain, @@ -394,7 +404,7 @@ main() { for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { - .extent = {swapchain_extent.width, swapchain_extent.width}, + .extent = { swapchain_extent.width, swapchain_extent.width }, .format = surface_properties.format.format, .aspect = vk::image_aspect_flags::color_bit, .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, @@ -403,12 +413,12 @@ main() { .phsyical_memory_properties = physical_device.memory_properties(), }; - - swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); + swapchain_images[i] = + vk::sample_image(logical_device, images[i], swapchain_image_config); // Creating Images for depth buffering vk::image_params image_config = { - .extent = {swapchain_extent.width, swapchain_extent.width}, + .extent = { swapchain_extent.width, swapchain_extent.width }, .format = depth_format, .aspect = vk::image_aspect_flags::depth_bit, .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, @@ -416,7 +426,8 @@ main() { .layer_count = 1, .phsyical_memory_properties = physical_device.memory_properties(), }; - swapchain_depth_images[i] = vk::sample_image(logical_device, image_config); + swapchain_depth_images[i] = + vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -466,26 +477,28 @@ main() { // Setting up swapchain framebuffers - std::vector swapchain_framebuffers(image_count); - for (uint32_t i = 0; i < swapchain_framebuffers.size(); i++) { - // image_view_attachments.push_back(swapchain_images[i].view); + std::vector swapchain_framebuffers(image_count); + for (uint32_t i = 0; i < swapchain_framebuffers.size(); i++) { + // image_view_attachments.push_back(swapchain_images[i].view); // image_view_attachments.push_back(swapchain_depth_images[i].view); - // NOTE: This must match the amount of attachments the renderpass also has to match the image_view attachment for per-framebuffers as well - // I just set the size to whatever the renderpass attachment size are to ensure this is the case - // Since you have an image for color attachment and another image for the depth atttachment to specify - std::array image_view_attachments = { - swapchain_images[i].image_view(), - swapchain_depth_images[i].image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = main_renderpass, - .views = image_view_attachments, - .extent = swapchain_extent - }; - swapchain_framebuffers[i] = vk::framebuffer(logical_device, framebuffer_info); - } + // NOTE: This must match the amount of attachments the renderpass also + // has to match the image_view attachment for per-framebuffers as well + // I just set the size to whatever the renderpass attachment size are to + // ensure this is the case Since you have an image for color attachment + // and another image for the depth atttachment to specify + std::array + image_view_attachments = { swapchain_images[i].image_view(), + swapchain_depth_images[i].image_view() }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = main_renderpass, + .views = image_view_attachments, + .extent = swapchain_extent + }; + swapchain_framebuffers[i] = + vk::framebuffer(logical_device, framebuffer_info); + } std::println("Created VkFramebuffer's with size = {}", swapchain_framebuffers.size()); @@ -501,65 +514,58 @@ main() { // gets set with the renderpass std::array color = { 0.f, 0.5f, 0.5f, 1.f }; - std::println("Start implementing graphics pipeline!!!"); + std::println("Start implementing graphics pipeline!!!"); - // Now creating a vulkan graphics pipeline for the shader loading - std::array shader_sources = { - vk::shader_source{ - .filename = "shader_samples/sample6/test.vert.spv", - .stage = vk::shader_stage::vertex - }, - vk::shader_source{ - .filename = "shader_samples/sample6/test.frag.spv", - .stage = vk::shader_stage::fragment - }, - }; + // Now creating a vulkan graphics pipeline for the shader loading + std::array shader_sources = { + vk::shader_source{ .filename = "shader_samples/sample6/test.vert.spv", + .stage = vk::shader_stage::vertex }, + vk::shader_source{ .filename = "shader_samples/sample6/test.frag.spv", + .stage = vk::shader_stage::fragment }, + }; // Setting up vertex attributes in the test shaders std::array attribute_entries = { - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position) - }, - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color) - }, - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv) - }, - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals) - } + vk::vertex_attribute_entry{ .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = + offsetof(vk::vertex_input, position) }, + vk::vertex_attribute_entry{ .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = + offsetof(vk::vertex_input, color) }, + vk::vertex_attribute_entry{ .location = 2, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv) }, + vk::vertex_attribute_entry{ .location = 3, + .format = vk::format::rgb32_sfloat, + .stride = + offsetof(vk::vertex_input, normals) } }; std::array attributes = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; + vk::vertex_attribute{ + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, + }, + }; // To render triangle, we do not need to set any vertex attributes - vk::shader_resource_info shader_info = { - .sources = shader_sources, - .vertex_attributes = attributes // this is to explicitly set to none, but also dont need to set this at all regardless - }; - vk::shader_resource geometry_resource(logical_device, shader_info); + vk::shader_resource_info shader_info = { + .sources = shader_sources, + .vertex_attributes = + attributes // this is to explicitly set to none, but also dont need to + // set this at all regardless + }; + vk::shader_resource geometry_resource(logical_device, shader_info); geometry_resource.vertex_attributes(attributes); - if(geometry_resource.is_valid()) { - std::println("geometry resource is valid!"); - } + if (geometry_resource.is_valid()) { + std::println("geometry resource is valid!"); + } // Setting up descriptor sets for graphics pipeline std::vector entries = { @@ -584,59 +590,57 @@ main() { }; // uint32_t image_count = image_count; vk::descriptor_layout set0_layout = { - .slot = 0, // represents as set 0 + .slot = 0, // represents as set 0 .max_sets = image_count, // max of descriptor sets able to allocate .entries = entries, // specifies pool sizes and descriptor layout }; vk::descriptor_resource set0_resource(logical_device, set0_layout); - std::array layouts = { - set0_resource.layout() - }; - - /* - // This get_pipeline_configuration can work as an easy way for specfying the vulkan configurations as an ease of setting things up - // TODO: Probably provide a shorthand - which could work as this: - vk::pipeline_settings pipeline_configuration = vk::get_pipeline_configuration(main_renderpass, geometry_resource); - */ - vk::pipeline_settings pipeline_configuration = { - .renderpass = main_renderpass, - .shader_modules = geometry_resource.handles(), - .vertex_attributes = geometry_resource.vertex_attributes(), - .vertex_bind_attributes = geometry_resource.vertex_bind_attributes(), + std::array layouts = { set0_resource.layout() }; + + /* + // This get_pipeline_configuration can work as an easy way for + specfying the vulkan configurations as an ease of setting things up + // TODO: Probably provide a shorthand - which could work as this: + vk::pipeline_settings pipeline_configuration = + vk::get_pipeline_configuration(main_renderpass, geometry_resource); + */ + vk::pipeline_settings pipeline_configuration = { + .renderpass = main_renderpass, + .shader_modules = geometry_resource.handles(), + .vertex_attributes = geometry_resource.vertex_attributes(), + .vertex_bind_attributes = geometry_resource.vertex_bind_attributes(), .descriptor_layouts = layouts - }; - vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); + }; + vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if(main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", main_graphics_pipeline.alive()); - } + if (main_graphics_pipeline.alive()) { + std::println("Main graphics pipeline alive() = {}", + main_graphics_pipeline.alive()); + } // Loading mesh - obj_model test_model(std::filesystem::path("asset_samples/viking_room.obj"), logical_device, physical_device); + obj_model test_model(std::filesystem::path("asset_samples/viking_room.obj"), + logical_device, + physical_device); std::println("Obj Model Load Status = {}", test_model.loaded()); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) - }; - vk::uniform_buffer test_ubo = vk::uniform_buffer(logical_device, test_ubo_info); + vk::uniform_params test_ubo_info = { .phsyical_memory_properties = + physical_device.memory_properties(), + .size_bytes = sizeof(global_uniform) }; + vk::uniform_buffer test_ubo = + vk::uniform_buffer(logical_device, test_ubo_info); std::println("uniform_buffer.alive() = {}", test_ubo.alive()); - std::array uniforms0 = { - vk::write_buffer{ - .buffer = test_ubo, - .offset = 0, - .range = test_ubo.size_bytes() - } - }; + std::array uniforms0 = { vk::write_buffer{ + .buffer = test_ubo, .offset = 0, .range = test_ubo.size_bytes() } }; std::array uniforms = { vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = uniforms0, + .dst_binding = 0, + .uniforms = uniforms0, } }; @@ -650,17 +654,15 @@ main() { std::println("texture1.valid = {}", texture1.loaded()); // Moving update call here because now we add textures to set0 - std::array samplers = { - vk::write_image{ - .sampler = texture1.image().sampler(), - .view = texture1.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - } - }; + std::array samplers = { vk::write_image{ + .sampler = texture1.image().sampler(), + .view = texture1.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + } }; std::array sample_images = { vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = samplers, + .dst_binding = 1, + .sample_images = samplers, } }; set0_resource.update(uniforms, sample_images); @@ -678,29 +680,25 @@ main() { .phsyical_memory_properties = physical_device.memory_properties(), .size_bytes = sizeof(skybox_camera_data) }; - vk::uniform_buffer skybox_ubo = vk::uniform_buffer(logical_device, skybox_ubo_info); + vk::uniform_buffer skybox_ubo = + vk::uniform_buffer(logical_device, skybox_ubo_info); std::println("skybox_ubo.alive() = {}", skybox_ubo.alive()); - // loading in skybox shaders, vertex attributes std::array skybox_shader_sources = { - vk::shader_source{ - .filename = "shader_samples/sample6/test.vert.spv", - .stage = vk::shader_stage::vertex - }, - vk::shader_source{ - .filename = "shader_samples/sample6/test.frag.spv", - .stage = vk::shader_stage::fragment - }, - }; + vk::shader_source{ .filename = "shader_samples/sample6/test.vert.spv", + .stage = vk::shader_stage::vertex }, + vk::shader_source{ .filename = "shader_samples/sample6/test.frag.spv", + .stage = vk::shader_stage::fragment }, + }; // Setting up vertex attributes in the test shaders // To render triangle, we do not need to set any vertex attributes - vk::shader_resource_info skybox_shader_info = { - .sources = skybox_shader_sources, - }; - vk::shader_resource skybox_resource(logical_device, skybox_shader_info); + vk::shader_resource_info skybox_shader_info = { + .sources = skybox_shader_sources, + }; + vk::shader_resource skybox_resource(logical_device, skybox_shader_info); // for skybox no vertex attributes needed // geometry_resource.vertex_attributes(skybox_vertex_attributes); @@ -729,11 +727,12 @@ main() { // in skybox shader, this descriptor set is for set 0 in the skybox shader vk::descriptor_layout skybox_layout = { - .slot = 0, // indicate that this is descriptor set 1 + .slot = 0, // indicate that this is descriptor set 1 .max_sets = image_count, // max of descriptor sets able to allocate - .entries = skybox_descriptor_entries, // specifies pool sizes and descriptor layout + .entries = skybox_descriptor_entries, // specifies pool sizes and + // descriptor layout }; - + // descriptor for skybox-specific resources on the GPU vk::descriptor_resource skybox_descriptor(logical_device, skybox_layout); @@ -743,35 +742,29 @@ main() { }; // Creating skybox graphics pipeline - vk::pipeline_settings skybox_pipeline_configuration = { - .renderpass = main_renderpass, - .shader_modules = geometry_resource.handles(), - .vertex_attributes = geometry_resource.vertex_attributes(), - .vertex_bind_attributes = geometry_resource.vertex_bind_attributes(), + vk::pipeline_settings skybox_pipeline_configuration = { + .renderpass = main_renderpass, + .shader_modules = geometry_resource.handles(), + .vertex_attributes = geometry_resource.vertex_attributes(), + .vertex_bind_attributes = geometry_resource.vertex_bind_attributes(), .descriptor_layouts = skybox_layouts - }; + }; // skybox renderpass and graphics pipeline specification - + // separate render operation for the skybox vk::renderpass skybox_renderpass; // separate graphics pipeline for loading the skybox shaders - vk::pipeline skybox_graphics_pipeline(logical_device, skybox_pipeline_configuration); - - - - + vk::pipeline skybox_graphics_pipeline(logical_device, + skybox_pipeline_configuration); // Loading Skybox std::array faces = { - "asset_samples/skybox/front.jpg", - "asset_samples/skybox/back.jpg", - "asset_samples/skybox/top.jpg", - "asset_samples/skybox/bottom.jpg", - "asset_samples/skybox/right.jpg", - "asset_samples/skybox/left.jpg" + "asset_samples/skybox/front.jpg", "asset_samples/skybox/back.jpg", + "asset_samples/skybox/top.jpg", "asset_samples/skybox/bottom.jpg", + "asset_samples/skybox/right.jpg", "asset_samples/skybox/left.jpg" }; // std::array skybox_textures; @@ -780,7 +773,8 @@ main() { // .physical = physical_device, // .filepath = std::filesystem::path(faces[i]), // }; - // skybox_textures[i] = vk::texture(logical_device, skybox_texture_info); + // skybox_textures[i] = vk::texture(logical_device, + // skybox_texture_info); // if(skybox_textures[i].loaded()) { // std::println("Skybox Texture[{}] {} loaded!", i, faces[i]); @@ -790,7 +784,6 @@ main() { // } // } - // vk::skybox_texture_info skybox_properties = { // .physical_handle = physical_device, // .faces = faces, @@ -800,7 +793,6 @@ main() { // vk::buffer_handle test_buffer; // write_array(logical_device, test_buffer); - while (!glfwWindowShouldClose(window)) { glfwPollEvents(); @@ -820,8 +812,9 @@ main() { main_renderpass.begin(begin_renderpass); // Binding a graphics pipeline -- before drawing stuff - // Inside of this graphics pipeline bind, is where you want to do the drawing stuff to - main_graphics_pipeline.bind(current); + // Inside of this graphics pipeline bind, is where you want to do the + // drawing stuff to + main_graphics_pipeline.bind(current); // Must be binded before descriptor resource gets binded test_model.bind(current); @@ -829,13 +822,23 @@ main() { static auto start_time = std::chrono::high_resolution_clock::now(); auto current_time = std::chrono::high_resolution_clock::now(); - float time = std::chrono::duration(current_time - start_time).count(); + float time = std::chrono::duration( + current_time - start_time) + .count(); // We set the uniforms and then we offload that to the GPU global_uniform ubo = { - .model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - .proj = glm::perspective(glm::radians(45.0f), (float)swapchain_extent.width / (float)swapchain_extent.height, 0.1f, 10.0f) + .model = glm::rotate(glm::mat4(1.0f), + time * glm::radians(90.0f), + glm::vec3(0.0f, 0.0f, 1.0f)), + .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, 1.0f)), + .proj = glm::perspective(glm::radians(45.0f), + (float)swapchain_extent.width / + (float)swapchain_extent.height, + 0.1f, + 10.0f) }; ubo.proj[1][1] *= -1; test_ubo.update(&ubo); @@ -843,25 +846,29 @@ main() { // Last thing that we set is going to be the skybox // This is setting the skybox uniform within the skybox.vert shader skybox_camera_data skybox_uniform_data = { - .forward = { 1.f, 0.f, 0.f, 0.f}, - .right = { 0.f, -1.f, 0.f, 0.f}, - .up = { 0.f, 0.f, 1.f, 0.f}, + .forward = { 1.f, 0.f, 0.f, 0.f }, + .right = { 0.f, -1.f, 0.f, 0.f }, + .up = { 0.f, 0.f, 1.f, 0.f }, }; skybox_ubo.update(&skybox_uniform_data); - // Before we can send stuff to the GPU, since we already updated the descriptor set 0 beforehand, we must bind that descriptor resource before making any of the draw calls - // Something to note: You cannot update descriptor sets in the process of a current-recording command buffers or else that becomes undefined behavior + // Before we can send stuff to the GPU, since we already updated the + // descriptor set 0 beforehand, we must bind that descriptor resource + // before making any of the draw calls Something to note: You cannot + // update descriptor sets in the process of a current-recording command + // buffers or else that becomes undefined behavior set0_resource.bind(current, main_graphics_pipeline.layout()); // Drawing-call to render actual triangle to the screen - // vkCmdDrawIndexed(current, static_cast(indices.size()), 1, 0, 0, 0); + // vkCmdDrawIndexed(current, static_cast(indices.size()), 1, + // 0, 0, 0); test_model.draw(current); main_renderpass.end(current); current.end(); // Submitting and then presenting to the screen - std::array commands = {current}; + std::array commands = { current }; presentation_queue.submit_async(commands); presentation_queue.present_frame(current_frame); } @@ -875,7 +882,7 @@ main() { // for(auto& skybox_texture : skybox_textures) { // if(skybox_texture.loaded()) { - // skybox_texture.destroy(); + // skybox_texture.destroy(); // } // } @@ -894,9 +901,9 @@ main() { command.destroy(); } - for (auto& fb : swapchain_framebuffers) { - fb.destroy(); - } + for (auto& fb : swapchain_framebuffers) { + fb.destroy(); + } for (auto& image : swapchain_images) { image.destroy(); @@ -906,8 +913,8 @@ main() { depth_img.destroy(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); + main_graphics_pipeline.destroy(); + geometry_resource.destroy(); main_renderpass.destroy(); presentation_queue.destroy(); diff --git a/demos/13-skybox/conanfile.py b/demos/13-skybox/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/13-skybox/conanfile.py +++ b/demos/13-skybox/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/2-physical-device/CMakeLists.txt b/demos/2-physical-device/CMakeLists.txt index 67ac695..1283a29 100644 --- a/demos/2-physical-device/CMakeLists.txt +++ b/demos/2-physical-device/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/2-physical-device/application.cpp b/demos/2-physical-device/application.cpp index eadc8a2..312a802 100644 --- a/demos/2-physical-device/application.cpp +++ b/demos/2-physical-device/application.cpp @@ -1,11 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -#define FMT_HEADER_ONLY -#include -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -57,7 +65,7 @@ int main() { //! @note Just added the some test code to test the conan-starter setup code if (!glfwInit()) { - fmt::print("glfwInit could not be initialized!\n"); + std::print("glfwInit could not be initialized!\n"); return -1; } @@ -74,7 +82,7 @@ main() { std::string title = "Hello Window"; GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); - + glfwMakeContextCurrent(window); std::array validation_layers = { @@ -86,29 +94,32 @@ main() { initialize_instance_extensions(); vk::debug_message_utility debug_callback_info = { - .severity = vk::message::verbose | vk::message::warning | vk::message::error, - .message_type = vk::debug::general | vk::debug::validation | vk::debug::performance, + .severity = + vk::message::verbose | vk::message::warning | vk::message::error, + .message_type = + vk::debug::general | vk::debug::validation | vk::debug::performance, .callback = debug_callback }; vk::application_params config = { .name = "vulkan instance", .version = vk::api_version::vk_1_3, // specify to using vulkan 1.3 - .validations = validation_layers, // .validation takes in a std::span - .extensions = global_extensions // .extensions also takes in std::span + .validations = + validation_layers, // .validation takes in a std::span + .extensions = + global_extensions // .extensions also takes in std::span }; // Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if(api_instance.alive()) { + if (api_instance.alive()) { std::println("\napi_instance alive and initiated!!!"); } // setting up physical device - vk::physical_enumeration enumerate_devices { - .device_type = vk::physical::discrete - }; + vk::physical_enumeration enumerate_devices{ .device_type = + vk::physical::discrete }; vk::physical_device device(api_instance, enumerate_devices); diff --git a/demos/2-physical-device/conanfile.py b/demos/2-physical-device/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/2-physical-device/conanfile.py +++ b/demos/2-physical-device/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/3-logical-device/CMakeLists.txt b/demos/3-logical-device/CMakeLists.txt index 1ebf5a1..07272fd 100644 --- a/demos/3-logical-device/CMakeLists.txt +++ b/demos/3-logical-device/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/3-logical-device/application.cpp b/demos/3-logical-device/application.cpp index 00fa7d7..125e32f 100644 --- a/demos/3-logical-device/application.cpp +++ b/demos/3-logical-device/application.cpp @@ -1,14 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -#define FMT_HEADER_ONLY -#include -#include -#include -#include -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -60,7 +65,7 @@ int main() { //! @note Just added the some test code to test the conan-starter setup code if (!glfwInit()) { - fmt::print("glfwInit could not be initialized!\n"); + std::print("glfwInit could not be initialized!\n"); return -1; } diff --git a/demos/3-logical-device/conanfile.py b/demos/3-logical-device/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/3-logical-device/conanfile.py +++ b/demos/3-logical-device/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/4-surface/CMakeLists.txt b/demos/4-surface/CMakeLists.txt index 321cc7a..22743e4 100644 --- a/demos/4-surface/CMakeLists.txt +++ b/demos/4-surface/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/4-surface/application.cpp b/demos/4-surface/application.cpp index 6eb357e..a9c636c 100644 --- a/demos/4-surface/application.cpp +++ b/demos/4-surface/application.cpp @@ -1,16 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -#include - -#define FMT_HEADER_ONLY -#include -#include -#include -#include -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -62,7 +65,7 @@ int main() { //! @note Just added the some test code to test the conan-starter setup code if (!glfwInit()) { - fmt::print("glfwInit could not be initialized!\n"); + std::print("glfwInit could not be initialized!\n"); return -1; } diff --git a/demos/4-surface/conanfile.py b/demos/4-surface/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/4-surface/conanfile.py +++ b/demos/4-surface/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/5-swapchain/CMakeLists.txt b/demos/5-swapchain/CMakeLists.txt index 39d4aa3..46bc736 100644 --- a/demos/5-swapchain/CMakeLists.txt +++ b/demos/5-swapchain/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/5-swapchain/application.cpp b/demos/5-swapchain/application.cpp index a8d7c89..c438eed 100644 --- a/demos/5-swapchain/application.cpp +++ b/demos/5-swapchain/application.cpp @@ -1,22 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -#include - -#define FMT_HEADER_ONLY -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -68,7 +65,7 @@ int main() { //! @note Just added the some test code to test the conan-starter setup code if (!glfwInit()) { - fmt::print("glfwInit could not be initialized!\n"); + std::print("glfwInit could not be initialized!\n"); return -1; } @@ -218,7 +215,8 @@ main() { // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // .mip_levels = 1, // .layer_count = 1, - // .phsyical_memory_properties = physical_device.memory_properties(), + // .phsyical_memory_properties = + // physical_device.memory_properties(), // }; // swapchain_depth_images[i] = // vk::sample_image(logical_device, depth_image_config); @@ -266,10 +264,11 @@ main() { std::vector swapchain_framebuffers(image_count); for (uint32_t i = 0; i < swapchain_framebuffers.size(); i++) { - std::array image_view_attachments = { - swapchain_images[i].image_view(), - // swapchain_depth_images[i].image_view() - }; + std::array + image_view_attachments = { + swapchain_images[i].image_view(), + // swapchain_depth_images[i].image_view() + }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, diff --git a/demos/5-swapchain/conanfile.py b/demos/5-swapchain/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/5-swapchain/conanfile.py +++ b/demos/5-swapchain/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/6-graphics-pipeline/CMakeLists.txt b/demos/6-graphics-pipeline/CMakeLists.txt index fef28e7..c3f91fb 100644 --- a/demos/6-graphics-pipeline/CMakeLists.txt +++ b/demos/6-graphics-pipeline/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/6-graphics-pipeline/application.cpp b/demos/6-graphics-pipeline/application.cpp index 174b24d..82aefb8 100644 --- a/demos/6-graphics-pipeline/application.cpp +++ b/demos/6-graphics-pipeline/application.cpp @@ -1,24 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( diff --git a/demos/6-graphics-pipeline/conanfile.py b/demos/6-graphics-pipeline/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/6-graphics-pipeline/conanfile.py +++ b/demos/6-graphics-pipeline/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/7-vertex-buffer/CMakeLists.txt b/demos/7-vertex-buffer/CMakeLists.txt index c6ec4b6..88e3ab7 100644 --- a/demos/7-vertex-buffer/CMakeLists.txt +++ b/demos/7-vertex-buffer/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/7-vertex-buffer/application.cpp b/demos/7-vertex-buffer/application.cpp index 3a75e8a..d5c7bf2 100644 --- a/demos/7-vertex-buffer/application.cpp +++ b/demos/7-vertex-buffer/application.cpp @@ -1,25 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( diff --git a/demos/7-vertex-buffer/conanfile.py b/demos/7-vertex-buffer/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/7-vertex-buffer/conanfile.py +++ b/demos/7-vertex-buffer/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/8-index-uniform-buffers/CMakeLists.txt b/demos/8-index-uniform-buffers/CMakeLists.txt index e2eaded..5ea113e 100644 --- a/demos/8-index-uniform-buffers/CMakeLists.txt +++ b/demos/8-index-uniform-buffers/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/8-index-uniform-buffers/application.cpp b/demos/8-index-uniform-buffers/application.cpp index 0a5be31..90e836d 100644 --- a/demos/8-index-uniform-buffers/application.cpp +++ b/demos/8-index-uniform-buffers/application.cpp @@ -1,27 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -436,9 +428,8 @@ main() { std::println("index_buffer.alive() = {}", test_ibo.alive()); vk::uniform_params ubo_info = { .phsyical_memory_properties = - physical_device.memory_properties(), - .size_bytes = - sizeof(vk::vertex_input) }; + physical_device.memory_properties(), + .size_bytes = sizeof(vk::vertex_input) }; vk::uniform_buffer test_ubo(logical_device, ubo_info); std::println("uniform_buffer.alive() = {}", test_ubo.alive()); diff --git a/demos/8-index-uniform-buffers/conanfile.py b/demos/8-index-uniform-buffers/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/8-index-uniform-buffers/conanfile.py +++ b/demos/8-index-uniform-buffers/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/9-uniforms/CMakeLists.txt b/demos/9-uniforms/CMakeLists.txt index 7d258f9..8a64b9c 100644 --- a/demos/9-uniforms/CMakeLists.txt +++ b/demos/9-uniforms/CMakeLists.txt @@ -6,13 +6,13 @@ build_application( application.cpp PACKAGES + vulkan-cpp Vulkan - VulkanHeaders - # vulkan-cpp + glfw3 + glm + stb LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp vulkan-cpp + Vulkan::Vulkan ) \ No newline at end of file diff --git a/demos/9-uniforms/application.cpp b/demos/9-uniforms/application.cpp index a511612..bd48b24 100644 --- a/demos/9-uniforms/application.cpp +++ b/demos/9-uniforms/application.cpp @@ -1,28 +1,19 @@ +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + #include #include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include +import vk; #include #define GLM_FORCE_RADIANS @@ -432,9 +423,9 @@ main() { // Setting up descriptor set layout for the set0 vk::descriptor_layout set0_layout = { - .slot = 0, // indicate that this is descriptor set 0 + .slot = 0, // indicate that this is descriptor set 0 .max_sets = image_count, // max of descriptor sets able to allocate - .entries = entries, // specifies pool sizes and descriptor layout + .entries = entries, // specifies pool sizes and descriptor layout }; // Setting up the actual descriptor set 0 and array to pass into the @@ -495,29 +486,21 @@ main() { // bind so the shader resource knows how to look up our data layout and see // if they match Will get validation layer error messages if the data layout // does not match (meaning size_bytes doesn't match) - vk::uniform_params test_ubo_info = { - // .physical_handle = physical_device, - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) + vk::uniform_params test_ubo_info = { // .physical_handle = physical_device, + .phsyical_memory_properties = + physical_device.memory_properties(), + .size_bytes = sizeof(global_uniform) }; vk::uniform_buffer test_ubo = vk::uniform_buffer(logical_device, test_ubo_info); std::println("uniform_buffer.alive() = {}", test_ubo.alive()); // vk::write_buffer_descriptor - std::array uniforms0 = { - vk::write_buffer{ - .buffer = test_ubo, - .offset = 0, - .range = test_ubo.size_bytes() - } - }; + std::array uniforms0 = { vk::write_buffer{ + .buffer = test_ubo, .offset = 0, .range = test_ubo.size_bytes() } }; std::array uniforms = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = uniforms0 - } + vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = uniforms0 } }; set0_resource.update(uniforms); @@ -576,8 +559,7 @@ main() { // before making any of the draw calls Something to note: You cannot // update descriptor sets in the process of a current-recording command // buffers or else that becomes undefined behavior - set0_resource.bind( - current, main_graphics_pipeline.layout()); + set0_resource.bind(current, main_graphics_pipeline.layout()); // Drawing-call to render actual triangle to the screen // vkCmdDraw(current, 3, 1, 0, 0); diff --git a/demos/9-uniforms/conanfile.py b/demos/9-uniforms/conanfile.py index e60d6ae..4c514cb 100644 --- a/demos/9-uniforms/conanfile.py +++ b/demos/9-uniforms/conanfile.py @@ -1,7 +1,7 @@ from conan import ConanFile from conan.tools.cmake import CMake, cmake_layout -class GameDemo(ConanFile): +class Demo(ConanFile): name = "game-demo" version = "1.0" settings = "os", "compiler", "build_type", "arch" @@ -10,16 +10,19 @@ class GameDemo(ConanFile): # Putting all of your build-related dependencies here def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") self.tool_requires("engine3d-cmake-utils/4.0") # Putting all of your packages here # To build engine3d/1.0 locally do the following: # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("tinyobjloader/2.0.0-rc10") + self.requires("vulkan-cpp/2.0") def build(self): cmake = CMake(self) diff --git a/demos/imgui-will-add-after-textures-get-into-demos/CMakeLists.txt b/demos/imgui-will-add-after-textures-get-into-demos/CMakeLists.txt deleted file mode 100644 index 6b2444d..0000000 --- a/demos/imgui-will-add-after-textures-get-into-demos/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.27) -project(descriptors CXX) - -build_application( - SOURCES - application.cpp - - PACKAGES - Vulkan - VulkanHeaders - # vulkan-cpp - - LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp - vulkan-cpp -) \ No newline at end of file diff --git a/demos/imgui-will-add-after-textures-get-into-demos/application.cpp b/demos/imgui-will-add-after-textures-get-into-demos/application.cpp deleted file mode 100644 index 559acf5..0000000 --- a/demos/imgui-will-add-after-textures-get-into-demos/application.cpp +++ /dev/null @@ -1,484 +0,0 @@ -#include -#include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static VKAPI_ATTR VkBool32 VKAPI_CALL -debug_callback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, - const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, - [[maybe_unused]] void* p_user_data) { - std::print("validation layer:\t\t{}\n\n", p_callback_data->pMessage); - return false; -} - -std::vector -initialize_instance_extensions() { - std::vector extension_names; - - extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); - - // An additional surface extension needs to be loaded. This extension is - // platform-specific so needs to be selected based on the platform the - // example is going to be deployed to. Preprocessor directives are used - // here to select the correct platform. -#ifdef VK_USE_PLATFORM_WIN32_KHR - extension_names.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XLIB_KHR - extensionNames.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XCB_KHR - extensionNames.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_ANDROID_KHR - extensionNames.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_WAYLAND_KHR - extensionNames.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_MACOS_MVK - extensionNames.emplace_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); -#endif -#ifdef USE_PLATFORM_NULLWS - extensionNames.emplace_back(VK_KHR_DISPLAY_EXTENSION_NAME); -#endif - return extension_names; -} - -int -main() { - //! @note Just added the some test code to test the conan-starter setup code - if (!glfwInit()) { - std::println("glfwInit could not be initialized!"); - return -1; - } - - if (!glfwVulkanSupported()) { - std::println("GLFW: Vulkan is not supported!"); - return -1; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - - int width = 800; - int height = 600; - std::string title = "Hello Window"; - GLFWwindow* window = - glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); - - glfwMakeContextCurrent(window); - - std::array validation_layers = { - "VK_LAYER_KHRONOS_validation", - }; - - // setting up extensions - std::vector global_extensions = - initialize_instance_extensions(); - - vk::debug_message_utility debug_callback_info = { - // .severity essentially takes in vk::message::verbose, - // vk::message::warning, vk::message::error - .severity = - vk::message::verbose | vk::message::warning | vk::message::error, - // .message_type essentially takes in vk::debug. Like: - // vk::debug::general, vk::debug::validation, vk::debug::performance - .message_type = - vk::debug::general | vk::debug::validation | vk::debug::performance, - .callback = debug_callback - }; - - vk::application_params config = { - .name = "vulkan instance", - .version = vk::api_version::vk_1_3, // specify to using vulkan 1.3 - .validations = - validation_layers, // .validation takes in a std::span - .extensions = - global_extensions // .extensions also takes in std::span - }; - - // 1. Setting up vk instance - vk::instance api_instance(config, debug_callback_info); - - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - // TODO: Implement this as a way to setup physical devices - // vk::enumerate_physical_devices(vk::instance) -> returns - // std::span - - // setting up physical device - // TODO: Probably enforce the use of vk::enumerate_physical_device({.device_type = vk::physical::discrete}) - vk::physical_enumeration enumerate_devices{ .device_type = - vk::physical::discrete }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - // selecting depth format - std::array format_support = { VK_FORMAT_D32_SFLOAT, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_FORMAT_D24_UNORM_S8_UINT }; - - // We provide a selection of format support that we want to check is - // supported on current hardware device. - VkFormat depth_format = - vk::select_depth_format(physical_device, format_support); - - vk::queue_indices queue_indices = physical_device.family_indices(); - std::println("Graphics Queue Family Index = {}", queue_indices.graphics); - std::println("Compute Queue Family Index = {}", queue_indices.compute); - std::println("Transfer Queue Family Index = {}", queue_indices.transfer); - - // setting up logical device - std::array priorities = { 0.f }; - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - vk::device_params logical_device_params = { - .queue_priorities = priorities, - .extensions = extensions, - .queue_family_index = 0, - }; - - vk::device logical_device(physical_device, logical_device_params); - - vk::surface window_surface(api_instance, window); - std::println("Starting implementation of the swapchain!!!"); - - vk::surface_params surface_properties = - vk::enumerate_surface(physical_device, window_surface); - - if (surface_properties.format.format != VK_FORMAT_UNDEFINED) { - std::println("Surface Format.format is not undefined!!!"); - } - - vk::swapchain_params enumerate_swapchain_settings = { - .width = (uint32_t)width, - .height = (uint32_t)height, - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index - }; - vk::swapchain main_swapchain(logical_device, - window_surface, - enumerate_swapchain_settings, - surface_properties); - - // querying swapchain images - // TODO: Make the images and framebuffers contained within the vk::swapchain - // Considering if you have two display they will prob have their own set of images to display to the two separate screens - uint32_t image_count = 0; - vkGetSwapchainImagesKHR(logical_device, - main_swapchain, - &image_count, - nullptr); // used to get the amount of images - std::vector images(image_count); - vkGetSwapchainImagesKHR(logical_device, - main_swapchain, - &image_count, - images.data()); // used to store in the images - - // Creating Images - std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); - - VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; - - // Setting up the images - uint32_t layer_count = 1; - uint32_t mip_levels = 1; - for (uint32_t i = 0; i < swapchain_images.size(); i++) { - vk::swapchain_image_enumeration enumerate_image_properties = { - .image = images[i], - .format = surface_properties.format.format, - // .aspect = VK_IMAGE_ASPECT_COLOR_BIT, - .aspect = vk::image_aspect_flags::color_bit, - .layer_count = 1, - .mip_levels = mip_levels - }; - swapchain_images[i] = - create_image2d_view(logical_device, enumerate_image_properties); - - // Creating Depth Images for depth buffering - vk::image_enumeration depth_image_enumeration = { - .width = swapchain_extent.width, - .height = swapchain_extent.height, - .format = depth_format, - .aspect = VK_IMAGE_ASPECT_DEPTH_BIT - }; - - // Retrieving the image resource memory requirements for specific memory - // allocation Parameter is default to using - // vk::memory_property::device_local_bit - // TODO: think about how to minimize the requirement of vk::physical_device for requesting vk::image_memory_requirements - uint32_t memory_type_index = vk::image_memory_requirements( - physical_device, logical_device, swapchain_images[i]); - swapchain_depth_images[i] = create_depth_image2d( - logical_device, depth_image_enumeration, memory_type_index); - } - - // setting up command buffers - std::vector swapchain_command_buffers(image_count); - for (size_t i = 0; i < swapchain_command_buffers.size(); i++) { - vk::command_params settings = { - enumerate_swapchain_settings.present_index, - vk::command_levels::primary, - vk::command_pool_flags::reset - }; - - swapchain_command_buffers[i] = - vk::command_buffer(logical_device, settings); - } - - // setting up renderpass - - // setting up attachments for the renderpass - std::array renderpass_attachments = { - vk::attachment{ - .format = surface_properties.format.format, - .layout = vk::image_layout::color_optimal, - .samples = vk::sample_bit::count_1, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::dont_care, - .stencil_load = vk::attachment_load::clear, - .stencil_store = vk::attachment_store::dont_care, - .initial_layout = vk::image_layout::undefined, - .final_layout = vk::image_layout::present_src_khr, - }, - vk::attachment{ - .format = depth_format, - .layout = vk::image_layout::depth_stencil_optimal, - .samples = vk::sample_bit::count_1, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::dont_care, - .stencil_load = vk::attachment_load::clear, - .stencil_store = vk::attachment_store::dont_care, - .initial_layout = vk::image_layout::undefined, - .final_layout = vk::image_layout::present_src_khr, - }, - }; - - vk::renderpass main_renderpass(logical_device, renderpass_attachments); - - std::println("renderpass created!!!"); - - // Setting up swapchain framebuffers - - std::vector swapchain_framebuffers(image_count); - for (uint32_t i = 0; i < swapchain_framebuffers.size(); i++) { - // image_view_attachments.push_back(swapchain_images[i].view); - // image_view_attachments.push_back(swapchain_depth_images[i].view); - - // NOTE: This must match the amount of attachments the renderpass also has to match the image_view attachment for per-framebuffers as well - // I just set the size to whatever the renderpass attachment size are to ensure this is the case - // Since you have an image for color attachment and another image for the depth atttachment to specify - std::array image_view_attachments = { - swapchain_images[i].view, - swapchain_depth_images[i].view - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = main_renderpass, - .views = image_view_attachments, - .extent = swapchain_extent - }; - swapchain_framebuffers[i] = vk::framebuffer(logical_device, framebuffer_info); - } - - std::println("Created VkFramebuffer's with size = {}", - swapchain_framebuffers.size()); - - // setting up presentation queue to display commands to the screen - vk::queue_params enumerate_present_queue{ - .family = 0, - .index = 0, - }; - vk::device_present_queue presentation_queue( - logical_device, main_swapchain, enumerate_present_queue); - - // gets set with the renderpass - std::array color = { 0.f, 0.5f, 0.5f, 1.f }; - - std::println("Start implementing graphics pipeline!!!"); - - // Now creating a vulkan graphics pipeline for the shader loading - std::array shader_sources = { - vk::shader_source{ - .filename = "shader_samples/test.vert.spv", - .stage = vk::shader_stage::vertex - }, - vk::shader_source{ - .filename = "shader_samples/test.frag.spv", - .stage = vk::shader_stage::fragment - }, - }; - - // To render triangle, we do not need to set any vertex attributes - vk::shader_resource_info shader_info = { - .sources = shader_sources, - .vertex_attributes = {} // this is to explicitly set to none, but also dont need to set this at all regardless - }; - vk::shader_resource geometry_resource(logical_device, shader_info); - - if(geometry_resource.is_valid()) { - std::println("geometry resource is valid!"); - } - - /* - // This get_pipeline_configuration can work as an easy way for specfying the vulkan configurations as an ease of setting things up - // TODO: Probably provide a shorthand - which could work as this: - vk::pipeline_settings pipeline_configuration = vk::get_pipeline_configuration(main_renderpass, geometry_resource); - */ - vk::pipeline_settings pipeline_configuration = { - .renderpass = main_renderpass, - .shader_modules = geometry_resource.handles(), - .vertex_attributes = geometry_resource.vertex_attributes(), - .vertex_bind_attributes = geometry_resource.vertex_bind_attributes() - }; - vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - - if(main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", main_graphics_pipeline.alive()); - } - - // NOTE: THis is for testing to see how to setup secondary command buffers for imgui-specifically - /* - Notes for self -- am going to try to consider this with the API's - */ - /* - VkCommandBufferBeginInfo imgui_cmd_buffer_begin_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT - }; - - // Gets assigned to VkCommandBufferBeginInfo - VkCommandBufferInheritanceInfo cmd_buffer_inherit_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - .pNext = nullptr, - .renderPass = main_renderpass, - .subpass = 0, - .framebuffer = nullptr, - }; - - // Assigned here - imgui_cmd_buffer_begin_info.pInheritanceInfo = &cmd_buffer_inherit_info; - */ - - // TODO -- Add this support to vk::command_buffer for preparing for applying secondary command buffers - uint32_t usage_flags = uint32_t(vk::command_usage::one_time_submit | vk::command_usage::renderpass_continue_bit); - vk::command_usage usage = (vk::command_usage)usage_flags; - - if(usage & vk::command_usage::one_time_submit) { - std::println("bitwise and'd vk::command_usage::one_time_submit"); - } - - if(usage & vk::command_usage::renderpass_continue_bit) { - std::println("bitwise and'd vk::command_usage::renderpass_continue_bit"); - } - - - while (!glfwWindowShouldClose(window)) { - glfwPollEvents(); - - uint32_t current_frame = presentation_queue.acquire_next_image(); - vk::command_buffer current = swapchain_command_buffers[current_frame]; - - current.begin(vk::command_usage::simulatneous_use_bit); - - // renderpass begin/end must be within a recording command buffer - vk::renderpass_begin_params begin_renderpass = { - .current_command = current, - .extent = swapchain_extent, - .current_framebuffer = swapchain_framebuffers[current_frame], - .color = color, - .subpass = vk::subpass_contents::inline_bit - }; - main_renderpass.begin(begin_renderpass); - - // Binding a graphics pipeline -- before drawing stuff - // Inside of this graphics pipeline bind, is where you want to do the drawing stuff to - main_graphics_pipeline.bind(current); - - // Drawing-call to render actual triangle to the screen - vkCmdDraw(current, 3, 1, 0, 0); - - main_renderpass.end(current); - current.end(); - - // Submitting and then presenting to the screen - presentation_queue.submit_async(current); - presentation_queue.present_frame(current_frame); - } - - // TODO: Make the cleanup much saner. For now we are cleaning it up like - // Potentially bring back submit_resource_free([this](){ .. free stuff .. - // }); (???) - // this to ensure they are cleaned up in the proper order - logical_device.wait(); - main_swapchain.destroy(); - - for (auto& command : swapchain_command_buffers) { - command.destroy(); - } - - for (auto& fb : swapchain_framebuffers) { - fb.destroy(); - } - - - for (auto& img : swapchain_images) { - // vk::free_image(logical_device, img); - vkDestroyImageView(logical_device, img.view, nullptr); - } - - for (auto& depth_img : swapchain_depth_images) { - vk::free_image(logical_device, depth_img); - } - - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); - - logical_device.destroy(); - window_surface.destroy(); - glfwDestroyWindow(window); - api_instance.destroy(); - return 0; -} - - - -/* - -std::vector imgui_command_buffers(frames_in_flight); - -for(size_t i = 0; i < imgui_command_buffers.size(); i++) { - vk::command_params settings = { - enumerate_swapchain_settings.present_index, - vk::command_levels::secondary, - vk::command_pool_flags::reset - }; - - imgui_command_buffers[i] = vk::command_buffer() -} - - -*/ \ No newline at end of file diff --git a/demos/imgui-will-add-after-textures-get-into-demos/conanfile.py b/demos/imgui-will-add-after-textures-get-into-demos/conanfile.py deleted file mode 100644 index e60d6ae..0000000 --- a/demos/imgui-will-add-after-textures-get-into-demos/conanfile.py +++ /dev/null @@ -1,34 +0,0 @@ -from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout - -class GameDemo(ConanFile): - name = "game-demo" - version = "1.0" - settings = "os", "compiler", "build_type", "arch" - generators = "CMakeDeps", "CMakeToolchain" - export_source = "CMakeLists.txt", "application.cpp" - - # Putting all of your build-related dependencies here - def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") - self.tool_requires("engine3d-cmake-utils/4.0") - - # Putting all of your packages here - # To build engine3d/1.0 locally do the following: - # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 - def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def package(self): - cmake = CMake(self) - cmake.install() - - def layout(self): - cmake_layout(self) \ No newline at end of file diff --git a/demos/sandbox/CMakeLists.txt b/demos/sandbox/CMakeLists.txt deleted file mode 100644 index d7de541..0000000 --- a/demos/sandbox/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -cmake_minimum_required(VERSION 3.27) -project(sandbox CXX) - -build_application( - SOURCES - application.cpp - - PACKAGES - Vulkan - VulkanHeaders - # vulkan-cpp - - LINK_PACKAGES - Vulkan::Vulkan - vulkan-headers::vulkan-headers - # vulkan-cpp::vulkan-cpp - vulkan-cpp -) \ No newline at end of file diff --git a/demos/sandbox/application.cpp b/demos/sandbox/application.cpp deleted file mode 100644 index 228b855..0000000 --- a/demos/sandbox/application.cpp +++ /dev/null @@ -1,737 +0,0 @@ -#include -#include - -// This is required to select the correct extension for specific platform -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#define GLM_FORCE_RADIANS -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include "obj_model.hpp" - -static VKAPI_ATTR VkBool32 VKAPI_CALL -debug_callback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, - const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, - [[maybe_unused]] void* p_user_data) { - std::print("validation layer:\t\t{}\n\n", p_callback_data->pMessage); - return false; -} - -std::vector -initialize_instance_extensions() { - std::vector extension_names; - - extension_names.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); - extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - - // An additional surface extension needs to be loaded. This extension is - // platform-specific so needs to be selected based on the platform the - // example is going to be deployed to. Preprocessor directives are used - // here to select the correct platform. -#ifdef VK_USE_PLATFORM_WIN32_KHR - extension_names.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XLIB_KHR - extensionNames.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_XCB_KHR - extensionNames.emplace_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_ANDROID_KHR - extensionNames.emplace_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_WAYLAND_KHR - extensionNames.emplace_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); -#endif -#ifdef VK_USE_PLATFORM_MACOS_MVK - extensionNames.emplace_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); -#endif -#ifdef USE_PLATFORM_NULLWS - extensionNames.emplace_back(VK_KHR_DISPLAY_EXTENSION_NAME); -#endif - return extension_names; -} - - -struct global_ubo { - glm::mat4 proj_view; -}; - -struct geometry_ubo { - glm::mat4 model; - glm::vec4 color; -}; - -int -main() { - //! @note Just added the some test code to test the conan-starter setup code - if (!glfwInit()) { - std::println("glfwInit could not be initialized!"); - return -1; - } - - if (!glfwVulkanSupported()) { - std::println("GLFW: Vulkan is not supported!"); - return -1; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - - int width = 800; - int height = 600; - std::string title = "Hello Window"; - GLFWwindow* window = - glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); - - glfwMakeContextCurrent(window); - - std::array validation_layers = { - "VK_LAYER_KHRONOS_validation", - }; - - // setting up extensions - std::vector global_extensions = - initialize_instance_extensions(); - - vk::debug_message_utility debug_callback_info = { - .severity = - vk::message::verbose | vk::message::warning | vk::message::error, - .message_type = - vk::debug::general | vk::debug::validation | vk::debug::performance, - .callback = debug_callback - }; - - vk::application_params config = { - .name = "vulkan instance", - .version = vk::api_version::vk_1_3, // using vulkan 1.3 - .validations = - validation_layers, - .extensions = global_extensions - }; - - // 1. Setting up vk instance - vk::instance api_instance(config, debug_callback_info); - - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - // TODO: Implement this as a way to setup physical devices - // vk::enumerate_physical_devices(vk::instance) -> returns - // std::span - - // setting up physical device - // TODO: Probably enforce the use of vk::enumerate_physical_device({.device_type = vk::physical::discrete}) - vk::physical_enumeration enumerate_devices{ .device_type = - vk::physical::discrete }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - // selecting depth format - std::array format_support = { - // VK_FORMAT_D32_SFLOAT, - // VK_FORMAT_D32_SFLOAT_S8_UINT, - // VK_FORMAT_D24_UNORM_S8_UINT, - vk::format::d32_sfloat, - vk::format::d32_sfloat_s8_uint, - vk::format::d24_unorm_s8_uint - }; - - // We provide a selection of format support that we want to check is - // supported on current hardware device. - VkFormat depth_format = - vk::select_depth_format(physical_device, format_support); - - vk::queue_indices queue_indices = physical_device.family_indices(); - std::println("Graphics Queue Family Index = {}", queue_indices.graphics); - std::println("Compute Queue Family Index = {}", queue_indices.compute); - std::println("Transfer Queue Family Index = {}", queue_indices.transfer); - - // setting up logical device - std::array priorities = { 0.f }; - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, "VK_EXT_descriptor_indexing" }; - vk::device_params logical_device_params = { - .queue_priorities = priorities, - .extensions = extensions, - .queue_family_index = 0, - }; - - vk::device logical_device(physical_device, logical_device_params); - - vk::surface window_surface(api_instance, window); - std::println("Starting implementation of the swapchain!!!"); - - vk::surface_params surface_properties = - vk::enumerate_surface(physical_device, window_surface); - - if (surface_properties.format.format != VK_FORMAT_UNDEFINED) { - std::println("Surface Format.format is not undefined!!!"); - } - - // creating our swapchain handle - vk::swapchain_params enumerate_swapchain_settings = { - .width = (uint32_t)width, - .height = (uint32_t)height, - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index - }; - vk::swapchain main_swapchain(logical_device, - window_surface, - enumerate_swapchain_settings, - surface_properties); - - // querying swapchain images - // TODO: Make the images and framebuffers contained within the vk::swapchain - // Considering if you have two display they will prob have their own set of images to display to the two separate screens - // uint32_t image_count = 0; - // vkGetSwapchainImagesKHR(logical_device, - // main_swapchain, - // &image_count, - // nullptr); // used to get the amount of images - // std::vector images(image_count); - // vkGetSwapchainImagesKHR(logical_device, - // main_swapchain, - // &image_count, - // images.data()); // used to store in the images - - // getting our presentable attachments from the associated swapchain handle - std::span images = main_swapchain.presentable_images(); - - uint32_t image_count = images.size(); - - // Creating Images for color and depth attachments - std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); - - VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; - - // setup presentable images - uint32_t layer_count = 1; - uint32_t mip_levels = 1; - for (uint32_t i = 0; i < swapchain_images.size(); i++) { - // image for color attachment - vk::image_params swapchain_image_config = { - .extent = {swapchain_extent.width, swapchain_extent.width}, - .format = surface_properties.format.format, - .aspect = vk::image_aspect_flags::color_bit, - // .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - .usage = vk::image_usage::color_attachment_bit, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = physical_device.memory_properties(), - }; - swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - // image for depth attachment - vk::image_params image_config = { - .extent = {swapchain_extent.width, swapchain_extent.width}, - .format = depth_format, - .aspect = vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = physical_device.memory_properties(), - }; - swapchain_depth_images[i] = vk::sample_image(logical_device, image_config); - } - - // setup swapchain command buffers - std::vector swapchain_command_buffers(image_count); - for (size_t i = 0; i < swapchain_command_buffers.size(); i++) { - vk::command_params settings = { - .levels = vk::command_levels::primary, - .queue_index = enumerate_swapchain_settings.present_index, - .flags = vk::command_pool_flags::reset, - }; - - swapchain_command_buffers[i] = vk::command_buffer(logical_device, settings); - } - - // setup renderpass attachments - std::array renderpass_attachments = { - // setting up color attachment - vk::attachment{ - .format = surface_properties.format.format, - .layout = vk::image_layout::color_optimal, - .samples = vk::sample_bit::count_1, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .stencil_load = vk::attachment_load::dont_care, - .stencil_store = vk::attachment_store::dont_care, - .initial_layout = vk::image_layout::undefined, - .final_layout = vk::image_layout::present_src_khr, - }, - // setting up depth attachment - vk::attachment{ - .format = depth_format, - .layout = vk::image_layout::depth_stencil_optimal, - .samples = vk::sample_bit::count_1, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::dont_care, - .stencil_load = vk::attachment_load::dont_care, - .stencil_store = vk::attachment_store::dont_care, - .initial_layout = vk::image_layout::undefined, - .final_layout = vk::image_layout::depth_stencil_read_only_optimal, - }, - }; - - vk::renderpass main_renderpass(logical_device, renderpass_attachments); - - // setup framebuffers for presentation - std::vector swapchain_framebuffers(image_count); - for (uint32_t i = 0; i < swapchain_framebuffers.size(); i++) { - std::array image_view_attachments = { - swapchain_images[i].image_view(), - swapchain_depth_images[i].image_view() - }; - - vk::framebuffer_params framebuffer_params = { - .renderpass = main_renderpass, - .views = image_view_attachments, - .extent = swapchain_extent - }; - swapchain_framebuffers[i] = vk::framebuffer(logical_device, framebuffer_params); - } - - // setup presentation queue to draw our images to the screen - vk::queue_params device_queue_params{ - .family = 0, - .index = 0, - }; - vk::device_present_queue presentation_queue( - logical_device, main_swapchain, device_queue_params); - - // background color to specify to the renderpass - std::array color = { 0.f, 0.5f, 0.5f, 1.f }; - - - // Loading shader sources - std::array shader_sources = { - vk::shader_source{ - .filename = "shader_samples/sandbox-shader-samples/test.vert.spv", - .stage = vk::shader_stage::vertex - }, - vk::shader_source{ - .filename = "shader_samples/sandbox-shader-samples/test.frag.spv", - .stage = vk::shader_stage::fragment - }, - }; - - // Define each entry in the vertex shader's attributes - std::array attribute_entries = { - // layout(location = 0) in vec3 inPosition; - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position) - }, - // layout(location = 1) in vec3 inColor; - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color) - }, - // layout(location = 2) in vec2 inTexCoords; - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv) - }, - // layout(location = 3) in vec3 inNormals; - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals) - } - }; - - std::array attributes = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; - - vk::shader_resource_info shader_info = { - .sources = shader_sources, - .vertex_attributes = attributes // this is to explicitly set to none, but also dont need to set this at all regardless - }; - vk::shader_resource geometry_resource(logical_device, shader_info); - geometry_resource.vertex_attributes(attributes); - - if(geometry_resource.is_valid()) { - std::println("geometry resource is valid!"); - } - - // Setting up descriptor sets for graphics pipeline - std::vector entries = { - vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 0) uniform UniformBufferObject" - .type = vk::buffer::uniform, - .binding_point = { - .binding = 0, - .stage = vk::shader_stage::vertex, - }, - .descriptor_count = 1, - } - }; - - vk::descriptor_layout set0_layout = { - .slot = 0, // indicate that this is descriptor set 0 - .max_sets = image_count, // max of descriptor sets able to allocate - .entries = entries, // specifies pool sizes and descriptor layout - }; - vk::descriptor_resource set0_resource(logical_device, set0_layout); - - // Loading 3D model geometry - obj_model test_model(std::filesystem::path("asset_samples/backpack/backpack.obj"), logical_device, physical_device); - - // Setting global uniforms for the global_ubo struct - vk::uniform_params global_uniform_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(global_ubo), - .debug_name = "\nglobal_uniforms\n", - .vkSetDebugUtilsObjectNameEXT = api_instance.get_debug_object_name() - }; - vk::uniform_buffer global_uniforms = vk::uniform_buffer(logical_device, global_uniform_info); - - std::array set0_buffers = { - vk::write_buffer{ - .buffer = global_uniforms, - .offset = 0, - .range = global_uniforms.size_bytes() - } - }; - std::array uniforms = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = set0_buffers - } - }; - - set0_resource.update(uniforms); - - std::vector set1_entries = { - vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 0) uniform geometry_ubo" - .type = vk::buffer::uniform, - .binding_point = { - .binding = 0, - .stage = vk::shader_stage::vertex, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // layout (set = 1, binding = 1) uniform sampler2D - .type = vk::buffer::combined_image_sampler, - .binding_point = { - .binding = 1, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // layout (set = 1, binding = 2) uniform sampler2D - .type = vk::buffer::combined_image_sampler, - .binding_point = { - .binding = 2, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - } - }; - // uint32_t image_count = image_count; - vk::descriptor_layout set1_layout = { - .slot = 1, // indicate that this is descriptor set 0 - .max_sets = image_count, // max of descriptor sets able to allocate - .entries = set1_entries - }; - - vk::descriptor_resource set1 = vk::descriptor_resource(logical_device, set1_layout); - - vk::uniform_params geo_uniform_info = { - .phsyical_memory_properties = physical_device.memory_properties(), - .size_bytes = sizeof(geometry_ubo) - }; - vk::uniform_buffer geometry_uniform = vk::uniform_buffer(logical_device, geo_uniform_info); - - std::array buffers = { - vk::write_buffer{ - .buffer = geometry_uniform, - .offset = 0, - .range = geometry_uniform.size_bytes() - } - }; - std::array write_set1_buffers = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = buffers - } - }; - - // Loading a texture -- for testing - vk::texture_info diffuse_config = { - .phsyical_memory_properties = physical_device.memory_properties(), - .filepath = std::filesystem::path("asset_samples/backpack/diffuse.jpg") - // .filepath = std::filesystem::path("asset_samples/viking_room.png") - }; - vk::texture diffuse_texture(logical_device, diffuse_config); - - vk::texture_info config_texture = { - .phsyical_memory_properties = physical_device.memory_properties(), - .filepath = std::filesystem::path("asset_samples/backpack/specular.jpg") - }; - vk::texture specular_texture(logical_device, config_texture); - - // layout(set = 1, binding = 1) uniform sampler2D - std::array binding1_images = { - vk::write_image{ - .sampler = diffuse_texture.image().sampler(), - .view = diffuse_texture.image().image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - .layout = vk::image_layout::shader_read_only_optimal - }, - }; - - std::array binding2_images2 = { - vk::write_image{ - .sampler = specular_texture.image().sampler(), - .view = specular_texture.image().image_view(), - // .image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - .layout = vk::image_layout::shader_read_only_optimal - } - }; - - std::vector sample_images = { - // layout(set = 1, binding = 1) uniform sampler2D - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = binding1_images - }, - // layout(set = 1, binding = 2) uniform sampler2D - vk::write_image_descriptor{ - .dst_binding = 2, - .sample_images = binding2_images2 - } - }; - set1.update(write_set1_buffers, sample_images); - - - - - std::array layouts = { - set0_resource.layout(), - set1.layout() - }; - - /* - // This get_pipeline_configuration can work as an easy way for specfying the vulkan configurations as an ease of setting things up - // TODO: Probably provide a shorthand - which could work as this: - vk::pipeline_settings pipeline_configuration = vk::get_pipeline_configuration(main_renderpass, geometry_resource); - */ - vk::pipeline_settings pipeline_configuration = { - .renderpass = main_renderpass, - .shader_modules = geometry_resource.handles(), - .vertex_attributes = geometry_resource.vertex_attributes(), - .vertex_bind_attributes = geometry_resource.vertex_bind_attributes(), - .descriptor_layouts = layouts - }; - vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - - - /* - - Descriptor Indexing - - glsl shader - - - layout(set = 0, binding = 0) readonly buffer mesh_data { - mesh_uniform goemetry_data[]; // unbounded mesh arrays that contain all of the meshes array - }; - - In Vulkan API for specifically doing descriptor resources - - // 1.) Setup descriptor variable count allocation parameters - uint32_t actual_descriptor_count = 50; - VkDescriptorSetVariableDescriptorCountjAllocateInfo descriptor_count_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, - .descriptorSetCount = 1, - .pDescriptorCounts = &actual_descriptor_count, // current size of descriptors - }; - - 2.) Setup descriptor layout bindings create infos to-be chained - - 2.1.) Setting up parameter flags - VkDescriptorBindingFlags flags = - VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT; // Allows only N buffers to be bound - - 2.2.) setting up the actual binding flags for descriptors - VkDescriptorSetLayoutBindingFlagsCreateInfo bindings_flags_ci = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, - .pNext = nullptr, - .bindingCount = 1, - .pBindingFlags = &flags, - }; - - 3.) Once setting up the parameters to setup descriptor indexing then we pass that into descriptor layout - VkDescriptorSetLayoutCreateInfo layout_ci = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - // Chain the binding flags struct - .pNext = &bindingFlagsInfo, - // Flag the set layout for update-after-bind usage (common for bindless) - .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, // will be represnted as vk::descriptor_layout_flag::update_after_bind_pool - .bindingCount = 1, - .pBindings = &binding, - }; - - */ - - while (!glfwWindowShouldClose(window)) { - glfwPollEvents(); - - uint32_t current_frame = presentation_queue.acquire_next_image(); - vk::command_buffer current = swapchain_command_buffers[current_frame]; - - current.begin(vk::command_usage::simulatneous_use_bit); - - // renderpass begin/end must be within a recording command buffer - vk::renderpass_begin_params begin_renderpass = { - .current_command = current, - .extent = swapchain_extent, - .current_framebuffer = swapchain_framebuffers[current_frame], - .color = color, - .subpass = vk::subpass_contents::inline_bit - }; - main_renderpass.begin(begin_renderpass); - - // Bind before drawing - main_graphics_pipeline.bind(current); - - // bind obj model before drawing - test_model.bind(current); - - static auto start_time = std::chrono::high_resolution_clock::now(); - - auto current_time = std::chrono::high_resolution_clock::now(); - float time = std::chrono::duration(current_time - start_time).count(); - - // We set the uniforms and then we offload that to the GPU - glm::mat4 view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f),glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)); - glm::mat4 proj = glm::perspective(glm::radians(45.0f),(float)swapchain_extent.width / (float)swapchain_extent.height, 0.1f, 10.0f); - - glm::mat4 proj_view = proj * view; - proj[1][1] *= -1; - - glm::mat4 model_test = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); - - global_ubo uniform = { - .proj_view = proj * view - }; - - geometry_ubo uniform_geometry = { - .model = model_test, - .color = glm::vec4(1.f, 1.f, 1.f, 1.f) - }; - - // global_uniform ubo = { - // .model = glm::rotate(glm::mat4(1.0f), time * glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - // .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)), - // .proj = glm::perspective(glm::radians(45.0f), (float)swapchain_extent.width / (float)swapchain_extent.height, 0.1f, 10.0f) - // }; - // ubo.proj[1][1] *= -1; - global_uniforms.update(&uniform); - - geometry_uniform.update(&uniform_geometry); - - // Before we can send stuff to the GPU, since we already updated the descriptor set 0 beforehand, we must bind that descriptor resource before making any of the draw calls - // Something to note: You cannot update descriptor sets in the process of a current-recording command buffers or else that becomes undefined behavior - set0_resource.bind(current, main_graphics_pipeline.layout()); - set1.bind(current, main_graphics_pipeline.layout()); - - // Draw call here - test_model.draw(current); - - main_renderpass.end(current); - current.end(); - - // Submitting and then presenting to the screen - std::array commands = {current}; - presentation_queue.submit_async(commands); - presentation_queue.present_frame(current_frame); - } - - // TODO: Make the cleanup much saner. For now we are cleaning it up like - // Potentially bring back submit_resource_free([this](){ .. free stuff .. - // }); (???) - // this to ensure they are cleaned up in the proper order - logical_device.wait(); - main_swapchain.destroy(); - - diffuse_texture.destroy(); - specular_texture.destroy(); - set0_resource.destroy(); - set1.destroy(); - global_uniforms.destroy(); - geometry_uniform.destroy(); - test_model.destroy(); - - for (auto& command : swapchain_command_buffers) { - command.destroy(); - } - - for (auto& fb : swapchain_framebuffers) { - fb.destroy(); - } - - for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); - } - - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); - - logical_device.destroy(); - window_surface.destroy(); - glfwDestroyWindow(window); - api_instance.destroy(); - return 0; -} \ No newline at end of file diff --git a/demos/sandbox/conanfile.py b/demos/sandbox/conanfile.py deleted file mode 100644 index e60d6ae..0000000 --- a/demos/sandbox/conanfile.py +++ /dev/null @@ -1,34 +0,0 @@ -from conan import ConanFile -from conan.tools.cmake import CMake, cmake_layout - -class GameDemo(ConanFile): - name = "game-demo" - version = "1.0" - settings = "os", "compiler", "build_type", "arch" - generators = "CMakeDeps", "CMakeToolchain" - export_source = "CMakeLists.txt", "application.cpp" - - # Putting all of your build-related dependencies here - def build_requirements(self): - self.tool_requires("make/4.4.1") - self.tool_requires("cmake/3.27.1") - self.tool_requires("engine3d-cmake-utils/4.0") - - # Putting all of your packages here - # To build engine3d/1.0 locally do the following: - # conan create . --name=engine3d --version=0.1.0 --user=local --channel=12345 - def requirements(self): - self.requires("vulkan-headers/1.3.290.0") - self.requires("vulkan-cpp/1.0") - - def build(self): - cmake = CMake(self) - cmake.configure() - cmake.build() - - def package(self): - cmake = CMake(self) - cmake.install() - - def layout(self): - cmake_layout(self) \ No newline at end of file diff --git a/demos/sandbox/cubemap.hpp b/demos/sandbox/cubemap.hpp deleted file mode 100644 index 5d3b6ef..0000000 --- a/demos/sandbox/cubemap.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include - -struct cubemap_ubo { - glm::vec4 forwards; - glm::vec4 right; - glm::vec4 up; -}; - -class skybox { -public: - skybox() = default; - skybox(const VkDevice& p_device, VkPhysicalDeviceMemoryProperties p_memory_properties, std::filesystem::path& p_path) : m_device(p_device) { - vk::texture_info params = { - .phsyical_memory_properties = p_memory_properties, - .filepath = p_path, - }; - m_cubemap_texture = vk::texture(p_device, params, true); - - vk::uniform_params uniforms_params = { - .size_bytes = sizeof(cubemap_ubo), - }; - m_cubemap_uniform = vk::uniform_buffer(p_device, uniforms_params); - } - - - void load_descriptors() { - - std::vector set0_entries = { - vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 0) uniform global_uniform" - .type = vk::buffer::uniform, - .binding_point = { - .binding = 0, - .stage = vk::shader_stage::vertex, - }, - .descriptor_count = 1, - } - }; - - vk::descriptor_layout set0_layout = { - .slot = 0, - .max_sets = 1, - .entries = set0_entries, - }; - - m_skybox_descriptor = vk::descriptor_resource(m_device, set0_layout); - } - - - void load_shaders() { - std::array sources = { - vk::shader_source{ - .filename = "shader_samples/sandbox-shader-samples/skybox.vert.spv", - .stage = vk::shader_stage::vertex, - }, - vk::shader_source{ - .filename = "shader_samples/sandbox-shader-samples/skybox.frag.spv", - .stage = vk::shader_stage::fragment, - } - }; - - std::array attribute_entries = { - // layout(location = 0) in vec3 inPosition; - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position) - }, - // layout(location = 1) in vec3 inColor; - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color) - }, - // layout(location = 2) in vec2 inTexCoords; - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv) - }, - // layout(location = 3) in vec3 inNormals; - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals) - } - }; - - std::array attributes = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; - - vk::shader_resource_info info = { - .sources = sources - }; - m_skybox_shaders = vk::shader_resource(m_device, info); - m_skybox_shaders.vertex_attributes(attributes); - } - - void load_pipeline() { - std::array layouts = {m_skybox_descriptor.layout()}; - - vk::pipeline_settings pipeline_params = { - .renderpass = m_skybox_renderpass, - .shader_modules = m_skybox_shaders.handles(), - .vertex_attributes = m_skybox_shaders.vertex_attributes(), - .vertex_bind_attributes = m_skybox_shaders.vertex_bind_attributes(), - .descriptor_layouts = layouts - }; - m_skybox_pipeline = vk::pipeline(m_device, pipeline_params); - } - -private: - VkDevice m_device=nullptr; - vk::texture m_cubemap_texture; - vk::uniform_buffer m_cubemap_uniform; - vk::pipeline m_skybox_pipeline; - vk::descriptor_resource m_skybox_descriptor; - - vk::shader_resource m_skybox_shaders; - - vk::renderpass m_skybox_renderpass; -}; \ No newline at end of file diff --git a/demos/sandbox/obj_model.hpp b/demos/sandbox/obj_model.hpp deleted file mode 100644 index 1f4dfb4..0000000 --- a/demos/sandbox/obj_model.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#define GLM_FORCE_RADIANS -#include -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include - -// loading tinyobjloader library here -#include -#include "uniforms.hpp" -#include -#include -#include - -template -void hash_combine(size_t& seed, const T& v, const Rest&... rest) { - seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); - (hash_combine(seed, rest), ...); -} - - -namespace std { - - template<> - struct hash { - size_t operator()(const vk::vertex_input& vertex) const { - size_t seed = 0; - hash_combine( - seed, vertex.position, vertex.color, vertex.normals, vertex.uv); - return seed; - } - }; -} - -// This is how we are going to load a .obj model for this demo -// Example of how you might want to have your own classes for loading geometry-meshes -class obj_model { -public: - obj_model() = default; - obj_model(const std::filesystem::path& p_filename, const VkDevice& p_device, const vk::physical_device& p_physical, bool p_flip=false) { - tinyobj::attrib_t attrib; - std::vector shapes; - std::vector materials; - std::string warn, err; - - //! @note If we return the constructor then we can check if the mesh - //! loaded successfully - //! @note We also receive hints if the loading is successful! - //! @note Return default constructor automatically returns false means - //! that mesh will return the boolean as false because it wasnt - //! successful - if (!tinyobj::LoadObj(&attrib, - &shapes, - &materials, - &warn, - &err, - p_filename.string().c_str())) { - std::println("Could not load model from path {}", p_filename.string()); - m_is_loaded = false; - return; - } - - std::vector vertices; - std::vector indices; - std::unordered_map unique_vertices{}; - - std::println("p_flip = {}", p_flip); - - for(size_t i = 0; i < shapes.size(); i++) { - auto shape = shapes[i]; - // for (const auto& index : shape.mesh.indices) { - for(size_t j = 0; j < shape.mesh.indices.size(); j++) { - auto index = shape.mesh.indices[j]; - ::vk::vertex_input vertex{}; - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - if (index.vertex_index >= 0) { - vertex.position = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; - - vertex.color = { - attrib.colors[3 * index.vertex_index + 0], - attrib.colors[3 * index.vertex_index + 1], - attrib.colors[3 * index.vertex_index + 2] - }; - } - - if (!attrib.normals.empty()) { - vertex.normals = { - attrib.normals[3 * index.normal_index + 0], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2] - }; - } - if(!attrib.texcoords.empty()) { - glm::vec2 flipped_uv = { - attrib.texcoords[static_cast(index.texcoord_index) * 2], - 1.0f - attrib.texcoords[static_cast(index.texcoord_index) * 2 + 1], - }; - - glm::vec2 original_uv = { - attrib.texcoords[static_cast(index.texcoord_index) * 2], - attrib.texcoords[static_cast(index.texcoord_index) * 2 + 1], - }; - - // vertex.uv = m_flip ? flipped_uv : original_uv; - if(p_flip) { - vertex.uv = flipped_uv; - } - else { - vertex.uv = original_uv; - } - } - else { - vertex.uv = glm::vec2(0.f, 0.f); - } - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - indices.push_back(unique_vertices[vertex]); - } - } - vk::vertex_params vertex_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .vertices = vertices - }; - - vk::index_params index_info = { - .phsyical_memory_properties = p_physical.memory_properties(), - .indices = indices - }; - m_vertex_buffer = vk::vertex_buffer(p_device, vertex_info); - m_index_buffer = vk::index_buffer(p_device, index_info); - m_is_loaded = true; - } - - [[nodiscard]] bool loaded() const { return m_is_loaded; } - - void bind(const VkCommandBuffer& p_command) { - m_vertex_buffer.bind(p_command); - if(m_index_buffer.size() > 0) { - m_index_buffer.bind(p_command); - } - } - - void draw(const VkCommandBuffer& p_command) { - if(m_index_buffer.size() > 0) { - vkCmdDrawIndexed(p_command, static_cast(m_index_buffer.size()), 1, 0, 0, 0); - } - else { - vkCmdDraw(p_command, m_vertex_buffer.size(), 1, 0, 0); - } - } - - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); - } - -private: - bool m_is_loaded=false; - vk::vertex_buffer m_vertex_buffer{}; - vk::index_buffer m_index_buffer{}; -}; \ No newline at end of file diff --git a/demos/sandbox/uniforms.hpp b/demos/sandbox/uniforms.hpp deleted file mode 100644 index 3636ab4..0000000 --- a/demos/sandbox/uniforms.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -struct global_uniform { - glm::mat4 model; - glm::mat4 view; - glm::mat4 proj; -}; \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index a84b3a3..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ - -set( - all_src - vulkan-cpp/instance.cpp - vulkan-cpp/utilities.cpp - vulkan-cpp/physical_device.cpp - vulkan-cpp/device.cpp - vulkan-cpp/device_queue.cpp - vulkan-cpp/surface.cpp - vulkan-cpp/swapchain.cpp - vulkan-cpp/device_present_queue.cpp - vulkan-cpp/command_buffer.cpp - vulkan-cpp/renderpass.cpp - vulkan-cpp/framebuffer.cpp - vulkan-cpp/shader_resource.cpp - vulkan-cpp/pipeline.cpp - vulkan-cpp/vertex_buffer.cpp - vulkan-cpp/index_buffer.cpp - vulkan-cpp/uniform_buffer.cpp - vulkan-cpp/descriptor_resource.cpp - vulkan-cpp/texture.cpp - vulkan-cpp/buffer_streams.cpp - vulkan-cpp/buffer_streams16.cpp - vulkan-cpp/buffer_streams32.cpp - vulkan-cpp/sample_image.cpp - # vulkan-cpp/skybox_texture.cpp -) - -add_library(${PROJECT_NAME} ${all_src}) - - diff --git a/src/vulkan-cpp/buffer_streams.cpp b/src/vulkan-cpp/buffer_streams.cpp deleted file mode 100644 index df861c4..0000000 --- a/src/vulkan-cpp/buffer_streams.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include - -namespace vk { - - buffer_stream::buffer_stream(const VkDevice& p_device, - const buffer_parameters& p_settings) - : m_device(p_device) { - m_allocation_size = p_settings.device_size; - - VkBufferCreateInfo buffer_ci = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = m_allocation_size, // size in bytes - .usage = p_settings.usage, - .sharingMode = p_settings.share_mode, - }; - - vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), - "vkCreateBuffer"); - - // 2. retrieving buffer memory requirements - VkMemoryRequirements memory_requirements = {}; - vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); - - // 3. selects the required memory requirements for this specific buffer - // allocations - uint32_t memory_index = - select_memory_requirements(p_settings.physical_memory_properties, - memory_requirements, - p_settings.property_flags); - - // 4. allocatring the necessary memory based on memory requirements for - // the buffer handles - VkMemoryAllocateInfo memory_alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = memory_requirements.size, - .memoryTypeIndex = memory_index - }; - -#if _DEBUG - // 1. Define the structure - VkDebugUtilsObjectNameInfoEXT debug_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, - .pNext = nullptr, - .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is - .pObjectName = p_settings.debug_name // specify what type of buffer this is - }; - - if(p_settings.vkSetDebugUtilsObjectNameEXT != nullptr) { - // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - p_settings.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - } -#endif - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); - - // 5. bind memory resource of this buffer handle - vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), - "vkBindBufferMemory"); - } - - void buffer_stream::write(std::span p_data) { - void* mapped = nullptr; - vk_check( - vkMapMemory( - m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_data.data(), p_data.size_bytes()); - vkUnmapMemory(m_device, m_device_memory); - } - - void buffer_stream::copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent) { - VkBufferImageCopy buffer_image_copy = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1 }, - .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } - }; - - vkCmdCopyBufferToImage(p_command, - m_handle, - p_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &buffer_image_copy); - } - - void buffer_stream::destroy() { - if (m_handle != nullptr) { - vkDestroyBuffer(m_device, m_handle, nullptr); - } - - if (m_device_memory != nullptr) { - vkFreeMemory(m_device, m_device_memory, nullptr); - } - } - -}; \ No newline at end of file diff --git a/src/vulkan-cpp/buffer_streams16.cpp b/src/vulkan-cpp/buffer_streams16.cpp deleted file mode 100644 index a5c4edb..0000000 --- a/src/vulkan-cpp/buffer_streams16.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include - -namespace vk { - buffer_stream16::buffer_stream16(const VkDevice& p_device, const buffer_parameters& p_params) : m_device(p_device) { - VkBufferCreateInfo buffer_ci = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = p_params.device_size, // size in bytes - .usage = p_params.usage, - .sharingMode = p_params.share_mode, - }; - - vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), - "vkCreateBuffer"); - - // 2. retrieving buffer memory requirements - VkMemoryRequirements memory_requirements = {}; - vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); - - // 3. selects the required memory requirements for this specific buffer - // allocations - uint32_t memory_index = - select_memory_requirements(p_params.physical_memory_properties, - memory_requirements, - p_params.property_flags); - - // 4. allocatring the necessary memory based on memory requirements for - // the buffer handles - VkMemoryAllocateInfo memory_alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = memory_requirements.size, - .memoryTypeIndex = memory_index - }; - -#if _DEBUG - // 1. Define the structure - VkDebugUtilsObjectNameInfoEXT debug_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, - .pNext = nullptr, - .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is - .pObjectName = p_params.debug_name // specify what type of buffer this is - }; - - if(p_params.vkSetDebugUtilsObjectNameEXT != nullptr) { - // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - p_params.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - } -#endif - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); - - // 5. bind memory resource of this buffer handle - vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), - "vkBindBufferMemory"); - } - - void buffer_stream16::write(std::span p_data) { - void* mapped = nullptr; - vk_check( - vkMapMemory( - m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_data.data(), p_data.size_bytes()); - vkUnmapMemory(m_device, m_device_memory); - } - - void buffer_stream16::copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent) { - VkBufferImageCopy buffer_image_copy = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1 }, - .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } - }; - - vkCmdCopyBufferToImage(p_command, - m_handle, - p_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &buffer_image_copy); - } - - void buffer_stream16::destroy() { - if (m_handle != nullptr) { - vkDestroyBuffer(m_device, m_handle, nullptr); - } - - if (m_device_memory != nullptr) { - vkFreeMemory(m_device, m_device_memory, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/buffer_streams32.cpp b/src/vulkan-cpp/buffer_streams32.cpp deleted file mode 100644 index 7ce531d..0000000 --- a/src/vulkan-cpp/buffer_streams32.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include - -namespace vk { - buffer_stream32::buffer_stream32(const VkDevice& p_device, const buffer_parameters& p_params) : m_device(p_device) { - VkBufferCreateInfo buffer_ci = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .size = p_params.device_size, // size in bytes - .usage = p_params.usage, - .sharingMode = p_params.share_mode, - }; - - vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), - "vkCreateBuffer"); - - // 2. retrieving buffer memory requirements - VkMemoryRequirements memory_requirements = {}; - vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); - - // 3. selects the required memory requirements for this specific buffer - // allocations - uint32_t memory_index = - select_memory_requirements(p_params.physical_memory_properties, - memory_requirements, - p_params.property_flags); - - // 4. allocatring the necessary memory based on memory requirements for - // the buffer handles - VkMemoryAllocateInfo memory_alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = memory_requirements.size, - .memoryTypeIndex = memory_index - }; - -#if _DEBUG - // 1. Define the structure - VkDebugUtilsObjectNameInfoEXT debug_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, - .pNext = nullptr, - .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is - .pObjectName = p_params.debug_name // specify what type of buffer this is - }; - - if(p_params.vkSetDebugUtilsObjectNameEXT != nullptr) { - // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - p_params.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - } -#endif - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); - - // 5. bind memory resource of this buffer handle - vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), - "vkBindBufferMemory"); - } - - void buffer_stream32::write(std::span p_data) { - void* mapped = nullptr; - vk_check( - vkMapMemory( - m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_data.data(), p_data.size_bytes()); - vkUnmapMemory(m_device, m_device_memory); - } - - void buffer_stream32::copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent) { - VkBufferImageCopy buffer_image_copy = { - .bufferOffset = 0, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1 }, - .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } - }; - - vkCmdCopyBufferToImage(p_command, - m_handle, - p_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &buffer_image_copy); - } - - void buffer_stream32::destroy() { - if (m_handle != nullptr) { - vkDestroyBuffer(m_device, m_handle, nullptr); - } - - if (m_device_memory != nullptr) { - vkFreeMemory(m_device, m_device_memory, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/command_buffer.cpp b/src/vulkan-cpp/command_buffer.cpp deleted file mode 100644 index a4b518a..0000000 --- a/src/vulkan-cpp/command_buffer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include - -namespace vk { - command_buffer::command_buffer( - const VkDevice& p_device, - const command_params& p_enumerate_command_info) - : m_device(p_device) { - VkCommandPoolCreateInfo pool_ci = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .pNext = nullptr, - // .flags = - // (VkCommandPoolCreateFlags)p_enumerate_command_info.pool_flag, - .flags = static_cast(p_enumerate_command_info.flags), - .queueFamilyIndex = p_enumerate_command_info.queue_index - }; - - vk_check( - vkCreateCommandPool(m_device, &pool_ci, nullptr, &m_command_pool), - "vkCreateCommandPool"); - - VkCommandBufferAllocateInfo command_buffer_alloc_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .pNext = nullptr, - .commandPool = m_command_pool, - .level = - static_cast(p_enumerate_command_info.levels), - .commandBufferCount = 1 - }; - - vk_check(vkAllocateCommandBuffers( - m_device, &command_buffer_alloc_info, &m_command_buffer), - "vkAllocateCommandBuffers"); - } - - void command_buffer::begin( - command_usage p_usage, - std::span p_inherit_info) { - // Resets to zero if get called every frame - if (m_begin_end_count == 2) { - m_begin_end_count = 0; - } - m_begin_end_count++; - - std::vector inheritance_infos( - p_inherit_info.size()); - - for (size_t i = 0; i < inheritance_infos.size(); i++) { - inheritance_infos[i] = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, - .renderPass = p_inherit_info[i].renderpass, - .subpass = p_inherit_info[i].subpass_index, - .framebuffer = p_inherit_info[i].framebuffer - }; - } - - VkCommandBufferBeginInfo command_begin_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .pNext = nullptr, - .flags = static_cast(p_usage) - }; - vk_check(vkBeginCommandBuffer(m_command_buffer, &command_begin_info), - "vkBeginCommandBuffer"); - } - - void command_buffer::end() { - m_begin_end_count++; - vkEndCommandBuffer(m_command_buffer); - } - - void command_buffer::copy_buffer(const VkBuffer& p_src, const VkBuffer& p_dst, uint64_t p_size_bytes) { - VkBufferCopy copy_region{}; - copy_region.size = p_size_bytes; - vkCmdCopyBuffer(m_command_buffer, p_src, p_dst, 1, ©_region); - } - - void command_buffer::execute(std::span p_commands) { - vkCmdExecuteCommands(m_command_buffer, - static_cast(p_commands.size()), - p_commands.data()); - } - - void command_buffer::destroy() { - vkFreeCommandBuffers(m_device, m_command_pool, 1, &m_command_buffer); - vkDestroyCommandPool(m_device, m_command_pool, nullptr); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/descriptor_resource.cpp b/src/vulkan-cpp/descriptor_resource.cpp deleted file mode 100644 index ab5f1b6..0000000 --- a/src/vulkan-cpp/descriptor_resource.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include - -namespace vk { - - descriptor_resource::descriptor_resource(const VkDevice& p_device, - const descriptor_layout& p_info) - : m_device(p_device) - , m_slot(p_info.slot) { - std::vector pool_sizes(p_info.entries.size()); - std::vector descriptor_layout_bindings( - p_info.entries.size()); - - for (size_t i = 0; i < pool_sizes.size(); i++) { - VkDescriptorType descriptor_type = static_cast(p_info.entries[i].type); - pool_sizes[i] = { - .type = descriptor_type, - .descriptorCount = - static_cast(p_info.entries[i].descriptor_count) * - p_info.max_sets, - }; - } - - for (size_t i = 0; i < descriptor_layout_bindings.size(); i++) { - descriptor_entry entry = p_info.entries[i]; - descriptor_binding_point bind = entry.binding_point; - - VkDescriptorType type = static_cast(entry.type); - - descriptor_layout_bindings[i] = { - .binding = bind.binding, - .descriptorType = type, - .descriptorCount = entry.descriptor_count, - .stageFlags = static_cast(bind.stage), - }; - } - - VkDescriptorPoolCreateInfo pool_ci = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .maxSets = p_info.max_sets, - .poolSizeCount = static_cast(pool_sizes.size()), - .pPoolSizes = pool_sizes.data() - }; - - vk_check(vkCreateDescriptorPool( - m_device, &pool_ci, nullptr, &m_descriptor_pool), - "vkCreateDescriptorPool"); - - VkDescriptorSetLayoutCreateInfo descriptor_layout_ci = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .bindingCount = - static_cast(descriptor_layout_bindings.size()), - .pBindings = descriptor_layout_bindings.data() - }; - - vk_check( - vkCreateDescriptorSetLayout( - m_device, &descriptor_layout_ci, nullptr, &m_descriptor_layout), - "vkCreateDescriptorSetLayout"); - VkDescriptorSetAllocateInfo descriptor_set_alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .pNext = nullptr, - .descriptorPool = m_descriptor_pool, - .descriptorSetCount = 1, - .pSetLayouts = &m_descriptor_layout - }; - - vk_check(vkAllocateDescriptorSets(m_device, - &descriptor_set_alloc_info, - &m_descriptor_set), - "vkAllocateDescriptorSets"); - } - - void descriptor_resource::update(std::span p_uniforms, std::span p_images) { - std::vector write_descriptors; - - // uint32_t represent the destination bindings to those resources (uniforms and sample images) - std::unordered_map> buffer_infos; - std::unordered_map> image_infos; - - // handle uniforms - for(const auto& ubo : p_uniforms) { - for(const auto& uniform : ubo.uniforms) { - buffer_infos[ubo.dst_binding].emplace_back(uniform.buffer, uniform.offset, uniform.range); - } - - VkWriteDescriptorSet write_descriptor = { - . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = m_descriptor_set, - .dstBinding = ubo.dst_binding, - .dstArrayElement = 0, - .descriptorCount = static_cast(buffer_infos[ubo.dst_binding].size()), - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pBufferInfo = buffer_infos[ubo.dst_binding].data(), - }; - - write_descriptors.emplace_back(write_descriptor); - } - - for(const auto& ubo : p_images) { - - for(const auto& sample_image : ubo.sample_images) { - image_infos[ubo.dst_binding].emplace_back(sample_image.sampler, sample_image.view, static_cast(sample_image.layout)); - } - - VkWriteDescriptorSet write_descriptor = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .pNext = nullptr, - .dstSet = m_descriptor_set, - .dstBinding = ubo.dst_binding, - .dstArrayElement = 0, - .descriptorCount = static_cast(image_infos[ubo.dst_binding].size()), - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .pImageInfo = image_infos[ubo.dst_binding].data(), - }; - - write_descriptors.emplace_back(write_descriptor); - } - - vkUpdateDescriptorSets( - m_device, - static_cast(write_descriptors.size()), - write_descriptors.data(), - 0, - nullptr); - - // Ensures to clear up so we dont have any existing handles because they only need to exist until we've updated the descriptors - buffer_infos.clear(); - image_infos.clear(); - } - - void descriptor_resource::bind(const VkCommandBuffer& p_current, - const VkPipelineLayout& p_pipeline_layout) { - - vkCmdBindDescriptorSets(p_current, - VK_PIPELINE_BIND_POINT_GRAPHICS, - p_pipeline_layout, - m_slot, - 1, - &m_descriptor_set, - 0, - nullptr); - } - - void descriptor_resource::destroy() { - if (m_descriptor_pool != nullptr) { - vkDestroyDescriptorPool(m_device, m_descriptor_pool, nullptr); - } - - if (m_descriptor_layout != nullptr) { - vkDestroyDescriptorSetLayout( - m_device, m_descriptor_layout, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/device.cpp b/src/vulkan-cpp/device.cpp deleted file mode 100644 index 3517f81..0000000 --- a/src/vulkan-cpp/device.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -namespace vk { - - device::device(const VkPhysicalDevice& p_physical, - const device_params& p_config) { - - VkDeviceQueueCreateInfo device_queue_ci = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = p_config.queue_family_index, - .queueCount = - static_cast(p_config.queue_priorities.size()), - .pQueuePriorities = p_config.queue_priorities.data(), - }; - - VkDeviceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &device_queue_ci, - .enabledLayerCount = 0, - .ppEnabledLayerNames = nullptr, - .enabledExtensionCount = - static_cast(p_config.extensions.size()), - .ppEnabledExtensionNames = p_config.extensions.data(), - }; - - VkPhysicalDeviceFeatures features; - vkGetPhysicalDeviceFeatures(p_physical, &features); - features.robustBufferAccess = false; - create_info.pEnabledFeatures = &features; - - vk_check(vkCreateDevice(p_physical, &create_info, nullptr, &m_device), - "vkCreateDevice"); - } - - void device::wait() { - vkDeviceWaitIdle(m_device); - } - - void device::destroy() { - - if (m_device != nullptr) { - vkDestroyDevice(m_device, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/device_present_queue.cpp b/src/vulkan-cpp/device_present_queue.cpp deleted file mode 100644 index fee2c67..0000000 --- a/src/vulkan-cpp/device_present_queue.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include - -namespace vk { - - device_present_queue::device_present_queue( - const VkDevice& p_device, - const VkSwapchainKHR& p_swapchain_context, - const queue_params& p_config) - : m_device(p_device) - , m_swapchain(p_swapchain_context) { - vkGetDeviceQueue( - m_device, p_config.family, p_config.index, &m_queue_handler); - - m_work_completed = create_semaphore(m_device); - m_presentation_completed = create_semaphore(m_device); - m_out_of_date = false; - } - - void device_present_queue::wait_idle() { - vkQueueWaitIdle(m_queue_handler); - } - - bool device_present_queue::out_of_date(bool p_is_reset) { - // The return value we return - bool return_value = false; - - // If the bool is set to true meaning its out of date - // Then we set the internal variable tracking the acquired next image - // state to false, and return false This is for ensuring that we do not - // need to set the boolean ourselves. Should we handle this state to - // reset to false if checked or user should set the state??? - if (m_out_of_date) { - return_value = m_out_of_date; - if (p_is_reset) { - m_out_of_date = false; - } - return return_value; - } - - return return_value; - } - - uint32_t device_present_queue::acquire_next_image() { - wait_idle(); - - uint32_t image_acquired; - VkResult acquired_next_image_res = - vkAcquireNextImageKHR(m_device, - m_swapchain, - std::numeric_limits::max(), - m_presentation_completed, - nullptr, - &image_acquired); - - if (acquired_next_image_res == VK_ERROR_OUT_OF_DATE_KHR) { - m_out_of_date = true; - } - - vk_check(acquired_next_image_res, "vkAcquireNextImageKHR"); - - return image_acquired; - } - - void device_present_queue::submit_sync( - std::span p_commands) { - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = nullptr, - .waitSemaphoreCount = 0, - .pWaitSemaphores = nullptr, - .pWaitDstStageMask = nullptr, - .commandBufferCount = static_cast(p_commands.size()), - .pCommandBuffers = p_commands.data(), - .signalSemaphoreCount = 0, - .pSignalSemaphores = nullptr, - }; - - VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); - vk_check(res, "vkQueueSubmit"); - } - - void device_present_queue::submit_async( - std::span p_commands, - pipeline_stage_flags p_flags) { - VkPipelineStageFlags flags = static_cast(p_flags); - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pNext = nullptr, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &m_presentation_completed, - .pWaitDstStageMask = &flags, - .commandBufferCount = static_cast(p_commands.size()), - .pCommandBuffers = p_commands.data(), - .signalSemaphoreCount = 1, - .pSignalSemaphores = &m_work_completed, - }; - - VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); - vk_check(res, "vkQueueSubmit"); - } - - void device_present_queue::present_frame(uint32_t p_frame_idx) { - VkPresentInfoKHR present_info = { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .pNext = nullptr, - .waitSemaphoreCount = 1, - .pWaitSemaphores = &m_work_completed, - .swapchainCount = 1, - .pSwapchains = &m_swapchain, - .pImageIndices = &p_frame_idx, - }; - - VkResult res = vkQueuePresentKHR(m_queue_handler, &present_info); - vk_check(res, "vkQueuePresentKHR"); - if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) { - m_out_of_date = true; - } - } - - void device_present_queue::destroy() { - vkDeviceWaitIdle(m_device); - vkDestroySemaphore(m_device, m_presentation_completed, nullptr); - vkDestroySemaphore(m_device, m_work_completed, nullptr); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/device_queue.cpp b/src/vulkan-cpp/device_queue.cpp deleted file mode 100644 index 4fa41f9..0000000 --- a/src/vulkan-cpp/device_queue.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -namespace vk { - device_queue::device_queue(const VkDevice& p_device, - const queue_params& p_config) { - vkGetDeviceQueue( - p_device, p_config.family, p_config.index, &m_queue_handler); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/framebuffer.cpp b/src/vulkan-cpp/framebuffer.cpp deleted file mode 100644 index 545a4bd..0000000 --- a/src/vulkan-cpp/framebuffer.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -namespace vk { - framebuffer::framebuffer(const VkDevice& p_device, - const framebuffer_params& p_setting) - : m_device(p_device) { - VkFramebufferCreateInfo framebuffer_ci = { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .renderPass = p_setting.renderpass, - .attachmentCount = static_cast(p_setting.views.size()), - .pAttachments = p_setting.views.data(), - .width = p_setting.extent.width, - .height = p_setting.extent.height, - .layers = 1 - }; - - vk::vk_check(vkCreateFramebuffer( - m_device, &framebuffer_ci, nullptr, &m_framebuffer), - "vkCreateFramebuffer"); - } - - void framebuffer::destroy() { - if (m_framebuffer != nullptr) { - vkDestroyFramebuffer(m_device, m_framebuffer, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/index_buffer.cpp b/src/vulkan-cpp/index_buffer.cpp deleted file mode 100644 index 5fd392a..0000000 --- a/src/vulkan-cpp/index_buffer.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include - -namespace vk { - - index_buffer::index_buffer(const VkDevice& p_device, - const index_params& p_info) - : m_device(p_device) { - m_indices_count = p_info.indices.size(); - - uint32_t property_flags = - memory_property::host_visible_bit | memory_property::host_cached_bit; - buffer_parameters index_params = { - .device_size = p_info.indices.size_bytes(), - .physical_memory_properties = p_info.phsyical_memory_properties, - .property_flags = (memory_property)property_flags, - .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - .debug_name = p_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_info.vkSetDebugUtilsObjectNameEXT - }; - - m_index_buffer = buffer_stream32(m_device, index_params); - - m_index_buffer.write(p_info.indices); - } - - void index_buffer::bind(const VkCommandBuffer& p_current) { - vkCmdBindIndexBuffer( - p_current, m_index_buffer, 0, VK_INDEX_TYPE_UINT32); - } - - void index_buffer::destroy() { - m_index_buffer.destroy(); - } -} \ No newline at end of file diff --git a/src/vulkan-cpp/instance.cpp b/src/vulkan-cpp/instance.cpp deleted file mode 100644 index b6438f5..0000000 --- a/src/vulkan-cpp/instance.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#define GLFW_INCLUDE_VULKAN -#include -#include -#include -#include -#include - -namespace vk { - - instance::instance(const application_params& p_config, - const debug_message_utility& p_debug_message_utils) { - VkApplicationInfo app_info = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = nullptr, - .applicationVersion = 1, - .pEngineName = p_config.name.c_str(), - .engineVersion = 1, - .apiVersion = static_cast(p_config.version), - }; - - VkInstanceCreateInfo instance_ci = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .pApplicationInfo = &app_info - }; - - // Setting up validation layers properties - uint32_t layer_count = 0; - std::vector layer_properties; - vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - // std::vector layer_properties(layer_count); - layer_properties.resize(layer_count); - vkEnumerateInstanceLayerProperties(&layer_count, - layer_properties.data()); - - for (const VkLayerProperties property : layer_properties) { - m_layer_properties.emplace_back(property.layerName, - property.specVersion, - property.implementationVersion, - property.description); - } - - // Setting up instance extensions - instance_ci.enabledExtensionCount = - static_cast(p_config.extensions.size()); - instance_ci.ppEnabledExtensionNames = p_config.extensions.data(); - - // Only run validation layers if we are running vulkan-cpp in debug mode -#if _DEBUG - // Setting up validation layers - instance_ci.enabledLayerCount = - static_cast(p_config.validations.size()); - instance_ci.ppEnabledLayerNames = p_config.validations.data(); - - VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = static_cast(p_debug_message_utils.severity), - .messageType = static_cast(p_debug_message_utils.message_type), - .pfnUserCallback = p_debug_message_utils.callback, - }; - - // This is to invoke the vulkan debug utils if it is a valid callback - // To ensure that we are not using an invalid debug callback - if (p_debug_message_utils.callback != nullptr) { - instance_ci.pNext = - (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; - } - else { - instance_ci.pNext = nullptr; - } -#else - instance_ci.enabledLayerCount = 0; - instance_ci.ppEnabledLayerNames = nullptr; - instance_ci.pNext = nullptr; -#endif - vk_check(vkCreateInstance(&instance_ci, nullptr, &m_instance), - "vkCreateInstance"); - -#if _DEBUG - // This needs to be created after the VkInstance is or else it wont be applied the debug information during validation layer error message execution - m_vk_set_debug_utils_object_name_ext = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkSetDebugUtilsObjectNameEXT")); -#endif - } - - void instance::destroy() { - // only destroy if VkInstance is valid - if (alive()) { - vkDestroyInstance(m_instance, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/physical_device.cpp b/src/vulkan-cpp/physical_device.cpp deleted file mode 100644 index be099d3..0000000 --- a/src/vulkan-cpp/physical_device.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - -namespace vk { - physical_device::physical_device( - const VkInstance& p_instance, - const physical_enumeration& p_physical_enumeration) { - m_physical_device = enumerate_physical_devices( - p_instance, p_physical_enumeration.device_type); - - if (m_physical_device == nullptr) { - throw std::runtime_error("m_physical_device was nullptr!!!"); - } - - m_queue_family_properties = - enumerate_queue_family_properties(m_physical_device); - - // This makes sure that we get the graphics, compute, and transfer queue - // indices from the physical queue family assigned - uint32_t queue_index = 0; - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - m_queue_family_indices.graphics = queue_index; - break; - } - - queue_index++; - } - queue_index = 0; - - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_COMPUTE_BIT) { - m_queue_family_indices.compute = queue_index; - } - queue_index++; - } - queue_index = 0; - - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_TRANSFER_BIT) { - m_queue_family_indices.transfer = queue_index; - } - queue_index++; - } - queue_index = 0; - } - - uint32_t physical_device::queue_present_index( - const VkSurfaceKHR& p_surface) { - uint32_t presentation_index = 0; - uint32_t compatible = false; - uint32_t i = 0; - for (const auto& queue_family : m_queue_family_properties) { - vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( - m_physical_device, i, p_surface, &compatible), - "vkGetPhysicalDeviceSurfaceSupportKHR"); - - if (compatible) { - presentation_index = i; - } - } - - return presentation_index; - } - - VkPhysicalDeviceMemoryProperties physical_device::memory_properties() - const { - VkPhysicalDeviceMemoryProperties physical_memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_device, - &physical_memory_properties); - return physical_memory_properties; - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/pipeline.cpp b/src/vulkan-cpp/pipeline.cpp deleted file mode 100644 index 6492edb..0000000 --- a/src/vulkan-cpp/pipeline.cpp +++ /dev/null @@ -1,222 +0,0 @@ -#include -#include -#include - -namespace vk { - pipeline::pipeline(const VkDevice& p_device, - const pipeline_settings& p_info) - : m_device(p_device) { - create(p_info); - } - - void pipeline::create(const pipeline_settings& p_info) { - std::vector pipeline_shader_stages( - p_info.shader_modules.size()); - - uint32_t shader_src_index = 0; - - // 1. Load in and setup the VKShaderModule handlers for VkPipeline - for (const shader_handle& src : p_info.shader_modules) { - VkShaderStageFlags stage = static_cast(src.stage); - pipeline_shader_stages[shader_src_index] = - VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = (VkShaderStageFlagBits)stage, - .module = src.module, - .pName = "main" - }; - - shader_src_index++; - } - - // 2. Setting up the vertex attribute details for VkPipeline - std::span bind_attributes = - p_info.vertex_bind_attributes; - std::span attributes = - p_info.vertex_attributes; - - VkPipelineVertexInputStateCreateInfo vertex_input_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = - static_cast(bind_attributes.size()), - .pVertexBindingDescriptions = bind_attributes.data(), - .vertexAttributeDescriptionCount = - static_cast(attributes.size()), - .pVertexAttributeDescriptions = attributes.data() - }; - - VkPipelineInputAssemblyStateCreateInfo input_assembly = { - .sType = - VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - .primitiveRestartEnable = VK_FALSE, - }; - - VkPipelineViewportStateCreateInfo viewport_state = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .scissorCount = 1, - }; - - //! @note Rasterization - // Keep in mind: if lineWidth is zero, validation layers will occur - // because cant be zero. Must be set to 1.0f - VkPipelineRasterizationStateCreateInfo rasterizer_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .depthClampEnable = false, - .rasterizerDiscardEnable = - false, // set to true make fragmenta that are beyond near/far - // planes clamped to them as opposed to discarding them - .polygonMode = - VK_POLYGON_MODE_FILL, // if set to true then geometry never passes - // through rasterizer stage. This basically - // disables output to frame_buffer - .cullMode = VK_CULL_MODE_NONE, // determines what culling to use. - // Can also be disabled, culls - // front-face, back-face or both - .frontFace = - VK_FRONT_FACE_COUNTER_CLOCKWISE, // specifies vertex order of - // fdaces considered front-face - // or clockwise/counter-clockwise - .depthBiasEnable = false, - .depthBiasConstantFactor = 0.0f, // Optional - .depthBiasClamp = 0.0f, // Optional - .depthBiasSlopeFactor = 0.0f, // Optional - .lineWidth = 1.f - }; - - //! @note Multi-sampling - VkPipelineMultisampleStateCreateInfo multisampling_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - .sampleShadingEnable = false, - // .minSampleShading = 1.0f, // Optional - // .pSampleMask = nullptr, // Optional - // .alphaToCoverageEnable = VK_FALSE, // Optional - // .alphaToOneEnable = VK_FALSE, // Optional - }; - - // Color blending Attachment -- blending color when the fragment returns - // the color - VkPipelineColorBlendAttachmentState color_blend_attachment = { - .blendEnable = true, - .srcColorBlendFactor = - VK_BLEND_FACTOR_SRC_ALPHA, // Enabled: alpha blending - .dstColorBlendFactor = - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // Enabled: alpha blending - .colorBlendOp = VK_BLEND_OP_ADD, // Enabled: alpha blending - .srcAlphaBlendFactor = - VK_BLEND_FACTOR_ONE, // Enabled: alpha blending - .dstAlphaBlendFactor = - VK_BLEND_FACTOR_ZERO, // Enabled: alpha blending - .alphaBlendOp = VK_BLEND_OP_ADD, // Enabled: alpha blending - .colorWriteMask = - VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, - }; - - VkPipelineColorBlendStateCreateInfo color_blending_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .logicOpEnable = VK_FALSE, - .logicOp = VK_LOGIC_OP_COPY, // Optional - .attachmentCount = 1, - .pAttachments = &color_blend_attachment, - // these are optional - .blendConstants = { 0.f, 0.f, 0.f, 0.f } // optional - }; - - // Enable depth-stencil state - VkPipelineDepthStencilStateCreateInfo pipeline_deth_stencil_state_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .depthTestEnable = true, - .depthWriteEnable = true, - .depthCompareOp = VK_COMPARE_OP_LESS, - .depthBoundsTestEnable = false, - .stencilTestEnable = false, - }; - - //! @note Dynamic State - //! @note -- pipeline states needs to be baked into the pipeline state - std::array dynamic_states = { - VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR - }; - - VkPipelineDynamicStateCreateInfo dynamic_state_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = static_cast(dynamic_states.size()), - .pDynamicStates = dynamic_states.data() - }; - - VkPipelineLayoutCreateInfo pipeline_layout_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - }; - - //! This is just to double-check that the descriptor set layout is - //! valid. If the descriptor set layout is invalid, then proceed but not - //! use the descriptor set layout - // if (m_descriptor_set_layout != nullptr) { - // if (!m_descriptor_layouts.empty()) { - // pipeline_layout_ci.setLayoutCount = - // static_cast(m_descriptor_layouts.size()); - // pipeline_layout_ci.pSetLayouts = m_descriptor_layouts.data(); - // } - // else { - // // TODO: Uncomment this when adding back in descriptor sets - // // For now I will disable it to get the base working and add - // // descriptor sets back in afterwards - // pipeline_layout_ci.setLayoutCount = 0; - // pipeline_layout_ci.pSetLayouts = nullptr; - // } - pipeline_layout_ci.setLayoutCount = - static_cast(p_info.descriptor_layouts.size()); - pipeline_layout_ci.pSetLayouts = p_info.descriptor_layouts.data(); - vk_check(vkCreatePipelineLayout( - m_device, &pipeline_layout_ci, nullptr, &m_pipeline_layout), - "vkCreatePipelineLayout"); - - VkGraphicsPipelineCreateInfo graphics_pipeline_ci = { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .stageCount = static_cast(pipeline_shader_stages.size()), - .pStages = pipeline_shader_stages.data(), - .pVertexInputState = &vertex_input_info, - .pInputAssemblyState = &input_assembly, - .pViewportState = &viewport_state, - .pRasterizationState = &rasterizer_ci, - .pMultisampleState = &multisampling_ci, - // .pDepthStencilState = nullptr, // Optional - .pDepthStencilState = &pipeline_deth_stencil_state_ci, - .pColorBlendState = &color_blending_ci, - .pDynamicState = &dynamic_state_ci, - .layout = m_pipeline_layout, - .renderPass = p_info.renderpass, - .subpass = 0, - .basePipelineHandle = nullptr, - .basePipelineIndex = -1 - }; - - vk::vk_check( - vkCreateGraphicsPipelines( - m_device, nullptr, 1, &graphics_pipeline_ci, nullptr, &m_pipeline), - "vkCreateGraphicsPipelines"); - } - - void pipeline::bind(const VkCommandBuffer& p_command, pipeline_bind_point p_bind_point) { - vkCmdBindPipeline( - p_command, static_cast(p_bind_point), m_pipeline); - } - - void pipeline::push_constant(const VkCommandBuffer& p_current, shader_stage p_stage, uint32_t p_offset, uint32_t p_range, const void* p_data) { - vkCmdPushConstants(p_current, m_pipeline_layout, static_cast(p_stage), p_offset, p_range, p_data); - } - - void pipeline::destroy() { - if (m_pipeline_layout != nullptr) { - vkDestroyPipelineLayout(m_device, m_pipeline_layout, nullptr); - } - if (m_pipeline != nullptr) { - vkDestroyPipeline(m_device, m_pipeline, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/renderpass.cpp b/src/vulkan-cpp/renderpass.cpp deleted file mode 100644 index c51582d..0000000 --- a/src/vulkan-cpp/renderpass.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include -#include - -namespace vk { - - renderpass::renderpass(const VkDevice& p_device, - std::span p_renderpass_attachments, - bool p_enable_subpasses) - : m_device(p_device) { - - create(p_renderpass_attachments, p_enable_subpasses); - } - - void renderpass::create( - std::span p_renderpass_attachments, - bool p_enable_subpasses) { - // 1. Specifically for setting up the attachment description - std::vector attachment_description( - p_renderpass_attachments.size()); - - // color attachment reference slots to set to help the - // VkAttachmentReference know which color attachment they correspond to - std::vector color_attachment_indices; - - // depth attachment reference slots to set to help the - // VkAttachmentReference know which depth attachment they correspond to - std::vector depth_attachment_indices; - - for (size_t i = 0; i < attachment_description.size(); i++) { - attachment attachment_spec = p_renderpass_attachments[i]; - attachment_description[i] = { - .flags = 0, - .format = attachment_spec.format, - // .samples = VK_SAMPLE_COUNT_1_BIT, - .samples = static_cast(attachment_spec.samples), - // .loadOp = to_attachment_load(attachment_spec.load), - .loadOp = static_cast(attachment_spec.load), - // .storeOp = to_attachment_store(attachment_spec.store), - .storeOp = static_cast(attachment_spec.store), - .stencilLoadOp = - static_cast(attachment_spec.stencil_load), - .stencilStoreOp = - static_cast(attachment_spec.stencil_store), - .initialLayout = static_cast(attachment_spec.initial_layout), - .finalLayout = static_cast(attachment_spec.final_layout) - }; - - // I do a check here to save the slots for specifying the - // VkAttachmentReference Since .attachment is the slot index for - // corresponding which attachment layout is to which - if (has_depth_specified(attachment_spec.layout)) { - depth_attachment_indices.emplace_back(i); - } - else { - color_attachment_indices.emplace_back(i); - } - } - - // 2. Setting up the color attachment reference to specifying specific - // attachments they correspond to (using the indices) - std::vector color_attachment_references( - color_attachment_indices.size()); - - for (size_t i = 0; i < color_attachment_indices.size(); i++) { - uint32_t slot = color_attachment_indices[i]; - color_attachment_references[i] = { - .attachment = slot, - // .layout = to_image_layout(p_renderpass_attachments[slot].layout) - .layout = static_cast(p_renderpass_attachments[slot].layout) - }; - } - - // 3. Setting up the depth attachment reference to specifying specific - // attachments they correspond to (using the indices) - std::vector depth_attachment_references( - depth_attachment_indices.size()); - for (size_t i = 0; i < depth_attachment_indices.size(); i++) { - uint32_t slot = depth_attachment_indices[i]; - depth_attachment_references[i] = { - .attachment = slot, - // .layout = to_image_layout(p_renderpass_attachments[slot].layout) - .layout = static_cast(p_renderpass_attachments[slot].layout) - }; - } - - // 4. Setting up subpass descriptions that may/may not be applied to - // this renderpass based on the p_enable_subpass is set to true - // TODO: VkSubpassDescription is deprecated in vulkan 1.2+, we should - // change to VkSubpassDescription2 - // TODO: Change from VkRenderPassCreateInfo to VkRenderPassCreateInfo2 - // since they have different parameter modifications - VkSubpassDescription subpass_description = { - .flags = 0, - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .pInputAttachments = nullptr, - .colorAttachmentCount = - static_cast(color_attachment_references.size()), - .pColorAttachments = color_attachment_references.data(), - .pResolveAttachments = nullptr, - .pDepthStencilAttachment = depth_attachment_references.data(), - .preserveAttachmentCount = 0, - .pPreserveAttachments = nullptr - }; - - std::array subpasses; - - if (p_enable_subpasses) { - subpasses = { subpass_description }; - } - - VkRenderPassCreateInfo renderpass_ci = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .attachmentCount = - static_cast(attachment_description.size()), - .pAttachments = attachment_description.data(), - .subpassCount = static_cast(subpasses.size()), - .pSubpasses = subpasses.data(), - .dependencyCount = 0, - .pDependencies = nullptr - }; - - vk_check( - vkCreateRenderPass(m_device, &renderpass_ci, nullptr, &m_renderpass), - "vkCreateRenderPass"); - } - - void renderpass::begin(const renderpass_begin_params& p_begin_info) { - // TODO: Move VkViewport and VkScissor to vk::swapchain since these are - // information more closely set by the swapchain - VkViewport viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(p_begin_info.extent.width), - .height = static_cast(p_begin_info.extent.height), - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; - - vkCmdSetViewport(p_begin_info.current_command, 0, 1, &viewport); - - VkRect2D scissor = { - .offset = { 0, 0 }, - .extent = { p_begin_info.extent.width, p_begin_info.extent.height }, - }; - - vkCmdSetScissor(p_begin_info.current_command, 0, 1, &scissor); - - // setting color for this specific renderpass - VkClearColorValue renderpass_color = { { p_begin_info.color.at(0), - p_begin_info.color.at(1), - p_begin_info.color.at(2), - p_begin_info.color.at(3) } }; - std::array clear_values = {}; - - clear_values[0].color = renderpass_color; - clear_values[1].depthStencil = { 1.f, 0 }; - - VkRenderPassBeginInfo renderpass_begin_params = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = m_renderpass, - .framebuffer = p_begin_info.current_framebuffer, - .renderArea = { - .offset = { - .x = 0, - .y = 0 - }, - .extent = { - .width = p_begin_info.extent.width, - .height = p_begin_info.extent.height - }, - }, - .clearValueCount = static_cast(clear_values.size()), - .pClearValues = clear_values.data(), - }; - - vkCmdBeginRenderPass(p_begin_info.current_command, - &renderpass_begin_params, - static_cast(p_begin_info.subpass)); - } - - void renderpass::end(const VkCommandBuffer& p_current) { - vkCmdEndRenderPass(p_current); - } - - void renderpass::destroy() { - vkDestroyRenderPass(m_device, m_renderpass, nullptr); - } - -}; \ No newline at end of file diff --git a/src/vulkan-cpp/sample_image.cpp b/src/vulkan-cpp/sample_image.cpp deleted file mode 100644 index 2d5c9b8..0000000 --- a/src/vulkan-cpp/sample_image.cpp +++ /dev/null @@ -1,523 +0,0 @@ -#include -#include -#include - -namespace vk { - - sample_image::sample_image( - const VkDevice& p_device, - const image_params& p_image_properties) - : m_device(p_device) { - - // 1. creating VkImage handle - VkImageCreateInfo image_ci = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = nullptr, - .flags = p_image_properties.image_flags, - .imageType = VK_IMAGE_TYPE_2D, - .format = p_image_properties.format, - .extent = { .width = p_image_properties.extent.width, - .height = p_image_properties.extent.height, - .depth = 1 }, - .mipLevels = p_image_properties.mip_levels, - .arrayLayers = p_image_properties.array_layers, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = static_cast(p_image_properties.usage), - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .queueFamilyIndexCount = 0, - .pQueueFamilyIndices = nullptr, - .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED - }; - - vk_check(vkCreateImage(p_device, &image_ci, nullptr, &m_image), - "vkCreateImage"); - - // 2. get image memory requirements from physical device - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(p_device, m_image, &memory_requirements); - // uint32_t memory_type_index = - // vk::image_memory_requirements(p_image_properties.physical_device, - // p_device, m_image); - uint32_t memory_index = select_memory_requirements( - p_image_properties.phsyical_memory_properties, - memory_requirements, - p_image_properties.property); - - // 4. Allocate info - VkMemoryAllocateInfo memory_alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = nullptr, - .allocationSize = memory_requirements.size, - .memoryTypeIndex = memory_index - }; - - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); - - // 5. bind image memory - vk_check(vkBindImageMemory(p_device, m_image, m_device_memory, 0), - "vkBindImageMemory"); - - // Needs to create VkImageView after VkImage - // because VkImageView expects a VkImage to be binded to a singl - // VkDeviceMemory beforehand - VkImageViewCreateInfo image_view_ci = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .image = m_image, - // .viewType = VK_IMAGE_VIEW_TYPE_2D, - .viewType = p_image_properties.view_type, - .format = p_image_properties.format, - .components = { .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY }, - .subresourceRange = { .aspectMask = static_cast( - p_image_properties.aspect), - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = - p_image_properties.layer_count }, - }; - - vk_check( - vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), - "vkCreateImage"); - - // Create VkSampler handler - VkSamplerCreateInfo sampler_info = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .magFilter = p_image_properties.range.min, - .minFilter = p_image_properties.range.max, - .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = static_cast(p_image_properties.addrses_mode_u), - .addressModeV = static_cast(p_image_properties.addrses_mode_v), - .addressModeW = static_cast(p_image_properties.addrses_mode_w), - .mipLodBias = 0.0f, - .anisotropyEnable = false, - .maxAnisotropy = 1, - .compareEnable = false, - .compareOp = VK_COMPARE_OP_ALWAYS, - .minLod = 0.0f, - .maxLod = 0.0f, - .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, - .unnormalizedCoordinates = false - }; - - vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), - "vkCreateSampler"); - } - - sample_image::sample_image( - const VkDevice& p_device, - const VkImage& p_image, - const image_params& p_image_properties) - : m_device(p_device) - , m_image(p_image) { - - // Needs to create VkImageView after VkImage - // because VkImageView expects a VkImage to be binded to a singl - // VkDeviceMemory beforehand - VkImageViewCreateInfo image_view_ci = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .image = m_image, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = p_image_properties.format, - .components = { .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY }, - .subresourceRange = { .aspectMask = static_cast( - p_image_properties.aspect), - .baseMipLevel = 0, - .levelCount = p_image_properties.mip_levels, - .baseArrayLayer = 0, - .layerCount = - p_image_properties.layer_count }, - }; - - vk_check( - vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), - "vkCreateImage"); - - // Create VkSampler handler - VkSamplerCreateInfo sampler_info = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .magFilter = p_image_properties.range.min, - .minFilter = p_image_properties.range.max, - .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = static_cast(p_image_properties.addrses_mode_u), - .addressModeV = static_cast(p_image_properties.addrses_mode_v), - .addressModeW = static_cast(p_image_properties.addrses_mode_w), - .mipLodBias = 0.0f, - .anisotropyEnable = false, - .maxAnisotropy = 1, - .compareEnable = false, - .compareOp = VK_COMPARE_OP_ALWAYS, - .minLod = 0.0f, - .maxLod = 0.0f, - .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, - .unnormalizedCoordinates = false - }; - - vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), - "vkCreateSampler"); - - m_only_destroy_image_view = true; - } - - /** - * We shift 32-bits to the high 32-bits for the old layout and OR the new layout lsb 32-bits additional to the shifted 32-bits - * - * This is to ensure the image layouts do not overlap and can be used to directly jump to set specific image loyouts rather then doing an if-statement originally to check for that - */ - static constexpr uint64_t image_layout(VkImageLayout p_old, VkImageLayout p_new) { - // Shift the old_layout into the high 32 bits, and combine with new_layout in the low 32 bits. - return (static_cast(p_old) << 32) | static_cast(p_new); - } - - void sample_image::memory_barrier(const VkCommandBuffer& p_command, VkFormat p_format, VkImageLayout p_old, VkImageLayout p_new) { - /* - VkImageMemoryBarrier image_memory_barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = 0, - .dstAccessMask = 0, - .oldLayout = p_old, - .newLayout = p_new, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = m_image, - .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1 } - }; - - VkPipelineStageFlags source_stage; - VkPipelineStageFlags dst_stages; - - if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || - (p_format == VK_FORMAT_D16_UNORM) || - (p_format == VK_FORMAT_X8_D24_UNORM_PACK32) || - (p_format == VK_FORMAT_D32_SFLOAT) || - (p_format == VK_FORMAT_S8_UINT) || - (p_format == VK_FORMAT_D16_UNORM_S8_UINT) || - (p_format == VK_FORMAT_D24_UNORM_S8_UINT)) { - image_memory_barrier.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_DEPTH_BIT; - - if (has_stencil_attachment(p_format)) { - image_memory_barrier.subresourceRange.aspectMask |= - VK_IMAGE_ASPECT_STENCIL_BIT; - } - } - else { - image_memory_barrier.subresourceRange.aspectMask = - VK_IMAGE_ASPECT_COLOR_BIT; - } - - if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && - p_new == VK_IMAGE_LAYOUT_GENERAL) { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - - if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && - p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - } // Convert back from read-only to updateable - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - } // Convert from updateable texture to shader read-only - else if (p_old == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert depth texture from undefined state to depth-stencil buffer - else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && - p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - } // Wait for render pass to complete - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = - 0; // VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = 0; - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert back from read-only to color attachment - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - } // Convert from updateable texture to shader read-only - else if (p_old == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert back from read-only to depth attachment - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - } // Convert from updateable depth texture to shader read-only - else if (p_old == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = - VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } - - vkCmdPipelineBarrier(p_command, - source_stage, - dst_stages, - 0, - 0, - nullptr, - 0, - nullptr, - 1, - &image_memory_barrier); - */ - // 1. Image Memory Barrier Initialization (using C++ Designated Initializers - C++20) - VkImageMemoryBarrier image_memory_barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = 0, - .dstAccessMask = 0, - .oldLayout = p_old, - .newLayout = p_new, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = m_image, - .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1 } - }; - - VkPipelineStageFlags source_stage = VK_PIPELINE_STAGE_NONE; - VkPipelineStageFlags dst_stages = VK_PIPELINE_STAGE_NONE; - - // 2. Aspect Mask Logic (Keep as if/else, but use helper function) - if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || has_stencil_attachment(p_format)) { - - image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - - // Assuming has_stencil_attachment(p_format) is defined elsewhere - // works as the same as the if-statement, leaving it here for testing purposes - // image_memory_barrier.subresourceRange.aspectMask |= has_stencil_attachment(p_format) ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; - if (has_stencil_attachment(p_format)) { - image_memory_barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - } - } - else { - image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - } - - // 3. Main Transition Logic using Combined Switch - const uint64_t current_layout = image_layout(p_old, p_new); - - switch (current_layout) { - - // UNDEFINED -> SHADER_READ_ONLY_OPTIMAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - // UNDEFINED -> GENERAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL): { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - // UNDEFINED -> TRANSFER_DST_OPTIMAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - } - - // SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL (Convert back from read-only to transferr) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - break; - } - - // TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable texture to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - // UNDEFINED -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert depth texture from undefined state) - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - dst_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - break; - } - - // SHADER_READ_ONLY_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Wait for render pass to complete - Note: This case is unusual but kept as per your original logic) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - // Note: Your original code had conflicting re-assignments for source_stage/dst_stages here. - // The last pair of assignments is used. - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = 0; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - // SHADER_READ_ONLY_OPTIMAL -> COLOR_ATTACHMENT_OPTIMAL (Convert back from read-only to color attachment) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - break; - } - - // COLOR_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable color to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - // SHADER_READ_ONLY_OPTIMAL -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert back from read-only to depth attachment) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - break; - } - - // DEPTH_STENCIL_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable depth texture to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - break; - } - - default: { - // Unhandled Transition - break; - } - } - - vkCmdPipelineBarrier( - p_command, - source_stage, - dst_stages, - 0, // dependencyFlags - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); - } - - void sample_image::destroy() { - if (m_image_view != nullptr) { - vkDestroyImageView(m_device, m_image_view, nullptr); - } - - // Boolean check is to make sure we might only want - // to destroy vk::sample_image resources. - - // Example of this is the swapchain may pass in - // its images and we should only destruct the VkImageView - // and not the swapchain's images directly - if (m_image != nullptr and !m_only_destroy_image_view) { - vkDestroyImage(m_device, m_image, nullptr); - } - - if (m_sampler != nullptr) { - vkDestroySampler(m_device, m_sampler, nullptr); - } - - if (m_device_memory != nullptr) { - vkFreeMemory(m_device, m_device_memory, nullptr); - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/shader_resource.cpp b/src/vulkan-cpp/shader_resource.cpp deleted file mode 100644 index 1758065..0000000 --- a/src/vulkan-cpp/shader_resource.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include -#include -#include - -namespace vk { - // Reading the raw .spv binaries - static std::vector read(const std::string& p_file) { - std::vector out_buffer; - std::ifstream ins(p_file, std::ios::ate | std::ios::binary); - - if (!ins) { - return {}; - } - - uint32_t file_size = (uint32_t)ins.tellg(); - out_buffer.resize(file_size); - ins.seekg(0); - ins.read(out_buffer.data(), file_size); - return out_buffer; - } - - //! @brief Ensure file reads are valid before reading raw .spv binaries - static std::vector compile_binary_shader_source( - const shader_source& p_shader_source) { - std::vector binary_blob{}; - - if (std::filesystem::is_regular_file(p_shader_source.filename)) { - binary_blob = read(p_shader_source.filename); - } - - return binary_blob; - } - - shader_resource::shader_resource(const VkDevice& p_device, - const shader_resource_info& p_info) - : m_device(p_device) { - m_shader_module_handlers.resize(p_info.sources.size()); - - for (size_t i = 0; i < p_info.sources.size(); i++) { - const shader_source shader_src = p_info.sources[i]; - std::vector blob = compile_binary_shader_source(shader_src); - - if (blob.empty()) { - m_is_resource_valid = false; - return; - } - - std::span binary(blob.begin(), blob.end()); - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = static_cast(binary.size_bytes()), - .pCode = (const uint32_t*)binary.data() - }; - - // Setting m_shader_module_handlers[i]'s stage and the - // VkShaderModule handle altogether - vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_shader_module_handlers[i].module), - "vkCreateShaderModule"); - m_shader_module_handlers[i].stage = shader_src.stage; - } - - m_is_resource_valid = true; - } - - void shader_resource::vertex_attributes( - std::span p_attributes) { - - m_vertex_binding_attributes.resize(p_attributes.size()); - - for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { - // setting up vertex binding - const vertex_attribute attribute = p_attributes[i]; - m_vertex_attributes.resize(attribute.entries.size()); - m_vertex_binding_attributes[i] = { - .binding = attribute.binding, - .stride = attribute.stride, - .inputRate = to_input_rate(attribute.input_rate), - }; - - // then setting up the vertex attributes for the vertex data layouts - for (size_t j = 0; j < attribute.entries.size(); j++) { - const vertex_attribute_entry entry = attribute.entries[j]; - m_vertex_attributes[j] = { - .location = entry.location, - .binding = attribute.binding, - .format = static_cast(entry.format), - .offset = entry.stride, - }; - } - } - } - - void shader_resource::destroy() { - for (auto& handle : m_shader_module_handlers) { - if (handle.module != nullptr) { - vkDestroyShaderModule(m_device, handle.module, nullptr); - } - } - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/skybox_texture.cpp b/src/vulkan-cpp/skybox_texture.cpp deleted file mode 100644 index cdf3327..0000000 --- a/src/vulkan-cpp/skybox_texture.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include -#include -#include -#include - -namespace vk { - - skybox_texture::skybox_texture(const VkDevice& p_device, - const skybox_texture_info& p_config) - : m_device(p_device) { - if (p_config.physical_handle == nullptr) { - std::println("Cannot utilize a nullptr physical handle!!!"); - return; - } - - // uint32_t bytes_per_pixel = - // bytes_per_texture_format(cubemap_config.format); uint32_t - // layer_size_with_bytes = cubemap_config.extent.width * - // cubemap_config.extent.height * bytes_per_pixel; uint32_t layer_count - // = 1; uint32_t image_size = layer_size_with_bytes * layer_count; - - // 1. Creating temporary command buffer for texture - command_params copy_command_params = { - .levels = command_levels::primary, - .queue_index = 0, - .flags = command_pool_flags::reset, - }; - command_buffer temp_command_buffer = - command_buffer(p_device, copy_command_params); - // -------------------------------------- - // BEGIN COMMAND BUFFER RECORDING - // -------------------------------------- - temp_command_buffer.begin(command_usage::one_time_submit); - - // Cubemap implementation below - - // 1. Load Faces stb image - - stbi_uc* image_pixel_data[6]; - for (size_t i = 0; i < p_config.faces.size(); i++) { - int channels; - image_pixel_data[i] = stbi_load(p_config.faces[i].c_str(), - &m_width, - &m_height, - &channels, - STBI_rgb_alpha); - - // int bytes_per_pixel = bytes_per_pixel_format(p_config.format) - // int image_size = m_width * m_height * 4; - - if (!image_pixel_data[i]) { - std::println("Cannot load face[{}] = filanme with {}", - i, - p_config.faces[i]); - return; - } - - image_params skybox_image_info = { - .extent = { (uint32_t)m_width, (uint32_t)m_height }, - .format = VK_FORMAT_R8G8B8A8_UNORM, - .usage = (VkImageUsageFlagBits)VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT, - .image_flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, - .array_layers = 6, - .physical_device = p_config.physical_handle - }; - m_cubemap_images[i] = vk::sample_image(m_device, skybox_image_info); - - int bytes_per_pixel = - bytes_per_texture_format(skybox_image_info.format); - uint64_t layer_size_with_bytes = - (uint64_t)skybox_image_info.extent.width * - skybox_image_info.extent.height * bytes_per_pixel; - int layer_count = 1; - uint64_t image_size = layer_size_with_bytes * layer_count; - - int property_flag = memory_property::host_visible_bit | - memory_property::host_cached_bit; - buffer_configuration staging_buffer_config = { - .device_size = (VkDeviceSize)image_size, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .property_flags = (memory_property)property_flag, - .physical = skybox_image_info.physical_device - }; - - buffer_handle staging_buffer = - create_buffer(m_device, staging_buffer_config); - write_info write_staging_buffer = { .offset = i * image_size, - .size_bytes = - layer_size_with_bytes }; - - write( - m_device, staging_buffer, image_pixel_data, write_staging_buffer); - - free_buffer(m_device, staging_buffer); - } - - // 2. creating staging buffer - - // 2. Load each face with vk::sample_image - // image_params skybox_image_info = { - // .extent = {(uint32_t)m_width, (uint32_t)m_height}, - // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .usage = (VkImageUsageFlagBits)VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT, .image_flags = - // VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, .array_layers = 6, - // .physical_device = p_config.physical_handle - // }; - // m_skybox_image = vk::sample_image(m_device, skybox_image_info); - - // int bytes_per_pixel = - // bytes_per_texture_format(skybox_image_info.format); int - // layer_size_with_bytes = - // static_cast(skybox_image_info.extent.width * - // skybox_image_info.extent.height * bytes_per_pixel); - // std::println("layer_size = {}", layer_size_with_bytes); - // int layer_count = 6; - // int image_size = layer_size_with_bytes * layer_count; - // std::println("image_size = {}", image_size); - - // int property_flag = memory_property::host_visible_bit | - // memory_property::host_cached_bit; buffer_configuration - // staging_buffer_config = { - // .device_size = (VkDeviceSize)image_size, - // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - // .property_flags = (memory_property)property_flag, - // .physical = skybox_image_info.physical_device - // }; - - // buffer_handle staging_buffer = create_buffer(m_device, - // staging_buffer_config); - - // for(size_t i = 0; i < 6; i++) { - // std::println("i * image_size = {}", (i * image_size)); - // write(m_device, staging_buffer, image_pixel_data, i * - // image_size); - // // std::println("Mapping i = {}", i); - // // void* mapped = nullptr; - // // vk_check( - // // vkMapMemory( - // // p_device, staging_buffer.device_memory, i * image_size, - // image_size, 0, &mapped), - // // "vkMapMemory"); - - // // memcpy(mapped, image_pixel_data[i], image_size); - // // vkUnmapMemory(p_device, staging_buffer.device_memory); - // } - - // 4. Load single command buffer to copy all 6 images - - // 5. Offloading all 6 images to the device_queue - - // Order of Operation for the faces - - // [per-face filename] => [staging buffer] => [image] -> - // image_layout_transition => copy operation => transfer to color - // attachment layout - - // -------------------------------------- - // END COMMAND BUFFER RECORDING - // -------------------------------------- - temp_command_buffer.end(); - // 7. Create temporary graphics queue to offload the texture image into - // GPU memory - //! TODO: Do this better then just retrieving graphics queue 0 - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - VkQueue temp_graphics_queue; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - // 8. now submit that texture data to be stored in GPU memory - VkCommandBuffer handle = temp_command_buffer; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &handle, - }; - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - temp_command_buffer.destroy(); - } - - void skybox_texture::destroy() { - // m_skybox_image.destroy(); - for (auto& image : m_cubemap_images) { - image.destroy(); - } - } - -}; \ No newline at end of file diff --git a/src/vulkan-cpp/surface.cpp b/src/vulkan-cpp/surface.cpp deleted file mode 100644 index 6430e78..0000000 --- a/src/vulkan-cpp/surface.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include - -namespace vk { - surface::surface(const VkInstance& p_instance, GLFWwindow* p_window_handle) - : m_instance(p_instance) { - - vk_check(glfwCreateWindowSurface( - m_instance, p_window_handle, nullptr, &m_surface_handler), - "glfwCreateWindowSurface"); - } - - void surface::destroy() { - if (m_surface_handler != nullptr) { - vkDestroySurfaceKHR(m_instance, m_surface_handler, nullptr); - } - vkDestroyInstance(m_instance, nullptr); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/swapchain.cpp b/src/vulkan-cpp/swapchain.cpp deleted file mode 100644 index ee8f747..0000000 --- a/src/vulkan-cpp/swapchain.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include - -namespace vk { - swapchain::swapchain(const VkDevice& p_device, - const VkSurfaceKHR& p_surface, - const swapchain_params& p_settings, - const surface_params& p_surface_properties) - : m_device(p_device) - , m_surface_handler(p_surface) - , m_surface_params(p_surface_properties) { - - m_image_size = surface_image_size(m_surface_params.capabilities); - - std::println("Surface Image Size = {}", m_image_size); - - create(p_settings); - } - - void swapchain::create(const swapchain_params& p_settings) { - VkSwapchainCreateInfoKHR swapchain_ci = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = m_surface_handler, - .minImageCount = m_image_size, - .imageFormat = m_surface_params.format.format, - .imageColorSpace = m_surface_params.format.colorSpace, - // use physical device surface formats to getting the right formats - // in vulkan - .imageExtent = m_surface_params.capabilities.currentExtent, - .imageArrayLayers = 1, - .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT), - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &p_settings.present_index, - .preTransform = m_surface_params.capabilities.currentTransform, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR, - .clipped = true - }; - - vk_check(vkCreateSwapchainKHR( - m_device, &swapchain_ci, nullptr, &m_swapchain_handler), - "vkCreateSwapchainKHR"); - } - - std::span swapchain::presentable_images() { - uint32_t image_count=0; - vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, nullptr); - - m_images.resize(image_count); - vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, m_images.data()); - - return m_images; - } - - void swapchain::destroy() { - vkDestroySwapchainKHR(m_device, m_swapchain_handler, nullptr); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/texture.cpp b/src/vulkan-cpp/texture.cpp deleted file mode 100644 index 66a0b7f..0000000 --- a/src/vulkan-cpp/texture.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include -#include -#include - -#ifndef STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_IMPLEMENTATION -#include -#endif - -namespace vk { - - static sample_image create_texture_with_data( - const VkDevice& p_device, - const image_params& p_config, - const void* p_data) { - // 1. Creating temporary command buffer for texture - command_params copy_command_params = { - .levels = command_levels::primary, - .queue_index = 0, - .flags = command_pool_flags::reset, - }; - command_buffer temp_command_buffer = - command_buffer(p_device, copy_command_params); - - // 2. loading texture - - sample_image texture_image = sample_image(p_device, p_config); - int bytes_per_pixel = bytes_per_texture_format(p_config.format); - - // 3. getting layer size - uint32_t layer_size_with_bytes = - p_config.extent.width * p_config.extent.height * bytes_per_pixel; - uint32_t layer_count = 1; - uint32_t image_size = layer_size_with_bytes * layer_count; - - // 4. transfer data from staging buffer - uint32_t property_flag = - memory_property::host_visible_bit | memory_property::host_cached_bit; - // buffer_configuration staging_buffer_config = { - // .device_size = (uint32_t)image_size, - // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - // .property_flags = (memory_property)property_flag, - // .physical = p_config.physical_device - // }; - - buffer_parameters staging_buffer_config = { - .device_size = (uint32_t)image_size, - .physical_memory_properties = p_config.phsyical_memory_properties, - .property_flags = (memory_property)property_flag, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - // .physical = p_config.physical_device - }; - - // buffer_handle staging_buffer = create_buffer(p_device, - // staging_buffer_config); - buffer_stream staging(p_device, staging_buffer_config); - - // 5. write data to the staging buffer with specific size specified - // write(p_device, staging, p_data, image_size); - staging.write(p_data, image_size); - - // 6. start recording to this command buffer - VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED; - VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - VkFormat texture_format = p_config.format; - - temp_command_buffer.begin(command_usage::one_time_submit); - - // 6.1 -- transition image layout - // image_memory_barrier(temp_command_buffer, - // texture_image, - // texture_format, - // old_layout, - // new_layout); - texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); - - // 6.2 -- copy buffer to image handles - // copy(temp_command_buffer, - // texture_image, - // staging, - // p_config.extent.width, - // p_config.extent.height); - staging.copy_to_image(temp_command_buffer, texture_image, p_config.extent); - - // 6.3 -- transition image layout back to the layout specification - old_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // image_memory_barrier(temp_command_buffer, - // texture_image, - // texture_format, - // old_layout, - // new_layout); - texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); - - temp_command_buffer.end(); - - // 7. Create temporary graphics queue to offload the texture image into - // GPU memory - //! TODO: Do this better then just retrieving graphics queue 0 - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - VkQueue temp_graphics_queue; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - // 8. now submit that texture data to be stored in GPU memory - VkCommandBuffer handle = temp_command_buffer; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &handle, - }; - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - temp_command_buffer.destroy(); - // free_buffer(p_device, staging_buffer); - staging.destroy(); - - return texture_image; - } - - - texture::texture(const VkDevice& p_device, const image_extent& p_extent, VkPhysicalDeviceMemoryProperties p_property) : m_device(p_device) { - command_params settings = { - .levels = command_levels::primary, - .queue_index = 0, - .flags = command_pool_flags::reset, - }; - - // 1.) Load in extent dimensions - // Loading in raw white pixels for our texture. - // TODO: Take in a std::span for pixels that will then be - // written to the texture - std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; - - m_width = p_extent.width; - m_height = p_extent.height; - - // texture_properties properties = { - // .width = m_width, - // .height = m_height, - // .usage = (VkImageUsageFlagBits)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT), - // .property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - // // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .format = VK_FORMAT_R8G8B8A8_SRGB - // // .format = VK_FORMAT_R64G64B64A64_SFLOAT - // }; - image_params config_image = { - .extent = { .width = p_extent.width, .height = p_extent.height }, - .format = VK_FORMAT_R8G8B8A8_UNORM, - .property = memory_property::device_local_bit, - .aspect = image_aspect_flags::color_bit, - // .usage = (VkImageUsageFlags)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT), - .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, - // .physical_device = p_texture_info.physical - .phsyical_memory_properties = p_property - }; - m_image = - create_texture_with_data(m_device, config_image, white_color.data()); - m_texture_loaded = true; - } - - texture::texture(const VkDevice& p_device, - const texture_info& p_texture_info) - : m_device(p_device) { - - // 1. load from file - int w, h; - int channels; - stbi_uc* image_pixel_data = - stbi_load(p_texture_info.filepath.string().c_str(), - &w, - &h, - &channels, - STBI_rgb_alpha); - - m_width = w; - m_height = h; - - if (!image_pixel_data) { - m_texture_loaded = false; - return; - } - - // 2. create vulkan image handlers + loading in the image data - uint32_t property_flag = memory_property::device_local_bit; - - image_params config_image = { - .extent = { .width = (uint32_t)w, .height = (uint32_t)h }, - .format = VK_FORMAT_R8G8B8A8_UNORM, - .property = (memory_property)property_flag, - .aspect = image_aspect_flags::color_bit, - // .usage = (VkImageUsageFlags)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT), - .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, - // .physical_device = p_texture_info.physical - .phsyical_memory_properties = - p_texture_info.phsyical_memory_properties - }; - - m_image = - create_texture_with_data(p_device, config_image, image_pixel_data); - - m_texture_loaded = true; - } - - void texture::destroy() { - m_image.destroy(); - } -}; \ No newline at end of file diff --git a/src/vulkan-cpp/uniform_buffer.cpp b/src/vulkan-cpp/uniform_buffer.cpp deleted file mode 100644 index 2daa46c..0000000 --- a/src/vulkan-cpp/uniform_buffer.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -namespace vk { - - uniform_buffer::uniform_buffer(const VkDevice& p_device, - const uniform_params& p_uniform_info) - : m_device(p_device) - , m_size_bytes(p_uniform_info.size_bytes) { - uint32_t property_flags = memory_property::host_visible_bit | - memory_property::host_coherent_bit; - buffer_parameters uniform_info = { - .device_size = m_size_bytes, - .physical_memory_properties = - p_uniform_info.phsyical_memory_properties, - .property_flags = (memory_property)property_flags, - .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - .debug_name = p_uniform_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_uniform_info.vkSetDebugUtilsObjectNameEXT - }; - m_uniform_handle = buffer_stream(m_device, uniform_info); - } - - void uniform_buffer::update(const void* p_data) { - m_uniform_handle.write(p_data, m_size_bytes); - } - - void uniform_buffer::destroy() { - m_uniform_handle.destroy(); - } - -}; \ No newline at end of file diff --git a/src/vulkan-cpp/vertex_buffer.cpp b/src/vulkan-cpp/vertex_buffer.cpp deleted file mode 100644 index 96d25a6..0000000 --- a/src/vulkan-cpp/vertex_buffer.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include - -namespace vk { - - vertex_buffer::vertex_buffer(const VkDevice& p_device, - const vertex_params& p_vertex_info) - : m_device(p_device) { - m_size = p_vertex_info.vertices.size(); - m_size_bytes = p_vertex_info.vertices.size_bytes(); - - VkBufferUsageFlags usage = - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - - // 1. creating staging buffer - uint32_t property_flags = - memory_property::host_visible_bit | memory_property::host_cached_bit; - - buffer_parameters new_staging_buffer_settings = { - .device_size = m_size_bytes, - .physical_memory_properties = - p_vertex_info.phsyical_memory_properties, - .property_flags = (memory_property)property_flags, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - .debug_name = p_vertex_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_vertex_info.vkSetDebugUtilsObjectNameEXT - }; - buffer_stream staging_buffer(m_device, new_staging_buffer_settings); - std::span vertices = p_vertex_info.vertices; - staging_buffer.write(vertices); - - // 3.) Now creating our actual vertex buffer handler - buffer_parameters vertex_params = { - .device_size = m_size_bytes, - .physical_memory_properties = - p_vertex_info.phsyical_memory_properties, - .property_flags = memory_property::device_local_bit, - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - }; - m_vertex_handler = buffer_stream(m_device, vertex_params); - - // 4. Copy data from staging buffer to the actual vertex buffer itself! - buffer_copy_info info = { .src = staging_buffer, - .dst = m_vertex_handler }; - // copy(m_device, info, m_size_bytes); - - // 1. Retrieve the first queue - // TODO: Use vk::device_queue for this - VkQueue temp_graphics_queue = nullptr; - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - // command_buffer_info - command_params enumerate_command_info = { - .levels = command_levels::primary, - .queue_index = 0, - }; - command_buffer copy_command_buffer(p_device, enumerate_command_info); - - copy_command_buffer.begin(command_usage::one_time_submit); - // VkBufferCopy copy_region{}; - // copy_region.size = (VkDeviceSize)m_size_bytes; - // vkCmdCopyBuffer( - // copy_command_buffer, staging_buffer, m_vertex_handler, 1, ©_region); - copy_command_buffer.copy_buffer(staging_buffer, m_vertex_handler, m_size_bytes); - copy_command_buffer.end(); - VkCommandBuffer temp = copy_command_buffer; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &temp; - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - // vkFreeCommandBuffers(, command_pool, 1, ©_cmd_buffer); - // vkDestroyCommandPool(driver, command_pool, nullptr); - copy_command_buffer.destroy(); - - // 5. cleanup staging buffer -- no longer used - staging_buffer.destroy(); - } - - void vertex_buffer::bind(const VkCommandBuffer& p_current) { - std::array handlers = { m_vertex_handler }; - VkDeviceSize offsets[] = { 0 }; - vkCmdBindVertexBuffers(p_current, 0, 1, handlers.data(), offsets); - } - - void vertex_buffer::destroy() { - m_vertex_handler.destroy(); - } - -}; \ No newline at end of file diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt new file mode 100644 index 0000000..5f25f2a --- /dev/null +++ b/test_package/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.28) +project(test_package CXX) + +build_application( + SOURCES + application.cpp + + PACKAGES + vulkan-cpp + glfw3 + Vulkan + glm + stb + + LINK_PACKAGES + vulkan-cpp + glfw + Vulkan::Vulkan + glm::glm + stb::stb +) diff --git a/test_package/application.cpp b/test_package/application.cpp new file mode 100644 index 0000000..a3de0c4 --- /dev/null +++ b/test_package/application.cpp @@ -0,0 +1,6 @@ +import vk; + +int +main() { + return 0; +} \ No newline at end of file diff --git a/test_package/conanfile.py b/test_package/conanfile.py new file mode 100644 index 0000000..0cf8386 --- /dev/null +++ b/test_package/conanfile.py @@ -0,0 +1,38 @@ +from conan import ConanFile +from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeDeps + + +class TestPackageConan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "VirtualRunEnv" + + def build_requirements(self): + self.tool_requires("cmake/[^4.0.0]") + self.tool_requires("ninja/[^1.3.0]") + self.tool_requires("engine3d-cmake-utils/4.0") + + def requirements(self): + self.requires("glfw/3.4") + self.requires("glm/1.0.1") + self.requires("stb/cci.20230920") + self.requires("boost-ext-ut/2.3.1") + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.generate() + + deps = CMakeDeps(self) + deps.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + # This is to run the example code + def test(self): + pass \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams.cppm b/vulkan-cpp/buffer_streams.cppm new file mode 100644 index 0000000..bf1c172 --- /dev/null +++ b/vulkan-cpp/buffer_streams.cppm @@ -0,0 +1,191 @@ +module; + +#include +#include +#include + +export module vk:buffer_streams; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @brief Represents a VkBuffer handler for creating VkBuffer handle + * + * Purpose for using VkBuffer handle to streaming bytes of data into the GPU memory + * + */ + class buffer_stream { + public: + buffer_stream() = default; + buffer_stream(const VkDevice& p_device, + const buffer_parameters& p_settings) : m_device(p_device) { + m_allocation_size = p_settings.device_size; + + VkBufferCreateInfo buffer_ci = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = m_allocation_size, // size in bytes + .usage = p_settings.usage, + .sharingMode = p_settings.share_mode, + }; + + vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + "vkCreateBuffer"); + + // 2. retrieving buffer memory requirements + VkMemoryRequirements memory_requirements = {}; + vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); + + // 3. selects the required memory requirements for this specific buffer + // allocations + uint32_t memory_index = + select_memory_requirements(p_settings.physical_memory_properties, + memory_requirements, + p_settings.property_flags); + + // 4. allocatring the necessary memory based on memory requirements for + // the buffer handles + VkMemoryAllocateInfo memory_alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = memory_index + }; + + #if _DEBUG + // 1. Define the structure + VkDebugUtilsObjectNameInfoEXT debug_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = nullptr, + .objectType = VK_OBJECT_TYPE_BUFFER, + .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is + .pObjectName = p_settings.debug_name // specify what type of buffer this is + }; + + if(p_settings.vkSetDebugUtilsObjectNameEXT != nullptr) { + // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + p_settings.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + } + #endif + vk_check(vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); + + // 5. bind memory resource of this buffer handle + vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), + "vkBindBufferMemory"); + } + + /** + * @param span writes some buffer data in the GPU's memory using + * vkMapMemory/vkUnmapMemory + */ + template + void write(std::span p_in_data) { + VkDeviceSize buffer_size = p_in_data.size_bytes(); + void* mapped = nullptr; + vk_check(vkMapMemory( + m_device, m_device_memory, 0, buffer_size, 0, &mapped), + "vkMapMemory"); + memcpy(mapped, p_in_data.data(), buffer_size); + vkUnmapMemory(m_device, m_device_memory); + } + + void write(const void* p_in_data, uint32_t p_size_bytes) { + void* mapped = nullptr; + vk_check(vkMapMemory( + m_device, m_device_memory, 0, p_size_bytes, 0, &mapped), + "vkMapMemory"); + memcpy(mapped, p_in_data, p_size_bytes); + vkUnmapMemory(m_device, m_device_memory); + } + + /** + * + * @brief This function automatically assumes the destination image + * layout is going to be set to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL + * + * @param p_command is the current command buffer to perform and store + * this operation into + * @param p_image is the destination to copy data from the buffer to + * @param p_extent is the size of the image that is being copied + * + * ```C++ + * + * buffer_streams texture_image(logical_device, ...); + * + * texture_image.copy(temp_command_buffer, texture_image, texture_format, old_layout, new_layout); + * ``` + * + */ + void copy_to_image(const VkCommandBuffer& p_command, + const VkImage& p_image, + image_extent p_extent) { + VkBufferImageCopy buffer_image_copy = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 }, + .imageOffset = { .x = 0, .y = 0, .z = 0 }, + .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } + }; + + vkCmdCopyBufferToImage(p_command, + m_handle, + p_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &buffer_image_copy); + } + + /** + * @param p_data is the bytes to write into the GPU's memory through the + * Vulkan vkMapMemory/vkUnmapMemory API's. + * + * ```C++ + * + * buffer_streams staging_buffer(logical_device, ...); + * + * std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; + * staging_buffer.write(white_color); + * ``` + * + */ + void write(std::span p_data) { + void* mapped = nullptr; + vk_check( + vkMapMemory( + m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), + "vkMapMemory"); + memcpy(mapped, p_data.data(), p_data.size_bytes()); + vkUnmapMemory(m_device, m_device_memory); + } + + void destroy() { + if (m_handle != nullptr) { + vkDestroyBuffer(m_device, m_handle, nullptr); + } + + if (m_device_memory != nullptr) { + vkFreeMemory(m_device, m_device_memory, nullptr); + } + } + + operator VkBuffer() const { return m_handle; } + + operator VkBuffer() { return m_handle; } + + private: + VkDevice m_device = nullptr; + VkBuffer m_handle; + VkDeviceMemory m_device_memory; + uint32_t m_allocation_size = 0; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams.hpp b/vulkan-cpp/buffer_streams.hpp deleted file mode 100644 index 6650286..0000000 --- a/vulkan-cpp/buffer_streams.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - /** - * @brief Represents a VkBuffer handler for creating VkBuffer handle - * - * Purpose for using VkBuffer handle to streaming bytes of data into the GPU memory - * - */ - class buffer_stream { - public: - buffer_stream() = default; - buffer_stream(const VkDevice& p_device, - const buffer_parameters& p_settings); - - /** - * @param span writes some buffer data in the GPU's memory using - * vkMapMemory/vkUnmapMemory - */ - template - void write(std::span p_in_data) { - VkDeviceSize buffer_size = p_in_data.size_bytes(); - void* mapped = nullptr; - vk_check(vkMapMemory( - m_device, m_device_memory, 0, buffer_size, 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_in_data.data(), buffer_size); - vkUnmapMemory(m_device, m_device_memory); - } - - void write(const void* p_in_data, uint32_t p_size_bytes) { - void* mapped = nullptr; - vk_check(vkMapMemory( - m_device, m_device_memory, 0, p_size_bytes, 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_in_data, p_size_bytes); - vkUnmapMemory(m_device, m_device_memory); - } - - /** - * - * @brief This function automatically assumes the destination image - * layout is going to be set to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL - * - * @param p_command is the current command buffer to perform and store - * this operation into - * @param p_image is the destination to copy data from the buffer to - * @param p_extent is the size of the image that is being copied - * - * ```C++ - * - * buffer_streams texture_image(logical_device, ...); - * - * texture_image.copy(temp_command_buffer, texture_image, texture_format, old_layout, new_layout); - * ``` - * - */ - void copy_to_image(const VkCommandBuffer& p_command, - const VkImage& p_image, - image_extent p_extent); - - /** - * @param p_data is the bytes to write into the GPU's memory through the - * Vulkan vkMapMemory/vkUnmapMemory API's. - * - * ```C++ - * - * buffer_streams staging_buffer(logical_device, ...); - * - * std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; - * staging_buffer.write(white_color); - * ``` - * - */ - void write(std::span p_data); - - void destroy(); - - operator VkBuffer() const { return m_handle; } - - operator VkBuffer() { return m_handle; } - - private: - VkDevice m_device = nullptr; - VkBuffer m_handle; - VkDeviceMemory m_device_memory; - uint32_t m_allocation_size = 0; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams16.cppm b/vulkan-cpp/buffer_streams16.cppm new file mode 100644 index 0000000..050da88 --- /dev/null +++ b/vulkan-cpp/buffer_streams16.cppm @@ -0,0 +1,44 @@ +module; + +#include +#include +#include +#include + +export module vk:buffer_streams16; + + +export import :types; +export import :utilities; + + +export namespace vk { + inline namespace v1 { + /** + * @brief buffer stream for streaming arbitrary buffers of 32-bytes + */ + class buffer_stream16 { + public: + buffer_stream16() = default; + buffer_stream16(const VkDevice& p_device, const buffer_parameters& p_params); + + /** + * @brief write arbitrary buffer of 32-bytes to GPU-memory + */ + void write(std::span p_data); + + void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent); + + void destroy(); + + operator VkBuffer() { return m_handle; } + + operator VkBuffer() const { return m_handle; } + + private: + VkDevice m_device=nullptr; + VkDeviceMemory m_device_memory=nullptr; + VkBuffer m_handle=nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams16.hpp b/vulkan-cpp/buffer_streams16.hpp deleted file mode 100644 index a6f2c8f..0000000 --- a/vulkan-cpp/buffer_streams16.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @brief buffer stream for streaming arbitrary buffers of 32-bytes - */ - class buffer_stream16 { - public: - buffer_stream16() = default; - buffer_stream16(const VkDevice& p_device, const buffer_parameters& p_params); - - /** - * @brief write arbitrary buffer of 32-bytes to GPU-memory - */ - void write(std::span p_data); - - void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent); - - void destroy(); - - operator VkBuffer() { return m_handle; } - - operator VkBuffer() const { return m_handle; } - - private: - VkDevice m_device=nullptr; - VkDeviceMemory m_device_memory=nullptr; - VkBuffer m_handle=nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams32.cppm b/vulkan-cpp/buffer_streams32.cppm new file mode 100644 index 0000000..2c958b2 --- /dev/null +++ b/vulkan-cpp/buffer_streams32.cppm @@ -0,0 +1,134 @@ +module; + +#include +#include +#include +#include + +export module vk:buffer_streams32; + + +export import :types; +export import :utilities; +export import :command_buffer; + + +export namespace vk { + inline namespace v1 { + /** + * @brief buffer stream for streaming arbitrary buffers of 32-bytes + */ + class buffer_stream32 { + public: + buffer_stream32() = default; + buffer_stream32(const VkDevice& p_device, const buffer_parameters& p_params) : m_device(p_device) { + VkBufferCreateInfo buffer_ci = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .size = p_params.device_size, // size in bytes + .usage = p_params.usage, + .sharingMode = p_params.share_mode, + }; + + vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + "vkCreateBuffer"); + + // 2. retrieving buffer memory requirements + VkMemoryRequirements memory_requirements = {}; + vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); + + // 3. selects the required memory requirements for this specific buffer + // allocations + uint32_t memory_index = + select_memory_requirements(p_params.physical_memory_properties, + memory_requirements, + p_params.property_flags); + + // 4. allocatring the necessary memory based on memory requirements for + // the buffer handles + VkMemoryAllocateInfo memory_alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = memory_index + }; + + #if _DEBUG + // 1. Define the structure + VkDebugUtilsObjectNameInfoEXT debug_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = nullptr, + .objectType = VK_OBJECT_TYPE_BUFFER, + .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is + .pObjectName = p_params.debug_name // specify what type of buffer this is + }; + + if(p_params.vkSetDebugUtilsObjectNameEXT != nullptr) { + // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + p_params.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + } + #endif + vk_check(vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); + + // 5. bind memory resource of this buffer handle + vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), + "vkBindBufferMemory"); + } + + /** + * @brief write arbitrary buffer of 32-bytes to GPU-memory + */ + void write(std::span p_data) { + void* mapped = nullptr; + vk_check( + vkMapMemory( + m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), + "vkMapMemory"); + memcpy(mapped, p_data.data(), p_data.size_bytes()); + vkUnmapMemory(m_device, m_device_memory); + } + + void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent) { + VkBufferImageCopy buffer_image_copy = { + .bufferOffset = 0, + .bufferRowLength = 0, + .bufferImageHeight = 0, + .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 }, + .imageOffset = { .x = 0, .y = 0, .z = 0 }, + .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } + }; + + vkCmdCopyBufferToImage(p_command, + m_handle, + p_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &buffer_image_copy); + } + + void destroy() { + if (m_handle != nullptr) { + vkDestroyBuffer(m_device, m_handle, nullptr); + } + + if (m_device_memory != nullptr) { + vkFreeMemory(m_device, m_device_memory, nullptr); + } + } + + operator VkBuffer() { return m_handle; } + + operator VkBuffer() const { return m_handle; } + + private: + VkDevice m_device=nullptr; + VkDeviceMemory m_device_memory=nullptr; + VkBuffer m_handle=nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams32.hpp b/vulkan-cpp/buffer_streams32.hpp deleted file mode 100644 index a229636..0000000 --- a/vulkan-cpp/buffer_streams32.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @brief buffer stream for streaming arbitrary buffers of 32-bytes - */ - class buffer_stream32 { - public: - buffer_stream32() = default; - buffer_stream32(const VkDevice& p_device, const buffer_parameters& p_params); - - /** - * @brief write arbitrary buffer of 32-bytes to GPU-memory - */ - void write(std::span p_data); - - void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent); - - void destroy(); - - operator VkBuffer() { return m_handle; } - - operator VkBuffer() const { return m_handle; } - - private: - VkDevice m_device=nullptr; - VkDeviceMemory m_device_memory=nullptr; - VkBuffer m_handle=nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/command_buffer.cppm b/vulkan-cpp/command_buffer.cppm new file mode 100644 index 0000000..f1c7ff9 --- /dev/null +++ b/vulkan-cpp/command_buffer.cppm @@ -0,0 +1,184 @@ +module; + +#include +#include +#include + +export module vk:command_buffer; + + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + struct command_inherit_info { + VkRenderPass renderpass = nullptr; + uint32_t subpass_index = 0; + VkFramebuffer framebuffer = nullptr; + }; + + /** + * @brief vk::command_buffer represents the wrapper around VkCommandBuffer + * + * Defines the command buffer and provides API's to directly interact with how + * the command buffer may be utilized based on the needs of the application that uses it + * + */ + class command_buffer { + public: + command_buffer() = default; + command_buffer(const VkDevice& p_device, const command_params& p_enumerate_command_info) : m_device(p_device) { + VkCommandPoolCreateInfo pool_ci = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .pNext = nullptr, + // .flags = + // (VkCommandPoolCreateFlags)p_enumerate_command_info.pool_flag, + .flags = static_cast(p_enumerate_command_info.flags), + .queueFamilyIndex = p_enumerate_command_info.queue_index + }; + + vk_check( + vkCreateCommandPool(m_device, &pool_ci, nullptr, &m_command_pool), + "vkCreateCommandPool"); + + VkCommandBufferAllocateInfo command_buffer_alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .pNext = nullptr, + .commandPool = m_command_pool, + .level = + static_cast(p_enumerate_command_info.levels), + .commandBufferCount = 1 + }; + + vk_check(vkAllocateCommandBuffers( + m_device, &command_buffer_alloc_info, &m_command_buffer), + "vkAllocateCommandBuffers"); + } + + /** + * @brief begins the recording operation of the particular command buffer + * + * @param p_usage are flags to specify the behavior of the command buffer + * @param p_inherit_info is if this command buffer is created and used as a secondary command buffer, then + * this defines any state that will be inherited from the primary command buffer + * + * + * ```C++ + * + * vk::command_buffer temp_command(logical_device, ....); + * + * temp_command.begin(command_usage::one_time_submit); + * temp_command.end(); // required whenever .begin is called + * ``` + * + */ + void begin(command_usage p_usage, std::span p_inherit_info = {}) { + // Resets to zero if get called every frame + if (m_begin_end_count == 2) { + m_begin_end_count = 0; + } + m_begin_end_count++; + + std::vector inheritance_infos( + p_inherit_info.size()); + + for (size_t i = 0; i < inheritance_infos.size(); i++) { + inheritance_infos[i] = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + .renderPass = p_inherit_info[i].renderpass, + .subpass = p_inherit_info[i].subpass_index, + .framebuffer = p_inherit_info[i].framebuffer + }; + } + + VkCommandBufferBeginInfo command_begin_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .pNext = nullptr, + .flags = static_cast(p_usage) + }; + vk_check(vkBeginCommandBuffer(m_command_buffer, &command_begin_info), + "vkBeginCommandBuffer"); + } + + /** + * @brief ends command buffer recording operation + */ + void end() { + m_begin_end_count++; + vkEndCommandBuffer(m_command_buffer); + } + + /** + * + * @brief Copy from the source buffer to a destination specified buffer + * + * + * Command buffer records this and expects a staging buffer to map chunks of data in GPU memory + * + * Then calling this API to handle copying the sources in staging buffer to its final destination buffer, moving those chunks into the final buffer handle + * + * + * @param p_src is the buffer to copy its region from + * @param p_dst is the buffer to copy that region into + * @param p_size_bytes is the amount of bytes stored in the buffer that is being copied into the destination buffer + * + * + * ```C++ + * + * // staging buffer to make sure we copy data regions chunks to vertex buffer correctly + * vk::buffer_stream staging_buffer(logical_device, ...); + * + * // vertex_buffer handle is the destination to copy the regions to + * vk::buffer_stream vertex_buffer(logical_device, ...); + * + * vk::command_buffer temp_command(logical_device, ...); + * + * temp_command.begin(command_usage::one_time_submit); + * temp_command.copy(staging_buffer, vertex_buffer, size_bytes); + * temp_command.end(); + * + * + * ``` + * + */ + void copy_buffer(const VkBuffer& p_src, const VkBuffer& p_dst, uint64_t p_size_bytes) { + VkBufferCopy copy_region{}; + copy_region.size = p_size_bytes; + vkCmdCopyBuffer(m_command_buffer, p_src, p_dst, 1, ©_region); + } + + [[nodiscard]] bool alive() const { return m_command_buffer; } + + /** + * @brief Used to execute secondary command buffers + * + * The command buffer that is executing these commands must be a + * specified primary command buffer + * + * @param p_commands is the secondary command buffer that gets executed + * if the command buffer itself is a primary command buffer + */ + void execute(std::span p_commands) { + vkCmdExecuteCommands(m_command_buffer, + static_cast(p_commands.size()), + p_commands.data()); + } + + void destroy() { + vkFreeCommandBuffers(m_device, m_command_pool, 1, &m_command_buffer); + vkDestroyCommandPool(m_device, m_command_pool, nullptr); + } + + operator VkCommandBuffer() const { return m_command_buffer; } + + operator VkCommandBuffer() { return m_command_buffer; } + + private: + VkDevice m_device = nullptr; + uint32_t m_begin_end_count = 0; + VkCommandPool m_command_pool = nullptr; + VkCommandBuffer m_command_buffer = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/command_buffer.hpp b/vulkan-cpp/command_buffer.hpp deleted file mode 100644 index 0ae460d..0000000 --- a/vulkan-cpp/command_buffer.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - struct command_inherit_info { - VkRenderPass renderpass = nullptr; - uint32_t subpass_index = 0; - VkFramebuffer framebuffer = nullptr; - }; - - /** - * @brief vk::command_buffer represents the wrapper around VkCommandBuffer - * - * Defines the command buffer and provides API's to directly interact with how - * the command buffer may be utilized based on the needs of the application that uses it - * - */ - class command_buffer { - public: - command_buffer() = default; - command_buffer(const VkDevice& p_device, - const command_params& p_enumerate_command_info); - - /** - * @brief begins the recording operation of the particular command buffer - * - * @param p_usage are flags to specify the behavior of the command buffer - * @param p_inherit_info is if this command buffer is created and used as a secondary command buffer, then - * this defines any state that will be inherited from the primary command buffer - * - * - * ```C++ - * - * vk::command_buffer temp_command(logical_device, ....); - * - * temp_command.begin(command_usage::one_time_submit); - * temp_command.end(); // required whenever .begin is called - * ``` - * - */ - void begin(command_usage p_usage, - std::span p_inherit_info = {}); - - /** - * @brief ends command buffer recording operation - */ - void end(); - - /** - * - * @brief Copy from the source buffer to a destination specified buffer - * - * - * Command buffer records this and expects a staging buffer to map chunks of data in GPU memory - * - * Then calling this API to handle copying the sources in staging buffer to its final destination buffer, moving those chunks into the final buffer handle - * - * - * @param p_src is the buffer to copy its region from - * @param p_dst is the buffer to copy that region into - * @param p_size_bytes is the amount of bytes stored in the buffer that is being copied into the destination buffer - * - * - * ```C++ - * - * // staging buffer to make sure we copy data regions chunks to vertex buffer correctly - * vk::buffer_stream staging_buffer(logical_device, ...); - * - * // vertex_buffer handle is the destination to copy the regions to - * vk::buffer_stream vertex_buffer(logical_device, ...); - * - * vk::command_buffer temp_command(logical_device, ...); - * - * temp_command.begin(command_usage::one_time_submit); - * temp_command.copy(staging_buffer, vertex_buffer, size_bytes); - * temp_command.end(); - * - * - * ``` - * - */ - void copy_buffer(const VkBuffer& p_src, const VkBuffer& p_dst, uint64_t p_size_bytes); - - [[nodiscard]] bool alive() const { return m_command_buffer; } - - /** - * @brief Used to execute secondary command buffers - * - * The command buffer that is executing these commands must be a - * specified primary command buffer - * - * @param p_commands is the secondary command buffer that gets executed - * if the command buffer itself is a primary command buffer - */ - void execute(std::span p_commands); - - void destroy(); - - operator VkCommandBuffer() const { return m_command_buffer; } - - operator VkCommandBuffer() { return m_command_buffer; } - - private: - VkDevice m_device = nullptr; - uint32_t m_begin_end_count = 0; - VkCommandPool m_command_pool = nullptr; - VkCommandBuffer m_command_buffer = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/descriptor_resource.cppm b/vulkan-cpp/descriptor_resource.cppm new file mode 100644 index 0000000..78dd88f --- /dev/null +++ b/vulkan-cpp/descriptor_resource.cppm @@ -0,0 +1,192 @@ +module; + +#include +#include +#include +#include + +export module vk:descriptor_resource; + + +export import :types; +export import :utilities; +export import :uniform_buffer; +export import :sample_image; + +export namespace vk { + inline namespace v1 { + /** + * @param slot is the slot specific to the number slot for the descriptor. + * Ex. layout (set = 0) + */ + struct descriptor_layout { + uint32_t slot = 0; + uint32_t max_sets = 0; + std::span entries; + }; + + class descriptor_resource { + public: + descriptor_resource() = default; + descriptor_resource(const VkDevice& p_device, const descriptor_layout& p_info) : m_device(p_device), m_slot(p_info.slot) { + std::vector pool_sizes(p_info.entries.size()); + std::vector descriptor_layout_bindings(p_info.entries.size()); + + for (size_t i = 0; i < pool_sizes.size(); i++) { + VkDescriptorType descriptor_type = static_cast(p_info.entries[i].type); + pool_sizes[i] = { + .type = descriptor_type, + .descriptorCount = + static_cast(p_info.entries[i].descriptor_count) * + p_info.max_sets, + }; + } + + for (size_t i = 0; i < descriptor_layout_bindings.size(); i++) { + descriptor_entry entry = p_info.entries[i]; + descriptor_binding_point bind = entry.binding_point; + + VkDescriptorType type = static_cast(entry.type); + + descriptor_layout_bindings[i] = { + .binding = bind.binding, + .descriptorType = type, + .descriptorCount = entry.descriptor_count, + .stageFlags = static_cast(bind.stage), + }; + } + + VkDescriptorPoolCreateInfo pool_ci = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .maxSets = p_info.max_sets, + .poolSizeCount = static_cast(pool_sizes.size()), + .pPoolSizes = pool_sizes.data() + }; + + vk_check(vkCreateDescriptorPool( + m_device, &pool_ci, nullptr, &m_descriptor_pool), + "vkCreateDescriptorPool"); + + VkDescriptorSetLayoutCreateInfo descriptor_layout_ci = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .bindingCount = + static_cast(descriptor_layout_bindings.size()), + .pBindings = descriptor_layout_bindings.data() + }; + + vk_check( + vkCreateDescriptorSetLayout( + m_device, &descriptor_layout_ci, nullptr, &m_descriptor_layout), + "vkCreateDescriptorSetLayout"); + VkDescriptorSetAllocateInfo descriptor_set_alloc_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .pNext = nullptr, + .descriptorPool = m_descriptor_pool, + .descriptorSetCount = 1, + .pSetLayouts = &m_descriptor_layout + }; + + vk_check(vkAllocateDescriptorSets(m_device, + &descriptor_set_alloc_info, + &m_descriptor_set), + "vkAllocateDescriptorSets"); + } + + void bind(const VkCommandBuffer& p_current, const VkPipelineLayout& p_pipeline_layout) { + vkCmdBindDescriptorSets(p_current, + VK_PIPELINE_BIND_POINT_GRAPHICS, + p_pipeline_layout, + m_slot, + 1, + &m_descriptor_set, + 0, + nullptr); + } + + void update(std::span p_uniforms, std::span p_images={}) { + std::vector write_descriptors; + + // uint32_t represent the destination bindings to those resources (uniforms and sample images) + std::unordered_map> buffer_infos; + std::unordered_map> image_infos; + + // handle uniforms + for(const auto& ubo : p_uniforms) { + for(const auto& uniform : ubo.uniforms) { + buffer_infos[ubo.dst_binding].emplace_back(uniform.buffer, uniform.offset, uniform.range); + } + + VkWriteDescriptorSet write_descriptor = { + . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = m_descriptor_set, + .dstBinding = ubo.dst_binding, + .dstArrayElement = 0, + .descriptorCount = static_cast(buffer_infos[ubo.dst_binding].size()), + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = buffer_infos[ubo.dst_binding].data(), + }; + + write_descriptors.emplace_back(write_descriptor); + } + + for(const auto& ubo : p_images) { + + for(const auto& sample_image : ubo.sample_images) { + image_infos[ubo.dst_binding].emplace_back(sample_image.sampler, sample_image.view, static_cast(sample_image.layout)); + } + + VkWriteDescriptorSet write_descriptor = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .pNext = nullptr, + .dstSet = m_descriptor_set, + .dstBinding = ubo.dst_binding, + .dstArrayElement = 0, + .descriptorCount = static_cast(image_infos[ubo.dst_binding].size()), + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = image_infos[ubo.dst_binding].data(), + }; + + write_descriptors.emplace_back(write_descriptor); + } + + vkUpdateDescriptorSets( + m_device, + static_cast(write_descriptors.size()), + write_descriptors.data(), + 0, + nullptr); + + // Ensures to clear up so we dont have any existing handles because they only need to exist until we've updated the descriptors + buffer_infos.clear(); + image_infos.clear(); + } + + [[nodiscard]] VkDescriptorSetLayout layout() const { + return m_descriptor_layout; + } + + void destroy() { + if (m_descriptor_pool != nullptr) { + vkDestroyDescriptorPool(m_device, m_descriptor_pool, nullptr); + } + + if (m_descriptor_layout != nullptr) { + vkDestroyDescriptorSetLayout( + m_device, m_descriptor_layout, nullptr); + } + } + + private: + VkDevice m_device = nullptr; + uint32_t m_slot; + VkDescriptorPool m_descriptor_pool = nullptr; + VkDescriptorSetLayout m_descriptor_layout = nullptr; + VkDescriptorSet m_descriptor_set = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/descriptor_resource.hpp b/vulkan-cpp/descriptor_resource.hpp deleted file mode 100644 index 74e149d..0000000 --- a/vulkan-cpp/descriptor_resource.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace vk { - - /** - * @param slot is the slot specific to the number slot for the descriptor. - * Ex. layout (set = 0) - */ - struct descriptor_layout { - uint32_t slot = 0; - uint32_t max_sets = 0; - std::span entries; - }; - - class descriptor_resource { - public: - descriptor_resource() = default; - descriptor_resource(const VkDevice& p_device, - const descriptor_layout& p_info); - - void bind(const VkCommandBuffer& p_current, - const VkPipelineLayout& p_layout); - - void update(std::span p_uniforms, std::span p_images={}); - - [[nodiscard]] VkDescriptorSetLayout layout() const { - return m_descriptor_layout; - } - - void destroy(); - - private: - VkDevice m_device = nullptr; - uint32_t m_slot; - VkDescriptorPool m_descriptor_pool = nullptr; - VkDescriptorSetLayout m_descriptor_layout = nullptr; - VkDescriptorSet m_descriptor_set = nullptr; - }; - -}; \ No newline at end of file diff --git a/vulkan-cpp/device.cppm b/vulkan-cpp/device.cppm new file mode 100644 index 0000000..311a184 --- /dev/null +++ b/vulkan-cpp/device.cppm @@ -0,0 +1,80 @@ +module; + +#include + +export module vk:device; + +export import :types; +export import :utilities; + + +export namespace vk { + inline namespace v1 { + /** + * @name device + * @brief represents a vulkan logical device + */ + class device { + struct queue_family { + VkQueue graphics = nullptr; + VkQueue compute = nullptr; + VkQueue transfer = nullptr; + }; + + public: + device(const VkPhysicalDevice& p_physical, const device_params& p_config) { + VkDeviceQueueCreateInfo device_queue_ci = { + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .queueFamilyIndex = p_config.queue_family_index, + .queueCount = + static_cast(p_config.queue_priorities.size()), + .pQueuePriorities = p_config.queue_priorities.data(), + }; + + VkDeviceCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .queueCreateInfoCount = 1, + .pQueueCreateInfos = &device_queue_ci, + .enabledLayerCount = 0, + .ppEnabledLayerNames = nullptr, + .enabledExtensionCount = + static_cast(p_config.extensions.size()), + .ppEnabledExtensionNames = p_config.extensions.data(), + }; + + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(p_physical, &features); + features.robustBufferAccess = false; + create_info.pEnabledFeatures = &features; + + vk_check(vkCreateDevice(p_physical, &create_info, nullptr, &m_device), + "vkCreateDevice"); + } + + [[nodiscard]] queue_family family() const { return m_queue_family; } + + void destroy() { + if (m_device != nullptr) { + vkDestroyDevice(m_device, nullptr); + } + } + + void wait() { + vkDeviceWaitIdle(m_device); + } + + operator VkDevice() const { return m_device; } + + operator VkDevice() { return m_device; } + + private: + VkDevice m_device = nullptr; + queue_family m_queue_family{}; + }; + + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/device.hpp b/vulkan-cpp/device.hpp deleted file mode 100644 index ae5b55b..0000000 --- a/vulkan-cpp/device.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - /** - * @name device - * @brief represents a vulkan logical device - */ - class device { - struct queue_family { - VkQueue graphics = nullptr; - VkQueue compute = nullptr; - VkQueue transfer = nullptr; - }; - - public: - device(const VkPhysicalDevice& p_physical, - const device_params& p_config); - - [[nodiscard]] queue_family family() const { return m_queue_family; } - - void destroy(); - - void wait(); - - operator VkDevice() const { return m_device; } - - operator VkDevice() { return m_device; } - - private: - VkDevice m_device = nullptr; - queue_family m_queue_family{}; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/device_present_queue.cppm b/vulkan-cpp/device_present_queue.cppm new file mode 100644 index 0000000..0d795a8 --- /dev/null +++ b/vulkan-cpp/device_present_queue.cppm @@ -0,0 +1,168 @@ +module; + +#include +#include +#include + +export module vk:device_present_queue; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @name device_present_queue + * @brief Represents a presentation queue that must have an associated + * context to present images to the screen + * + * This class is different from device_queue. device_present_queue + * represents a presentable queue for displaying to some specific screen + * context + */ + class device_present_queue { + public: + device_present_queue() = default; + device_present_queue(const VkDevice& p_device, + const VkSwapchainKHR& p_swapchain_context, + const queue_params& p_config) + : m_device(p_device), m_swapchain(p_swapchain_context) { + + vkGetDeviceQueue( + m_device, p_config.family, p_config.index, &m_queue_handler); + + m_work_completed = create_semaphore(m_device); + m_presentation_completed = create_semaphore(m_device); + m_out_of_date = false; + } + + void wait_idle() { + vkQueueWaitIdle(m_queue_handler); + } + + //! @return true if this queue is out of date + // Can occur when acquired_next_image or present_frame are out of date + // indication swapchain resizeability. + // TODO: Change this to using C++'s exceptions for handling out-of-date invalidation cases + bool out_of_date(bool p_is_reset = true) { + // The return value we return + bool return_value = false; + + // If the bool is set to true meaning its out of date + // Then we set the internal variable tracking the acquired next image + // state to false, and return false This is for ensuring that we do not + // need to set the boolean ourselves. Should we handle this state to + // reset to false if checked or user should set the state??? + if (m_out_of_date) { + return_value = m_out_of_date; + if (p_is_reset) { + m_out_of_date = false; + } + return return_value; + } + + return return_value; + } + + uint32_t acquire_next_image() { + wait_idle(); + + uint32_t image_acquired; + VkResult acquired_next_image_res = + vkAcquireNextImageKHR(m_device, + m_swapchain, + std::numeric_limits::max(), + m_presentation_completed, + nullptr, + &image_acquired); + + if (acquired_next_image_res == VK_ERROR_OUT_OF_DATE_KHR) { + m_out_of_date = true; + } + + vk_check(acquired_next_image_res, "vkAcquireNextImageKHR"); + + return image_acquired; + } + + //! @brief Submit commands to this specific present queue (without + //! asynchronously) + void submit_sync(std::span p_commands) { + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreCount = 0, + .pWaitSemaphores = nullptr, + .pWaitDstStageMask = nullptr, + .commandBufferCount = static_cast(p_commands.size()), + .pCommandBuffers = p_commands.data(), + .signalSemaphoreCount = 0, + .pSignalSemaphores = nullptr, + }; + + VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); + vk_check(res, "vkQueueSubmit"); + } + + //! @brief Submit commands to this specific present queue + //! (asynchronously) + void submit_async(std::span p_commands, + pipeline_stage_flags p_flags = + pipeline_stage_flags::color_attachment_output) { + VkPipelineStageFlags flags = static_cast(p_flags); + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &m_presentation_completed, + .pWaitDstStageMask = &flags, + .commandBufferCount = static_cast(p_commands.size()), + .pCommandBuffers = p_commands.data(), + .signalSemaphoreCount = 1, + .pSignalSemaphores = &m_work_completed, + }; + + VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); + vk_check(res, "vkQueueSubmit"); + } + + //! @brief Displays specific image to the presentation frame with + //! specific frame index + void present_frame(uint32_t p_frame_idx) { + VkPresentInfoKHR present_info = { + .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .pNext = nullptr, + .waitSemaphoreCount = 1, + .pWaitSemaphores = &m_work_completed, + .swapchainCount = 1, + .pSwapchains = &m_swapchain, + .pImageIndices = &p_frame_idx, + }; + + VkResult res = vkQueuePresentKHR(m_queue_handler, &present_info); + vk_check(res, "vkQueuePresentKHR"); + if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) { + m_out_of_date = true; + } + } + + void destroy() { + vkDeviceWaitIdle(m_device); + vkDestroySemaphore(m_device, m_presentation_completed, nullptr); + vkDestroySemaphore(m_device, m_work_completed, nullptr); + } + + operator VkQueue() { return m_queue_handler; } + + operator VkQueue() const { return m_queue_handler; } + + private: + VkDevice m_device = nullptr; + bool m_out_of_date = false; + VkSwapchainKHR m_swapchain = nullptr; + VkQueue m_queue_handler = nullptr; + VkSemaphore m_work_completed = nullptr; + VkSemaphore m_presentation_completed = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/device_present_queue.hpp b/vulkan-cpp/device_present_queue.hpp deleted file mode 100644 index a1cfac3..0000000 --- a/vulkan-cpp/device_present_queue.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - /** - * @name device_present_queue - * @brief Represents a presentation queue that must have an associated - * context to present images to the screen - * - * This class is different from device_queue. device_present_queue - * represents a presentable queue for displaying to some specific screen - * context - */ - class device_present_queue { - public: - device_present_queue() = default; - device_present_queue(const VkDevice& p_device, - const VkSwapchainKHR& p_swapchain_context, - const queue_params& p_config); - - void wait_idle(); - - uint32_t acquire_next_image(); - - //! @brief Submit commands to this specific present queue (without - //! asynchronously) - void submit_sync(std::span p_commands); - - //! @brief Submit commands to this specific present queue - //! (asynchronously) - void submit_async(std::span p_commands, - pipeline_stage_flags p_flags = - pipeline_stage_flags::color_attachment_output); - - //! @brief Displays specific image to the presentation frame with - //! specific frame index - void present_frame(uint32_t p_frame_idx); - - //! @return true if this queue is out of date - // Can occur when acquired_next_image or present_frame are out of date - // indication swapchain resizeability. - // TODO: Change this to using C++'s exceptions for handling out-of-date invalidation cases - bool out_of_date(bool p_is_reset = true); - - void destroy(); - - operator VkQueue() { return m_queue_handler; } - - operator VkQueue() const { return m_queue_handler; } - - private: - VkDevice m_device = nullptr; - bool m_out_of_date = false; - VkSwapchainKHR m_swapchain = nullptr; - VkQueue m_queue_handler = nullptr; - VkSemaphore m_work_completed = nullptr; - VkSemaphore m_presentation_completed = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/device_queue.cppm b/vulkan-cpp/device_queue.cppm new file mode 100644 index 0000000..4daecfc --- /dev/null +++ b/vulkan-cpp/device_queue.cppm @@ -0,0 +1,35 @@ +module; + +#include + +export module vk:device_queue; + +export import :types; +export import :utilities; + + +export namespace vk { + inline namespace v1 { + /** + * @name + * @brief Represents a queue part of a specific logical device created + */ + class device_queue { + public: + device_queue() = default; + + device_queue(const VkDevice& p_device, const queue_params& p_config) { + vkGetDeviceQueue(p_device, p_config.family, p_config.index, &m_queue_handler); + } + + [[nodiscard]] bool alive() const { return m_queue_handler; } + + operator VkQueue() const { return m_queue_handler; } + + operator VkQueue() { return m_queue_handler; } + + private: + VkQueue m_queue_handler = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/device_queue.hpp b/vulkan-cpp/device_queue.hpp deleted file mode 100644 index dbf4430..0000000 --- a/vulkan-cpp/device_queue.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include - -namespace vk { - /** - * @name - * @brief Represents a queue part of a specific logical device created - */ - class device_queue { - public: - device_queue() = default; - device_queue(const VkDevice& p_device, - const queue_params& p_config); - - [[nodiscard]] bool alive() const { return m_queue_handler; } - - operator VkQueue() const { return m_queue_handler; } - - operator VkQueue() { return m_queue_handler; } - - private: - VkQueue m_queue_handler = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/framebuffer.cppm b/vulkan-cpp/framebuffer.cppm new file mode 100644 index 0000000..76731ea --- /dev/null +++ b/vulkan-cpp/framebuffer.cppm @@ -0,0 +1,60 @@ +module; + +#include + +export module vk:framebuffer; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @name vk::framebuffer + * + * @param p_device is logical device that creates and manages the + * destruction of vulkan framebuffer handles. + * @param p_setting are specifications to configure the creation of vulkan + * VkFramebuffer handles. + */ + class framebuffer { + public: + framebuffer() = default; + framebuffer(const VkDevice& p_device, + const framebuffer_params& p_setting) : m_device(p_device) { + + VkFramebufferCreateInfo framebuffer_ci = { + .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .renderPass = p_setting.renderpass, + .attachmentCount = static_cast(p_setting.views.size()), + .pAttachments = p_setting.views.data(), + .width = p_setting.extent.width, + .height = p_setting.extent.height, + .layers = 1 + }; + + vk::vk_check(vkCreateFramebuffer( + m_device, &framebuffer_ci, nullptr, &m_framebuffer), + "vkCreateFramebuffer"); + } + + [[nodiscard]] bool alive() const { return m_framebuffer; } + + void destroy() { + if (m_framebuffer != nullptr) { + vkDestroyFramebuffer(m_device, m_framebuffer, nullptr); + } + } + + operator VkFramebuffer() const { return m_framebuffer; } + + operator VkFramebuffer() { return m_framebuffer; } + + private: + VkDevice m_device = nullptr; + VkFramebuffer m_framebuffer = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/framebuffer.hpp b/vulkan-cpp/framebuffer.hpp deleted file mode 100644 index 9dbe4bb..0000000 --- a/vulkan-cpp/framebuffer.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - /** - * @name vk::framebuffer - * - * @param p_device is logical device that creates and manages the - * destruction of vulkan framebuffer handles. - * @param p_setting are specifications to configure the creation of vulkan - * VkFramebuffer handles. - */ - class framebuffer { - public: - framebuffer() = default; - framebuffer(const VkDevice& p_device, - const framebuffer_params& p_setting); - - [[nodiscard]] bool alive() const { return m_framebuffer; } - - void destroy(); - - operator VkFramebuffer() const { return m_framebuffer; } - - operator VkFramebuffer() { return m_framebuffer; } - - private: - VkDevice m_device = nullptr; - VkFramebuffer m_framebuffer = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/imports.hpp b/vulkan-cpp/imports.hpp deleted file mode 100644 index 91d4652..0000000 --- a/vulkan-cpp/imports.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif \ No newline at end of file diff --git a/vulkan-cpp/index_buffer.cppm b/vulkan-cpp/index_buffer.cppm new file mode 100644 index 0000000..4b62ce8 --- /dev/null +++ b/vulkan-cpp/index_buffer.cppm @@ -0,0 +1,63 @@ +module; + +#include +#include +#include + +export module vk:index_buffer; + + +export import :types; +export import :utilities; +export import :command_buffer; +export import :buffer_streams32; + +export namespace vk { + inline namespace v1 { + class index_buffer { + public: + index_buffer() = default; + index_buffer(const VkDevice& p_device, + const index_params& p_info) : m_device(p_device) { + m_indices_count = p_info.indices.size(); + + uint32_t property_flags = + memory_property::host_visible_bit | memory_property::host_cached_bit; + buffer_parameters index_params = { + .device_size = p_info.indices.size_bytes(), + .physical_memory_properties = p_info.phsyical_memory_properties, + .property_flags = (memory_property)property_flags, + .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, + .debug_name = p_info.debug_name.c_str(), + .vkSetDebugUtilsObjectNameEXT = p_info.vkSetDebugUtilsObjectNameEXT + }; + + m_index_buffer = buffer_stream32(m_device, index_params); + + m_index_buffer.write(p_info.indices); + } + + [[nodiscard]] bool alive() const { return m_index_buffer; } + + [[nodiscard]] uint32_t size() const { return m_indices_count; } + + void bind(const VkCommandBuffer& p_current) { + vkCmdBindIndexBuffer( + p_current, m_index_buffer, 0, VK_INDEX_TYPE_UINT32); + } + + operator VkBuffer() const { return m_index_buffer; } + + operator VkBuffer() { return m_index_buffer; } + + void destroy() { + m_index_buffer.destroy(); + } + + private: + VkDevice m_device = nullptr; + uint32_t m_indices_count = 0; + buffer_stream32 m_index_buffer{}; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/index_buffer.hpp b/vulkan-cpp/index_buffer.hpp deleted file mode 100644 index 8ff1ad0..0000000 --- a/vulkan-cpp/index_buffer.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - - class index_buffer { - public: - index_buffer() = default; - index_buffer(const VkDevice& p_device, - const index_params& p_info); - - [[nodiscard]] bool alive() const { return m_index_buffer; } - - [[nodiscard]] uint32_t size() const { return m_indices_count; } - - void bind(const VkCommandBuffer& p_current); - - operator VkBuffer() const { return m_index_buffer; } - - operator VkBuffer() { return m_index_buffer; } - - void destroy(); - - private: - VkDevice m_device = nullptr; - uint32_t m_indices_count = 0; - buffer_stream32 m_index_buffer{}; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/instance.cppm b/vulkan-cpp/instance.cppm new file mode 100644 index 0000000..94085e4 --- /dev/null +++ b/vulkan-cpp/instance.cppm @@ -0,0 +1,139 @@ +module; + +#include +#include +#include + +export module vk:instance; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @brief vk::instance represents VkInstance to initialize the vulkan API. + * + * Provides configuration settings that can be applied to the application + * and the vulkan debug utility for the validation layers + */ + class instance { + public: + /** + * @param p_config sets the application information that vulkan has + * optionally. + * @param p_debug_message_utils is for setting up vulkan's utility + * tooling for debugging and enabling validation layers + */ + instance(const application_params& p_config, + const debug_message_utility& p_debug_message_utils) { + VkApplicationInfo app_info = { + .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, + .pNext = nullptr, + .applicationVersion = 1, + .pEngineName = p_config.name.c_str(), + .engineVersion = 1, + .apiVersion = static_cast(p_config.version), + }; + + VkInstanceCreateInfo instance_ci = { + .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .pApplicationInfo = &app_info + }; + + // Setting up validation layers properties + uint32_t layer_count = 0; + std::vector layer_properties; + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); + // std::vector layer_properties(layer_count); + layer_properties.resize(layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, + layer_properties.data()); + + for (const VkLayerProperties property : layer_properties) { + m_layer_properties.emplace_back(property.layerName, + property.specVersion, + property.implementationVersion, + property.description); + } + + // Setting up instance extensions + instance_ci.enabledExtensionCount = + static_cast(p_config.extensions.size()); + instance_ci.ppEnabledExtensionNames = p_config.extensions.data(); + + // Only run validation layers if we are running vulkan-cpp in debug mode + #if _DEBUG + // Setting up validation layers + instance_ci.enabledLayerCount = + static_cast(p_config.validations.size()); + instance_ci.ppEnabledLayerNames = p_config.validations.data(); + + VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = static_cast(p_debug_message_utils.severity), + .messageType = static_cast(p_debug_message_utils.message_type), + .pfnUserCallback = p_debug_message_utils.callback, + }; + + // This is to invoke the vulkan debug utils if it is a valid callback + // To ensure that we are not using an invalid debug callback + if (p_debug_message_utils.callback != nullptr) { + instance_ci.pNext = + (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; + } + else { + instance_ci.pNext = nullptr; + } + #else + instance_ci.enabledLayerCount = 0; + instance_ci.ppEnabledLayerNames = nullptr; + instance_ci.pNext = nullptr; + #endif + vk_check(vkCreateInstance(&instance_ci, nullptr, &m_instance), + "vkCreateInstance"); + + #if _DEBUG + // This needs to be created after the VkInstance is or else it wont be applied the debug information during validation layer error message execution + m_vk_set_debug_utils_object_name_ext = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkSetDebugUtilsObjectNameEXT")); + #endif + } + + //! @return true if a valid VkInstance + [[nodiscard]] bool alive() const { return !m_instance; } + + //! @return available validation layers + std::span validation() { + return m_layer_properties; + } + + /** + * @brief returns function pointer to allow for setting debug object name + * + * + * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug builds + * + * This allows for setting up object names that is useful to the programmer when a validation layer error message occurs unexpectedly + * + */ + [[nodiscard]] PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() const { + return m_vk_set_debug_utils_object_name_ext; + } + + operator VkInstance() { return m_instance; } + + operator VkInstance() const { return m_instance; } + + //! @brief Invokes the destruction of the VkInstance. + void destroy() {} + + private: + VkInstance m_instance = nullptr; + std::vector m_layer_properties{}; + // This needs to be set or else it becomes nullptr + PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/instance.hpp b/vulkan-cpp/instance.hpp deleted file mode 100644 index a355cac..0000000 --- a/vulkan-cpp/instance.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @brief vk::instance represents VkInstance to initialize the vulkan API. - * - * Provides configuration settings that can be applied to the application - * and the vulkan debug utility for the validation layers - */ - class instance { - public: - /** - * @param p_config sets the application information that vulkan has - * optionally. - * @param p_debug_message_utils is for setting up vulkan's utility - * tooling for debugging and enabling validation layers - */ - instance(const application_params& p_config, - const debug_message_utility& p_debug_message_utils); - - //! @return true if a valid VkInstance - [[nodiscard]] bool alive() const { return !m_instance; } - - //! @return available validation layers - std::span validation() { - return m_layer_properties; - } - - /** - * @brief returns function pointer to allow for setting debug object name - * - * - * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug builds - * - * This allows for setting up object names that is useful to the programmer when a validation layer error message occurs unexpectedly - * - */ - [[nodiscard]] PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() const { - return m_vk_set_debug_utils_object_name_ext; - } - - operator VkInstance() { return m_instance; } - - operator VkInstance() const { return m_instance; } - - //! @brief Invokes the destruction of the VkInstance. - void destroy(); - - private: - VkInstance m_instance = nullptr; - std::vector m_layer_properties{}; - // This needs to be set or else it becomes nullptr - PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/physical_device.cppm b/vulkan-cpp/physical_device.cppm new file mode 100644 index 0000000..9607227 --- /dev/null +++ b/vulkan-cpp/physical_device.cppm @@ -0,0 +1,135 @@ +module; + +#include +#include +#include + +export module vk:physical_device; + +export import :utilities; +export import :types; + + +export namespace vk { + inline namespace v1 { + class physical_device { + public: + physical_device() = default; + + physical_device(const VkInstance& p_instance, const physical_enumeration& p_physical_enumeration) { + m_physical_device = enumerate_physical_devices(p_instance, p_physical_enumeration.device_type); + + if (m_physical_device == nullptr) { + throw std::runtime_error("m_physical_device was nullptr!!!"); + } + + m_queue_family_properties = + enumerate_queue_family_properties(m_physical_device); + + // This makes sure that we get the graphics, compute, and transfer queue + // indices from the physical queue family assigned + uint32_t queue_index = 0; + for (const auto& queue_family : m_queue_family_properties) { + if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + m_queue_family_indices.graphics = queue_index; + break; + } + + queue_index++; + } + queue_index = 0; + + for (const auto& queue_family : m_queue_family_properties) { + if (queue_family.queueFlags & VK_QUEUE_COMPUTE_BIT) { + m_queue_family_indices.compute = queue_index; + } + queue_index++; + } + queue_index = 0; + + for (const auto& queue_family : m_queue_family_properties) { + if (queue_family.queueFlags & VK_QUEUE_TRANSFER_BIT) { + m_queue_family_indices.transfer = queue_index; + } + queue_index++; + } + queue_index = 0; + } + + //! @return true if physical device is valid + [[nodiscard]] bool alive() const { return m_physical_device; } + + //! @return queue family indices for graphics, compute, and transfer + //! operations + [[nodiscard]] queue_indices family_indices() const { + return m_queue_family_indices; + } + + //! @return the presentation index for the presentation queue + uint32_t queue_present_index(const VkSurfaceKHR& p_surface) { + uint32_t presentation_index = 0; + uint32_t compatible = false; + uint32_t i = 0; + for (const auto& queue_family : m_queue_family_properties) { + vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( + m_physical_device, i, p_surface, &compatible), + "vkGetPhysicalDeviceSurfaceSupportKHR"); + + if (compatible) { + presentation_index = i; + } + } + + return presentation_index; + } + + //! @return physical device memory requirements + [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() const { + VkPhysicalDeviceMemoryProperties physical_memory_properties; + vkGetPhysicalDeviceMemoryProperties(m_physical_device, + &physical_memory_properties); + return physical_memory_properties; + } + + operator VkPhysicalDevice() { return m_physical_device; } + + operator VkPhysicalDevice() const { return m_physical_device; } + + + private: + VkPhysicalDevice enumerate_physical_devices( + const VkInstance& p_instance, + const physical& p_physical_device_type) { + uint32_t device_count = 0; + vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); + + if (device_count == 0) { + throw std::runtime_error("device_count is zero!"); + } + + + // TODO: Turn this into map + std::vector physical_devices(device_count); + vkEnumeratePhysicalDevices( + p_instance, &device_count, physical_devices.data()); + VkPhysicalDevice physical_device = nullptr; + + for (const auto& device : physical_devices) { + VkPhysicalDeviceProperties device_properties; + vkGetPhysicalDeviceProperties(device, &device_properties); + + if (device_properties.deviceType == + static_cast(p_physical_device_type)) { + physical_device = device; + } + } + return physical_device; + } + + private: + VkPhysicalDevice m_physical_device = nullptr; + std::vector m_queue_family_properties; + queue_indices m_queue_family_indices{}; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/physical_device.hpp b/vulkan-cpp/physical_device.hpp deleted file mode 100644 index 860a9e5..0000000 --- a/vulkan-cpp/physical_device.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - - class physical_device { - public: - physical_device() = default; - - physical_device(const VkInstance& p_instance, - const physical_enumeration& p_physical_enumeration); - - //! @return true if physical device is valid - [[nodiscard]] bool alive() const { return m_physical_device; } - - //! @return queue family indices for graphics, compute, and transfer - //! operations - [[nodiscard]] queue_indices family_indices() const { - return m_queue_family_indices; - } - - //! @return the presentation index for the presentation queue - uint32_t queue_present_index(const VkSurfaceKHR& p_surface); - - //! @return physical device memory requirements - [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() - const; - - operator VkPhysicalDevice() { return m_physical_device; } - - operator VkPhysicalDevice() const { return m_physical_device; } - - private: - VkPhysicalDevice m_physical_device = nullptr; - std::vector m_queue_family_properties; - queue_indices m_queue_family_indices{}; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/pipeline.cppm b/vulkan-cpp/pipeline.cppm new file mode 100644 index 0000000..a0a1d31 --- /dev/null +++ b/vulkan-cpp/pipeline.cppm @@ -0,0 +1,377 @@ +module; + +#include +#include +#include + +export module vk:pipeline; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @param renderpass is required for a VkPipeline to know up front + * @param shader_modules is a std::span of the loaded shader + * sources for the pipeline to correspond to + * @param descriptor_layouts are the VkDescriptorSetLayout that you pass up + * front to the graphics pipeline if there are any provided + */ + struct pipeline_settings { + VkRenderPass renderpass = nullptr; + std::span shader_modules{}; + std::span vertex_attributes; + std::span vertex_bind_attributes; + std::span descriptor_layouts; + }; + + /** + * @brief pipeline represents a vulkan graphics pipeline implementation + */ + class pipeline { + public: + pipeline() = default; + + /** + * @brief constructs the graphics pipeline handle + * + * @param p_device is logical device to create the graphics pipeline handles + * @param p_info are the parameters for creating the pipelines with + */ + pipeline(const VkDevice& p_device, const pipeline_settings& p_info) : m_device(p_device) { + create(p_info); + } + + /** + * @brief explicit API for creating a VkPipeline and VkPipelineLayout + * handle + * + * Code Usage Example + * + * ```C++ + * + * vk::pipeline_settings pipeline_params = { + * .renderpass = main_renderpass // pass in VkRenderPass handle + * .shader_modules = shader_resource.handles() // sets the std::span + * .vertex_attributes = shader_resource.vertex_attributes(), + * .vertex_bind_attributes = shader_resource.vertex_bind_attributes(), + * .descriptor_layouts = layouts + * }; + * + * vk::pipeline graphics_pipeline(logical_device, pipeline_params); + * + * // or when need to invalidate, explicitly call create + * graphics_pipeline.create(pipeline_params); + * + * ``` + * + * @param p_info is the parameters required to set the graphics pipeline handles + * + * More info on vulkan's official + * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateGraphicsPipelines.html) + */ + void create(const pipeline_settings& p_info) { + std::vector pipeline_shader_stages(p_info.shader_modules.size()); + + uint32_t shader_src_index = 0; + + // 1. Load in and setup the VKShaderModule handlers for VkPipeline + for (const shader_handle& src : p_info.shader_modules) { + VkShaderStageFlags stage = static_cast(src.stage); + pipeline_shader_stages[shader_src_index] = + VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = (VkShaderStageFlagBits)stage, + .module = src.module, + .pName = "main" + }; + + shader_src_index++; + } + + // 2. Setting up the vertex attribute details for VkPipeline + std::span bind_attributes = + p_info.vertex_bind_attributes; + std::span attributes = + p_info.vertex_attributes; + + VkPipelineVertexInputStateCreateInfo vertex_input_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = + static_cast(bind_attributes.size()), + .pVertexBindingDescriptions = bind_attributes.data(), + .vertexAttributeDescriptionCount = + static_cast(attributes.size()), + .pVertexAttributeDescriptions = attributes.data() + }; + + VkPipelineInputAssemblyStateCreateInfo input_assembly = { + .sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineViewportStateCreateInfo viewport_state = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .viewportCount = 1, + .scissorCount = 1, + }; + + //! @note Rasterization + // Keep in mind: if lineWidth is zero, validation layers will occur + // because cant be zero. Must be set to 1.0f + VkPipelineRasterizationStateCreateInfo rasterizer_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = false, + .rasterizerDiscardEnable = + false, // set to true make fragmenta that are beyond near/far + // planes clamped to them as opposed to discarding them + .polygonMode = + VK_POLYGON_MODE_FILL, // if set to true then geometry never passes + // through rasterizer stage. This basically + // disables output to frame_buffer + .cullMode = VK_CULL_MODE_NONE, // determines what culling to use. + // Can also be disabled, culls + // front-face, back-face or both + .frontFace = + VK_FRONT_FACE_COUNTER_CLOCKWISE, // specifies vertex order of + // fdaces considered front-face + // or clockwise/counter-clockwise + .depthBiasEnable = false, + .depthBiasConstantFactor = 0.0f, // Optional + .depthBiasClamp = 0.0f, // Optional + .depthBiasSlopeFactor = 0.0f, // Optional + .lineWidth = 1.f + }; + + //! @note Multi-sampling + VkPipelineMultisampleStateCreateInfo multisampling_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .sampleShadingEnable = false, + // .minSampleShading = 1.0f, // Optional + // .pSampleMask = nullptr, // Optional + // .alphaToCoverageEnable = VK_FALSE, // Optional + // .alphaToOneEnable = VK_FALSE, // Optional + }; + + // Color blending Attachment -- blending color when the fragment returns + // the color + VkPipelineColorBlendAttachmentState color_blend_attachment = { + .blendEnable = true, + .srcColorBlendFactor = + VK_BLEND_FACTOR_SRC_ALPHA, // Enabled: alpha blending + .dstColorBlendFactor = + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // Enabled: alpha blending + .colorBlendOp = VK_BLEND_OP_ADD, // Enabled: alpha blending + .srcAlphaBlendFactor = + VK_BLEND_FACTOR_ONE, // Enabled: alpha blending + .dstAlphaBlendFactor = + VK_BLEND_FACTOR_ZERO, // Enabled: alpha blending + .alphaBlendOp = VK_BLEND_OP_ADD, // Enabled: alpha blending + .colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT, + }; + + VkPipelineColorBlendStateCreateInfo color_blending_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, // Optional + .attachmentCount = 1, + .pAttachments = &color_blend_attachment, + // these are optional + .blendConstants = { 0.f, 0.f, 0.f, 0.f } // optional + }; + + // Enable depth-stencil state + VkPipelineDepthStencilStateCreateInfo pipeline_deth_stencil_state_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = true, + .depthWriteEnable = true, + .depthCompareOp = VK_COMPARE_OP_LESS, + .depthBoundsTestEnable = false, + .stencilTestEnable = false, + }; + + //! @note Dynamic State + //! @note -- pipeline states needs to be baked into the pipeline state + std::array dynamic_states = { + VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = static_cast(dynamic_states.size()), + .pDynamicStates = dynamic_states.data() + }; + + VkPipelineLayoutCreateInfo pipeline_layout_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + }; + + //! This is just to double-check that the descriptor set layout is + //! valid. If the descriptor set layout is invalid, then proceed but not + //! use the descriptor set layout + // if (m_descriptor_set_layout != nullptr) { + // if (!m_descriptor_layouts.empty()) { + // pipeline_layout_ci.setLayoutCount = + // static_cast(m_descriptor_layouts.size()); + // pipeline_layout_ci.pSetLayouts = m_descriptor_layouts.data(); + // } + // else { + // // TODO: Uncomment this when adding back in descriptor sets + // // For now I will disable it to get the base working and add + // // descriptor sets back in afterwards + // pipeline_layout_ci.setLayoutCount = 0; + // pipeline_layout_ci.pSetLayouts = nullptr; + // } + pipeline_layout_ci.setLayoutCount = + static_cast(p_info.descriptor_layouts.size()); + pipeline_layout_ci.pSetLayouts = p_info.descriptor_layouts.data(); + vk_check(vkCreatePipelineLayout( + m_device, &pipeline_layout_ci, nullptr, &m_pipeline_layout), + "vkCreatePipelineLayout"); + + VkGraphicsPipelineCreateInfo graphics_pipeline_ci = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stageCount = static_cast(pipeline_shader_stages.size()), + .pStages = pipeline_shader_stages.data(), + .pVertexInputState = &vertex_input_info, + .pInputAssemblyState = &input_assembly, + .pViewportState = &viewport_state, + .pRasterizationState = &rasterizer_ci, + .pMultisampleState = &multisampling_ci, + // .pDepthStencilState = nullptr, // Optional + .pDepthStencilState = &pipeline_deth_stencil_state_ci, + .pColorBlendState = &color_blending_ci, + .pDynamicState = &dynamic_state_ci, + .layout = m_pipeline_layout, + .renderPass = p_info.renderpass, + .subpass = 0, + .basePipelineHandle = nullptr, + .basePipelineIndex = -1 + }; + + vk::vk_check( + vkCreateGraphicsPipelines( + m_device, nullptr, 1, &graphics_pipeline_ci, nullptr, &m_pipeline), + "vkCreateGraphicsPipelines"); + } + + /** + * + * @brief Once a pipeline is created can be bounded to the command + * buffer + * + * + * Code Example Usage + * + * ```C++ + * + * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_settings is specified*); + * + * // bound to current command buffer + * // in this example we set binding point to VK_PIPELINE_BIND_POINT_GRAPHICS + * graphics_pipeline.bind(current_command, + * pipeline_bind_point::graphics); + * ``` + * + * @param p_command is the current command buffer the graphics pipeline + * is bound to + * @param p_bind_point is the specified bind point graphics pipeline is + * bound to. + * + * More info on vulkan's official + * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdBindPipeline.html) + */ + void bind(const VkCommandBuffer& p_command, pipeline_bind_point p_bind_point = pipeline_bind_point::graphics) { + vkCmdBindPipeline(p_command, static_cast(p_bind_point), m_pipeline); + } + + /** + * @brief Update values of push constants + * + * Push constants let us send small amount of data with a small + * limited size to the shader + * + * Push constants only accept up to a max of 128 bytes of push constant + * data + * + * They allow for sending data to any specified shader stage (both + * vertex and fragment) that are stored within the command buffer itself + * + * Using push constants are commonly used when you have chunks of data + * that may be changed every frame. + * + * Data that may need to be updated every frame such as camera + * projection/view and model matrices. + * + * Example Code Usage: + * + * ```C++ + * + * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_settings is specified*); + * + * m_pipeline.push_constants(current, shader_stage::vertex, 0, 1, + * &global_data); + * + * ``` + * + * @param p_current current command to push constants directly to the + * shader + * @param p_stage is specifying what stage of the push constants are at + * @param p_offset is specified of the beginning of the offset to start + * from + * @param p_range is the range of bytes of the specified push constant + * data + * @param p_data is the data that is represented into bytes to push + * constants + * + * More info on vulkan's official + * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdPushConstants.html) + */ + void push_constant(const VkCommandBuffer& p_current, + shader_stage p_stage, + uint32_t p_offset, + uint32_t p_range, + const void* p_data) { + vkCmdPushConstants(p_current, m_pipeline_layout, static_cast(p_stage), p_offset, p_range, p_data); + } + + //! @return true if m_pipeline is valid, false if invalid + [[nodiscard]] bool alive() const { return m_pipeline; } + + //! @return VkPipelineLayout that has been created with the vk::pipeline + //! handle + [[nodiscard]] VkPipelineLayout layout() const { + return m_pipeline_layout; + } + + //! @brief explicit cleanup performed on vk::pipeline + void destroy() { + if (m_pipeline_layout != nullptr) { + vkDestroyPipelineLayout(m_device, m_pipeline_layout, nullptr); + } + if (m_pipeline != nullptr) { + vkDestroyPipeline(m_device, m_pipeline, nullptr); + } + } + + //! @brief allows for treating vk::pipeline as a VkPipeline handle for + //! simple use + operator VkPipeline() const { return m_pipeline; } + + operator VkPipeline() { return m_pipeline; } + + private: + VkDevice m_device = nullptr; + VkPipelineLayout m_pipeline_layout; + VkPipeline m_pipeline = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/pipeline.hpp b/vulkan-cpp/pipeline.hpp deleted file mode 100644 index ab40aee..0000000 --- a/vulkan-cpp/pipeline.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - /** - * @param renderpass is required for a VkPipeline to know up front - * @param shader_modules is a std::span of the loaded shader - * sources for the pipeline to correspond to - * @param descriptor_layouts are the VkDescriptorSetLayout that you pass up - * front to the graphics pipeline if there are any provided - */ - struct pipeline_settings { - VkRenderPass renderpass = nullptr; - std::span shader_modules{}; - std::span vertex_attributes; - std::span vertex_bind_attributes; - std::span descriptor_layouts; - }; - - /** - * @brief pipeline represents a vulkan graphics pipeline implementation - */ - class pipeline { - public: - pipeline() = default; - - /** - * @brief constructs the graphics pipeline handle - * - * @param p_device is logical device to create the graphics pipeline handles - * @param p_info are the parameters for creating the pipelines with - */ - pipeline(const VkDevice& p_device, const pipeline_settings& p_info); - - /** - * @brief explicit API for creating a VkPipeline and VkPipelineLayout - * handle - * - * Code Usage Example - * - * ```C++ - * - * vk::pipeline_settings pipeline_params = { - * .renderpass = main_renderpass // pass in VkRenderPass handle - * .shader_modules = shader_resource.handles() // sets the std::span - * .vertex_attributes = shader_resource.vertex_attributes(), - * .vertex_bind_attributes = shader_resource.vertex_bind_attributes(), - * .descriptor_layouts = layouts - * }; - * - * vk::pipeline graphics_pipeline(logical_device, pipeline_params); - * - * // or when need to invalidate, explicitly call create - * graphics_pipeline.create(pipeline_params); - * - * ``` - * - * @param p_info is the parameters required to set the graphics pipeline handles - * - * More info on vulkan's official - * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateGraphicsPipelines.html) - */ - void create(const pipeline_settings& p_info); - - /** - * - * @brief Once a pipeline is created can be bounded to the command - * buffer - * - * - * Code Example Usage - * - * ```C++ - * - * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_settings is specified*); - * - * // bound to current command buffer - * // in this example we set binding point to VK_PIPELINE_BIND_POINT_GRAPHICS - * graphics_pipeline.bind(current_command, - * pipeline_bind_point::graphics); - * ``` - * - * @param p_command is the current command buffer the graphics pipeline - * is bound to - * @param p_bind_point is the specified bind point graphics pipeline is - * bound to. - * - * More info on vulkan's official - * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdBindPipeline.html) - */ - void bind( - const VkCommandBuffer& p_command, - pipeline_bind_point p_bind_point = pipeline_bind_point::graphics); - - /** - * @brief Update values of push constants - * - * Push constants let us send small amount of data with a small - * limited size to the shader - * - * Push constants only accept up to a max of 128 bytes of push constant - * data - * - * They allow for sending data to any specified shader stage (both - * vertex and fragment) that are stored within the command buffer itself - * - * Using push constants are commonly used when you have chunks of data - * that may be changed every frame. - * - * Data that may need to be updated every frame such as camera - * projection/view and model matrices. - * - * Example Code Usage: - * - * ```C++ - * - * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_settings is specified*); - * - * m_pipeline.push_constants(current, shader_stage::vertex, 0, 1, - * &global_data); - * - * ``` - * - * @param p_current current command to push constants directly to the - * shader - * @param p_stage is specifying what stage of the push constants are at - * @param p_offset is specified of the beginning of the offset to start - * from - * @param p_range is the range of bytes of the specified push constant - * data - * @param p_data is the data that is represented into bytes to push - * constants - * - * More info on vulkan's official - * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdPushConstants.html) - */ - void push_constant(const VkCommandBuffer& p_current, - shader_stage p_stage, - uint32_t p_offset, - uint32_t p_range, - const void* p_data); - - //! @return true if m_pipeline is valid, false if invalid - [[nodiscard]] bool alive() const { return m_pipeline; } - - //! @return VkPipelineLayout that has been created with the vk::pipeline - //! handle - [[nodiscard]] VkPipelineLayout layout() const { - return m_pipeline_layout; - } - - //! @brief explicit cleanup performed on vk::pipeline - void destroy(); - - //! @brief allows for treating vk::pipeline as a VkPipeline handle for - //! simple use - operator VkPipeline() const { return m_pipeline; } - - operator VkPipeline() { return m_pipeline; } - - private: - VkDevice m_device = nullptr; - VkPipelineLayout m_pipeline_layout; - VkPipeline m_pipeline = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/renderpass.cppm b/vulkan-cpp/renderpass.cppm new file mode 100644 index 0000000..f9ec230 --- /dev/null +++ b/vulkan-cpp/renderpass.cppm @@ -0,0 +1,224 @@ +module; + +#include +#include +#include +#include + +export module vk:renderpass; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * @name renderpass + * + * @param p_device is the logical device to associate the creation of + * renderpasses + * @param p_renderpass_attachment is a vk::attachment to specify the + * individual attachment operation that handle in creating + * VkAttachmentDescription, VkAttachmentReference, and VkSubpassDescription + * + * @param p_enable_subpass because subpasses are optional, this is a boolean + * to enable if we want to apply subpasses + */ + class renderpass { + public: + renderpass() = default; + renderpass(const VkDevice& p_device, + std::span p_renderpass_attachments, + bool p_enable_subpasses = true) : m_device(p_device) { + create(p_renderpass_attachments, p_enable_subpasses); + } + + void create(std::span p_renderpass_attachments, bool p_enable_subpasses = true) { + // 1. Specifically for setting up the attachment description + std::vector attachment_description( + p_renderpass_attachments.size()); + + // color attachment reference slots to set to help the + // VkAttachmentReference know which color attachment they correspond to + std::vector color_attachment_indices; + + // depth attachment reference slots to set to help the + // VkAttachmentReference know which depth attachment they correspond to + std::vector depth_attachment_indices; + + for (size_t i = 0; i < attachment_description.size(); i++) { + attachment attachment_spec = p_renderpass_attachments[i]; + attachment_description[i] = { + .flags = 0, + .format = attachment_spec.format, + // .samples = VK_SAMPLE_COUNT_1_BIT, + .samples = static_cast(attachment_spec.samples), + // .loadOp = to_attachment_load(attachment_spec.load), + .loadOp = static_cast(attachment_spec.load), + // .storeOp = to_attachment_store(attachment_spec.store), + .storeOp = static_cast(attachment_spec.store), + .stencilLoadOp = + static_cast(attachment_spec.stencil_load), + .stencilStoreOp = + static_cast(attachment_spec.stencil_store), + .initialLayout = static_cast(attachment_spec.initial_layout), + .finalLayout = static_cast(attachment_spec.final_layout) + }; + + // I do a check here to save the slots for specifying the + // VkAttachmentReference Since .attachment is the slot index for + // corresponding which attachment layout is to which + if (has_depth_specified(attachment_spec.layout)) { + depth_attachment_indices.emplace_back(i); + } + else { + color_attachment_indices.emplace_back(i); + } + } + + // 2. Setting up the color attachment reference to specifying specific + // attachments they correspond to (using the indices) + std::vector color_attachment_references( + color_attachment_indices.size()); + + for (size_t i = 0; i < color_attachment_indices.size(); i++) { + uint32_t slot = color_attachment_indices[i]; + color_attachment_references[i] = { + .attachment = slot, + // .layout = to_image_layout(p_renderpass_attachments[slot].layout) + .layout = static_cast(p_renderpass_attachments[slot].layout) + }; + } + + // 3. Setting up the depth attachment reference to specifying specific + // attachments they correspond to (using the indices) + std::vector depth_attachment_references( + depth_attachment_indices.size()); + for (size_t i = 0; i < depth_attachment_indices.size(); i++) { + uint32_t slot = depth_attachment_indices[i]; + depth_attachment_references[i] = { + .attachment = slot, + // .layout = to_image_layout(p_renderpass_attachments[slot].layout) + .layout = static_cast(p_renderpass_attachments[slot].layout) + }; + } + + // 4. Setting up subpass descriptions that may/may not be applied to + // this renderpass based on the p_enable_subpass is set to true + // TODO: VkSubpassDescription is deprecated in vulkan 1.2+, we should + // change to VkSubpassDescription2 + // TODO: Change from VkRenderPassCreateInfo to VkRenderPassCreateInfo2 + // since they have different parameter modifications + VkSubpassDescription subpass_description = { + .flags = 0, + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .pInputAttachments = nullptr, + .colorAttachmentCount = + static_cast(color_attachment_references.size()), + .pColorAttachments = color_attachment_references.data(), + .pResolveAttachments = nullptr, + .pDepthStencilAttachment = depth_attachment_references.data(), + .preserveAttachmentCount = 0, + .pPreserveAttachments = nullptr + }; + + std::array subpasses; + + if (p_enable_subpasses) { + subpasses = { subpass_description }; + } + + VkRenderPassCreateInfo renderpass_ci = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .attachmentCount = + static_cast(attachment_description.size()), + .pAttachments = attachment_description.data(), + .subpassCount = static_cast(subpasses.size()), + .pSubpasses = subpasses.data(), + .dependencyCount = 0, + .pDependencies = nullptr + }; + + vk_check( + vkCreateRenderPass(m_device, &renderpass_ci, nullptr, &m_renderpass), + "vkCreateRenderPass"); + } + + [[nodiscard]] bool alive() const { return m_renderpass; } + + void begin(const renderpass_begin_params& p_begin_info) { + // TODO: Move VkViewport and VkScissor to vk::swapchain since these are + // information more closely set by the swapchain + VkViewport viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(p_begin_info.extent.width), + .height = static_cast(p_begin_info.extent.height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + + vkCmdSetViewport(p_begin_info.current_command, 0, 1, &viewport); + + VkRect2D scissor = { + .offset = { 0, 0 }, + .extent = { p_begin_info.extent.width, p_begin_info.extent.height }, + }; + + vkCmdSetScissor(p_begin_info.current_command, 0, 1, &scissor); + + // setting color for this specific renderpass + VkClearColorValue renderpass_color = { { p_begin_info.color.at(0), + p_begin_info.color.at(1), + p_begin_info.color.at(2), + p_begin_info.color.at(3) } }; + std::array clear_values = {}; + + clear_values[0].color = renderpass_color; + clear_values[1].depthStencil = { 1.f, 0 }; + + VkRenderPassBeginInfo renderpass_begin_params = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .pNext = nullptr, + .renderPass = m_renderpass, + .framebuffer = p_begin_info.current_framebuffer, + .renderArea = { + .offset = { + .x = 0, + .y = 0 + }, + .extent = { + .width = p_begin_info.extent.width, + .height = p_begin_info.extent.height + }, + }, + .clearValueCount = static_cast(clear_values.size()), + .pClearValues = clear_values.data(), + }; + + vkCmdBeginRenderPass(p_begin_info.current_command, + &renderpass_begin_params, + static_cast(p_begin_info.subpass)); + } + + void end(const VkCommandBuffer& p_current) { + vkCmdEndRenderPass(p_current); + } + + void destroy() { + vkDestroyRenderPass(m_device, m_renderpass, nullptr); + } + + operator VkRenderPass() const { return m_renderpass; } + + operator VkRenderPass() { return m_renderpass; } + + private: + VkDevice m_device = nullptr; + VkRenderPass m_renderpass = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/renderpass.hpp b/vulkan-cpp/renderpass.hpp deleted file mode 100644 index 45ec039..0000000 --- a/vulkan-cpp/renderpass.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - /** - * @name renderpass - * - * @param p_device is the logical device to associate the creation of - * renderpasses - * @param p_renderpass_attachment is a vk::attachment to specify the - * individual attachment operation that handle in creating - * VkAttachmentDescription, VkAttachmentReference, and VkSubpassDescription - * - * @param p_enable_subpass because subpasses are optional, this is a boolean - * to enable if we want to apply subpasses - */ - - class renderpass { - public: - renderpass() = default; - renderpass(const VkDevice& p_device, - std::span p_renderpass_attachments, - bool p_enable_subpasses = true); - - void create(std::span p_renderpass_attachments, - bool p_enable_subpass = true); - - [[nodiscard]] bool alive() const { return m_renderpass; } - - void begin(const renderpass_begin_params& p_begin_info); - - void end(const VkCommandBuffer& p_current); - - void destroy(); - - operator VkRenderPass() const { return m_renderpass; } - - operator VkRenderPass() { return m_renderpass; } - - private: - VkDevice m_device = nullptr; - VkRenderPass m_renderpass = nullptr; - }; - -}; \ No newline at end of file diff --git a/vulkan-cpp/sample_image.cppm b/vulkan-cpp/sample_image.cppm new file mode 100644 index 0000000..41b833f --- /dev/null +++ b/vulkan-cpp/sample_image.cppm @@ -0,0 +1,571 @@ +module; + +#include +#include +#include + +export module vk:sample_image; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + /** + * We shift 32-bits to the high 32-bits for the old layout and OR the new layout lsb 32-bits additional to the shifted 32-bits + * + * This is to ensure the image layouts do not overlap and can be used to directly jump to set specific image loyouts rather then doing an if-statement originally to check for that + */ + constexpr uint64_t image_layout(VkImageLayout p_old, VkImageLayout p_new) { + // Shift the old_layout into the high 32 bits, and combine with new_layout in the low 32 bits. + return (static_cast(p_old) << 32) | static_cast(p_new); + } + class sample_image { + public: + sample_image() = default; + sample_image(const VkDevice& p_device, + const image_params& p_image_properties) : m_device(p_device) { + // 1. creating VkImage handle + VkImageCreateInfo image_ci = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .pNext = nullptr, + .flags = p_image_properties.image_flags, + .imageType = VK_IMAGE_TYPE_2D, + .format = p_image_properties.format, + .extent = { .width = p_image_properties.extent.width, + .height = p_image_properties.extent.height, + .depth = 1 }, + .mipLevels = p_image_properties.mip_levels, + .arrayLayers = p_image_properties.array_layers, + .samples = VK_SAMPLE_COUNT_1_BIT, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .usage = static_cast(p_image_properties.usage), + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .queueFamilyIndexCount = 0, + .pQueueFamilyIndices = nullptr, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED + }; + + vk_check(vkCreateImage(p_device, &image_ci, nullptr, &m_image), + "vkCreateImage"); + + // 2. get image memory requirements from physical device + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements(p_device, m_image, &memory_requirements); + // uint32_t memory_type_index = + // vk::image_memory_requirements(p_image_properties.physical_device, + // p_device, m_image); + uint32_t memory_index = select_memory_requirements( + p_image_properties.phsyical_memory_properties, + memory_requirements, + p_image_properties.property); + + // 4. Allocate info + VkMemoryAllocateInfo memory_alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = nullptr, + .allocationSize = memory_requirements.size, + .memoryTypeIndex = memory_index + }; + + vk_check(vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); + + // 5. bind image memory + vk_check(vkBindImageMemory(p_device, m_image, m_device_memory, 0), + "vkBindImageMemory"); + + // Needs to create VkImageView after VkImage + // because VkImageView expects a VkImage to be binded to a singl + // VkDeviceMemory beforehand + VkImageViewCreateInfo image_view_ci = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .image = m_image, + // .viewType = VK_IMAGE_VIEW_TYPE_2D, + .viewType = p_image_properties.view_type, + .format = p_image_properties.format, + .components = { .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY }, + .subresourceRange = { .aspectMask = static_cast( + p_image_properties.aspect), + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = + p_image_properties.layer_count }, + }; + + vk_check( + vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), + "vkCreateImage"); + + // Create VkSampler handler + VkSamplerCreateInfo sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .magFilter = p_image_properties.range.min, + .minFilter = p_image_properties.range.max, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = static_cast(p_image_properties.addrses_mode_u), + .addressModeV = static_cast(p_image_properties.addrses_mode_v), + .addressModeW = static_cast(p_image_properties.addrses_mode_w), + .mipLodBias = 0.0f, + .anisotropyEnable = false, + .maxAnisotropy = 1, + .compareEnable = false, + .compareOp = VK_COMPARE_OP_ALWAYS, + .minLod = 0.0f, + .maxLod = 0.0f, + .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, + .unnormalizedCoordinates = false + }; + + vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + "vkCreateSampler"); + } + + sample_image(const VkDevice& p_device, + const VkImage& p_image, + const image_params& p_image_properties) + : m_device(p_device), + m_image(p_image) { + // Needs to create VkImageView after VkImage + // because VkImageView expects a VkImage to be binded to a singl + // VkDeviceMemory beforehand + VkImageViewCreateInfo image_view_ci = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .image = m_image, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = p_image_properties.format, + .components = { .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY }, + .subresourceRange = { .aspectMask = static_cast( + p_image_properties.aspect), + .baseMipLevel = 0, + .levelCount = p_image_properties.mip_levels, + .baseArrayLayer = 0, + .layerCount = + p_image_properties.layer_count }, + }; + + vk_check( + vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), + "vkCreateImage"); + + // Create VkSampler handler + VkSamplerCreateInfo sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .magFilter = p_image_properties.range.min, + .minFilter = p_image_properties.range.max, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = static_cast(p_image_properties.addrses_mode_u), + .addressModeV = static_cast(p_image_properties.addrses_mode_v), + .addressModeW = static_cast(p_image_properties.addrses_mode_w), + .mipLodBias = 0.0f, + .anisotropyEnable = false, + .maxAnisotropy = 1, + .compareEnable = false, + .compareOp = VK_COMPARE_OP_ALWAYS, + .minLod = 0.0f, + .maxLod = 0.0f, + .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, + .unnormalizedCoordinates = false + }; + + vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + "vkCreateSampler"); + + m_only_destroy_image_view = true; + } + + [[nodiscard]] VkSampler sampler() const { return m_sampler; } + + [[nodiscard]] VkImageView image_view() const { return m_image_view; } + + + /** + * @brief performs vkCmdPipelineBarrier to handle transitioning image layouts + * + * @param p_command is the current command buffer to record the image layout transition + * @param p_format is the image format to make sure if there is a depth format available then request the aspect mask to include the stencil bit + * @param p_old is the source image layout transition from + * @param p_new is the destination image layout transition to. + * + * + * ```C++ + * + * sample_image texture_image(logical_device, ...); + * + * + * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + * + * // do some operation during this transition image layout + * // such as copying from an buffer data to an image + * // staging_buffer.copy_to_image(...); + * + * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + * + * ``` + * + */ + void memory_barrier(const VkCommandBuffer& p_command, VkFormat p_format, VkImageLayout p_old, VkImageLayout p_new) { + /* + VkImageMemoryBarrier image_memory_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = 0, + .dstAccessMask = 0, + .oldLayout = p_old, + .newLayout = p_new, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = m_image, + .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1 } + }; + + VkPipelineStageFlags source_stage; + VkPipelineStageFlags dst_stages; + + if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || + (p_format == VK_FORMAT_D16_UNORM) || + (p_format == VK_FORMAT_X8_D24_UNORM_PACK32) || + (p_format == VK_FORMAT_D32_SFLOAT) || + (p_format == VK_FORMAT_S8_UINT) || + (p_format == VK_FORMAT_D16_UNORM_S8_UINT) || + (p_format == VK_FORMAT_D24_UNORM_S8_UINT)) { + image_memory_barrier.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_DEPTH_BIT; + + if (has_stencil_attachment(p_format)) { + image_memory_barrier.subresourceRange.aspectMask |= + VK_IMAGE_ASPECT_STENCIL_BIT; + } + } + else { + image_memory_barrier.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; + } + + if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && + p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && + p_new == VK_IMAGE_LAYOUT_GENERAL) { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + + if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && + p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + } // Convert back from read-only to updateable + else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + } // Convert from updateable texture to shader read-only + else if (p_old == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } // Convert depth texture from undefined state to depth-stencil buffer + else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && + p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + } // Wait for render pass to complete + else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + image_memory_barrier.srcAccessMask = + 0; // VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = 0; + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } // Convert back from read-only to color attachment + else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + } // Convert from updateable texture to shader read-only + else if (p_old == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + image_memory_barrier.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } // Convert back from read-only to depth attachment + else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + } // Convert from updateable depth texture to shader read-only + else if (p_old == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && + p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + image_memory_barrier.srcAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } + + vkCmdPipelineBarrier(p_command, + source_stage, + dst_stages, + 0, + 0, + nullptr, + 0, + nullptr, + 1, + &image_memory_barrier); + */ + // 1. Image Memory Barrier Initialization (using C++ Designated Initializers - C++20) + VkImageMemoryBarrier image_memory_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .pNext = nullptr, + .srcAccessMask = 0, + .dstAccessMask = 0, + .oldLayout = p_old, + .newLayout = p_new, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = m_image, + .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1 } + }; + + VkPipelineStageFlags source_stage = VK_PIPELINE_STAGE_NONE; + VkPipelineStageFlags dst_stages = VK_PIPELINE_STAGE_NONE; + + // 2. Aspect Mask Logic (Keep as if/else, but use helper function) + if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || has_stencil_attachment(p_format)) { + + image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + + // Assuming has_stencil_attachment(p_format) is defined elsewhere + // works as the same as the if-statement, leaving it here for testing purposes + // image_memory_barrier.subresourceRange.aspectMask |= has_stencil_attachment(p_format) ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; + if (has_stencil_attachment(p_format)) { + image_memory_barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } + else { + image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + + // 3. Main Transition Logic using Combined Switch + const uint64_t current_layout = image_layout(p_old, p_new); + + switch (current_layout) { + + // UNDEFINED -> SHADER_READ_ONLY_OPTIMAL + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + // UNDEFINED -> GENERAL + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL): { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + // UNDEFINED -> TRANSFER_DST_OPTIMAL + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + } + + // SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL (Convert back from read-only to transferr) + case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + break; + } + + // TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable texture to shader read-only) + case image_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + // UNDEFINED -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert depth texture from undefined state) + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dst_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + break; + } + + // SHADER_READ_ONLY_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Wait for render pass to complete - Note: This case is unusual but kept as per your original logic) + case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + // Note: Your original code had conflicting re-assignments for source_stage/dst_stages here. + // The last pair of assignments is used. + image_memory_barrier.srcAccessMask = 0; + image_memory_barrier.dstAccessMask = 0; + source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + // SHADER_READ_ONLY_OPTIMAL -> COLOR_ATTACHMENT_OPTIMAL (Convert back from read-only to color attachment) + case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + break; + } + + // COLOR_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable color to shader read-only) + case image_layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + // SHADER_READ_ONLY_OPTIMAL -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert back from read-only to depth attachment) + case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + break; + } + + // DEPTH_STENCIL_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable depth texture to shader read-only) + case image_layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + break; + } + + default: { + // Unhandled Transition + break; + } + } + + vkCmdPipelineBarrier( + p_command, + source_stage, + dst_stages, + 0, // dependencyFlags + 0, nullptr, + 0, nullptr, + 1, &image_memory_barrier); + } + + void destroy() { + if (m_image_view != nullptr) { + vkDestroyImageView(m_device, m_image_view, nullptr); + } + + // Boolean check is to make sure we might only want + // to destroy vk::sample_image resources. + + // Example of this is the swapchain may pass in + // its images and we should only destruct the VkImageView + // and not the swapchain's images directly + if (m_image != nullptr and !m_only_destroy_image_view) { + vkDestroyImage(m_device, m_image, nullptr); + } + + if (m_sampler != nullptr) { + vkDestroySampler(m_device, m_sampler, nullptr); + } + + if (m_device_memory != nullptr) { + vkFreeMemory(m_device, m_device_memory, nullptr); + } + } + + operator VkImage() const { return m_image; } + + operator VkImage() { return m_image; } + + private: + bool m_only_destroy_image_view = false; + VkDevice m_device = nullptr; + VkImage m_image = nullptr; + VkImageView m_image_view = nullptr; + VkSampler m_sampler = nullptr; + VkDeviceMemory m_device_memory = nullptr; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/sample_image.hpp b/vulkan-cpp/sample_image.hpp deleted file mode 100644 index c19cd7c..0000000 --- a/vulkan-cpp/sample_image.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - class sample_image { - public: - sample_image() = default; - sample_image(const VkDevice& p_device, - const image_params& p_image_properties); - sample_image(const VkDevice& p_device, - const VkImage& p_image, - const image_params& p_image_properties); - - [[nodiscard]] VkSampler sampler() const { return m_sampler; } - - [[nodiscard]] VkImageView image_view() const { return m_image_view; } - - - /** - * @brief performs vkCmdPipelineBarrier to handle transitioning image layouts - * - * @param p_command is the current command buffer to record the image layout transition - * @param p_format is the image format to make sure if there is a depth format available then request the aspect mask to include the stencil bit - * @param p_old is the source image layout transition from - * @param p_new is the destination image layout transition to. - * - * - * ```C++ - * - * sample_image texture_image(logical_device, ...); - * - * - * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - * - * // do some operation during this transition image layout - * // such as copying from an buffer data to an image - * // staging_buffer.copy_to_image(...); - * - * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - * - * ``` - * - */ - void memory_barrier(const VkCommandBuffer& p_command, VkFormat p_format, VkImageLayout p_old, VkImageLayout p_new); - - void destroy(); - - operator VkImage() const { return m_image; } - - operator VkImage() { return m_image; } - - private: - - private: - bool m_only_destroy_image_view = false; - VkDevice m_device = nullptr; - VkImage m_image = nullptr; - VkImageView m_image_view = nullptr; - VkSampler m_sampler = nullptr; - VkDeviceMemory m_device_memory = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/shader_resource.cppm b/vulkan-cpp/shader_resource.cppm new file mode 100644 index 0000000..fe3a2d3 --- /dev/null +++ b/vulkan-cpp/shader_resource.cppm @@ -0,0 +1,170 @@ +module; + +#include +#include +#include +#include +#include + +export module vk:shader_resource; + +export import :types; +export import :utilities; + +export namespace vk { + inline namespace v1 { + + /** + * @param sources holds data the shader source and stage the source it + * corresponds to. + * @param vertex_attributes are the vertex attributes that are used to setup + * vulkan vertex attributes and the binding attributes. + */ + struct shader_resource_info { + std::span sources{}; + std::span vertex_attributes{}; + }; + + /** + * @brief shader_resource acts as a unit of shader sources that a vulkan + * graphics pipeline will associate with + * + * Every graphics pipeline as an associated group of shader sources with + * their own specific shader stages they are apart of. + * + * @param p_device is the logical device for creating the vulkan handlers + * @param p_info is the shader_resource properties for providing shader + * sources to load and what vertex attributes to return from this shader + * resource + * + */ + class shader_resource { + public: + shader_resource() = default; + shader_resource(const VkDevice& p_device, const shader_resource_info& p_info) : m_device(p_device) { + m_shader_module_handlers.resize(p_info.sources.size()); + + for (size_t i = 0; i < p_info.sources.size(); i++) { + const shader_source shader_src = p_info.sources[i]; + std::vector blob = compile_binary_shader_source(shader_src); + + if (blob.empty()) { + m_is_resource_valid = false; + return; + } + + std::span binary(blob.begin(), blob.end()); + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = static_cast(binary.size_bytes()), + .pCode = (const uint32_t*)binary.data() + }; + + // Setting m_shader_module_handlers[i]'s stage and the + // VkShaderModule handle altogether + vk_check(vkCreateShaderModule(m_device, + &shader_module_ci, + nullptr, + &m_shader_module_handlers[i].module), + "vkCreateShaderModule"); + m_shader_module_handlers[i].stage = shader_src.stage; + } + + m_is_resource_valid = true; + } + + [[nodiscard]] bool is_valid() const { return m_is_resource_valid; } + + void vertex_attributes(std::span p_attributes) { + m_vertex_binding_attributes.resize(p_attributes.size()); + + for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { + // setting up vertex binding + const vertex_attribute attribute = p_attributes[i]; + m_vertex_attributes.resize(attribute.entries.size()); + m_vertex_binding_attributes[i] = { + .binding = attribute.binding, + .stride = attribute.stride, + .inputRate = to_input_rate(attribute.input_rate), + }; + + // then setting up the vertex attributes for the vertex data layouts + for (size_t j = 0; j < attribute.entries.size(); j++) { + const vertex_attribute_entry entry = attribute.entries[j]; + m_vertex_attributes[j] = { + .location = entry.location, + .binding = attribute.binding, + .format = static_cast(entry.format), + .offset = entry.stride, + }; + } + } + } + + //! @return the handlers of vulkan shader modules for each individual + //! shader source loaded altogether + [[nodiscard]] std::span handles() const { + return m_shader_module_handlers; + } + + //! @return vulkan data spec for vertex attributes + [[nodiscard]] std::span + vertex_attributes() const { + return m_vertex_attributes; + } + + //! @return vulkan data spec for vertex binding attributes + [[nodiscard]] std::span + vertex_bind_attributes() const { + return m_vertex_binding_attributes; + } + + //! @brief used for explicit cleanup for this resource + void destroy() { + for (auto& handle : m_shader_module_handlers) { + if (handle.module != nullptr) { + vkDestroyShaderModule(m_device, handle.module, nullptr); + } + } + } + + private: + // Reading the raw .spv binaries + std::vector read(const std::string& p_file) { + std::vector out_buffer; + std::ifstream ins(p_file, std::ios::ate | std::ios::binary); + + if (!ins) { + return {}; + } + + uint32_t file_size = (uint32_t)ins.tellg(); + out_buffer.resize(file_size); + ins.seekg(0); + ins.read(out_buffer.data(), file_size); + return out_buffer; + } + + //! @brief Ensure file reads are valid before reading raw .spv binaries + std::vector compile_binary_shader_source( + const shader_source& p_shader_source) { + std::vector binary_blob{}; + + if (std::filesystem::is_regular_file(p_shader_source.filename)) { + binary_blob = read(p_shader_source.filename); + } + + return binary_blob; + } + + private: + VkDevice m_device = nullptr; + bool m_is_resource_valid = false; + std::vector m_vertex_attributes; + std::vector + m_vertex_binding_attributes; + std::vector m_shader_module_handlers; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/shader_resource.hpp b/vulkan-cpp/shader_resource.hpp deleted file mode 100644 index 94d017e..0000000 --- a/vulkan-cpp/shader_resource.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @param sources holds data the shader source and stage the source it - * corresponds to. - * @param vertex_attributes are the vertex attributes that are used to setup - * vulkan vertex attributes and the binding attributes. - */ - struct shader_resource_info { - std::span sources{}; - std::span vertex_attributes{}; - }; - - /** - * @brief shader_resource acts as a unit of shader sources that a vulkan - * graphics pipeline will associate with - * - * Every graphics pipeline as an associated group of shader sources with - * their own specific shader stages they are apart of. - * - * @param p_device is the logical device for creating the vulkan handlers - * @param p_info is the shader_resource properties for providing shader - * sources to load and what vertex attributes to return from this shader - * resource - * - */ - class shader_resource { - public: - shader_resource() = default; - shader_resource(const VkDevice& p_device, - const shader_resource_info& p_info); - - [[nodiscard]] bool is_valid() const { return m_is_resource_valid; } - - void vertex_attributes(std::span p_attributes); - - //! @return the handlers of vulkan shader modules for each individual - //! shader source loaded altogether - [[nodiscard]] std::span handles() const { - return m_shader_module_handlers; - } - - //! @return vulkan data spec for vertex attributes - [[nodiscard]] std::span - vertex_attributes() const { - return m_vertex_attributes; - } - - //! @return vulkan data spec for vertex binding attributes - [[nodiscard]] std::span - vertex_bind_attributes() const { - return m_vertex_binding_attributes; - } - - //! @brief used for explicit cleanup for this resource - void destroy(); - - private: - VkDevice m_device = nullptr; - bool m_is_resource_valid = false; - std::vector m_vertex_attributes; - std::vector - m_vertex_binding_attributes; - std::vector m_shader_module_handlers; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/skybox_texture.hpp b/vulkan-cpp/skybox_texture.hpp deleted file mode 100644 index 296d7c5..0000000 --- a/vulkan-cpp/skybox_texture.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace vk { - struct skybox_texture_info { - VkPhysicalDevice physical_handle=nullptr; - const std::array& faces; - }; - class skybox_texture { - public: - skybox_texture(const VkDevice& p_device, const skybox_texture_info& p_config); - - [[nodiscard]] bool loaded() const { return m_is_loaded; } - - void destroy(); - - private: - VkDevice m_device=nullptr; - bool m_is_loaded=false; - - std::array m_cubemap_images{}; - int m_width=0; - int m_height=0; - sample_image m_skybox_image; - // sample_image m_cube_image; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/surface.cppm b/vulkan-cpp/surface.cppm new file mode 100644 index 0000000..ad55854 --- /dev/null +++ b/vulkan-cpp/surface.cppm @@ -0,0 +1,49 @@ +module; + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + +export module vk:surface; + + +export import :types; +export import :utilities; +export import :instance; + +export namespace vk { + inline namespace v1 { + + class surface { + public: + surface(const VkInstance& p_instance, GLFWwindow* p_window_handle) : m_instance(p_instance) { + vk_check(glfwCreateWindowSurface( m_instance, p_window_handle, nullptr, &m_surface_handler), "glfwCreateWindowSurface"); + } + + [[nodiscard]] bool alive() const { return m_surface_handler; } + + void destroy() { + if (m_surface_handler != nullptr) { + vkDestroySurfaceKHR(m_instance, m_surface_handler, nullptr); + } + vkDestroyInstance(m_instance, nullptr); + } + + operator VkSurfaceKHR() const { return m_surface_handler; } + operator VkSurfaceKHR() { return m_surface_handler; } + + private: + VkInstance m_instance = nullptr; + VkSurfaceKHR m_surface_handler = nullptr; + }; + + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/surface.hpp b/vulkan-cpp/surface.hpp deleted file mode 100644 index a968c66..0000000 --- a/vulkan-cpp/surface.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include -#include - -namespace vk { - - class surface { - public: - surface(const VkInstance& p_device, GLFWwindow* p_window_handle); - - [[nodiscard]] bool alive() const { return m_surface_handler; } - - void destroy(); - - operator VkSurfaceKHR() const { return m_surface_handler; } - operator VkSurfaceKHR() { return m_surface_handler; } - - private: - VkInstance m_instance = nullptr; - VkSurfaceKHR m_surface_handler = nullptr; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/swapchain.cppm b/vulkan-cpp/swapchain.cppm new file mode 100644 index 0000000..c919944 --- /dev/null +++ b/vulkan-cpp/swapchain.cppm @@ -0,0 +1,100 @@ +module; + +#include +#include +#include +#include + +export module vk:swapchain; + +export import :types; +export import :utilities; +export import :device_queue; + +export namespace vk { + inline namespace v1 { + class swapchain { + public: + swapchain(const VkDevice& p_device, + const VkSurfaceKHR& p_surface, + const swapchain_params& p_settings, + const surface_params& p_surface_properties) : m_device(p_device), m_surface_handler(p_surface), m_surface_params(p_surface_properties) { + m_image_size = surface_image_size(m_surface_params.capabilities); + + std::println("Surface Image Size = {}", m_image_size); + + create(p_settings); + } + + void create(const swapchain_params& p_settings) { + VkSwapchainCreateInfoKHR swapchain_ci = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .surface = m_surface_handler, + .minImageCount = m_image_size, + .imageFormat = m_surface_params.format.format, + .imageColorSpace = m_surface_params.format.colorSpace, + // use physical device surface formats to getting the right formats + // in vulkan + .imageExtent = m_surface_params.capabilities.currentExtent, + .imageArrayLayers = 1, + .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT), + .queueFamilyIndexCount = 1, + .pQueueFamilyIndices = &p_settings.present_index, + .preTransform = m_surface_params.capabilities.currentTransform, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR, + .clipped = true + }; + + vk_check(vkCreateSwapchainKHR( + m_device, &swapchain_ci, nullptr, &m_swapchain_handler), + "vkCreateSwapchainKHR"); + } + + + /** + * @brief gets the presentable images from this associated swapchain + * + * @return std::span which are the presentable available images that can be presented to the swapchain + * + * ```C++ + * + * vk::swapchain main_swapchain(logical_device, ...); + * + * std::span images = main_swapchain.enumerate_images(); + * + * ``` + * + */ + std::span presentable_images() { + uint32_t image_count=0; + vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, nullptr); + + m_images.resize(image_count); + vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, m_images.data()); + + return m_images; + } + + void destroy() { + vkDestroySwapchainKHR(m_device, m_swapchain_handler, nullptr); + } + + operator VkSwapchainKHR() const { return m_swapchain_handler; } + + operator VkSwapchainKHR() { return m_swapchain_handler; } + + private: + VkDevice m_device = nullptr; + VkSwapchainKHR m_swapchain_handler = nullptr; + VkSurfaceKHR m_surface_handler = nullptr; + surface_params m_surface_params{}; + uint32_t m_image_size = 0; + + device_queue m_present_queue; + + std::vector m_images; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/swapchain.hpp b/vulkan-cpp/swapchain.hpp deleted file mode 100644 index 30678c1..0000000 --- a/vulkan-cpp/swapchain.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace vk { - - class swapchain { - public: - swapchain(const VkDevice& p_device, - const VkSurfaceKHR& p_surface, - const swapchain_params& p_settings, - const surface_params& p_surface_properties); - - void create(const swapchain_params& p_settings); - - - /** - * @brief gets the presentable images from this associated swapchain - * - * @return std::span which are the presentable available images that can be presented to the swapchain - * - * ```C++ - * - * vk::swapchain main_swapchain(logical_device, ...); - * - * std::span images = main_swapchain.enumerate_images(); - * - * ``` - * - */ - std::span presentable_images(); - - void destroy(); - - operator VkSwapchainKHR() const { return m_swapchain_handler; } - - operator VkSwapchainKHR() { return m_swapchain_handler; } - - private: - VkDevice m_device = nullptr; - VkSwapchainKHR m_swapchain_handler = nullptr; - VkSurfaceKHR m_surface_handler = nullptr; - surface_params m_surface_params{}; - uint32_t m_image_size = 0; - - device_queue m_present_queue; - - std::vector m_images; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/texture.cppm b/vulkan-cpp/texture.cppm new file mode 100644 index 0000000..5bf2b1c --- /dev/null +++ b/vulkan-cpp/texture.cppm @@ -0,0 +1,251 @@ +module; + +#include +#include +#include +#include + +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +export module vk:texture; + + +export import :types; +export import :utilities; +export import :buffer_streams; +export import :sample_image; +export import :command_buffer; + +export namespace vk { + inline namespace v1 { + sample_image create_texture_with_data(const VkDevice& p_device, const image_params& p_config, const void* p_data) { + // 1. Creating temporary command buffer for texture + command_params copy_command_params = { + .levels = command_levels::primary, + .queue_index = 0, + .flags = command_pool_flags::reset, + }; + command_buffer temp_command_buffer = + command_buffer(p_device, copy_command_params); + + // 2. loading texture + + sample_image texture_image = sample_image(p_device, p_config); + int bytes_per_pixel = bytes_per_texture_format(p_config.format); + + // 3. getting layer size + uint32_t layer_size_with_bytes = + p_config.extent.width * p_config.extent.height * bytes_per_pixel; + uint32_t layer_count = 1; + uint32_t image_size = layer_size_with_bytes * layer_count; + + // 4. transfer data from staging buffer + uint32_t property_flag = + memory_property::host_visible_bit | memory_property::host_cached_bit; + // buffer_configuration staging_buffer_config = { + // .device_size = (uint32_t)image_size, + // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + // .property_flags = (memory_property)property_flag, + // .physical = p_config.physical_device + // }; + + buffer_parameters staging_buffer_config = { + .device_size = (uint32_t)image_size, + .physical_memory_properties = p_config.phsyical_memory_properties, + .property_flags = (memory_property)property_flag, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + // .physical = p_config.physical_device + }; + + // buffer_handle staging_buffer = create_buffer(p_device, + // staging_buffer_config); + buffer_stream staging(p_device, staging_buffer_config); + + // 5. write data to the staging buffer with specific size specified + // write(p_device, staging, p_data, image_size); + staging.write(p_data, image_size); + + // 6. start recording to this command buffer + VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + VkFormat texture_format = p_config.format; + + temp_command_buffer.begin(command_usage::one_time_submit); + + // 6.1 -- transition image layout + // image_memory_barrier(temp_command_buffer, + // texture_image, + // texture_format, + // old_layout, + // new_layout); + texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); + + // 6.2 -- copy buffer to image handles + // copy(temp_command_buffer, + // texture_image, + // staging, + // p_config.extent.width, + // p_config.extent.height); + staging.copy_to_image(temp_command_buffer, texture_image, p_config.extent); + + // 6.3 -- transition image layout back to the layout specification + old_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + // image_memory_barrier(temp_command_buffer, + // texture_image, + // texture_format, + // old_layout, + // new_layout); + texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); + + temp_command_buffer.end(); + + // 7. Create temporary graphics queue to offload the texture image into + // GPU memory + //! TODO: Do this better then just retrieving graphics queue 0 + uint32_t queue_family_index = 0; + uint32_t queue_index = 0; + VkQueue temp_graphics_queue; + vkGetDeviceQueue( + p_device, queue_family_index, queue_index, &temp_graphics_queue); + + // 8. now submit that texture data to be stored in GPU memory + VkCommandBuffer handle = temp_command_buffer; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &handle, + }; + + vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(temp_graphics_queue); + + temp_command_buffer.destroy(); + // free_buffer(p_device, staging_buffer); + staging.destroy(); + + return texture_image; + } + + struct texture_info { + // for getting image memory requirements for the texture + VkPhysicalDeviceMemoryProperties phsyical_memory_properties; + std::filesystem::path filepath; + }; + + struct texture_extent { + uint32_t width=0; + uint32_t height=0; + }; + + class texture { + public: + texture() = default; + + texture(const VkDevice& p_device, const image_extent& p_extent, VkPhysicalDeviceMemoryProperties p_property) : m_device(p_device) { + command_params settings = { + .levels = command_levels::primary, + .queue_index = 0, + .flags = command_pool_flags::reset, + }; + + // 1.) Load in extent dimensions + // Loading in raw white pixels for our texture. + // TODO: Take in a std::span for pixels that will then be + // written to the texture + std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; + + m_width = p_extent.width; + m_height = p_extent.height; + + // texture_properties properties = { + // .width = m_width, + // .height = m_height, + // .usage = (VkImageUsageFlagBits)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | + // VK_IMAGE_USAGE_SAMPLED_BIT), + // .property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + // // .format = VK_FORMAT_R8G8B8A8_UNORM, + // .format = VK_FORMAT_R8G8B8A8_SRGB + // // .format = VK_FORMAT_R64G64B64A64_SFLOAT + // }; + image_params config_image = { + .extent = { .width = p_extent.width, .height = p_extent.height }, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .property = memory_property::device_local_bit, + .aspect = image_aspect_flags::color_bit, + // .usage = (VkImageUsageFlags)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | + // VK_IMAGE_USAGE_SAMPLED_BIT), + .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, + // .physical_device = p_texture_info.physical + .phsyical_memory_properties = p_property + }; + m_image = + create_texture_with_data(m_device, config_image, white_color.data()); + m_texture_loaded = true; + } + + texture(const VkDevice& p_device, const texture_info& p_texture_info) : m_device(p_device) { + // 1. load from file + int w, h; + int channels; + stbi_uc* image_pixel_data = + stbi_load(p_texture_info.filepath.string().c_str(), + &w, + &h, + &channels, + STBI_rgb_alpha); + + m_width = w; + m_height = h; + + if (!image_pixel_data) { + m_texture_loaded = false; + return; + } + + // 2. create vulkan image handlers + loading in the image data + uint32_t property_flag = memory_property::device_local_bit; + + image_params config_image = { + .extent = { .width = (uint32_t)w, .height = (uint32_t)h }, + .format = VK_FORMAT_R8G8B8A8_UNORM, + .property = (memory_property)property_flag, + .aspect = image_aspect_flags::color_bit, + // .usage = (VkImageUsageFlags)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | + // VK_IMAGE_USAGE_SAMPLED_BIT), + .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, + // .physical_device = p_texture_info.physical + .phsyical_memory_properties = + p_texture_info.phsyical_memory_properties + }; + + m_image = create_texture_with_data(p_device, config_image, image_pixel_data); + + m_texture_loaded = true; + } + + [[nodiscard]] bool loaded() const { return m_texture_loaded; } + + [[nodiscard]] sample_image image() const { return m_image; } + + [[nodiscard]] uint32_t width() const { return m_width; } + + [[nodiscard]] uint32_t height() const { return m_height; } + + void destroy() { + m_image.destroy(); + } + + private: + VkDevice m_device = nullptr; + bool m_texture_loaded = false; + // sampled_image m_image_handle{}; + sample_image m_image{}; + uint32_t m_width = 0; + uint32_t m_height = 0; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/texture.hpp b/vulkan-cpp/texture.hpp deleted file mode 100644 index 00278e8..0000000 --- a/vulkan-cpp/texture.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace vk { - struct texture_info { - // for getting image memory requirements for the texture - VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - std::filesystem::path filepath; - }; - - struct texture_extent { - uint32_t width=0; - uint32_t height=0; - }; - - class texture { - public: - texture() = default; - texture(const VkDevice& p_device, const image_extent& p_extent, VkPhysicalDeviceMemoryProperties p_property); - texture(const VkDevice& p_device, const texture_info& p_filepath); - - [[nodiscard]] bool loaded() const { return m_texture_loaded; } - - [[nodiscard]] sample_image image() const { return m_image; } - - [[nodiscard]] uint32_t width() const { return m_width; } - - [[nodiscard]] uint32_t height() const { return m_height; } - - void destroy(); - - private: - VkDevice m_device = nullptr; - bool m_texture_loaded = false; - // sampled_image m_image_handle{}; - sample_image m_image{}; - uint32_t m_width = 0; - uint32_t m_height = 0; - }; - -}; \ No newline at end of file diff --git a/vulkan-cpp/types.cppm b/vulkan-cpp/types.cppm new file mode 100644 index 0000000..15cf7a1 --- /dev/null +++ b/vulkan-cpp/types.cppm @@ -0,0 +1,1257 @@ +module; + +#include +#include +#include +#include +#include +#include +#include + +export module vk:types; + +export namespace vk { + inline namespace v1 { + enum format : uint32_t { + // Core Formats + undefined = VK_FORMAT_UNDEFINED, + r4g4_unorm_pack8 = VK_FORMAT_R4G4_UNORM_PACK8, + r4g4b4a4_unorm_pack16 = VK_FORMAT_R4G4B4A4_UNORM_PACK16, + b4g4r4a4_unorm_pack16 = VK_FORMAT_B4G4R4A4_UNORM_PACK16, + r5g6b5_unorm_pack16 = VK_FORMAT_R5G6B5_UNORM_PACK16, + b5g6r5_unorm_pack16 = VK_FORMAT_B5G6R5_UNORM_PACK16, + r5g5b5a1_unorm_pack16 = VK_FORMAT_R5G5B5A1_UNORM_PACK16, + b5g5r5a1_unorm_pack16 = VK_FORMAT_B5G5R5A1_UNORM_PACK16, + a1r5g5b5_unorm_pack16 = VK_FORMAT_A1R5G5B5_UNORM_PACK16, + r8_unorm = VK_FORMAT_R8_UNORM, + r8_snorm = VK_FORMAT_R8_SNORM, + r8_uscaled = VK_FORMAT_R8_USCALED, + r8_sscaled = VK_FORMAT_R8_SSCALED, + r8_uint = VK_FORMAT_R8_UINT, + r8_sint = VK_FORMAT_R8_SINT, + r8_srgb = VK_FORMAT_R8_SRGB, + r8g8_unorm = VK_FORMAT_R8G8_UNORM, + r8g8_snorm = VK_FORMAT_R8G8_SNORM, + r8g8_uscaled = VK_FORMAT_R8G8_USCALED, + r8g8_sscaled = VK_FORMAT_R8G8_SSCALED, + r8g8_uint = VK_FORMAT_R8G8_UINT, + r8g8_sint = VK_FORMAT_R8G8_SINT, + r8g8_srgb = VK_FORMAT_R8G8_SRGB, + r8g8b8_unorm = VK_FORMAT_R8G8B8_UNORM, + r8g8b8_snorm = VK_FORMAT_R8G8B8_SNORM, + r8g8b8_uscaled = VK_FORMAT_R8G8B8_USCALED, + r8g8b8_sscaled = VK_FORMAT_R8G8B8_SSCALED, + r8g8b8_uint = VK_FORMAT_R8G8B8_UINT, + r8g8b8_sint = VK_FORMAT_R8G8B8_SINT, + r8g8b8_srgb = VK_FORMAT_R8G8B8_SRGB, + b8g8r8_unorm = VK_FORMAT_B8G8R8_UNORM, + b8g8r8_snorm = VK_FORMAT_B8G8R8_SNORM, + b8g8r8_uscaled = VK_FORMAT_B8G8R8_USCALED, + b8g8r8_sscaled = VK_FORMAT_B8G8R8_SSCALED, + b8g8r8_uint = VK_FORMAT_B8G8R8_UINT, + b8g8r8_sint = VK_FORMAT_B8G8R8_SINT, + b8g8r8_srgb = VK_FORMAT_B8G8R8_SRGB, + r8g8b8a8_unorm = VK_FORMAT_R8G8B8A8_UNORM, + r8g8b8a8_snorm = VK_FORMAT_R8G8B8A8_SNORM, + r8g8b8a8_uscaled = VK_FORMAT_R8G8B8A8_USCALED, + r8g8b8a8_sscaled = VK_FORMAT_R8G8B8A8_SSCALED, + r8g8b8a8_uint = VK_FORMAT_R8G8B8A8_UINT, + r8g8b8a8_sint = VK_FORMAT_R8G8B8A8_SINT, + r8g8b8a8_srgb = VK_FORMAT_R8G8B8A8_SRGB, + b8g8r8a8_unorm = VK_FORMAT_B8G8R8A8_UNORM, + b8g8r8a8_snorm = VK_FORMAT_B8G8R8A8_SNORM, + b8g8r8a8_uscaled = VK_FORMAT_B8G8R8A8_USCALED, + b8g8r8a8_sscaled = VK_FORMAT_B8G8R8A8_SSCALED, + b8g8r8a8_uint = VK_FORMAT_B8G8R8A8_UINT, + b8g8r8a8_sint = VK_FORMAT_B8G8R8A8_SINT, + b8g8r8a8_srgb = VK_FORMAT_B8G8R8A8_SRGB, + a8b8g8r8_unorm_pack32 = VK_FORMAT_A8B8G8R8_UNORM_PACK32, + a8b8g8r8_snorm_pack32 = VK_FORMAT_A8B8G8R8_SNORM_PACK32, + a8b8g8r8_uscaled_pack32 = VK_FORMAT_A8B8G8R8_USCALED_PACK32, + a8b8g8r8_sscaled_pack32 = VK_FORMAT_A8B8G8R8_SSCALED_PACK32, + a8b8g8r8_uint_pack32 = VK_FORMAT_A8B8G8R8_UINT_PACK32, + a8b8g8r8_sint_pack32 = VK_FORMAT_A8B8G8R8_SINT_PACK32, + a8b8g8r8_srgb_pack32 = VK_FORMAT_A8B8G8R8_SRGB_PACK32, + a2r10g10b10_unorm_pack32 = VK_FORMAT_A2R10G10B10_UNORM_PACK32, + a2r10g10b10_snorm_pack32 = VK_FORMAT_A2R10G10B10_SNORM_PACK32, + a2r10g10b10_uscaled_pack32 = VK_FORMAT_A2R10G10B10_USCALED_PACK32, + a2r10g10b10_sscaled_pack32 = VK_FORMAT_A2R10G10B10_SSCALED_PACK32, + a2r10g10b10_uint_pack32 = VK_FORMAT_A2R10G10B10_UINT_PACK32, + a2r10g10b10_sint_pack32 = VK_FORMAT_A2R10G10B10_SINT_PACK32, + a2b10g10r10_unorm_pack32 = VK_FORMAT_A2B10G10R10_UNORM_PACK32, + a2b10g10r10_snorm_pack32 = VK_FORMAT_A2B10G10R10_SNORM_PACK32, + a2b10g10r10_uscaled_pack32 = VK_FORMAT_A2B10G10R10_USCALED_PACK32, + a2b10g10r10_sscaled_pack32 = VK_FORMAT_A2B10G10R10_SSCALED_PACK32, + a2b10g10r10_uint_pack32 = VK_FORMAT_A2B10G10R10_UINT_PACK32, + a2b10g10r10_sint_pack32 = VK_FORMAT_A2B10G10R10_SINT_PACK32, + r16_unorm = VK_FORMAT_R16_UNORM, + r16_snorm = VK_FORMAT_R16_SNORM, + r16_uscaled = VK_FORMAT_R16_USCALED, + r16_sscaled = VK_FORMAT_R16_SSCALED, + r16_uint = VK_FORMAT_R16_UINT, + r16_sint = VK_FORMAT_R16_SINT, + r16_sfloat = VK_FORMAT_R16_SFLOAT, + r16g16_unorm = VK_FORMAT_R16G16_UNORM, + r16g16_snorm = VK_FORMAT_R16G16_SNORM, + r16g16_uscaled = VK_FORMAT_R16G16_USCALED, + r16g16_sscaled = VK_FORMAT_R16G16_SSCALED, + r16g16_uint = VK_FORMAT_R16G16_UINT, + r16g16_sint = VK_FORMAT_R16G16_SINT, + r16g16_sfloat = VK_FORMAT_R16G16_SFLOAT, + r16g16b16_unorm = VK_FORMAT_R16G16B16_UNORM, + r16g16b16_snorm = VK_FORMAT_R16G16B16_SNORM, + r16g16b16_uscaled = VK_FORMAT_R16G16B16_USCALED, + r16g16b16_sscaled = VK_FORMAT_R16G16B16_SSCALED, + r16g16b16_uint = VK_FORMAT_R16G16B16_UINT, + r16g16b16_sint = VK_FORMAT_R16G16B16_SINT, + r16g16b16_sfloat = VK_FORMAT_R16G16B16_SFLOAT, + r16g16b16a16_unorm = VK_FORMAT_R16G16B16A16_UNORM, + r16g16b16a16_snorm = VK_FORMAT_R16G16B16A16_SNORM, + r16g16b16a16_uscaled = VK_FORMAT_R16G16B16A16_USCALED, + r16g16b16a16_sscaled = VK_FORMAT_R16G16B16A16_SSCALED, + r16g16b16a16_uint = VK_FORMAT_R16G16B16A16_UINT, + r16g16b16a16_sint = VK_FORMAT_R16G16B16A16_SINT, + r16g16b16a16_sfloat = VK_FORMAT_R16G16B16A16_SFLOAT, + r32_uint = VK_FORMAT_R32_UINT, + r32_sint = VK_FORMAT_R32_SINT, + r32_sfloat = VK_FORMAT_R32_SFLOAT, + rg32_uint = VK_FORMAT_R32G32_UINT, + rg32_sint = VK_FORMAT_R32G32_SINT, + rg32_sfloat = VK_FORMAT_R32G32_SFLOAT, + rgb32_uint = VK_FORMAT_R32G32B32_UINT, + rgb32_sint = VK_FORMAT_R32G32B32_SINT, + rgb32_sfloat = + VK_FORMAT_R32G32B32_SFLOAT, // Example from prompt: + // VK_FORMAT_R32G32B32_SFLOAT + rgba_uint = VK_FORMAT_R32G32B32A32_UINT, + rgba_sint = VK_FORMAT_R32G32B32A32_SINT, + rgba_sfloat = VK_FORMAT_R32G32B32A32_SFLOAT, + r64_uint = VK_FORMAT_R64_UINT, + r64_sint = VK_FORMAT_R64_SINT, + r64_sfloat = VK_FORMAT_R64_SFLOAT, + rg64_uint = VK_FORMAT_R64G64_UINT, + rg64_sint = VK_FORMAT_R64G64_SINT, + rg64_sfloat = VK_FORMAT_R64G64_SFLOAT, + rgb64_uint = VK_FORMAT_R64G64B64_UINT, + rgb64_sint = VK_FORMAT_R64G64B64_SINT, + rgb64_sfloat = VK_FORMAT_R64G64B64_SFLOAT, + rgba64_uint = VK_FORMAT_R64G64B64A64_UINT, + rgba64_sint = VK_FORMAT_R64G64B64A64_SINT, + r64g64b64a64_sfloat = VK_FORMAT_R64G64B64A64_SFLOAT, + b10g11r11_ufloat_pack32 = VK_FORMAT_B10G11R11_UFLOAT_PACK32, + e5b9g9r9_ufloat_pack32 = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, + + // Depth/Stencil Formats + d16_unorm = VK_FORMAT_D16_UNORM, + x8_d24_unorm_pack32 = VK_FORMAT_X8_D24_UNORM_PACK32, + d32_sfloat = VK_FORMAT_D32_SFLOAT, + s8_uint = VK_FORMAT_S8_UINT, + d16_unorm_s8_uint = VK_FORMAT_D16_UNORM_S8_UINT, + d24_unorm_s8_uint = VK_FORMAT_D24_UNORM_S8_UINT, + d32_sfloat_s8_uint = VK_FORMAT_D32_SFLOAT_S8_UINT, + + // Compressed Formats (BC) + bc1_rgb_unorm_block = VK_FORMAT_BC1_RGB_UNORM_BLOCK, + bc1_rgb_srgb_block = VK_FORMAT_BC1_RGB_SRGB_BLOCK, + bc1_rgba_unorm_block = VK_FORMAT_BC1_RGBA_UNORM_BLOCK, + bc1_rgba_srgb_block = VK_FORMAT_BC1_RGBA_SRGB_BLOCK, + bc2_unorm_block = VK_FORMAT_BC2_UNORM_BLOCK, + bc2_srgb_block = VK_FORMAT_BC2_SRGB_BLOCK, + bc3_unorm_block = VK_FORMAT_BC3_UNORM_BLOCK, + bc3_srgb_block = VK_FORMAT_BC3_SRGB_BLOCK, + bc4_unorm_block = VK_FORMAT_BC4_UNORM_BLOCK, + bc4_snorm_block = VK_FORMAT_BC4_SNORM_BLOCK, + bc5_unorm_block = VK_FORMAT_BC5_UNORM_BLOCK, + bc5_snorm_block = VK_FORMAT_BC5_SNORM_BLOCK, + bc6h_ufloat_block = VK_FORMAT_BC6H_UFLOAT_BLOCK, + bc6h_sfloat_block = VK_FORMAT_BC6H_SFLOAT_BLOCK, + bc7_unorm_block = VK_FORMAT_BC7_UNORM_BLOCK, + bc7_srgb_block = VK_FORMAT_BC7_SRGB_BLOCK, + + // Compressed Formats (ETC2/EAC) + etc2_r8g8b8_unorm_block = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, + etc2_r8g8b8_srgb_block = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, + etc2_r8g8b8a1_unorm_block = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, + etc2_r8g8b8a1_srgb_block = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, + etc2_r8g8b8a8_unorm_block = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, + etc2_r8g8b8a8_srgb_block = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, + eac_r11_unorm_block = VK_FORMAT_EAC_R11_UNORM_BLOCK, + eac_r11_snorm_block = VK_FORMAT_EAC_R11_SNORM_BLOCK, + eac_r11g11_unorm_block = VK_FORMAT_EAC_R11G11_UNORM_BLOCK, + eac_r11g11_snorm_block = VK_FORMAT_EAC_R11G11_SNORM_BLOCK, + + // Compressed Formats (ASTC) + astc_4x4_unorm_block = VK_FORMAT_ASTC_4x4_UNORM_BLOCK, + astc_4x4_srgb_block = VK_FORMAT_ASTC_4x4_SRGB_BLOCK, + astc_5x4_unorm_block = VK_FORMAT_ASTC_5x4_UNORM_BLOCK, + astc_5x4_srgb_block = VK_FORMAT_ASTC_5x4_SRGB_BLOCK, + astc_5x5_unorm_block = VK_FORMAT_ASTC_5x5_UNORM_BLOCK, + astc_5x5_srgb_block = VK_FORMAT_ASTC_5x5_SRGB_BLOCK, + astc_6x5_unorm_block = VK_FORMAT_ASTC_6x5_UNORM_BLOCK, + astc_6x5_srgb_block = VK_FORMAT_ASTC_6x5_SRGB_BLOCK, + astc_6x6_unorm_block = VK_FORMAT_ASTC_6x6_UNORM_BLOCK, + astc_6x6_srgb_block = VK_FORMAT_ASTC_6x6_SRGB_BLOCK, + astc_8x5_unorm_block = VK_FORMAT_ASTC_8x5_UNORM_BLOCK, + astc_8x5_srgb_block = VK_FORMAT_ASTC_8x5_SRGB_BLOCK, + astc_8x6_unorm_block = VK_FORMAT_ASTC_8x6_UNORM_BLOCK, + astc_8x6_srgb_block = VK_FORMAT_ASTC_8x6_SRGB_BLOCK, + astc_8x8_unorm_block = VK_FORMAT_ASTC_8x8_UNORM_BLOCK, + astc_8x8_srgb_block = VK_FORMAT_ASTC_8x8_SRGB_BLOCK, + astc_10x5_unorm_block = VK_FORMAT_ASTC_10x5_UNORM_BLOCK, + astc_10x5_srgb_block = VK_FORMAT_ASTC_10x5_SRGB_BLOCK, + astc_10x6_unorm_block = VK_FORMAT_ASTC_10x6_UNORM_BLOCK, + astc_10x6_srgb_block = VK_FORMAT_ASTC_10x6_SRGB_BLOCK, + astc_10x8_unorm_block = VK_FORMAT_ASTC_10x8_UNORM_BLOCK, + astc_10x8_srgb_block = VK_FORMAT_ASTC_10x8_SRGB_BLOCK, + astc_10x10_unorm_block = VK_FORMAT_ASTC_10x10_UNORM_BLOCK, + astc_10x10_srgb_block = VK_FORMAT_ASTC_10x10_SRGB_BLOCK, + astc_12x10_unorm_block = VK_FORMAT_ASTC_12x10_UNORM_BLOCK, + astc_12x10_srgb_block = VK_FORMAT_ASTC_12x10_SRGB_BLOCK, + astc_12x12_unorm_block = VK_FORMAT_ASTC_12x12_UNORM_BLOCK, + astc_12x12_srgb_block = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, + + // YCbCr Formats (KHR Extension, now Core in 1.1) + g8b8g8r8_422_unorm = VK_FORMAT_G8B8G8R8_422_UNORM, + b8g8r8g8_422_unorm = VK_FORMAT_B8G8R8G8_422_UNORM, + g8_b8_r8_3plane_420_unorm = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + g8_b8r8_2plane_420_unorm = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, + g8_b8_r8_3plane_422_unorm = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + g8_b8r8_2plane_422_unorm = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, + g8_b8_r8_3plane_444_unorm = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + r10x6_unorm_pack16 = VK_FORMAT_R10X6_UNORM_PACK16, + r10x6g10x6_unorm_2pack16 = VK_FORMAT_R10X6G10X6_UNORM_2PACK16, + r10x6g10x6b10x6a10x6_unorm_4pack16 = + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, + g10x6b10x6g10x6r10x6_422_unorm_4pack16 = + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + b10x6g10x6r10x6g10x6_422_unorm_4pack16 = + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + g10x6_b10x6_r10x6_3plane_420_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + g10x6_b10x6r10x6_2plane_420_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + g10x6_b10x6_r10x6_3plane_422_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + g10x6_b10x6r10x6_2plane_422_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + g10x6_b10x6_r10x6_3plane_444_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + r12x4_unorm_pack16 = VK_FORMAT_R12X4_UNORM_PACK16, + r12x4g12x4_unorm_2pack16 = VK_FORMAT_R12X4G12X4_UNORM_2PACK16, + r12x4g12x4b12x4a12x4_unorm_4pack16 = + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, + g12x4b12x4g12x4r12x4_422_unorm_4pack16 = + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + b12x4g12x4r12x4g12x4_422_unorm_4pack16 = + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + g12x4_b12x4_r12x4_3plane_420_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + g12x4_b12x4r12x4_2plane_420_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + g12x4_b12x4_r12x4_3plane_422_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + g12x4_b12x4r12x4_2plane_422_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + g12x4_b12x4_r12x4_3plane_444_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + g16b16g16r16_422_unorm = VK_FORMAT_G16B16G16R16_422_UNORM, + b16g16r16g16_422_unorm = VK_FORMAT_B16G16R16G16_422_UNORM, + g16_b16_r16_3plane_420_unorm = + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + g16_b16r16_2plane_420_unorm = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, + g16_b16_r16_3plane_422_unorm = + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + g16_b16r16_2plane_422_unorm = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, + g16_b16_r16_3plane_444_unorm = + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + + // EXT/Vendor YCbCr Formats + g8_b8r8_2plane_444_unorm = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, + g10x6_b10x6r10x6_2plane_444_unorm_3pack16 = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, + g12x4_b12x4r12x4_2plane_444_unorm_3pack16 = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, + g16_b16r16_2plane_444_unorm = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, + + // EXT Packed Formats + a4r4g4b4_unorm_pack16 = VK_FORMAT_A4R4G4B4_UNORM_PACK16, + a4b4g4r4_unorm_pack16 = VK_FORMAT_A4B4G4R4_UNORM_PACK16, + + // ASTC SFLOAT Formats + astc_4x4_sfloat_block = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, + astc_5x4_sfloat_block = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, + astc_5x5_sfloat_block = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, + astc_6x5_sfloat_block = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK, + astc_6x6_sfloat_block = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK, + astc_8x5_sfloat_block = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK, + astc_8x6_sfloat_block = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK, + astc_8x8_sfloat_block = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK, + astc_10x5_sfloat_block = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK, + astc_10x6_sfloat_block = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK, + astc_10x8_sfloat_block = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK, + astc_10x10_sfloat_block = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK, + astc_12x10_sfloat_block = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK, + astc_12x12_sfloat_block = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK, + + // PVRTC Formats (IMG Vendor) + pvrtc1_2bpp_unorm_block_img = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, + pvrtc1_4bpp_unorm_block_img = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, + pvrtc2_2bpp_unorm_block_img = VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, + pvrtc2_4bpp_unorm_block_img = VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, + pvrtc1_2bpp_srgb_block_img = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, + pvrtc1_4bpp_srgb_block_img = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, + pvrtc2_2bpp_srgb_block_img = VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, + pvrtc2_4bpp_srgb_block_img = VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, + + // Vendor Specific (NV) + // r16g16_sfixed5_nv = VK_FORMAT_R16G16_SFIXED5_NV, + + // KHR/EXT Aliases (A1B5G5R5, A8) + a1b5g5r5_unorm_pack16_khr = VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR, + a8_unorm_khr = VK_FORMAT_A8_UNORM_KHR, + + // Aliases to Core Formats + // ASTC SFLOAT EXT Aliases + astc_4x4_sfloat_block_ext = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, + astc_5x4_sfloat_block_ext = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, + astc_5x5_sfloat_block_ext = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, + astc_6x5_sfloat_block_ext = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, + astc_6x6_sfloat_block_ext = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, + astc_8x5_sfloat_block_ext = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, + astc_8x6_sfloat_block_ext = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, + astc_8x8_sfloat_block_ext = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, + astc_10x5_sfloat_block_ext = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, + astc_10x6_sfloat_block_ext = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, + astc_10x8_sfloat_block_ext = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, + astc_10x10_sfloat_block_ext = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, + astc_12x10_sfloat_block_ext = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, + astc_12x12_sfloat_block_ext = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, + + // YCbCr KHR Aliases + g8b8g8r8_422_unorm_khr = VK_FORMAT_G8B8G8R8_422_UNORM_KHR, + b8g8r8g8_422_unorm_khr = VK_FORMAT_B8G8R8G8_422_UNORM_KHR, + g8_b8_r8_3plane_420_unorm_khr = + VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR, + g8_b8r8_2plane_420_unorm_khr = + VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR, + g8_b8_r8_3plane_422_unorm_khr = + VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR, + g8_b8r8_2plane_422_unorm_khr = + VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR, + g8_b8_r8_3plane_444_unorm_khr = + VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR, + r10x6_unorm_pack16_khr = VK_FORMAT_R10X6_UNORM_PACK16_KHR, + r10x6g10x6_unorm_2pack16_khr = + VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR, + r10x6g10x6b10x6a10x6_unorm_4pack16_khr = + VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR, + g10x6b10x6g10x6r10x6_422_unorm_4pack16_khr = + VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR, + b10x6g10x6r10x6g10x6_422_unorm_4pack16_khr = + VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR, + g10x6_b10x6_r10x6_3plane_420_unorm_3pack16_khr = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR, + g10x6_b10x6r10x6_2plane_420_unorm_3pack16_khr = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR, + g10x6_b10x6_r10x6_3plane_422_unorm_3pack16_khr = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR, + g10x6_b10x6r10x6_2plane_422_unorm_3pack16_khr = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR, + g10x6_b10x6_r10x6_3plane_444_unorm_3pack16_khr = + VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR, + r12x4_unorm_pack16_khr = VK_FORMAT_R12X4_UNORM_PACK16_KHR, + r12x4g12x4_unorm_2pack16_khr = + VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR, + r12x4g12x4b12x4a12x4_unorm_4pack16_khr = + VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR, + g12x4b12x4g12x4r12x4_422_unorm_4pack16_khr = + VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR, + b12x4g12x4r12x4g12x4_422_unorm_4pack16_khr = + VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR, + g12x4_b12x4_r12x4_3plane_420_unorm_3pack16_khr = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR, + g12x4_b12x4r12x4_2plane_420_unorm_3pack16_khr = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR, + g12x4_b12x4_r12x4_3plane_422_unorm_3pack16_khr = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR, + g12x4_b12x4r12x4_2plane_422_unorm_3pack16_khr = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR, + g12x4_b12x4_r12x4_3plane_444_unorm_3pack16_khr = + VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR, + g16b16g16r16_422_unorm_khr = VK_FORMAT_G16B16G16R16_422_UNORM_KHR, + b16g16r16g16_422_unorm_khr = VK_FORMAT_B16G16R16G16_422_UNORM_KHR, + g16_b16_r16_3plane_420_unorm_khr = + VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR, + g16_b16r16_2plane_420_unorm_khr = + VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR, + g16_b16_r16_3plane_422_unorm_khr = + VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR, + g16_b16r16_2plane_422_unorm_khr = + VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR, + g16_b16_r16_3plane_444_unorm_khr = + VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR, + + // YCbCr EXT Aliases + g8_b8r8_2plane_444_unorm_ext = + VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, + g10x6_b10x6r10x6_2plane_444_unorm_3pack16_ext = + VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT, + g12x4_b12x4r12x4_2plane_444_unorm_3pack16_ext = + VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT, + g16_b16r16_2plane_444_unorm_ext = + VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT, + + // A4 Packed EXT Aliases + a4r4g4b4_unorm_pack16_ext = VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, + a4b4g4r4_unorm_pack16_ext = VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, + + // NV Alias + r16g16_s10_5_nv = VK_FORMAT_R16G16_S10_5_NV, + + // Max Enum + max_enum_format = VK_FORMAT_MAX_ENUM + }; + + enum image_aspect_flags : uint32_t { + color_bit = VK_IMAGE_ASPECT_COLOR_BIT, + depth_bit = VK_IMAGE_ASPECT_DEPTH_BIT, + stencil_bit = VK_IMAGE_ASPECT_STENCIL_BIT, + metadata_bit = VK_IMAGE_ASPECT_METADATA_BIT, + plane0_bit = VK_IMAGE_ASPECT_PLANE_0_BIT, + plane1_bit = VK_IMAGE_ASPECT_PLANE_1_BIT, + plane2_bit = VK_IMAGE_ASPECT_PLANE_2_BIT, + none = VK_IMAGE_ASPECT_NONE, + memory_plane0_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, + memory_plane1_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, + memory_plane2_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT, + plane1_bit_khr = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR, + plane2_bit_khr = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR, + none_khr = VK_IMAGE_ASPECT_NONE_KHR, + bits_max_enum = VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM + }; + + /** + * @brief message sevierity explicitly to max size of a byte + */ + enum message : uint32_t { + verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, + info = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, + warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, + error = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, + max_num = VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT + }; + + enum debug : uint32_t { + general = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, + validation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, + performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, + device_address_binding_ext = + VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT, + max_enum = VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT + }; + + enum class api_version : uint32_t { + vk_1_2 = VK_API_VERSION_1_2, + vk_1_3 = VK_API_VERSION_1_3, // vulkan version 1.3 + // vk_1_2, // vulkan version 1.4 + }; + + struct debug_message_utility { + uint32_t severity; + uint32_t message_type; + uint32_t (*callback)(VkDebugUtilsMessageSeverityFlagBitsEXT, + VkDebugUtilsMessageTypeFlagsEXT, + const VkDebugUtilsMessengerCallbackDataEXT*, + void*) = nullptr; + }; + + struct application_params { + std::string name = ""; + api_version version; + std::span validations; + std::span extensions; + }; + + struct swapchain_params { + uint32_t width; + uint32_t height; + uint32_t present_index = -1; + + VkFormat depth; // depth format + }; + + struct filter_range { + VkFilter min; + VkFilter max; + }; + + struct layer_properties { + std::string name; + uint32_t version; + uint32_t impl_version; + std::string description; + }; + + //! @brief vk::physical defines what kinds of physical device + //! specification to use that is available based on your current + //! physical hardware specifications. + enum class physical : uint8_t { + integrated, + discrete, + virtualized, + cpu, + max_enum, + other + }; + + /** + * @brief Enumeration represents configuration for the physical device + * + * Defines the configuration for the VkPhysicalDevice handler to be + * created with + */ + struct physical_enumeration { + physical device_type; + }; + + struct surface_params { + VkSurfaceCapabilitiesKHR capabilities; + VkSurfaceFormatKHR format; + }; + + struct queue_params { + uint32_t family = -1; + uint32_t index = -1; + }; + + struct queue_indices { + uint32_t graphics = -1; + uint32_t compute = -1; + uint32_t transfer = -1; + }; + + struct device_params { + std::span queue_priorities{}; + std::span + extensions{}; // Can add VK_KHR_SWAPCHAIN_EXTENSION_NAME to this + // extension + uint32_t queue_family_index = 0; + }; + + // raw image handlers + // struct image { + // VkImage image = nullptr; + // VkImageView view = nullptr; + // }; + + // sampler + raw image handlers + // struct sampled_image { + // VkImage image = nullptr; + // VkImageView view = nullptr; + // VkSampler sampler = nullptr; + // VkDeviceMemory device_memory = nullptr; + // }; + + //! @brief enumeration if an image is provided + // struct swapchain_image_enumeration { + // VkImage image = nullptr; + // VkFormat format; + // // VkImageAspectFlags aspect; + // image_aspect_flags aspect; + // uint32_t layer_count = 0; + // uint32_t mip_levels = 1; + // }; + + // Image enumeration for creating a brand new VkImage/VkImageView + // handlers struct image_enumeration { + // uint32_t width = -1; + // uint32_t height = -1; + // VkFormat format; + // // VkImageAspectFlags aspect; + // image_aspect_flags aspect; + // uint32_t layer_count = 1; + // uint32_t mip_levels = 1; + // }; + + /** + * @param renderpass vulkan requires framebuffers to know renderpasses + * up front + * @param views framebuffers provide the actual image views that will + * serve as attachments to the renderpass handle + * @param extent are for framebuffers to pass in frame image views to + * the screen. Should be the size of the window viewport specified + */ + struct framebuffer_params { + VkRenderPass renderpass = nullptr; + std::span views; + VkExtent2D extent; + }; + + /** + * @param Primary + * submission: immediately to vulkan queue for executing on device + * execution: vkQueueSubmit primarily submits primary command buffers + * + * @param Seconary + * submission: Cannot be submitted directly to vulkan queue + * execution: Indirect execution by being called from primary command + * buffers using `vkCmdExecuteCommands` + * + * When executed within render-pass instance, they inherit + * renderpass/subpass state from primary command buffer + * + * Can be allocated and recorded in parallel, which can leverage + * devices that support multi-core processing + * + * Have independent lifetimes that can be managed independently of + * primary command buffers, allowing for more flexible resource + * management + */ + enum class command_levels : uint32_t { + primary = 0, + secondary = 1, + max_enum = VK_COMMAND_BUFFER_LEVEL_MAX_ENUM, + }; + + /** + * @param transient represents VK_COMMAND_POOL_CREATE_TRANSIENT_BIT + * + * Usage: specifies command buffers allocated from pool are short-lived, + * meaning they will reset or be freed in a short time-frame. Flag may + * also be used by implementation to control memory allocation behavior + * within the pool + * + * @param reset represents + * VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + * + * Usage: Allows command buffers allocated from the pool to be + * individually reset to their initial state; either by calling + * vkResetCommandBuffer or implicit reset when calling + * vkBeginCommandBuffer + * + * @param protected_bit represents VK_COMMAND_POOL_CREATE_PROTECTED_BIT + * + * Usage: Specifies command buffers allocated from pool are protected + * command buffers; meaning the the memory allocated with the command + * pool is protected + * + * + */ + enum command_pool_flags : uint32_t { + transient = + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // represents + // VK_COMMAND_POOL_CREATE_TRANSIENT_BIT + reset = + VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // represents + // VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT + protected_bit = + VK_COMMAND_POOL_CREATE_PROTECTED_BIT, // represents + // VK_COMMAND_POOL_CREATE_PROTECTED_BIT + max_enum_bit = + VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM, // represents + // VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM + }; + + /** + * @brief settings for specifying command buffers to construct + * + * @param Levels are for specifying the kind of command buffer being + * constructed + * + * queue_index specifies the queue family associated with this + * command buffer + * + * pool_flag in the context of the command buffers are used to + * control memory allocation behavior within the command buffer pool to + * allocate + * + * @param VK_COMMAND_POOL_CREATE_TRANSIENT_BIT Indicates command buffers + * allocated from pool will be short-lived, meaning they'll reset or + * freed quickly + * @param VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT Allows + * individual command buffers allocated from the pool to be reset to + * their initial state using `vkResetCommandBuffer` + * @param VK_COMMAND_POOL_CREATE_PROTECTED_BIT Designates command + * buffers allocated from the pool as protective command buffers, + * implying they are stored in protected memory and access to them is + * restricted to authorized operations + */ + struct command_params { + + command_levels levels; + uint32_t queue_index = -1; + // VkCommandPoolCreateFlagBits pool_flag; + command_pool_flags flags; + }; + + struct renderpass_attachments { + std::span clear_values{}; + std::span attachments{}; + std::span subpass_descriptions{}; + std::span dependencies{}; + }; + + enum subpass_contents : uint32_t { + inline_bit = + VK_SUBPASS_CONTENTS_INLINE, // represents + // VK_SUBPASS_CONTENTS_INLINE + secondary_command = + VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, // represents + // VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS + inline_and_secondary_command_khr = + VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT, // represents + // VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR + // and + // VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT + max_enum_content = + VK_SUBPASS_CONTENTS_MAX_ENUM // represents + // VK_SUBPASS_CONTENTS_MAX_ENUM + }; + + enum class image_layout : uint32_t { + undefined = VK_IMAGE_LAYOUT_UNDEFINED, // VK_IMAGE_LAYOUT_UNDEFINED + general = VK_IMAGE_LAYOUT_GENERAL, // VK_IMAGE_LAYOUT_GENERAL + color_optimal = + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + depth_stencil_optimal = + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL + depth_stencil_read_only_optimal = + VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_READ_ONLY_OPTIMAL + present_src_khr = + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR + shader_read_only_optimal = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + }; + + // enum class format : uint64_t { + // rgb32_sfloat, // Represent R32G32B32_SFLOAT + // rg32_sfloat, // Represent R32G32_SFLOAT + // }; + + enum buffer : uint8_t { + uniform = + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // represents + // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + storage = + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // represents + // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + combined_image_sampler = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // represents + // VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + sampled_only_image = + VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE // represents + // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + }; + + enum image_usage : uint32_t { + transfer_src_bit = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + transfer_dst_bit = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + sampled_bit = VK_IMAGE_USAGE_SAMPLED_BIT, + storage_bit = VK_IMAGE_USAGE_STORAGE_BIT, + color_attachment_bit = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + depth_stencil_bit = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + transient_attachment_bit = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + input_attachment_bit = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, + video_decide_dst_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR, + video_decode_src_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR, + video_decode_dpb_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR, + fragment_density_map_bit_ext = + VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT, + fragment_shading_rate_attachment_bit_khr = + VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + host_transfer_bit_ext = VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, + video_encode_dst_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR, + video_encode_src_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, + video_encode_dpb_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR, + attachment_feedback_loop_bit_ext = + VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, + invocation_mask_bit_huawei = + VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI, + sample_weight_bit_qcom = VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM, + sample_block_mtch_bit_qcom = + VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM, + shading_rate_image_bit_nv = + VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, + max_enum_usage = VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM + }; + + enum sampler_address_mode : uint32_t { + repeat = VK_SAMPLER_ADDRESS_MODE_REPEAT, + mirrored_repeat = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, + clamp_to_edge = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + clamp_to_border = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + mirror_clamp_to_edge = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, + mirror_clamp_to_edge_khr = + VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR, + max_enum_address_mode = VK_SAMPLER_ADDRESS_MODE_MAX_ENUM + }; + + /** + * @brief Refers to the input rate + * + * vertex - refers to most common rate. Indicates GPU to move next data + * entry (next vertex data) into a buffer for every single vertex that's + * processed. + * - Used for vertex attributes that change per vertex on the mesh + * - vertex attribute-only data + * - Per-object based specification in the next data entry + * + * instance - refers to data entry per-instance. Specifying to the GPU + * that the data entry in the buffer is to be after the instance of the + * object itself. + * - Typically used for instanced rendering. Specfying next + * entry of data to be after instanced drawn, could be shared. Therefore + * instance is an option to choose from if vertex data is across as a + * per-instance basis. + * - instance-based specification next data entry + * + */ + enum class input_rate : uint8_t { + vertex, + instance, + max_enum, + }; + + //! @brief Equivalent to doing VkSampleCountFlagBits but simplified + enum class sample_bit : uint32_t { + count_1 = VK_SAMPLE_COUNT_1_BIT, + count_2 = VK_SAMPLE_COUNT_2_BIT, + count_4 = VK_SAMPLE_COUNT_4_BIT, + count_8 = VK_SAMPLE_COUNT_8_BIT, + count_16 = VK_SAMPLE_COUNT_16_BIT, + count_32 = VK_SAMPLE_COUNT_32_BIT, + count_64 = VK_SAMPLE_COUNT_64_BIT, + max_enum = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM + }; + + //! @brief Equivalent to VkAttachmentLoadOp + enum class attachment_load : uint32_t { + load = VK_ATTACHMENT_LOAD_OP_LOAD, // LOAD_OP_LOAD + clear = VK_ATTACHMENT_LOAD_OP_CLEAR, // LOAD_OP_CLEAR + dont_care = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // lOAD_OP_DONT_CARE + none_khr = VK_ATTACHMENT_LOAD_OP_NONE_KHR, // LOAD_OP_NONE_KHR + none_ext = VK_ATTACHMENT_LOAD_OP_NONE_KHR, // LOAD_OP_NONE_EXT + max_enum = VK_ATTACHMENT_LOAD_OP_MAX_ENUM, // LOAD_OP_MAX_ENUM + }; + + //! @brief Equivalent to VkAttachmentStoreOp + enum class attachment_store : uint32_t { + store = VK_ATTACHMENT_STORE_OP_STORE, // STORE_OP_STORE + dont_care = VK_ATTACHMENT_STORE_OP_DONT_CARE, // STORE_OP_CLEAR + none_khr = VK_ATTACHMENT_STORE_OP_NONE_KHR, // STORE_OP_NONE + none_qcom = VK_ATTACHMENT_STORE_OP_NONE_QCOM, // STORE_OP_NONE_EXT + none_ext = VK_ATTACHMENT_STORE_OP_NONE_EXT, // STORE_OP_NONE_KHR + max_enum = VK_ATTACHMENT_STORE_OP_MAX_ENUM, // STORE_OP_MAX_ENUM + }; + + enum class pipeline_stage_flags : uint32_t { + top_of_pipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + draw_indirect = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, + vertex_input_bit = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, + vertex_shader_bit = + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, + tesselation_control_shader_bit = + VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, + tessellation_evaluation_shader_bit = + VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, + geoemtry_shaders_bit = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, + fragment_shaders_bit = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + early_fragment_shader_bit = + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, + late_fragment_tests_bit = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + color_attachment_output = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + compute_shader_bit = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + transient_bit = VK_PIPELINE_STAGE_TRANSFER_BIT, + bottom_of_pipe = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + host_bit = VK_PIPELINE_STAGE_HOST_BIT, + all_graphics_bit = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + all_commands_bit = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + none = VK_PIPELINE_STAGE_NONE, + transform_feedback_bit_ext = + VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, + conditional_rendering_bit_ext = + VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT, + acceleration_build_bit_khr = + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + ray_tracing_shader_bit_khr = + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, + fragment_density_process_bit_ext = + VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT, + command_preprocess_bit_nv = + VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV, + task_shader_bit_ext = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT, + mesh_shader_bit_ext = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, + shading_rate_image_bit_nv = + VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV, + ray_tracing_shader_bit_nv = + VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV, + task_shader_bit_nv = VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, + mesh_shader_bit_nv = VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, + none_khr = VK_PIPELINE_STAGE_NONE_KHR, + flag_bits_max_enum = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM + }; + + //! @brief Equivalent to VkPipelineBindPoint + enum class pipeline_bind_point : uint64_t { + graphics = + VK_PIPELINE_BIND_POINT_GRAPHICS, // VK_PIPELINE_BIND_POINT_GRAPHICS + compute = + VK_PIPELINE_BIND_POINT_COMPUTE, // VK_PIPELINE_BIND_POINT_COMPUTE + ray_tracing_khr = + VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, // VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR + subpass_shading_hauwei = + VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, // VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI + ray_tracing_nv = + VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, // VK_PIPELINE_BIND_POINT_RAY_TRACING_NV + max_enum = + VK_PIPELINE_BIND_POINT_MAX_ENUM // VK_PIPELINE_BIND_POINT_MAX_ENUM + }; + + /** + * @brief Specifies a specific attachment that a renderpass may operate + * using + * + * Renderpasses can consist of multiple attachment that can be specified + * under this one struct to represent both the VkAttachmentDescription + * and VkAttachmentReference + */ + struct attachment { + VkFormat format; + image_layout layout; // specify for VkAttachmentReference + sample_bit samples; + attachment_load load; + attachment_store store; + attachment_load stencil_load; + attachment_store stencil_store; + image_layout initial_layout; + image_layout final_layout; + }; + + struct renderpass_begin_params { + VkCommandBuffer current_command = nullptr; + VkExtent2D extent; + VkFramebuffer current_framebuffer = nullptr; + std::array color; + subpass_contents subpass; + }; + + //! @brief Bits that 1-to-1 map to VkCommandUsageFlags + enum command_usage : uint32_t { + one_time_submit = + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // Represents + // VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT + renderpass_continue_bit = + VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // Represents + // VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT + simulatneous_use_bit = + VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // Represents + // VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT + max_bit = + VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM // Represents + // VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM + }; + + /** + * @brief memory_property is a representation of vulkan's + * VkMemoryPropertyFlags. + * + * @param device_local_bit + * + * Meaning: indicates memory allocated with this type is most efficient + * for the GPU to access. \n + * + * Implications: The memory with this bit typically + * resides on the GPU's VRAM. Accessing memory directly from GPU's since + * its faster. \n + * + * Usage: For resources that are primarily accessed by the GPU in the + * case of textures, vertex buffers, and framebuffers. If a memory type + * has this bit associated with it, the heap memory will also have be + * set along with VK_MEMORY_HEAP_DEVICE_LOCAL_BIT. \n + * + * @param host_visible_bit + * + * Meaning: Indicates memory alloated can be mapped to host's (CPU) + * address space using the vkMapMemory API. \n + * + * Implications: ALlows CPU to directly + * read from and write to memory. Crucial for transferring data between + * CPU to GPU. \n + * + * Usage: Use-case is for staging buffers, where data initially + * uploaded from CPU before being copied to device-local memory or for + * resourcfes that need frequent CPU updates. \n + * + * @param host_coherent_bit + * + * Meaning: Indicates host cache managemnet commands + * (vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges) are + * not needed. Writes made by host will automatically become visible to + * the device, and writes made by device will automatically be visible + * to the host. \n + * + * Implications: Simplifies memory synchronization between CPU and GPU. + * Though can lead to slower CPU access if it means bypassing the CPU + * caches or involving more complex cache coherence protocols. \n + * + * Usage: Used with 'VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT' for easy data + * transfers, especially for frequent updated data where manual flushing + * would be cumbersome. \n + * + * + * @param host_cached_bit + * + * Meaning: Indicates memory allocated with this type is cached on the + * host (CPU). \n + * + * Implications: Host memory accesses (read/writes) to this memory + * type will go through CPU cache heirarchy. Significantly improves + * performance where random access patterns. If not set on + * `HOST_VISIBLE` memory, CPU accesses are often uncached and + * write-combined, meanming writes should be sequential and reads should + * be avoided for good performance. \n + * + * Usage: Does well for CPU-side reading of data written to GPU + * (screenshots or feedback data) and for CPU-side writing of data to be + * accessed randomly. Flag usually implies explicit cache management + * (flushing/invalidating) is required if `HOST_COHERENT_BIT` is not + * also set. \n + * + * + */ + enum memory_property : uint32_t { + device_local_bit = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + host_visible_bit = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + host_coherent_bit = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + host_cached_bit = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + lazily_allocated_bit = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, + device_protected_bit = VK_MEMORY_PROPERTY_PROTECTED_BIT, + device_coherent_bit_amd = + VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD, + device_uncached_bit_amd = + VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD, + rdma_capable_bit_nv = VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV, + flag_bits_max_enum = VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM + }; + + enum class shader_stage { + vertex = VK_SHADER_STAGE_VERTEX_BIT, + fragment = VK_SHADER_STAGE_FRAGMENT_BIT, + compute = VK_SHADER_STAGE_COMPUTE_BIT, + geometry = VK_SHADER_STAGE_GEOMETRY_BIT, + all_graphics = VK_SHADER_STAGE_ALL_GRAPHICS, + all = VK_SHADER_STAGE_ALL, + raygen_khr = VK_SHADER_STAGE_RAYGEN_BIT_KHR, + raygen_nv = VK_SHADER_STAGE_RAYGEN_BIT_NV, + any_hit_kht = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, + closest_hit_khr = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, + miss_bit_khr = VK_SHADER_STAGE_MISS_BIT_KHR, + intersection_khr = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, + callable_bit_khr = VK_SHADER_STAGE_CALLABLE_BIT_KHR, + task_bit_ext = VK_SHADER_STAGE_TASK_BIT_EXT, + mesh_bit_ext = VK_SHADER_STAGE_MESH_BIT_EXT, + supass_shading_huawei = VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI, + undefined + }; + + enum class descriptor_layout_flag { + update_after_bind_pool = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT + push_descriptor_khr = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR + descriptor_buffer_bit_ext = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT + embedded_immutable_samplers_bit_ext = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT, // represents VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT + indirect_bindable_bit_nv = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV + host_only_pool_bit_ext = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT + per_stage_bit_nv = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV + update_after_bind_pool_bit_ext = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT + host_only_pool_bit_valve = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE, // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE + flag_bits_max_enum = + VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM // represents + // VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM + }; + + //! @brief high-level specification for a shader source + struct shader_source { + std::string filename; + shader_stage stage = shader_stage::undefined; + }; + + //! @brief Represent the vulkan shader module that will get utilized by + //! VkPipeline + struct shader_handle { + VkShaderModule module = nullptr; + shader_stage stage = shader_stage::undefined; + }; + + struct vertex_attribute_entry { + uint32_t location; + format format; + uint32_t stride; + }; + + struct vertex_attribute { + uint32_t binding; + std::span entries; + uint32_t stride; + input_rate input_rate; + }; + + struct vertex_input { + glm::vec3 position; + glm::vec3 color; + glm::vec3 normals; + glm::vec2 uv; + + bool operator==(const vertex_input& other) const { + return position == other.position and color == other.color and + uv == other.uv and normals == other.normals; + } + }; + + //! @brief struct for copying from staging buffer to a destination + struct buffer_copy_info { + VkBuffer src; + VkBuffer dst; + }; + + struct vertex_params { + VkPhysicalDeviceMemoryProperties phsyical_memory_properties; + std::span vertices; + std::string debug_name; + PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = + nullptr; + }; + + struct index_params { + VkPhysicalDeviceMemoryProperties phsyical_memory_properties; + std::span indices; + std::string debug_name; + PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = + nullptr; + }; + + struct uniform_params { + // VkPhysicalDevice physical_handle=nullptr; + VkPhysicalDeviceMemoryProperties phsyical_memory_properties; + uint32_t size_bytes = 0; + std::string debug_name; + PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = + nullptr; + }; + + struct descriptor_binding_point { + uint32_t binding; + shader_stage stage; + }; + + struct descriptor_entry { + buffer type; + descriptor_binding_point binding_point; + uint32_t descriptor_count; + }; + + struct write_image { + VkSampler sampler = nullptr; + VkImageView view = nullptr; + // VkImageLayout + // image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_layout layout; + }; + struct write_buffer { + VkBuffer buffer = nullptr; + uint32_t offset = 0; + uint32_t range = 0; + }; + + struct write_buffer_descriptor { + uint32_t dst_binding; + std::span uniforms; + }; + + struct write_image_descriptor { + uint32_t dst_binding; + std::span sample_images; + }; + + struct image_extent { + uint32_t width = 1; + uint32_t height = 1; + }; + + struct image_params { + image_extent extent; + VkFormat format; + memory_property property = memory_property::device_local_bit; + image_aspect_flags aspect = image_aspect_flags::color_bit; + // VkImageUsageFlags usage; + uint32_t usage; + VkImageCreateFlags image_flags = 0; + VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; + uint32_t mip_levels = 1; + uint32_t layer_count = 1; + uint32_t array_layers = 1; + VkPhysicalDeviceMemoryProperties phsyical_memory_properties; + filter_range range{ + .min = VK_FILTER_LINEAR, + .max = VK_FILTER_LINEAR, + }; + // VkSamplerAddressMode addrses_mode_u = + // VK_SAMPLER_ADDRESS_MODE_REPEAT; VkSamplerAddressMode + // addrses_mode_v = VK_SAMPLER_ADDRESS_MODE_REPEAT; + // VkSamplerAddressMode addrses_mode_w = + // VK_SAMPLER_ADDRESS_MODE_REPEAT; + uint32_t addrses_mode_u = sampler_address_mode::repeat; + uint32_t addrses_mode_v = sampler_address_mode::repeat; + uint32_t addrses_mode_w = sampler_address_mode::repeat; + }; + + struct buffer_parameters { + VkDeviceSize device_size = 0; + VkPhysicalDeviceMemoryProperties physical_memory_properties; + memory_property property_flags; + VkBufferUsageFlags usage; + VkSharingMode share_mode = VK_SHARING_MODE_EXCLUSIVE; + const char* debug_name = "NA"; + PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = + nullptr; + }; + + // Used by vk::copy(const VkCommandBuffer& p_current, ) + struct copy_info { + uint32_t width; + uint32_t height; + uint32_t array_layers = 1; + }; + + struct image_barrier_info { + VkFormat format; + VkImageLayout old_layout; + VkImageLayout new_layout; + uint32_t level_count = 1; + VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT; + uint32_t base_array_count = 0; + uint32_t layer_count = 1; + }; + + struct write_info { + uint64_t offset = 0; + uint64_t size_bytes = 0; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/types.hpp b/vulkan-cpp/types.hpp deleted file mode 100644 index df73d5c..0000000 --- a/vulkan-cpp/types.hpp +++ /dev/null @@ -1,1122 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -#include - -namespace vk { - enum format : uint32_t{ - // Core Formats - undefined = VK_FORMAT_UNDEFINED, - r4g4_unorm_pack8 = VK_FORMAT_R4G4_UNORM_PACK8, - r4g4b4a4_unorm_pack16 = VK_FORMAT_R4G4B4A4_UNORM_PACK16, - b4g4r4a4_unorm_pack16 = VK_FORMAT_B4G4R4A4_UNORM_PACK16, - r5g6b5_unorm_pack16 = VK_FORMAT_R5G6B5_UNORM_PACK16, - b5g6r5_unorm_pack16 = VK_FORMAT_B5G6R5_UNORM_PACK16, - r5g5b5a1_unorm_pack16 = VK_FORMAT_R5G5B5A1_UNORM_PACK16, - b5g5r5a1_unorm_pack16 = VK_FORMAT_B5G5R5A1_UNORM_PACK16, - a1r5g5b5_unorm_pack16 = VK_FORMAT_A1R5G5B5_UNORM_PACK16, - r8_unorm = VK_FORMAT_R8_UNORM, - r8_snorm = VK_FORMAT_R8_SNORM, - r8_uscaled = VK_FORMAT_R8_USCALED, - r8_sscaled = VK_FORMAT_R8_SSCALED, - r8_uint = VK_FORMAT_R8_UINT, - r8_sint = VK_FORMAT_R8_SINT, - r8_srgb = VK_FORMAT_R8_SRGB, - r8g8_unorm = VK_FORMAT_R8G8_UNORM, - r8g8_snorm = VK_FORMAT_R8G8_SNORM, - r8g8_uscaled = VK_FORMAT_R8G8_USCALED, - r8g8_sscaled = VK_FORMAT_R8G8_SSCALED, - r8g8_uint = VK_FORMAT_R8G8_UINT, - r8g8_sint = VK_FORMAT_R8G8_SINT, - r8g8_srgb = VK_FORMAT_R8G8_SRGB, - r8g8b8_unorm = VK_FORMAT_R8G8B8_UNORM, - r8g8b8_snorm = VK_FORMAT_R8G8B8_SNORM, - r8g8b8_uscaled = VK_FORMAT_R8G8B8_USCALED, - r8g8b8_sscaled = VK_FORMAT_R8G8B8_SSCALED, - r8g8b8_uint = VK_FORMAT_R8G8B8_UINT, - r8g8b8_sint = VK_FORMAT_R8G8B8_SINT, - r8g8b8_srgb = VK_FORMAT_R8G8B8_SRGB, - b8g8r8_unorm = VK_FORMAT_B8G8R8_UNORM, - b8g8r8_snorm = VK_FORMAT_B8G8R8_SNORM, - b8g8r8_uscaled = VK_FORMAT_B8G8R8_USCALED, - b8g8r8_sscaled = VK_FORMAT_B8G8R8_SSCALED, - b8g8r8_uint = VK_FORMAT_B8G8R8_UINT, - b8g8r8_sint = VK_FORMAT_B8G8R8_SINT, - b8g8r8_srgb = VK_FORMAT_B8G8R8_SRGB, - r8g8b8a8_unorm = VK_FORMAT_R8G8B8A8_UNORM, - r8g8b8a8_snorm = VK_FORMAT_R8G8B8A8_SNORM, - r8g8b8a8_uscaled = VK_FORMAT_R8G8B8A8_USCALED, - r8g8b8a8_sscaled = VK_FORMAT_R8G8B8A8_SSCALED, - r8g8b8a8_uint = VK_FORMAT_R8G8B8A8_UINT, - r8g8b8a8_sint = VK_FORMAT_R8G8B8A8_SINT, - r8g8b8a8_srgb = VK_FORMAT_R8G8B8A8_SRGB, - b8g8r8a8_unorm = VK_FORMAT_B8G8R8A8_UNORM, - b8g8r8a8_snorm = VK_FORMAT_B8G8R8A8_SNORM, - b8g8r8a8_uscaled = VK_FORMAT_B8G8R8A8_USCALED, - b8g8r8a8_sscaled = VK_FORMAT_B8G8R8A8_SSCALED, - b8g8r8a8_uint = VK_FORMAT_B8G8R8A8_UINT, - b8g8r8a8_sint = VK_FORMAT_B8G8R8A8_SINT, - b8g8r8a8_srgb = VK_FORMAT_B8G8R8A8_SRGB, - a8b8g8r8_unorm_pack32 = VK_FORMAT_A8B8G8R8_UNORM_PACK32, - a8b8g8r8_snorm_pack32 = VK_FORMAT_A8B8G8R8_SNORM_PACK32, - a8b8g8r8_uscaled_pack32 = VK_FORMAT_A8B8G8R8_USCALED_PACK32, - a8b8g8r8_sscaled_pack32 = VK_FORMAT_A8B8G8R8_SSCALED_PACK32, - a8b8g8r8_uint_pack32 = VK_FORMAT_A8B8G8R8_UINT_PACK32, - a8b8g8r8_sint_pack32 = VK_FORMAT_A8B8G8R8_SINT_PACK32, - a8b8g8r8_srgb_pack32 = VK_FORMAT_A8B8G8R8_SRGB_PACK32, - a2r10g10b10_unorm_pack32 = VK_FORMAT_A2R10G10B10_UNORM_PACK32, - a2r10g10b10_snorm_pack32 = VK_FORMAT_A2R10G10B10_SNORM_PACK32, - a2r10g10b10_uscaled_pack32 = VK_FORMAT_A2R10G10B10_USCALED_PACK32, - a2r10g10b10_sscaled_pack32 = VK_FORMAT_A2R10G10B10_SSCALED_PACK32, - a2r10g10b10_uint_pack32 = VK_FORMAT_A2R10G10B10_UINT_PACK32, - a2r10g10b10_sint_pack32 = VK_FORMAT_A2R10G10B10_SINT_PACK32, - a2b10g10r10_unorm_pack32 = VK_FORMAT_A2B10G10R10_UNORM_PACK32, - a2b10g10r10_snorm_pack32 = VK_FORMAT_A2B10G10R10_SNORM_PACK32, - a2b10g10r10_uscaled_pack32 = VK_FORMAT_A2B10G10R10_USCALED_PACK32, - a2b10g10r10_sscaled_pack32 = VK_FORMAT_A2B10G10R10_SSCALED_PACK32, - a2b10g10r10_uint_pack32 = VK_FORMAT_A2B10G10R10_UINT_PACK32, - a2b10g10r10_sint_pack32 = VK_FORMAT_A2B10G10R10_SINT_PACK32, - r16_unorm = VK_FORMAT_R16_UNORM, - r16_snorm = VK_FORMAT_R16_SNORM, - r16_uscaled = VK_FORMAT_R16_USCALED, - r16_sscaled = VK_FORMAT_R16_SSCALED, - r16_uint = VK_FORMAT_R16_UINT, - r16_sint = VK_FORMAT_R16_SINT, - r16_sfloat = VK_FORMAT_R16_SFLOAT, - r16g16_unorm = VK_FORMAT_R16G16_UNORM, - r16g16_snorm = VK_FORMAT_R16G16_SNORM, - r16g16_uscaled = VK_FORMAT_R16G16_USCALED, - r16g16_sscaled = VK_FORMAT_R16G16_SSCALED, - r16g16_uint = VK_FORMAT_R16G16_UINT, - r16g16_sint = VK_FORMAT_R16G16_SINT, - r16g16_sfloat = VK_FORMAT_R16G16_SFLOAT, - r16g16b16_unorm = VK_FORMAT_R16G16B16_UNORM, - r16g16b16_snorm = VK_FORMAT_R16G16B16_SNORM, - r16g16b16_uscaled = VK_FORMAT_R16G16B16_USCALED, - r16g16b16_sscaled = VK_FORMAT_R16G16B16_SSCALED, - r16g16b16_uint = VK_FORMAT_R16G16B16_UINT, - r16g16b16_sint = VK_FORMAT_R16G16B16_SINT, - r16g16b16_sfloat = VK_FORMAT_R16G16B16_SFLOAT, - r16g16b16a16_unorm = VK_FORMAT_R16G16B16A16_UNORM, - r16g16b16a16_snorm = VK_FORMAT_R16G16B16A16_SNORM, - r16g16b16a16_uscaled = VK_FORMAT_R16G16B16A16_USCALED, - r16g16b16a16_sscaled = VK_FORMAT_R16G16B16A16_SSCALED, - r16g16b16a16_uint = VK_FORMAT_R16G16B16A16_UINT, - r16g16b16a16_sint = VK_FORMAT_R16G16B16A16_SINT, - r16g16b16a16_sfloat = VK_FORMAT_R16G16B16A16_SFLOAT, - r32_uint = VK_FORMAT_R32_UINT, - r32_sint = VK_FORMAT_R32_SINT, - r32_sfloat = VK_FORMAT_R32_SFLOAT, - rg32_uint = VK_FORMAT_R32G32_UINT, - rg32_sint = VK_FORMAT_R32G32_SINT, - rg32_sfloat = VK_FORMAT_R32G32_SFLOAT, - rgb32_uint = VK_FORMAT_R32G32B32_UINT, - rgb32_sint = VK_FORMAT_R32G32B32_SINT, - rgb32_sfloat = VK_FORMAT_R32G32B32_SFLOAT, // Example from prompt: VK_FORMAT_R32G32B32_SFLOAT - rgba_uint = VK_FORMAT_R32G32B32A32_UINT, - rgba_sint = VK_FORMAT_R32G32B32A32_SINT, - rgba_sfloat = VK_FORMAT_R32G32B32A32_SFLOAT, - r64_uint = VK_FORMAT_R64_UINT, - r64_sint = VK_FORMAT_R64_SINT, - r64_sfloat = VK_FORMAT_R64_SFLOAT, - rg64_uint = VK_FORMAT_R64G64_UINT, - rg64_sint = VK_FORMAT_R64G64_SINT, - rg64_sfloat = VK_FORMAT_R64G64_SFLOAT, - rgb64_uint = VK_FORMAT_R64G64B64_UINT, - rgb64_sint = VK_FORMAT_R64G64B64_SINT, - rgb64_sfloat = VK_FORMAT_R64G64B64_SFLOAT, - rgba64_uint = VK_FORMAT_R64G64B64A64_UINT, - rgba64_sint = VK_FORMAT_R64G64B64A64_SINT, - r64g64b64a64_sfloat = VK_FORMAT_R64G64B64A64_SFLOAT, - b10g11r11_ufloat_pack32 = VK_FORMAT_B10G11R11_UFLOAT_PACK32, - e5b9g9r9_ufloat_pack32 = VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, - - // Depth/Stencil Formats - d16_unorm = VK_FORMAT_D16_UNORM, - x8_d24_unorm_pack32 = VK_FORMAT_X8_D24_UNORM_PACK32, - d32_sfloat = VK_FORMAT_D32_SFLOAT, - s8_uint = VK_FORMAT_S8_UINT, - d16_unorm_s8_uint = VK_FORMAT_D16_UNORM_S8_UINT, - d24_unorm_s8_uint = VK_FORMAT_D24_UNORM_S8_UINT, - d32_sfloat_s8_uint = VK_FORMAT_D32_SFLOAT_S8_UINT, - - // Compressed Formats (BC) - bc1_rgb_unorm_block = VK_FORMAT_BC1_RGB_UNORM_BLOCK, - bc1_rgb_srgb_block = VK_FORMAT_BC1_RGB_SRGB_BLOCK, - bc1_rgba_unorm_block = VK_FORMAT_BC1_RGBA_UNORM_BLOCK, - bc1_rgba_srgb_block = VK_FORMAT_BC1_RGBA_SRGB_BLOCK, - bc2_unorm_block = VK_FORMAT_BC2_UNORM_BLOCK, - bc2_srgb_block = VK_FORMAT_BC2_SRGB_BLOCK, - bc3_unorm_block = VK_FORMAT_BC3_UNORM_BLOCK, - bc3_srgb_block = VK_FORMAT_BC3_SRGB_BLOCK, - bc4_unorm_block = VK_FORMAT_BC4_UNORM_BLOCK, - bc4_snorm_block = VK_FORMAT_BC4_SNORM_BLOCK, - bc5_unorm_block = VK_FORMAT_BC5_UNORM_BLOCK, - bc5_snorm_block = VK_FORMAT_BC5_SNORM_BLOCK, - bc6h_ufloat_block = VK_FORMAT_BC6H_UFLOAT_BLOCK, - bc6h_sfloat_block = VK_FORMAT_BC6H_SFLOAT_BLOCK, - bc7_unorm_block = VK_FORMAT_BC7_UNORM_BLOCK, - bc7_srgb_block = VK_FORMAT_BC7_SRGB_BLOCK, - - // Compressed Formats (ETC2/EAC) - etc2_r8g8b8_unorm_block = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, - etc2_r8g8b8_srgb_block = VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, - etc2_r8g8b8a1_unorm_block = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, - etc2_r8g8b8a1_srgb_block = VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, - etc2_r8g8b8a8_unorm_block = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, - etc2_r8g8b8a8_srgb_block = VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, - eac_r11_unorm_block = VK_FORMAT_EAC_R11_UNORM_BLOCK, - eac_r11_snorm_block = VK_FORMAT_EAC_R11_SNORM_BLOCK, - eac_r11g11_unorm_block = VK_FORMAT_EAC_R11G11_UNORM_BLOCK, - eac_r11g11_snorm_block = VK_FORMAT_EAC_R11G11_SNORM_BLOCK, - - // Compressed Formats (ASTC) - astc_4x4_unorm_block = VK_FORMAT_ASTC_4x4_UNORM_BLOCK, - astc_4x4_srgb_block = VK_FORMAT_ASTC_4x4_SRGB_BLOCK, - astc_5x4_unorm_block = VK_FORMAT_ASTC_5x4_UNORM_BLOCK, - astc_5x4_srgb_block = VK_FORMAT_ASTC_5x4_SRGB_BLOCK, - astc_5x5_unorm_block = VK_FORMAT_ASTC_5x5_UNORM_BLOCK, - astc_5x5_srgb_block = VK_FORMAT_ASTC_5x5_SRGB_BLOCK, - astc_6x5_unorm_block = VK_FORMAT_ASTC_6x5_UNORM_BLOCK, - astc_6x5_srgb_block = VK_FORMAT_ASTC_6x5_SRGB_BLOCK, - astc_6x6_unorm_block = VK_FORMAT_ASTC_6x6_UNORM_BLOCK, - astc_6x6_srgb_block = VK_FORMAT_ASTC_6x6_SRGB_BLOCK, - astc_8x5_unorm_block = VK_FORMAT_ASTC_8x5_UNORM_BLOCK, - astc_8x5_srgb_block = VK_FORMAT_ASTC_8x5_SRGB_BLOCK, - astc_8x6_unorm_block = VK_FORMAT_ASTC_8x6_UNORM_BLOCK, - astc_8x6_srgb_block = VK_FORMAT_ASTC_8x6_SRGB_BLOCK, - astc_8x8_unorm_block = VK_FORMAT_ASTC_8x8_UNORM_BLOCK, - astc_8x8_srgb_block = VK_FORMAT_ASTC_8x8_SRGB_BLOCK, - astc_10x5_unorm_block = VK_FORMAT_ASTC_10x5_UNORM_BLOCK, - astc_10x5_srgb_block = VK_FORMAT_ASTC_10x5_SRGB_BLOCK, - astc_10x6_unorm_block = VK_FORMAT_ASTC_10x6_UNORM_BLOCK, - astc_10x6_srgb_block = VK_FORMAT_ASTC_10x6_SRGB_BLOCK, - astc_10x8_unorm_block = VK_FORMAT_ASTC_10x8_UNORM_BLOCK, - astc_10x8_srgb_block = VK_FORMAT_ASTC_10x8_SRGB_BLOCK, - astc_10x10_unorm_block = VK_FORMAT_ASTC_10x10_UNORM_BLOCK, - astc_10x10_srgb_block = VK_FORMAT_ASTC_10x10_SRGB_BLOCK, - astc_12x10_unorm_block = VK_FORMAT_ASTC_12x10_UNORM_BLOCK, - astc_12x10_srgb_block = VK_FORMAT_ASTC_12x10_SRGB_BLOCK, - astc_12x12_unorm_block = VK_FORMAT_ASTC_12x12_UNORM_BLOCK, - astc_12x12_srgb_block = VK_FORMAT_ASTC_12x12_SRGB_BLOCK, - - // YCbCr Formats (KHR Extension, now Core in 1.1) - g8b8g8r8_422_unorm = VK_FORMAT_G8B8G8R8_422_UNORM, - b8g8r8g8_422_unorm = VK_FORMAT_B8G8R8G8_422_UNORM, - g8_b8_r8_3plane_420_unorm = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, - g8_b8r8_2plane_420_unorm = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, - g8_b8_r8_3plane_422_unorm = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, - g8_b8r8_2plane_422_unorm = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, - g8_b8_r8_3plane_444_unorm = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, - r10x6_unorm_pack16 = VK_FORMAT_R10X6_UNORM_PACK16, - r10x6g10x6_unorm_2pack16 = VK_FORMAT_R10X6G10X6_UNORM_2PACK16, - r10x6g10x6b10x6a10x6_unorm_4pack16 = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, - g10x6b10x6g10x6r10x6_422_unorm_4pack16 = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, - b10x6g10x6r10x6g10x6_422_unorm_4pack16 = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, - g10x6_b10x6_r10x6_3plane_420_unorm_3pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, - g10x6_b10x6r10x6_2plane_420_unorm_3pack16 = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, - g10x6_b10x6_r10x6_3plane_422_unorm_3pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, - g10x6_b10x6r10x6_2plane_422_unorm_3pack16 = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, - g10x6_b10x6_r10x6_3plane_444_unorm_3pack16 = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, - r12x4_unorm_pack16 = VK_FORMAT_R12X4_UNORM_PACK16, - r12x4g12x4_unorm_2pack16 = VK_FORMAT_R12X4G12X4_UNORM_2PACK16, - r12x4g12x4b12x4a12x4_unorm_4pack16 = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, - g12x4b12x4g12x4r12x4_422_unorm_4pack16 = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, - b12x4g12x4r12x4g12x4_422_unorm_4pack16 = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, - g12x4_b12x4_r12x4_3plane_420_unorm_3pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, - g12x4_b12x4r12x4_2plane_420_unorm_3pack16 = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, - g12x4_b12x4_r12x4_3plane_422_unorm_3pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, - g12x4_b12x4r12x4_2plane_422_unorm_3pack16 = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, - g12x4_b12x4_r12x4_3plane_444_unorm_3pack16 = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, - g16b16g16r16_422_unorm = VK_FORMAT_G16B16G16R16_422_UNORM, - b16g16r16g16_422_unorm = VK_FORMAT_B16G16R16G16_422_UNORM, - g16_b16_r16_3plane_420_unorm = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, - g16_b16r16_2plane_420_unorm = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, - g16_b16_r16_3plane_422_unorm = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, - g16_b16r16_2plane_422_unorm = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, - g16_b16_r16_3plane_444_unorm = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, - - // EXT/Vendor YCbCr Formats - g8_b8r8_2plane_444_unorm = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, - g10x6_b10x6r10x6_2plane_444_unorm_3pack16 = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16, - g12x4_b12x4r12x4_2plane_444_unorm_3pack16 = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16, - g16_b16r16_2plane_444_unorm = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, - - // EXT Packed Formats - a4r4g4b4_unorm_pack16 = VK_FORMAT_A4R4G4B4_UNORM_PACK16, - a4b4g4r4_unorm_pack16 = VK_FORMAT_A4B4G4R4_UNORM_PACK16, - - // ASTC SFLOAT Formats - astc_4x4_sfloat_block = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, - astc_5x4_sfloat_block = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK, - astc_5x5_sfloat_block = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK, - astc_6x5_sfloat_block = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK, - astc_6x6_sfloat_block = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK, - astc_8x5_sfloat_block = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK, - astc_8x6_sfloat_block = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK, - astc_8x8_sfloat_block = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK, - astc_10x5_sfloat_block = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK, - astc_10x6_sfloat_block = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK, - astc_10x8_sfloat_block = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK, - astc_10x10_sfloat_block = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK, - astc_12x10_sfloat_block = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK, - astc_12x12_sfloat_block = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK, - - // PVRTC Formats (IMG Vendor) - pvrtc1_2bpp_unorm_block_img = VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, - pvrtc1_4bpp_unorm_block_img = VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, - pvrtc2_2bpp_unorm_block_img = VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, - pvrtc2_4bpp_unorm_block_img = VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, - pvrtc1_2bpp_srgb_block_img = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, - pvrtc1_4bpp_srgb_block_img = VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, - pvrtc2_2bpp_srgb_block_img = VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, - pvrtc2_4bpp_srgb_block_img = VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, - - // Vendor Specific (NV) - r16g16_sfixed5_nv = VK_FORMAT_R16G16_SFIXED5_NV, - - // KHR/EXT Aliases (A1B5G5R5, A8) - a1b5g5r5_unorm_pack16_khr = VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR, - a8_unorm_khr = VK_FORMAT_A8_UNORM_KHR, - - // Aliases to Core Formats - // ASTC SFLOAT EXT Aliases - astc_4x4_sfloat_block_ext = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, - astc_5x4_sfloat_block_ext = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, - astc_5x5_sfloat_block_ext = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, - astc_6x5_sfloat_block_ext = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, - astc_6x6_sfloat_block_ext = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, - astc_8x5_sfloat_block_ext = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, - astc_8x6_sfloat_block_ext = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, - astc_8x8_sfloat_block_ext = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, - astc_10x5_sfloat_block_ext = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, - astc_10x6_sfloat_block_ext = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, - astc_10x8_sfloat_block_ext = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, - astc_10x10_sfloat_block_ext = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, - astc_12x10_sfloat_block_ext = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, - astc_12x12_sfloat_block_ext = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, - - // YCbCr KHR Aliases - g8b8g8r8_422_unorm_khr = VK_FORMAT_G8B8G8R8_422_UNORM_KHR, - b8g8r8g8_422_unorm_khr = VK_FORMAT_B8G8R8G8_422_UNORM_KHR, - g8_b8_r8_3plane_420_unorm_khr = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM_KHR, - g8_b8r8_2plane_420_unorm_khr = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM_KHR, - g8_b8_r8_3plane_422_unorm_khr = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM_KHR, - g8_b8r8_2plane_422_unorm_khr = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM_KHR, - g8_b8_r8_3plane_444_unorm_khr = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM_KHR, - r10x6_unorm_pack16_khr = VK_FORMAT_R10X6_UNORM_PACK16_KHR, - r10x6g10x6_unorm_2pack16_khr = VK_FORMAT_R10X6G10X6_UNORM_2PACK16_KHR, - r10x6g10x6b10x6a10x6_unorm_4pack16_khr = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16_KHR, - g10x6b10x6g10x6r10x6_422_unorm_4pack16_khr = VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16_KHR, - b10x6g10x6r10x6g10x6_422_unorm_4pack16_khr = VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16_KHR, - g10x6_b10x6_r10x6_3plane_420_unorm_3pack16_khr = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_KHR, - g10x6_b10x6r10x6_2plane_420_unorm_3pack16_khr = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_KHR, - g10x6_b10x6_r10x6_3plane_422_unorm_3pack16_khr = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16_KHR, - g10x6_b10x6r10x6_2plane_422_unorm_3pack16_khr = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16_KHR, - g10x6_b10x6_r10x6_3plane_444_unorm_3pack16_khr = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16_KHR, - r12x4_unorm_pack16_khr = VK_FORMAT_R12X4_UNORM_PACK16_KHR, - r12x4g12x4_unorm_2pack16_khr = VK_FORMAT_R12X4G12X4_UNORM_2PACK16_KHR, - r12x4g12x4b12x4a12x4_unorm_4pack16_khr = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16_KHR, - g12x4b12x4g12x4r12x4_422_unorm_4pack16_khr = VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16_KHR, - b12x4g12x4r12x4g12x4_422_unorm_4pack16_khr = VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16_KHR, - g12x4_b12x4_r12x4_3plane_420_unorm_3pack16_khr = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_KHR, - g12x4_b12x4r12x4_2plane_420_unorm_3pack16_khr = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_KHR, - g12x4_b12x4_r12x4_3plane_422_unorm_3pack16_khr = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16_KHR, - g12x4_b12x4r12x4_2plane_422_unorm_3pack16_khr = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16_KHR, - g12x4_b12x4_r12x4_3plane_444_unorm_3pack16_khr = VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16_KHR, - g16b16g16r16_422_unorm_khr = VK_FORMAT_G16B16G16R16_422_UNORM_KHR, - b16g16r16g16_422_unorm_khr = VK_FORMAT_B16G16R16G16_422_UNORM_KHR, - g16_b16_r16_3plane_420_unorm_khr = VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM_KHR, - g16_b16r16_2plane_420_unorm_khr = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM_KHR, - g16_b16_r16_3plane_422_unorm_khr = VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM_KHR, - g16_b16r16_2plane_422_unorm_khr = VK_FORMAT_G16_B16R16_2PLANE_422_UNORM_KHR, - g16_b16_r16_3plane_444_unorm_khr = VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM_KHR, - - // YCbCr EXT Aliases - g8_b8r8_2plane_444_unorm_ext = VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT, - g10x6_b10x6r10x6_2plane_444_unorm_3pack16_ext = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT, - g12x4_b12x4r12x4_2plane_444_unorm_3pack16_ext = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT, - g16_b16r16_2plane_444_unorm_ext = VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT, - - // A4 Packed EXT Aliases - a4r4g4b4_unorm_pack16_ext = VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, - a4b4g4r4_unorm_pack16_ext = VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, - - // NV Alias - r16g16_s10_5_nv = VK_FORMAT_R16G16_S10_5_NV, - - // Max Enum - max_enum_format = VK_FORMAT_MAX_ENUM - }; - - enum image_aspect_flags : uint32_t { - color_bit = VK_IMAGE_ASPECT_COLOR_BIT, - depth_bit = VK_IMAGE_ASPECT_DEPTH_BIT, - stencil_bit = VK_IMAGE_ASPECT_STENCIL_BIT, - metadata_bit = VK_IMAGE_ASPECT_METADATA_BIT, - plane0_bit = VK_IMAGE_ASPECT_PLANE_0_BIT, - plane1_bit = VK_IMAGE_ASPECT_PLANE_1_BIT, - plane2_bit = VK_IMAGE_ASPECT_PLANE_2_BIT, - none = VK_IMAGE_ASPECT_NONE, - memory_plane0_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, - memory_plane1_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, - memory_plane2_bit_ext = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT, - plane1_bit_khr = VK_IMAGE_ASPECT_PLANE_1_BIT_KHR, - plane2_bit_khr = VK_IMAGE_ASPECT_PLANE_2_BIT_KHR, - none_khr = VK_IMAGE_ASPECT_NONE_KHR, - bits_max_enum = VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM - }; - - /** - * @brief message sevierity explicitly to max size of a byte - */ - enum message : uint32_t { - verbose = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, - info = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, - warning = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, - error = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - max_num = VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT - }; - - enum debug : uint32_t { - general = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, - validation = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, - performance = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - device_address_binding_ext = VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT, - max_enum = VK_DEBUG_UTILS_MESSAGE_TYPE_FLAG_BITS_MAX_ENUM_EXT - }; - - enum class api_version : uint32_t { - vk_1_2 = VK_API_VERSION_1_2, - vk_1_3 = VK_API_VERSION_1_3, // vulkan version 1.3 - // vk_1_2, // vulkan version 1.4 - }; - - struct debug_message_utility { - uint32_t severity; - uint32_t message_type; - uint32_t (*callback)(VkDebugUtilsMessageSeverityFlagBitsEXT, - VkDebugUtilsMessageTypeFlagsEXT, - const VkDebugUtilsMessengerCallbackDataEXT*, - void*) = nullptr; - }; - - struct application_params { - std::string name = ""; - api_version version; - std::span validations; - std::span extensions; - }; - - struct swapchain_params { - uint32_t width; - uint32_t height; - uint32_t present_index = -1; - - VkFormat depth; // depth format - }; - - struct filter_range { - VkFilter min; - VkFilter max; - }; - - struct layer_properties { - std::string name; - uint32_t version; - uint32_t impl_version; - std::string description; - }; - - //! @brief vk::physical defines what kinds of physical device specification - //! to use that is available based on your current physical hardware - //! specifications. - enum class physical { - integrated, - discrete, - virtualized, - cpu, - max_enum, - other - }; - - /** - * @brief Enumeration represents configuration for the physical device - * - * Defines the configuration for the VkPhysicalDevice handler to be created - * with - */ - struct physical_enumeration { - physical device_type; - }; - - struct surface_params { - VkSurfaceCapabilitiesKHR capabilities; - VkSurfaceFormatKHR format; - }; - - struct queue_params { - uint32_t family = -1; - uint32_t index = -1; - }; - - struct queue_indices { - uint32_t graphics = -1; - uint32_t compute = -1; - uint32_t transfer = -1; - }; - - struct device_params { - std::span queue_priorities{}; - std::span - extensions{}; // Can add VK_KHR_SWAPCHAIN_EXTENSION_NAME to this - // extension - uint32_t queue_family_index = 0; - }; - - // raw image handlers - // struct image { - // VkImage image = nullptr; - // VkImageView view = nullptr; - // }; - - // sampler + raw image handlers - // struct sampled_image { - // VkImage image = nullptr; - // VkImageView view = nullptr; - // VkSampler sampler = nullptr; - // VkDeviceMemory device_memory = nullptr; - // }; - - //! @brief enumeration if an image is provided - // struct swapchain_image_enumeration { - // VkImage image = nullptr; - // VkFormat format; - // // VkImageAspectFlags aspect; - // image_aspect_flags aspect; - // uint32_t layer_count = 0; - // uint32_t mip_levels = 1; - // }; - - // Image enumeration for creating a brand new VkImage/VkImageView handlers - // struct image_enumeration { - // uint32_t width = -1; - // uint32_t height = -1; - // VkFormat format; - // // VkImageAspectFlags aspect; - // image_aspect_flags aspect; - // uint32_t layer_count = 1; - // uint32_t mip_levels = 1; - // }; - - /** - * @param renderpass vulkan requires framebuffers to know renderpasses up - * front - * @param views framebuffers provide the actual image views that will serve - * as attachments to the renderpass handle - * @param extent are for framebuffers to pass in frame image views to the - * screen. Should be the size of the window viewport specified - */ - struct framebuffer_params { - VkRenderPass renderpass = nullptr; - std::span views; - VkExtent2D extent; - }; - - /** - * @param Primary - * submission: immediately to vulkan queue for executing on device - * execution: vkQueueSubmit primarily submits primary command buffers - * - * @param Seconary - * submission: Cannot be submitted directly to vulkan queue - * execution: Indirect execution by being called from primary command - * buffers using `vkCmdExecuteCommands` - * - * When executed within render-pass instance, they inherit - * renderpass/subpass state from primary command buffer - * - * Can be allocated and recorded in parallel, which can leverage - * devices that support multi-core processing - * - * Have independent lifetimes that can be managed independently of - * primary command buffers, allowing for more flexible resource management - */ - enum class command_levels : uint32_t { - primary = 0, - secondary = 1, - max_enum = VK_COMMAND_BUFFER_LEVEL_MAX_ENUM, - }; - - /** - * @param transient represents VK_COMMAND_POOL_CREATE_TRANSIENT_BIT - * - * Usage: specifies command buffers allocated from pool are short-lived, - * meaning they will reset or be freed in a short time-frame. Flag may also - * be used by implementation to control memory allocation behavior within - * the pool - * - * @param reset represents VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT - * - * Usage: Allows command buffers allocated from the pool to be individually - * reset to their initial state; either by calling vkResetCommandBuffer or - * implicit reset when calling vkBeginCommandBuffer - * - * @param protected_bit represents VK_COMMAND_POOL_CREATE_PROTECTED_BIT - * - * Usage: Specifies command buffers allocated from pool are protected - * command buffers; meaning the the memory allocated with the command pool - * is protected - * - * - */ - enum command_pool_flags : uint32_t { - transient = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // represents VK_COMMAND_POOL_CREATE_TRANSIENT_BIT - reset = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // represents VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT - protected_bit = VK_COMMAND_POOL_CREATE_PROTECTED_BIT, // represents VK_COMMAND_POOL_CREATE_PROTECTED_BIT - max_enum_bit = VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM, // represents VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM - }; - - /** - * @brief settings for specifying command buffers to construct - * - * @param Levels are for specifying the kind of command buffer being - * constructed - * - * queue_index specifies the queue family associated with this - * command buffer - * - * pool_flag in the context of the command buffers are used to - * control memory allocation behavior within the command buffer pool to - * allocate - * - * @param VK_COMMAND_POOL_CREATE_TRANSIENT_BIT Indicates command buffers - * allocated from pool will be short-lived, meaning they'll reset or freed - * quickly - * @param VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT Allows individual - * command buffers allocated from the pool to be reset to their initial - * state using `vkResetCommandBuffer` - * @param VK_COMMAND_POOL_CREATE_PROTECTED_BIT Designates command buffers - * allocated from the pool as protective command buffers, implying they are - * stored in protected memory and access to them is restricted to authorized - * operations - */ - struct command_params { - - command_levels levels; - uint32_t queue_index = -1; - // VkCommandPoolCreateFlagBits pool_flag; - command_pool_flags flags; - }; - - struct renderpass_attachments { - std::span clear_values{}; - std::span attachments{}; - std::span subpass_descriptions{}; - std::span dependencies{}; - }; - - enum subpass_contents : uint32_t { - inline_bit = VK_SUBPASS_CONTENTS_INLINE, // represents VK_SUBPASS_CONTENTS_INLINE - secondary_command = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, // represents VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - inline_and_secondary_command_khr = VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR, // represents - // VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_KHR - // and - // VK_SUBPASS_CONTENTS_INLINE_AND_SECONDARY_COMMAND_BUFFERS_EXT - max_enum_content = VK_SUBPASS_CONTENTS_MAX_ENUM // represents VK_SUBPASS_CONTENTS_MAX_ENUM - }; - - enum class image_layout : uint32_t { - undefined = VK_IMAGE_LAYOUT_UNDEFINED, // VK_IMAGE_LAYOUT_UNDEFINED - general = VK_IMAGE_LAYOUT_GENERAL, // VK_IMAGE_LAYOUT_GENERAL - color_optimal = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - depth_stencil_optimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL - depth_stencil_read_only_optimal = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, // VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_READ_ONLY_OPTIMAL - present_src_khr = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR - shader_read_only_optimal = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - }; - - // enum class format : uint64_t { - // rgb32_sfloat, // Represent R32G32B32_SFLOAT - // rg32_sfloat, // Represent R32G32_SFLOAT - // }; - - enum buffer : uint8_t { - uniform = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // represents VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER - storage = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // represents VK_DESCRIPTOR_TYPE_STORAGE_BUFFER - combined_image_sampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // represents VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER - sampled_only_image = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE // represents VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE - }; - - enum image_usage : uint32_t { - transfer_src_bit = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - transfer_dst_bit = VK_IMAGE_USAGE_TRANSFER_DST_BIT, - sampled_bit = VK_IMAGE_USAGE_SAMPLED_BIT, - storage_bit = VK_IMAGE_USAGE_STORAGE_BIT, - color_attachment_bit = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - depth_stencil_bit = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - transient_attachment_bit = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, - input_attachment_bit= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, - video_decide_dst_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR, - video_decode_src_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR, - video_decode_dpb_bit_khr = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR, - fragment_density_map_bit_ext = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT, - fragment_shading_rate_attachment_bit_khr = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, - host_transfer_bit_ext = VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT, - video_encode_dst_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR, - video_encode_src_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, - video_encode_dpb_bit_khr = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR, - attachment_feedback_loop_bit_ext = VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, - invocation_mask_bit_huawei = VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI, - sample_weight_bit_qcom = VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM, - sample_block_mtch_bit_qcom = VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM, - shading_rate_image_bit_nv = VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV, - max_enum_usage = VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM - }; - - enum sampler_address_mode : uint32_t { - repeat = VK_SAMPLER_ADDRESS_MODE_REPEAT, - mirrored_repeat = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, - clamp_to_edge = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - clamp_to_border = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - mirror_clamp_to_edge = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, - mirror_clamp_to_edge_khr = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE_KHR, - max_enum_address_mode = VK_SAMPLER_ADDRESS_MODE_MAX_ENUM - }; - - /** - * @brief Refers to the input rate - * - * vertex - refers to most common rate. Indicates GPU to move next data - * entry (next vertex data) into a buffer for every single vertex that's - * processed. - * - Used for vertex attributes that change per vertex on the mesh - * - vertex attribute-only data - * - Per-object based specification in the next data entry - * - * instance - refers to data entry per-instance. Specifying to the GPU that - * the data entry in the buffer is to be after the instance of the - * object itself. - * - Typically used for instanced rendering. Specfying next entry of - * data to be after instanced drawn, could be shared. Therefore instance is - * an option to choose from if vertex data is across as a per-instance - * basis. - * - instance-based specification next data entry - * - */ - enum class input_rate : uint8_t { - vertex, - instance, - max_enum, - }; - - //! @brief Equivalent to doing VkSampleCountFlagBits but simplified - enum class sample_bit : uint32_t { - count_1 = VK_SAMPLE_COUNT_1_BIT, - count_2 = VK_SAMPLE_COUNT_2_BIT, - count_4 = VK_SAMPLE_COUNT_4_BIT, - count_8 = VK_SAMPLE_COUNT_8_BIT, - count_16 = VK_SAMPLE_COUNT_16_BIT, - count_32 = VK_SAMPLE_COUNT_32_BIT, - count_64 = VK_SAMPLE_COUNT_64_BIT, - max_enum = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM - }; - - //! @brief Equivalent to VkAttachmentLoadOp - enum class attachment_load : uint32_t { - load = VK_ATTACHMENT_LOAD_OP_LOAD, // LOAD_OP_LOAD - clear = VK_ATTACHMENT_LOAD_OP_CLEAR, // LOAD_OP_CLEAR - dont_care = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // lOAD_OP_DONT_CARE - none_khr = VK_ATTACHMENT_LOAD_OP_NONE_KHR, // LOAD_OP_NONE_KHR - none_ext = VK_ATTACHMENT_LOAD_OP_NONE_KHR, // LOAD_OP_NONE_EXT - max_enum = VK_ATTACHMENT_LOAD_OP_MAX_ENUM, // LOAD_OP_MAX_ENUM - }; - - //! @brief Equivalent to VkAttachmentStoreOp - enum class attachment_store : uint32_t { - store = VK_ATTACHMENT_STORE_OP_STORE, // STORE_OP_STORE - dont_care = VK_ATTACHMENT_STORE_OP_DONT_CARE, // STORE_OP_CLEAR - none_khr = VK_ATTACHMENT_STORE_OP_NONE_KHR, // STORE_OP_NONE - none_qcom = VK_ATTACHMENT_STORE_OP_NONE_QCOM, // STORE_OP_NONE_EXT - none_ext = VK_ATTACHMENT_STORE_OP_NONE_EXT, // STORE_OP_NONE_KHR - max_enum = VK_ATTACHMENT_STORE_OP_MAX_ENUM, // STORE_OP_MAX_ENUM - }; - - enum class pipeline_stage_flags : uint32_t { - top_of_pipe = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - draw_indirect = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, - vertex_input_bit = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, - vertex_shader_bit = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, - tesselation_control_shader_bit = VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, - tessellation_evaluation_shader_bit = VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, - geoemtry_shaders_bit = VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, - fragment_shaders_bit = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - early_fragment_shader_bit = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, - late_fragment_tests_bit = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - color_attachment_output = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - compute_shader_bit = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - transient_bit = VK_PIPELINE_STAGE_TRANSFER_BIT, - bottom_of_pipe = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - host_bit = VK_PIPELINE_STAGE_HOST_BIT, - all_graphics_bit = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - all_commands_bit = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - none = VK_PIPELINE_STAGE_NONE, - transform_feedback_bit_ext = VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, - conditional_rendering_bit_ext = VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT, - acceleration_build_bit_khr = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, - ray_tracing_shader_bit_khr = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, - fragment_density_process_bit_ext = VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT, - command_preprocess_bit_nv = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV, - task_shader_bit_ext = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT, - mesh_shader_bit_ext = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT, - shading_rate_image_bit_nv = VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV, - ray_tracing_shader_bit_nv = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV, - task_shader_bit_nv = VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV, - mesh_shader_bit_nv = VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV, - none_khr = VK_PIPELINE_STAGE_NONE_KHR, - flag_bits_max_enum = VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM - }; - - //! @brief Equivalent to VkPipelineBindPoint - enum class pipeline_bind_point : uint64_t { - graphics = VK_PIPELINE_BIND_POINT_GRAPHICS, // VK_PIPELINE_BIND_POINT_GRAPHICS - compute = VK_PIPELINE_BIND_POINT_COMPUTE, // VK_PIPELINE_BIND_POINT_COMPUTE - ray_tracing_khr = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, // VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR - subpass_shading_hauwei = VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI, // VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI - ray_tracing_nv = VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, // VK_PIPELINE_BIND_POINT_RAY_TRACING_NV - max_enum = VK_PIPELINE_BIND_POINT_MAX_ENUM // VK_PIPELINE_BIND_POINT_MAX_ENUM - }; - - /** - * @brief Specifies a specific attachment that a renderpass may operate - * using - * - * Renderpasses can consist of multiple attachment that can be specified - * under this one struct to represent both the VkAttachmentDescription and - * VkAttachmentReference - */ - struct attachment { - VkFormat format; - image_layout layout; // specify for VkAttachmentReference - sample_bit samples; - attachment_load load; - attachment_store store; - attachment_load stencil_load; - attachment_store stencil_store; - image_layout initial_layout; - image_layout final_layout; - }; - - struct renderpass_begin_params { - VkCommandBuffer current_command = nullptr; - VkExtent2D extent; - VkFramebuffer current_framebuffer = nullptr; - std::array color; - subpass_contents subpass; - }; - - //! @brief Bits that 1-to-1 map to VkCommandUsageFlags - enum command_usage : uint32_t { - one_time_submit = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // Represents VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - renderpass_continue_bit = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // Represents VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT - simulatneous_use_bit = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // Represents VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT - max_bit = VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM // Represents VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM - }; - - /** - * @brief memory_property is a representation of vulkan's - * VkMemoryPropertyFlags. - * - * @param device_local_bit - * - * Meaning: indicates memory allocated with this type is most efficient for - * the GPU to access. \n - * - * Implications: The memory with this bit typically - * resides on the GPU's VRAM. Accessing memory directly from GPU's since its - * faster. \n - * - * Usage: For resources that are primarily accessed by the GPU in the - * case of textures, vertex buffers, and framebuffers. If a memory type has - * this bit associated with it, the heap memory will also have be set along - * with VK_MEMORY_HEAP_DEVICE_LOCAL_BIT. \n - * - * @param host_visible_bit - * - * Meaning: Indicates memory alloated can be mapped to host's (CPU) address - * space using the vkMapMemory API. \n - * - * Implications: ALlows CPU to directly - * read from and write to memory. Crucial for transferring data between CPU - * to GPU. \n - * - * Usage: Use-case is for staging buffers, where data initially - * uploaded from CPU before being copied to device-local memory or for - * resourcfes that need frequent CPU updates. \n - * - * @param host_coherent_bit - * - * Meaning: Indicates host cache managemnet commands - * (vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges) are not - * needed. Writes made by host will automatically become visible to the - * device, and writes made by device will automatically be visible to the - * host. \n - * - * Implications: Simplifies memory synchronization between CPU and GPU. - * Though can lead to slower CPU access if it means bypassing the CPU caches - * or involving more complex cache coherence protocols. \n - * - * Usage: Used with 'VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT' for easy data - * transfers, especially for frequent updated data where manual flushing - * would be cumbersome. \n - * - * - * @param host_cached_bit - * - * Meaning: Indicates memory allocated with this type is cached on the host - * (CPU). \n - * - * Implications: Host memory accesses (read/writes) to this memory - * type will go through CPU cache heirarchy. Significantly improves - * performance where random access patterns. If not set on `HOST_VISIBLE` - * memory, CPU accesses are often uncached and write-combined, meanming - * writes should be sequential and reads should be avoided for good - * performance. \n - * - * Usage: Does well for CPU-side reading of data written to GPU (screenshots - * or feedback data) and for CPU-side writing of data to be accessed - * randomly. Flag usually implies explicit cache management - * (flushing/invalidating) is required if `HOST_COHERENT_BIT` is not also - * set. \n - * - * - */ - enum memory_property : uint32_t { - device_local_bit = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - host_visible_bit = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - host_coherent_bit = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - host_cached_bit = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - lazily_allocated_bit = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, - device_protected_bit = VK_MEMORY_PROPERTY_PROTECTED_BIT, - device_coherent_bit_amd = VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD, - device_uncached_bit_amd = VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD, - rdma_capable_bit_nv = VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV, - flag_bits_max_enum = VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM - }; - - enum class shader_stage { - vertex = VK_SHADER_STAGE_VERTEX_BIT, - fragment = VK_SHADER_STAGE_FRAGMENT_BIT, - compute = VK_SHADER_STAGE_COMPUTE_BIT, - geometry = VK_SHADER_STAGE_GEOMETRY_BIT, - all_graphics = VK_SHADER_STAGE_ALL_GRAPHICS, - all = VK_SHADER_STAGE_ALL, - raygen_khr = VK_SHADER_STAGE_RAYGEN_BIT_KHR, - raygen_nv = VK_SHADER_STAGE_RAYGEN_BIT_NV, - any_hit_kht = VK_SHADER_STAGE_ANY_HIT_BIT_KHR, - closest_hit_khr = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, - miss_bit_khr = VK_SHADER_STAGE_MISS_BIT_KHR, - intersection_khr = VK_SHADER_STAGE_INTERSECTION_BIT_KHR, - callable_bit_khr = VK_SHADER_STAGE_CALLABLE_BIT_KHR, - task_bit_ext = VK_SHADER_STAGE_TASK_BIT_EXT, - mesh_bit_ext = VK_SHADER_STAGE_MESH_BIT_EXT, - supass_shading_huawei = VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI, - undefined - }; - - enum class descriptor_layout_flag { - update_after_bind_pool = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT - push_descriptor_khr = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR - descriptor_buffer_bit_ext = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT - embedded_immutable_samplers_bit_ext = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT, // represents VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT - indirect_bindable_bit_nv = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV - host_only_pool_bit_ext = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT - per_stage_bit_nv = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV - update_after_bind_pool_bit_ext = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT - host_only_pool_bit_valve = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE, // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE - flag_bits_max_enum = - VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM // represents - // VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM - }; - - //! @brief high-level specification for a shader source - struct shader_source { - std::string filename; - shader_stage stage = shader_stage::undefined; - }; - - //! @brief Represent the vulkan shader module that will get utilized by - //! VkPipeline - struct shader_handle { - VkShaderModule module = nullptr; - shader_stage stage = shader_stage::undefined; - }; - - struct vertex_attribute_entry { - uint32_t location; - format format; - uint32_t stride; - }; - - struct vertex_attribute { - uint32_t binding; - std::span entries; - uint32_t stride; - input_rate input_rate; - }; - - struct vertex_input { - glm::vec3 position; - glm::vec3 color; - glm::vec3 normals; - glm::vec2 uv; - - bool operator==(const vertex_input& other) const { - return position == other.position and color == other.color and - uv == other.uv and normals == other.normals; - } - }; - - //! @brief struct for copying from staging buffer to a destination - struct buffer_copy_info { - VkBuffer src; - VkBuffer dst; - }; - - struct vertex_params { - VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - std::span vertices; - std::string debug_name; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; - }; - - struct index_params { - VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - std::span indices; - std::string debug_name; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; - }; - - struct uniform_params { - // VkPhysicalDevice physical_handle=nullptr; - VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - uint32_t size_bytes = 0; - std::string debug_name; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; - }; - - struct descriptor_binding_point { - uint32_t binding; - shader_stage stage; - }; - - struct descriptor_entry { - buffer type; - descriptor_binding_point binding_point; - uint32_t descriptor_count; - }; - - struct write_image { - VkSampler sampler=nullptr; - VkImageView view=nullptr; - // VkImageLayout image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - image_layout layout; - }; - struct write_buffer { - VkBuffer buffer=nullptr; - uint32_t offset=0; - uint32_t range=0; - }; - - struct write_buffer_descriptor { - uint32_t dst_binding; - std::span uniforms; - }; - - struct write_image_descriptor { - uint32_t dst_binding; - std::span sample_images; - }; - - struct image_extent { - uint32_t width = 1; - uint32_t height = 1; - }; - - struct image_params { - image_extent extent; - VkFormat format; - memory_property property = memory_property::device_local_bit; - image_aspect_flags aspect = image_aspect_flags::color_bit; - // VkImageUsageFlags usage; - uint32_t usage; - VkImageCreateFlags image_flags = 0; - VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; - uint32_t mip_levels = 1; - uint32_t layer_count = 1; - uint32_t array_layers = 1; - VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - filter_range range{ .min = VK_FILTER_LINEAR, .max = VK_FILTER_LINEAR, }; - // VkSamplerAddressMode addrses_mode_u = VK_SAMPLER_ADDRESS_MODE_REPEAT; - // VkSamplerAddressMode addrses_mode_v = VK_SAMPLER_ADDRESS_MODE_REPEAT; - // VkSamplerAddressMode addrses_mode_w = VK_SAMPLER_ADDRESS_MODE_REPEAT; - uint32_t addrses_mode_u = sampler_address_mode::repeat; - uint32_t addrses_mode_v = sampler_address_mode::repeat; - uint32_t addrses_mode_w = sampler_address_mode::repeat; - }; - - struct buffer_parameters { - VkDeviceSize device_size = 0; - VkPhysicalDeviceMemoryProperties physical_memory_properties; - memory_property property_flags; - VkBufferUsageFlags usage; - VkSharingMode share_mode = VK_SHARING_MODE_EXCLUSIVE; - const char* debug_name="NA"; - PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; - }; - - // Used by vk::copy(const VkCommandBuffer& p_current, ) - struct copy_info { - uint32_t width; - uint32_t height; - uint32_t array_layers = 1; - }; - - struct image_barrier_info { - VkFormat format; - VkImageLayout old_layout; - VkImageLayout new_layout; - uint32_t level_count = 1; - VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT; - uint32_t base_array_count = 0; - uint32_t layer_count = 1; - }; - - struct write_info { - uint64_t offset = 0; - uint64_t size_bytes = 0; - }; - -}; \ No newline at end of file diff --git a/vulkan-cpp/uniform_buffer.cppm b/vulkan-cpp/uniform_buffer.cppm new file mode 100644 index 0000000..c266b65 --- /dev/null +++ b/vulkan-cpp/uniform_buffer.cppm @@ -0,0 +1,64 @@ +module; + +#include +#include +#include + +export module vk:uniform_buffer; + + +export import :types; +export import :utilities; +export import :command_buffer; +export import :buffer_streams; + +export namespace vk { + inline namespace v1 { + /** + * @brief represents a vulkan uniform buffer + * + * Maps uniforms and gpu-specific resources + */ + class uniform_buffer { + public: + uniform_buffer() = default; + uniform_buffer(const VkDevice& p_device, + const uniform_params& p_uniform_info) : m_device(p_device), m_size_bytes(p_uniform_info.size_bytes) { + + uint32_t property_flags = memory_property::host_visible_bit | + memory_property::host_coherent_bit; + buffer_parameters uniform_info = { + .device_size = m_size_bytes, + .physical_memory_properties = + p_uniform_info.phsyical_memory_properties, + .property_flags = (memory_property)property_flags, + .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + .debug_name = p_uniform_info.debug_name.c_str(), + .vkSetDebugUtilsObjectNameEXT = p_uniform_info.vkSetDebugUtilsObjectNameEXT + }; + m_uniform_handle = buffer_stream(m_device, uniform_info); + } + + [[nodiscard]] bool alive() const { return m_uniform_handle; } + + void update(const void* p_data) { + m_uniform_handle.write(p_data, m_size_bytes); + } + + operator VkBuffer() const { return m_uniform_handle; } + + operator VkBuffer() { return m_uniform_handle; } + + [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } + + void destroy() { + m_uniform_handle.destroy(); + } + + private: + uint32_t m_size_bytes = 0; + VkDevice m_device = nullptr; + buffer_stream m_uniform_handle{}; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/uniform_buffer.hpp b/vulkan-cpp/uniform_buffer.hpp deleted file mode 100644 index 303ddfc..0000000 --- a/vulkan-cpp/uniform_buffer.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @brief represents a vulkan uniform buffer - * - * Maps uniforms and gpu-specific resources - */ - class uniform_buffer { - public: - uniform_buffer() = default; - uniform_buffer(const VkDevice& p_device, - const uniform_params& p_uniform_info); - - [[nodiscard]] bool alive() const { return m_uniform_handle; } - - void update(const void* p_data); - - operator VkBuffer() const { return m_uniform_handle; } - - operator VkBuffer() { return m_uniform_handle; } - - [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } - - void destroy(); - - private: - uint32_t m_size_bytes = 0; - VkDevice m_device = nullptr; - buffer_stream m_uniform_handle{}; - }; -}; \ No newline at end of file diff --git a/src/vulkan-cpp/utilities.cpp b/vulkan-cpp/utilities.cppm similarity index 87% rename from src/vulkan-cpp/utilities.cpp rename to vulkan-cpp/utilities.cppm index acb0466..d1716df 100644 --- a/src/vulkan-cpp/utilities.cpp +++ b/vulkan-cpp/utilities.cppm @@ -1,14 +1,22 @@ -#include +module; + #include #include #include -#include +#include +#include +#include + +export module vk:utilities; -namespace vk { +export import :types; + +export namespace vk { + inline namespace v1 { void vk_check(const VkResult& p_result, const std::string& p_name, - const std::source_location& p_source) { + const std::source_location& p_source={}) { if (p_result != VK_SUCCESS) { std::println( "File {} on line {} failed VkResult check", @@ -85,35 +93,6 @@ namespace vk { // VkPhysicalDevice handler = nullptr; // }; - VkPhysicalDevice enumerate_physical_devices( - const VkInstance& p_instance, - const physical& p_physical_device_type) { - uint32_t device_count = 0; - vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); - - if (device_count == 0) { - throw std::runtime_error("device_count is zero!"); - } - - - // TODO: Turn this into map - std::vector physical_devices(device_count); - vkEnumeratePhysicalDevices( - p_instance, &device_count, physical_devices.data()); - VkPhysicalDevice physical_device = nullptr; - - for (const auto& device : physical_devices) { - VkPhysicalDeviceProperties device_properties; - vkGetPhysicalDeviceProperties(device, &device_properties); - - if (device_properties.deviceType == - static_cast(p_physical_device_type)) { - physical_device = device; - } - } - return physical_device; - } - std::vector enumerate_queue_family_properties( const VkPhysicalDevice& p_physical) { uint32_t queue_family_count = 0; @@ -545,63 +524,63 @@ namespace vk { // } // } - VkCommandPool create_single_command_pool(const VkDevice& p_device, - uint32_t p_queue_family_index) { - // uint32_t graphics_queue_index = - // physical.read_queue_family_indices().graphics; - VkCommandPoolCreateInfo pool_ci = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = p_queue_family_index - }; + // VkCommandPool create_single_command_pool(const VkDevice& p_device, + // uint32_t p_queue_family_index) { + // // uint32_t graphics_queue_index = + // // physical.read_queue_family_indices().graphics; + // VkCommandPoolCreateInfo pool_ci = { + // .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + // .pNext = nullptr, + // .flags = 0, + // .queueFamilyIndex = p_queue_family_index + // }; - VkCommandPool command_pool = nullptr; - vk_check( - vkCreateCommandPool(p_device, &pool_ci, nullptr, &command_pool), - "vkCreateCommandPool"); + // VkCommandPool command_pool = nullptr; + // vk_check( + // vkCreateCommandPool(p_device, &pool_ci, nullptr, &command_pool), + // "vkCreateCommandPool"); - return command_pool; - } + // return command_pool; + // } - void copy(const VkDevice& p_device, - const buffer_copy_info& p_info, - size_t p_size_of_bytes) { - - // 1. Retrieve the first queue - // TODO: Use vk::device_queue for this - VkQueue temp_graphics_queue = nullptr; - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - // command_buffer_info - command_params enumerate_command_info = { - .levels = command_levels::primary, - .queue_index = 0, - }; - command_buffer copy_command_buffer(p_device, enumerate_command_info); - - copy_command_buffer.begin(command_usage::one_time_submit); - VkBufferCopy copy_region{}; - copy_region.size = (VkDeviceSize)p_size_of_bytes; - vkCmdCopyBuffer( - copy_command_buffer, p_info.src, p_info.dst, 1, ©_region); - copy_command_buffer.end(); - VkCommandBuffer temp = copy_command_buffer; - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &temp; - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - // vkFreeCommandBuffers(, command_pool, 1, ©_cmd_buffer); - // vkDestroyCommandPool(driver, command_pool, nullptr); - copy_command_buffer.destroy(); - } + // void copy(const VkDevice& p_device, + // const buffer_copy_info& p_info, + // size_t p_size_of_bytes) { + + // // 1. Retrieve the first queue + // // TODO: Use vk::device_queue for this + // VkQueue temp_graphics_queue = nullptr; + // uint32_t queue_family_index = 0; + // uint32_t queue_index = 0; + // vkGetDeviceQueue( + // p_device, queue_family_index, queue_index, &temp_graphics_queue); + + // // command_buffer_info + // command_params enumerate_command_info = { + // .levels = command_levels::primary, + // .queue_index = 0, + // }; + // command_buffer copy_command_buffer(p_device, enumerate_command_info); + + // copy_command_buffer.begin(command_usage::one_time_submit); + // VkBufferCopy copy_region{}; + // copy_region.size = (VkDeviceSize)p_size_of_bytes; + // vkCmdCopyBuffer( + // copy_command_buffer, p_info.src, p_info.dst, 1, ©_region); + // copy_command_buffer.end(); + // VkCommandBuffer temp = copy_command_buffer; + // VkSubmitInfo submit_info{}; + // submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + // submit_info.commandBufferCount = 1; + // submit_info.pCommandBuffers = &temp; + + // vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + // vkQueueWaitIdle(temp_graphics_queue); + + // // vkFreeCommandBuffers(, command_pool, 1, ©_cmd_buffer); + // // vkDestroyCommandPool(driver, command_pool, nullptr); + // copy_command_buffer.destroy(); + // } // VkDescriptorType to_descriptor_type(const buffer& p_type) { // switch (p_type) { @@ -694,4 +673,5 @@ namespace vk { return -1; } -} \ No newline at end of file +}; // end of v1 namespace +}; \ No newline at end of file diff --git a/vulkan-cpp/utilities.hpp b/vulkan-cpp/utilities.hpp deleted file mode 100644 index a314cc7..0000000 --- a/vulkan-cpp/utilities.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - - void vk_check( - const VkResult& p_result, - const std::string& p_name, - const std::source_location& p_location = std::source_location::current()); - - /** - * @brief converts vk::message to VkDebugUtilsMessageSeverityFlagsEXT - * - * Allows to set specific bit for setting up the message severity. - * - * Types of message severity for the specified debug callback - * VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT - * - * VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT - * - * VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT - */ - VkDebugUtilsMessageSeverityFlagsEXT to_debug_message_severity( - uint32_t p_flag); - - VkDebugUtilsMessageTypeFlagsEXT to_message_type(uint32_t p_flag); - - uint32_t vk_api_version(const api_version& p_version); - - VkPhysicalDeviceType vk_physical_device_type(physical p_physical_type); - - VkPhysicalDevice enumerate_physical_devices( - const VkInstance& p_instance, - const physical& p_physical_device_type); - - std::vector enumerate_queue_family_properties( - const VkPhysicalDevice& p_physical); - - //! @return a selected format with specific tiling and feature flags - VkFormat select_compatible_formats( - const VkPhysicalDevice& p_physical, - std::span p_format_selection, - VkImageTiling p_tiling, - VkFormatFeatureFlags p_feature_flag); - - //! @return the depth format which checks for compatible formats and is - //! specific to the depth stencil attachment specified - VkFormat select_depth_format(const VkPhysicalDevice& p_physical, - std::span p_format_selection); - - //! @return surface_params which contains VkSurfaceCapabilities and - //! VkSurfaceFormatKHR for the swapchain - surface_params enumerate_surface(const VkPhysicalDevice& p_physical, - const VkSurfaceKHR& p_surface); - - //! @return image size the surface requires - uint32_t surface_image_size(const VkSurfaceCapabilitiesKHR& p_capabilities); - - VkCommandBufferUsageFlags to_command_usage_flag_bits( - command_usage p_command_usage_flag); - - VkImageAspectFlags to_image_aspect_flags(image_aspect_flags p_flag); - - //! @return -1 if there are no flags available/compatible/valid - uint32_t physical_memory_properties(const VkPhysicalDevice& p_physical, - uint32_t p_type_filter, - VkMemoryPropertyFlags p_property_flag); - - VkSemaphore create_semaphore(const VkDevice& p_device); - - //! @brief Requests memory requirements from the physical hardware device - //! @brief Using it to get the type_filter to return the - //! image_memory_requirement - /** - * @param p_physical handle for physical hardware device - * @param p_device handle for logical device represent as the virtual device - * @param p_image the image context to retreive image memory requirements - * from - * @param p_property is memory_property for choosing a memory type for - * a specific resource; in this case an image resource - */ - uint32_t image_memory_requirements( - const VkPhysicalDevice& p_physical, - const VkDevice& p_device, - const VkImage& p_image, - memory_property p_property = memory_property::device_local_bit); - - VkCommandBufferLevel to_vk_command_buffer_level( - const command_levels& p_level); - - VkCommandPoolCreateFlagBits to_command_buffer_pool_flags( - command_pool_flags p_command_pool_flag); - - VkSubpassContents to_subpass_contents(subpass_contents p_content); - - VkPipelineBindPoint to_pipeline_bind_point( - pipeline_bind_point p_bind_point); - - VkAttachmentLoadOp to_attachment_load(attachment_load p_attachment_type); - - VkAttachmentStoreOp to_attachment_store(attachment_store p_attachment_type); - - VkSampleCountFlagBits to_sample_count_bits(sample_bit p_sample_count_bit); - - // VkImageLayout to_image_layout(image_layout p_layout); - - VkVertexInputRate to_input_rate(input_rate p_input_rate); - - bool has_depth_specified(image_layout p_layout); - - bool has_stencil_attachment(VkFormat p_format); - - // TODO: Use this to do bitwise checks rather then; since this only does - // switch-case statement checks - VkMemoryPropertyFlags to_memory_property_flags(memory_property p_flag); - - VkShaderStageFlags to_shader_stage(const shader_stage& p_stage); - - VkFormat to_format(const format& p_format); - - //! @brief Copies from one buffer source into another buffer source with a - //! specific size of bytes to be stored the buffer that is being copied to - void copy(const VkDevice& p_device, const buffer_copy_info& p_info, size_t p_size_of_bytes); - - - //! @return Returns the VkDescriptorType that represents a "handle" the - //! shader resource is acecssing - VkDescriptorType to_descriptor_type(const buffer& p_type); - - //! @brief passes a vulkan format - //! @return the amount of bytes per vulkan format specification - int bytes_per_texture_format(VkFormat p_format); - - uint32_t select_memory_requirements( - VkPhysicalDeviceMemoryProperties p_physical_memory_props, - VkMemoryRequirements p_memory_requirements, - memory_property p_property); -}; \ No newline at end of file diff --git a/vulkan-cpp/vertex_buffer.cppm b/vulkan-cpp/vertex_buffer.cppm new file mode 100644 index 0000000..e3ce41f --- /dev/null +++ b/vulkan-cpp/vertex_buffer.cppm @@ -0,0 +1,133 @@ +module; + +#include +#include +#include + +export module vk:vertex_buffer; + + +export import :types; +export import :utilities; +export import :command_buffer; +export import :buffer_streams; + +export namespace vk { + inline namespace v1 { + /** + * @brief vulkan implementation for loading in vertices to a vulkan buffer handle + * + * This implementation automates handle in loading the vertices and its memories for it + */ + class vertex_buffer { + public: + vertex_buffer() = default; + vertex_buffer(const VkDevice& p_device, + const vertex_params& p_vertex_info) : m_device(p_device) { + m_size = p_vertex_info.vertices.size(); + m_size_bytes = p_vertex_info.vertices.size_bytes(); + + VkBufferUsageFlags usage = + VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + // 1. creating staging buffer + uint32_t property_flags = + memory_property::host_visible_bit | memory_property::host_cached_bit; + + buffer_parameters new_staging_buffer_settings = { + .device_size = m_size_bytes, + .physical_memory_properties = + p_vertex_info.phsyical_memory_properties, + .property_flags = (memory_property)property_flags, + .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + .debug_name = p_vertex_info.debug_name.c_str(), + .vkSetDebugUtilsObjectNameEXT = p_vertex_info.vkSetDebugUtilsObjectNameEXT + }; + buffer_stream staging_buffer(m_device, new_staging_buffer_settings); + std::span vertices = p_vertex_info.vertices; + staging_buffer.write(vertices); + + // 3.) Now creating our actual vertex buffer handler + buffer_parameters vertex_params = { + .device_size = m_size_bytes, + .physical_memory_properties = + p_vertex_info.phsyical_memory_properties, + .property_flags = memory_property::device_local_bit, + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + }; + m_vertex_handler = buffer_stream(m_device, vertex_params); + + // 4. Copy data from staging buffer to the actual vertex buffer itself! + buffer_copy_info info = { .src = staging_buffer, + .dst = m_vertex_handler }; + // copy(m_device, info, m_size_bytes); + + // 1. Retrieve the first queue + // TODO: Use vk::device_queue for this + VkQueue temp_graphics_queue = nullptr; + uint32_t queue_family_index = 0; + uint32_t queue_index = 0; + vkGetDeviceQueue( + p_device, queue_family_index, queue_index, &temp_graphics_queue); + + // command_buffer_info + command_params enumerate_command_info = { + .levels = command_levels::primary, + .queue_index = 0, + }; + command_buffer copy_command_buffer(p_device, enumerate_command_info); + + copy_command_buffer.begin(command_usage::one_time_submit); + // VkBufferCopy copy_region{}; + // copy_region.size = (VkDeviceSize)m_size_bytes; + // vkCmdCopyBuffer( + // copy_command_buffer, staging_buffer, m_vertex_handler, 1, ©_region); + copy_command_buffer.copy_buffer(staging_buffer, m_vertex_handler, m_size_bytes); + copy_command_buffer.end(); + VkCommandBuffer temp = copy_command_buffer; + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &temp; + + vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(temp_graphics_queue); + + // vkFreeCommandBuffers(, command_pool, 1, ©_cmd_buffer); + // vkDestroyCommandPool(driver, command_pool, nullptr); + copy_command_buffer.destroy(); + + // 5. cleanup staging buffer -- no longer used + staging_buffer.destroy(); + } + + [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } + + [[nodiscard]] uint32_t size() const { return m_size; } + + [[nodiscard]] bool alive() const { return m_vertex_handler; } + + void bind(const VkCommandBuffer& p_current) { + std::array handlers = { m_vertex_handler }; + VkDeviceSize offsets[] = { 0 }; + vkCmdBindVertexBuffers(p_current, 0, 1, handlers.data(), offsets); + } + + operator VkBuffer() const { return m_vertex_handler; } + + operator VkBuffer() { return m_vertex_handler; } + + void destroy() { + m_vertex_handler.destroy(); + } + + private: + VkDevice m_device = nullptr; + uint32_t m_size_bytes = 0; + uint32_t m_size = 0; + buffer_stream m_vertex_handler; + }; + }; +}; \ No newline at end of file diff --git a/vulkan-cpp/vertex_buffer.hpp b/vulkan-cpp/vertex_buffer.hpp deleted file mode 100644 index 12f3e0b..0000000 --- a/vulkan-cpp/vertex_buffer.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include -#include -#include - -namespace vk { - /** - * @brief vulkan implementation for loading in vertices to a vulkan buffer handle - * - * This implementation automates handle in loading the vertices and its memories for it - */ - class vertex_buffer { - public: - vertex_buffer() = default; - vertex_buffer(const VkDevice& p_device, - const vertex_params& p_vertices); - - [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } - - [[nodiscard]] uint32_t size() const { return m_size; } - - [[nodiscard]] bool alive() const { return m_vertex_handler; } - - void bind(const VkCommandBuffer& p_current); - - operator VkBuffer() const { return m_vertex_handler; } - - operator VkBuffer() { return m_vertex_handler; } - - void destroy(); - - private: - VkDevice m_device = nullptr; - uint32_t m_size_bytes = 0; - uint32_t m_size = 0; - buffer_stream m_vertex_handler; - }; -}; \ No newline at end of file diff --git a/vulkan-cpp/vk.cppm b/vulkan-cpp/vk.cppm new file mode 100644 index 0000000..8170de9 --- /dev/null +++ b/vulkan-cpp/vk.cppm @@ -0,0 +1,28 @@ +export module vk; + +export import :types; +export import :instance; +export import :physical_device; +export import :device; +export import :device_queue; +export import :surface; +export import :command_buffer; +export import :swapchain; +export import :device_present_queue; +export import :renderpass; +export import :framebuffer; +export import :sample_image; +export import :shader_resource; +export import :pipeline; +export import :buffer_streams; +export import :buffer_streams32; +export import :vertex_buffer; +export import :index_buffer; +export import :uniform_buffer; +export import :descriptor_resource; +export import :texture; + +namespace vk { + inline namespace v1 { + }; +}; \ No newline at end of file