diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bad1769 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: 🛠️ CI + +on: [pull_request] + +jobs: + clang-format: + uses: ./.github/workflows/clang-format-deploy.yml + secrets: inherit + + windows: + uses: ./.github/workflows/windows.yml + secrets: inherit + + linux: + uses: ./.github/workflows/linux.yml + secrets: inherit + + mac-armv8: + uses: ./.github/workflows/mac.yml + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/clang-format-deploy.yml b/.github/workflows/clang-format-deploy.yml index 1e3234f..c28b442 100644 --- a/.github/workflows/clang-format-deploy.yml +++ b/.github/workflows/clang-format-deploy.yml @@ -1,5 +1,6 @@ -name: clang-format Check -on: [pull_request] +name: clang-format +on: [workflow_call] + jobs: formatting-check: name: Formatting Check diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index ea89922..7f3bd0c 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -7,26 +7,27 @@ jobs: cpp-linter: runs-on: ubuntu-latest steps: - # - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - uses: actions/checkout@v4 with: - persist-credentials: false - - uses: cpp-linter/cpp-linter-action@main + fetch-depth: 0 + + - uses: cpp-linter/cpp-linter-action@v2 id: linter - continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - style: '' - tidy-checks: '.clang-tidy' - extensions: 'cpp, cppm' - files-changed-only: true - thread-comments: false - extra-args: '-std=c++23' + style: '' # Disables clang-format so it strictly runs clang-tidy + # tidy-checks: '.clang-tidy' + extensions: 'cpp,cppm,h,hpp' # common C++ file extensions + # files-changed-only: true + thread-comments: ${{ github.event_name == 'pull_request' && 'update' }} + # Ensure clang-tidy knows how to parse modern C++ headers/modules without a compile_commands.json + extra-args: '-Wall -Wextra -Werror -std=c++23 --config-file=.clang-tidy' - - name: Fail fast?! - if: ${{ steps.linter.outputs.checks-failed > 0 }} + - name: Failed fast?! + # Does a check if any of the given clang-tidy checks failed! + if: steps.linter.outputs.checks-failed != '0' run: | - echo "some linter checks failed. ${{ steps.linter.outputs.checks-failed }}" - # for actual deployment + echo "Failed clang-tidy linters check" + echo "Total violations reported: ${{ steps.linter.outputs.checks-failed }}" exit 1 \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 4c8e012..0000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Breaking change was removing the bit timing sections from hal::can::settings, -# now it is just baud_rate. -name: 🚀 Deploy Version - -on: - workflow_dispatch: - -jobs: - engine3d: - uses: engine3d-dev/ci/.github/workflows/deploy.yml@main - with: - # version: ${{ github.ref_name }} - arch: x86_64 - os: Linux - secrets: inherit diff --git a/.github/workflows/deploy_all.yml b/.github/workflows/deploy_all.yml new file mode 100644 index 0000000..b027cfc --- /dev/null +++ b/.github/workflows/deploy_all.yml @@ -0,0 +1,23 @@ + +name: 🚀 Deployment + +# Trigger deployment CI when PRs get merged to main (production branch) +on: + pull_request: + types: [closed] + branches: + - main + workflow_call: + +jobs: + windows: + uses: ./.github/workflows/deploy_windows.yml + secrets: inherit + + linux: + uses: ./.github/workflows/deploy_linux.yml + secrets: inherit + + mac-armv8: + uses: ./.github/workflows/deploy_mac.yml + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/deploy_linux.yml b/.github/workflows/deploy_linux.yml index d53e951..b4963bf 100644 --- a/.github/workflows/deploy_linux.yml +++ b/.github/workflows/deploy_linux.yml @@ -1,10 +1,6 @@ -name: Deploy to Linux +name: Ubuntu Deployment -on: - pull_request: - types: [closed] - branches: - - main # Only trigger for PRs merged into main +on: [workflow_call] jobs: linux_x86_64: @@ -63,4 +59,4 @@ jobs: - name: Uploading vulkan-cpp to engine3d-conan remote repositories shell: pwsh - run: conan upload vulkan-cpp/5.0 --r=engine3d-conan --confirm \ No newline at end of file + run: conan upload vulkan-cpp/6.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 index 072fa2c..39ba0ae 100644 --- a/.github/workflows/deploy_mac.yml +++ b/.github/workflows/deploy_mac.yml @@ -1,10 +1,6 @@ -name: Deploy to MacOS Armv8 +name: MacOS Armv8 Deployment -on: - pull_request: - types: [closed] - branches: - - main # Only trigger for PRs merged into main +on: [workflow_call] jobs: macos_armv8: @@ -55,4 +51,4 @@ jobs: - name: Uploading vulkan-cpp to engine3d-conan remote repositories shell: pwsh - run: conan upload vulkan-cpp/5.0 --r=engine3d-conan --confirm \ No newline at end of file + run: conan upload vulkan-cpp/6.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 index 60b6bfc..1ccac9f 100644 --- a/.github/workflows/deploy_windows.yml +++ b/.github/workflows/deploy_windows.yml @@ -1,10 +1,7 @@ -name: Deploy to Windows +name: Windows Deployment -on: - pull_request: - types: [closed] - branches: - - main # Only trigger for PRs merged into main + +on: [workflow_call] jobs: windows_x86_64: @@ -55,4 +52,4 @@ jobs: - name: Uploading vulkan-cpp to engine3d-conan remote repositories shell: pwsh - run: conan upload vulkan-cpp/5.0 --r=engine3d-conan --confirm \ No newline at end of file + run: conan upload vulkan-cpp/6.0 --r=engine3d-conan --confirm \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 11d337b..bbb3af9 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -1,10 +1,11 @@ -name: Linux Platform Build +name: Linux + +# workflow_call to have linux.yml be able to be invoked by ci.yml +on: [workflow_call] -on: [pull_request] jobs: linux-build: - name: "Linux-Build" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -46,5 +47,4 @@ jobs: run: conan atlas create . -s build_type=Debug - name: Creating MinSizeRel build for vulkan-cpp - run: conan atlas create . -s build_type=MinSizeRel - + run: conan atlas create . -s build_type=MinSizeRel \ No newline at end of file diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index 4f18537..3bbe4d3 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -1,10 +1,10 @@ -name: Macos Platform Build +name: Macos Armv8 -on: [pull_request] +# workflow_call to have mac.yml be able to be invoked by ci.yml +on: [workflow_call] jobs: macos-build: - name: "M1 Mac Build" runs-on: macos-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/platform-config.yml b/.github/workflows/platform-config.yml new file mode 100644 index 0000000..53cc206 --- /dev/null +++ b/.github/workflows/platform-config.yml @@ -0,0 +1,226 @@ +name: Platform Configuration + +on: + workflow_call: + outputs: + cache-key-windows: + description: "Cached Key for the Windows Environment" + value: ${{ jobs.windows-setup.outputs.job-cache-key }} + # cache-key-linux: + # description: "Cached Key for the Ubuntu Environment" + # value: ${{ jobs.ubuntu-setup.outputs.cache-key }} + # cache-key-mac: + # description: "Cached Key for the Apple Silicon Armv8 Environment" + # value: ${{ jobs.armv8-setup.outputs.cache-key }} + +jobs: + windows-setup: + runs-on: windows-latest + # outputs: + # cache-key: ${{ steps.cache-info.outputs.key }} + outputs: + job-cache-key: ${{ steps.cache-info.outputs.key }} + steps: + - uses: actions/checkout@v4 + + - name: Generate Cache Key Info + id: cache-info + shell: pwsh + run: echo "key=windows-setup-${{ runner.os }}-${{ github.run_id }}" >> $ENV:GITHUB_OUTPUT + + - name: Check Cache + id: cache-env + uses: actions/cache@v4 + with: + path: | + ~\AppData\Local\Packages\PythonSoftwareFoundation* + ~\AppData\Local\Programs\Python* + ~\.conan2 + ${{ github.workspace }}\vulkan_sdk + key: ${{ steps.cache-info.outputs.key }} + restore-keys: | + windows-setup-${{ runner.os }}- + + - name: Install Vulkan SDK + if: steps.cache-env.outputs.cache-hit != 'true' + uses: humbletim/setup-vulkan-sdk@v1.2.1 + with: + vulkan-query-version: 1.4.304.1 + vulkan-components: Vulkan-Headers, Vulkan-Loader + destination: ${{ github.workspace }}\vulkan_sdk + + - name: Pip installing conan + if: steps.cache-env.outputs.cache-hit != 'true' + shell: pwsh + run: | + python -m pip install --upgrade pip + pip install conan + # Find out exactly where conan.exe was installed and write it to a marker file + $ConanPath = (Get-Command conan.exe -ErrorAction SilentlyContinue).Source + if (-not $ConanPath) { + $ConanPath = (Get-ChildItem -Path ~\AppData\Local -Filter conan.exe -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1).FullName + } + $ConanDir = Split-Path -Path $ConanPath -Parent + New-Item -ItemType Directory -Force -Path .github\artifacts + Out-File -FilePath .github\artifacts\conan_path.txt -InputObject $ConanDir + + - name: Setting up Conan configuration + if: steps.cache-env.outputs.cache-hit != 'true' + shell: pwsh + run: | + $ConanPath = Get-Content -Path .github\artifacts\conan_path.txt + & "$ConanPath\conan" config install https://github.com/engine3d-dev/conan-config.git + & "$ConanPath\conan" atlas setup + +# jobs: +# windows-setup: +# runs-on: windows-latest +# outputs: +# cache-key: ${{ steps.cache-info.outputs.key }} +# steps: +# - uses: actions/checkout@v4 + +# # Windows runners use PowerShell (pwsh) by default, using the $ENV:GITHUB_OUTPUT syntax +# - name: Generate Cache Key Info +# id: cache-info +# shell: pwsh +# run: echo "key=windows-setup-${{ runner.os }}-${{ github.run_id }}" >> $ENV:GITHUB_OUTPUT + +# - name: Check Cache +# id: cache-env +# uses: actions/cache@v4 +# with: +# path: | +# AppData\Local\pip\Cache +# .conan2 +# vulkan_sdk +# key: ${{ steps.cache-info.outputs.key }} +# restore-keys: | +# windows-setup-${{ runner.os }}- + +# - name: Installing Choco & Git +# if: steps.cache-env.outputs.cache-hit != 'true' +# 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')) +# choco install git -y + +# - name: Install Vulkan SDK +# if: steps.cache-env.outputs.cache-hit != 'true' +# uses: humbletim/setup-vulkan-sdk@v1.2.1 +# with: +# vulkan-query-version: 1.4.304.1 +# vulkan-components: Vulkan-Headers, Vulkan-Loader +# destination: ${{ github.workspace }}\vulkan_sdk + +# - name: Pip installing conan +# if: steps.cache-env.outputs.cache-hit != 'true' +# shell: pwsh +# run: pip install conan + +# - name: Setting up Conan configuration +# if: steps.cache-env.outputs.cache-hit != 'true' +# shell: pwsh +# run: | +# conan config install https://github.com/engine3d-dev/conan-config.git +# conan atlas setup + # ubuntu-setup: + # runs-on: ubuntu-latest + # outputs: + # cache-key: ${{ steps.cache-info.outputs.key }} + # steps: + # - uses: actions/checkout@v4 + + # # Note: We append a hardcoded version or file hash to trigger rebuilds when configs change + # - name: Generate Cache Key Info + # id: cache-info + # run: echo "key=ubuntu-setup-${{ runner.os }}-${{ github.run_id }}" >> $GITHUB_OUTPUT + + # - name: Check Cache + # id: cache-env + # uses: actions/cache@v4 + # with: + # path: | + # ~/.local/share/pipx + # ~/.conan2 + # ${{ github.workspace }}/vulkan_sdk + # key: ${{ steps.cache-info.outputs.key }} + # restore-keys: | + # ubuntu-setup-${{ runner.os }}- + + # - name: Install System Prerequisites + # if: steps.cache-env.outputs.cache-hit != 'true' + # run: | + # sudo apt-get update + # sudo apt-get install -y libc++-20-dev libc++abi-20-dev pipx software-properties-common + # sudo add-apt-repository ppa:deadsnakes/ppa -y + + # - name: Install Vulkan SDK + # if: steps.cache-env.outputs.cache-hit != 'true' + # uses: humbletim/setup-vulkan-sdk@v1.2.1 + # with: + # vulkan-query-version: 1.4.304.1 + # vulkan-components: Vulkan-Headers, Vulkan-Loader + # destination: ${{ github.workspace }}/vulkan_sdk + + # - name: Install and Configure Conan + # if: steps.cache-env.outputs.cache-hit != 'true' + # run: | + # pipx install "conan>=2.18.1" + # export PATH="$HOME/.local/bin:$PATH" + # conan config install https://github.com/engine3d-dev/conan-config.git + # conan atlas setup + + # armv8-setup: + # runs-on: macos-latest + # outputs: + # cache-key: ${{ steps.cache-info.outputs.key }} + # steps: + # - uses: actions/checkout@v4 + + # - name: Generate Cache Key Info + # id: cache-info + # run: echo "key=armv8-setup-${{ runner.os }}-${{ github.run_id }}" >> $GITHUB_OUTPUT + + # - name: Check Cache + # id: cache-env + # uses: actions/cache@v4 + # with: + # path: | + # ~/.local/share/pipx + # ~/.conan2 + # ${{ github.workspace }}/vulkan_sdk + # key: ${{ steps.cache-info.outputs.key }} + # restore-keys: | + # armv8-setup-${{ runner.os }}- + + # - name: Install Homebrew & Core Tooling + # if: steps.cache-env.outputs.cache-hit != 'true' + # run: | + # /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + # brew install python pipx + + # - name: Install Vulkan SDK + # if: steps.cache-env.outputs.cache-hit != 'true' + # uses: humbletim/setup-vulkan-sdk@v1.2.1 + # with: + # vulkan-query-version: 1.4.304.1 + # vulkan-components: Vulkan-Headers, Vulkan-Loader + # destination: ${{ github.workspace }}/vulkan_sdk + + # - name: Installing conan & clang-tidy + # if: steps.cache-env.outputs.cache-hit != 'true' + # run: | + # pipx install "conan>=2.18.2" + # pipx upgrade conan + # sudo ln -s $(brew --prefix llvm)/bin/clang-tidy /usr/local/bin/ + # /usr/sbin/softwareupdate --install-rosetta --agree-to-license + + # - name: Setting up Conan configuration + # if: steps.cache-env.outputs.cache-hit != 'true' + # run: | + # export PATH="$HOME/.local/bin:$PATH" + # conan config install https://github.com/engine3d-dev/conan-config.git + # conan atlas setup \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 864d1ef..f48b736 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,10 +1,11 @@ -name: Windows Platform Build +name: Windows + +# workflow_call to have linux.yml be able to be invoked by ci.yml +on: [workflow_call] -on: [pull_request, workflow_dispatch] jobs: windows-build: - name: "Windows-Build" runs-on: windows-latest steps: - uses: actions/checkout@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index d9655a3..40fe5d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,10 +46,10 @@ target_sources(${PROJECT_NAME} PUBLIC vulkan-cpp/sample_image.cppm vulkan-cpp/shader_resource.cppm vulkan-cpp/pipeline.cppm - vulkan-cpp/buffer_streams.cppm + vulkan-cpp/buffer.cppm vulkan-cpp/vertex_buffer.cppm - vulkan-cpp/buffer_streams16.cppm - vulkan-cpp/buffer_streams32.cppm + vulkan-cpp/buffer16.cppm + vulkan-cpp/buffer32.cppm vulkan-cpp/index_buffer.cppm vulkan-cpp/uniform_buffer.cppm vulkan-cpp/descriptor_resource.cppm diff --git a/README.md b/README.md index 99323b1..8b39749 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Custom Vulkan abstraction layer with native C++20 modules support using LLVM. +[![✅CI](https://github.com/engine3d-dev/vulkan-cpp/actions/workflows/ci.yml/badge.svg)](https://github.com/engine3d-dev/vulkan-cpp/actions/workflows/ci.yml) +[![GitHub stars](https://img.shields.io/github/stars/engine3d-dev/vulkan-cpp.svg)](https://github.com/engine3d-dev/vulkan-cpp/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/engine3d-dev/vulkan-cpp.svg)](https://github.com/engine3d-dev/vulkan-cpp/network) +[![GitHub issues](https://img.shields.io/github/issues/engine3d-dev/vulkan-cpp.svg)](https://github.com/engine3d-dev/vulkan-cpp/issues) + > [!TIP] > vulkan-cpp assumes you have some knowledge of graphics APIs such as OpenGL or Direct3D diff --git a/demos/1-instance/application.cpp b/demos/1-instance/application.cpp index 3125687..0b59d90 100644 --- a/demos/1-instance/application.cpp +++ b/demos/1-instance/application.cpp @@ -110,6 +110,6 @@ main() { } glfwDestroyWindow(window); - api_instance.destroy(); + api_instance.destruct(); return 0; } diff --git a/demos/10-textures/CMakeLists.txt b/demos/10-textures/CMakeLists.txt index c0d93d5..0d74170 100644 --- a/demos/10-textures/CMakeLists.txt +++ b/demos/10-textures/CMakeLists.txt @@ -13,6 +13,7 @@ build_application( stb LINK_PACKAGES + stb::stb 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 cc720db..6e99072 100644 --- a/demos/10-textures/application.cpp +++ b/demos/10-textures/application.cpp @@ -14,7 +14,6 @@ #include #include #include -import vk; #include #define GLM_FORCE_RADIANS @@ -22,6 +21,14 @@ import vk; #include #include #include +#include + +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -66,6 +73,80 @@ struct material_uniform { glm::vec4 color; }; +/** + * @brief STBI-specific implementation of the vk::image interface + */ +class stb_image : public vk::image { +public: + stb_image() = delete; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + +protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + vk::image_params image_options = { + .extent = m_extent, + .format = texture_format, + .memory_mask = p_params.memory_mask, + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .mip_levels = p_params.mip_levels, + .layer_count = p_params.layer_count, + }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + +private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; +}; + int main() { //! @note Just added the some test code to test the conan-starter setup code @@ -117,19 +198,9 @@ main() { // 1. Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -143,17 +214,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -167,21 +235,14 @@ main() { 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 = physical_device.request_surface(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 + .width = static_cast(width), + .height = static_cast(height), + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -194,7 +255,6 @@ main() { // Creating Images std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; @@ -209,28 +269,13 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - // Creating Depth Images for depth buffering - vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, - .format = depth_format, - .memory_mask = physical_device.memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - }; - swapchain_depth_images[i] = - vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -238,7 +283,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -249,7 +294,7 @@ main() { // setting up renderpass // setting up attachments for the renderpass - std::array renderpass_attachments = { + std::array renderpass_attachments = { vk::attachment{ .format = surface_properties.format.format, .layout = vk::image_layout::color_optimal, @@ -261,29 +306,14 @@ main() { .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::depth_stencil_read_only_optimal, - }, }; 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 @@ -291,8 +321,7 @@ main() { // 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() }; + image_view_attachments = { swapchain_images[i].image_view() }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, @@ -303,9 +332,6 @@ main() { 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, @@ -317,29 +343,35 @@ main() { // 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/sample4/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample4/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample4/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample4/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::rg32_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 = 0, + .format = vk::format::rg32_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), + } }; std::array attributes = { @@ -362,15 +394,11 @@ main() { 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 GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -379,7 +407,7 @@ main() { }, vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 1, .stage = vk::shader_stage::fragment, @@ -387,7 +415,7 @@ main() { .descriptor_count = 1, } }; - // uint32_t image_count = image_count; + 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 @@ -396,13 +424,6 @@ main() { 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); - */ std::array color_blend_attachments = { vk::color_blend_attachment_state{}, }; @@ -424,29 +445,32 @@ main() { }; vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if (main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", - main_graphics_pipeline.alive()); - } - // Setting up vertex buffer std::array vertices = { - vk::vertex_input{ .position = { -0.5f, -0.5f, 0.f }, - .color = { 1.0f, 0.0f, 0.0f }, - .normals = { 0.f, 0.f, 0.f }, - .uv = { 1.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, -0.5f, 0.f }, - .color = { 0.0f, 1.0f, 0.0f }, - .normals = { 0.f, 0.f, 0.f }, - .uv = { 0.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, 0.5f, 0.f }, - .color = { 0.0f, 0.0f, 1.0f }, - .normals = { 0.f, 0.f, 0.f }, - .uv = { 0.0f, 1.0f } }, - vk::vertex_input{ .position = { -0.5f, 0.5f, 0.f }, - .color = { 1.0f, 1.0f, 1.0f }, - .normals = { 0.f, 0.f, 0.f }, - .uv = { 1.0f, 1.0f } } + vk::vertex_input{ + .position = { -0.5f, -0.5f, 0.f }, + .color = { 1.0f, 0.0f, 0.0f }, + .normals = { 0.f, 0.f, 0.f }, + .uv = { 1.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, -0.5f, 0.f }, + .color = { 0.0f, 1.0f, 0.0f }, + .normals = { 0.f, 0.f, 0.f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, 0.5f, 0.f }, + .color = { 0.0f, 0.0f, 1.0f }, + .normals = { 0.f, 0.f, 0.f }, + .uv = { 0.0f, 1.0f }, + }, + vk::vertex_input{ + .position = { -0.5f, 0.5f, 0.f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.f, 0.f, 0.f }, + .uv = { 1.0f, 1.0f }, + } }; //! @brief Creating vertex/index buffers with host visibility flags const auto property_flags = @@ -456,8 +480,8 @@ main() { vk::buffer_parameters vertex_params = { .memory_mask = physical_device.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::vertex_buffer test_vbo(logical_device, vertices, vertex_params); @@ -468,7 +492,7 @@ main() { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; vk::index_buffer test_ibo(logical_device, indices, index_params); @@ -478,7 +502,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo = vk::uniform_buffer( logical_device, sizeof(global_uniform), uniform_params); @@ -502,12 +526,10 @@ main() { vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), }; - vk::texture texture1( - logical_device, - std::filesystem::path("asset_samples/container_diffuse.png"), - config_texture); - std::println("texture1.valid = {}", texture1.loaded()); + stb_image img = + stb_image("asset_samples/container_diffuse.png", config_texture); + vk::texture texture1(logical_device, &img, config_texture); // Moving update call here because now we add textures to set0 vk::buffer_parameters material_ubfo_info = { @@ -515,7 +537,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer material_ubo = vk::uniform_buffer( logical_device, sizeof(material_uniform), material_ubfo_info); @@ -634,39 +656,34 @@ main() { // }); (???) // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set0_resource.destroy(); - test_ubo.destroy(); - material_ubo.destroy(); - test_ibo.destroy(); - test_vbo.destroy(); + texture1.destruct(); + set0_resource.destruct(); + test_ubo.destruct(); + material_ubo.destruct(); + test_ibo.destruct(); + test_vbo.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + image.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/11-depth-buffering/CMakeLists.txt b/demos/11-depth-buffering/CMakeLists.txt index be80e23..f905274 100644 --- a/demos/11-depth-buffering/CMakeLists.txt +++ b/demos/11-depth-buffering/CMakeLists.txt @@ -13,6 +13,7 @@ build_application( stb LINK_PACKAGES + stb::stb 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 aff27f7..4e04dfb 100644 --- a/demos/11-depth-buffering/application.cpp +++ b/demos/11-depth-buffering/application.cpp @@ -14,12 +14,19 @@ #include #include #include -import vk; #include #define GLM_FORCE_RADIANS #include #include +#include + +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -60,6 +67,80 @@ struct global_uniform { glm::mat4 proj; }; +/** + * @brief STBI-specific implementation of the vk::image interface + */ +class stb_image : public vk::image { +public: + stb_image() = delete; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + +protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + vk::image_params image_options = { + .extent = m_extent, + .format = texture_format, + .memory_mask = p_params.memory_mask, + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .mip_levels = p_params.mip_levels, + .layer_count = p_params.layer_count, + }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + +private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; +}; + int main() { //! @note Just added the some test code to test the conan-starter setup code @@ -111,19 +192,9 @@ main() { // 1. Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -137,17 +208,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -161,21 +229,14 @@ main() { 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 = physical_device.request_surface(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 = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -195,13 +256,15 @@ main() { // Setting up the images for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = surface_properties.format.format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -211,13 +274,15 @@ main() { // Creating Images for depth buffering vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = depth_format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -238,8 +303,6 @@ main() { vk::command_buffer(logical_device, settings); } - // setting up renderpass - // setting up attachments for the renderpass std::array renderpass_attachments = { vk::attachment{ @@ -268,14 +331,9 @@ main() { 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 @@ -295,9 +353,6 @@ main() { 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, @@ -309,33 +364,40 @@ main() { // 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/sample4/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample4/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample4/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample4/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 = { @@ -358,15 +420,11 @@ main() { 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 GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -375,7 +433,7 @@ main() { }, vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 1, .stage = vk::shader_stage::fragment, @@ -383,7 +441,7 @@ main() { .descriptor_count = 1, } }; - // uint32_t image_count = image_count; + 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 @@ -414,46 +472,57 @@ main() { }; vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if (main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", - main_graphics_pipeline.alive()); - } - // Setting up vertex buffer std::array vertices = { - vk::vertex_input{ .position = { -0.5f, -0.5f, 0.f }, - .color = { 1.0f, 0.0f, 0.0f }, - .normals = { 1.0f, 0.0f, 0.f }, - .uv = { 1.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, -0.5f, 0.f }, - .color = { 0.0f, 1.0f, 0.0f }, - .normals = { 0.0f, 0.0f, 0.f }, - .uv = { 0.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, 0.5f, 0.f }, - .color = { 0.0f, 0.0f, 1.0f }, - .normals = { 0.0f, 1.0f, 0.f }, - .uv = { 0.0f, 1.0f } }, - vk::vertex_input{ .position = { -0.5f, 0.5f, 0.f }, - .color = { 1.0f, 1.0f, 1.0f }, - .normals = { 1.0f, 1.0f, 0.f }, - .uv = { 1.0f, 1.0f } }, - - vk::vertex_input{ .position = { -0.5f, -0.5f, -0.5f }, - .color = { 1.0f, 0.0f, 0.0f }, - .normals = { 0.0f, 0.0f, 0.f }, - .uv = { 1.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, -0.5f, -0.5f }, - .color = { 0.0f, 1.0f, 0.0f }, - .normals = { 1.0f, 0.0f, 0.f }, - .uv = { 0.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, 0.5f, -0.5f }, - .color = { 0.0f, 0.0f, 1.0f }, - .normals = { 1.0f, 1.0f, 0.f }, - .uv = { 0.0f, 1.0f } }, - vk::vertex_input{ .position = { -0.5f, 0.5f, -0.5f }, - .color = { 1.0f, 1.0f, 1.0f }, - .normals = { 0.0f, 1.0f, 0.f }, - .uv = { 1.0f, 1.0f } } + vk::vertex_input{ + .position = { -0.5f, -0.5f, 0.f }, + .color = { 1.0f, 0.0f, 0.0f }, + .normals = { 1.0f, 0.0f, 0.f }, + .uv = { 1.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, -0.5f, 0.f }, + .color = { 0.0f, 1.0f, 0.0f }, + .normals = { 0.0f, 0.0f, 0.f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, 0.5f, 0.f }, + .color = { 0.0f, 0.0f, 1.0f }, + .normals = { 0.0f, 1.0f, 0.f }, + .uv = { 0.0f, 1.0f }, + }, + vk::vertex_input{ + .position = { -0.5f, 0.5f, 0.f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 1.0f, 1.0f, 0.f }, + .uv = { 1.0f, 1.0f }, + }, + + vk::vertex_input{ + .position = { -0.5f, -0.5f, -0.5f }, + .color = { 1.0f, 0.0f, 0.0f }, + .normals = { 0.0f, 0.0f, 0.f }, + .uv = { 1.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, -0.5f, -0.5f }, + .color = { 0.0f, 1.0f, 0.0f }, + .normals = { 1.0f, 0.0f, 0.f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, 0.5f, -0.5f }, + .color = { 0.0f, 0.0f, 1.0f }, + .normals = { 1.0f, 1.0f, 0.f }, + .uv = { 0.0f, 1.0f }, + }, + vk::vertex_input{ + .position = { -0.5f, 0.5f, -0.5f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 1.0f, 0.f }, + .uv = { 1.0f, 1.0f }, + } }; //! @brief Setting host visibility property flags @@ -465,8 +534,8 @@ main() { vk::buffer_parameters vertex_params = { .memory_mask = physical_device.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::vertex_buffer test_vbo(logical_device, vertices, vertex_params); @@ -474,19 +543,17 @@ main() { std::array indices = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4 }; vk::buffer_parameters index_params = { .memory_mask = physical_device.memory_properties(property_flags), - .property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .property_flags = vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit, + .usage = vk::buffer_usage::index_buffer_bit, }; vk::index_buffer test_ibo(logical_device, indices, index_params); vk::buffer_parameters uniform_params = { - .memory_mask = - physical_device.memory_properties(static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .memory_mask = physical_device.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo = vk::uniform_buffer( @@ -507,25 +574,25 @@ main() { } }; - // Loading a texture -- for testing + // Loading a texture vk::texture_params config_texture = { .memory_mask = physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), }; - vk::texture texture1( - logical_device, - std::filesystem::path("asset_samples/container_diffuse.png"), - config_texture); - std::println("texture1.valid = {}", texture1.loaded()); + stb_image img = + stb_image("asset_samples/container_diffuse.png", config_texture); + vk::texture texture1(logical_device, &img, config_texture); - 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 = { @@ -627,38 +694,37 @@ main() { // }); (???) // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set0_resource.destroy(); - test_ubo.destroy(); - test_ibo.destroy(); - test_vbo.destroy(); + texture1.destruct(); + set0_resource.destruct(); + test_ubo.destruct(); + test_ibo.destruct(); + test_vbo.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + depth_img.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/12-loading-models/CMakeLists.txt b/demos/12-loading-models/CMakeLists.txt index a0f1d47..e89a9ad 100644 --- a/demos/12-loading-models/CMakeLists.txt +++ b/demos/12-loading-models/CMakeLists.txt @@ -14,6 +14,7 @@ build_application( tinyobjloader LINK_PACKAGES + stb::stb vulkan-cpp tinyobjloader Vulkan::Vulkan diff --git a/demos/12-loading-models/application.cpp b/demos/12-loading-models/application.cpp index 00ccd2e..c65f07c 100644 --- a/demos/12-loading-models/application.cpp +++ b/demos/12-loading-models/application.cpp @@ -14,7 +14,6 @@ #include #include #include -import vk; #include #define GLM_FORCE_RADIANS @@ -23,9 +22,15 @@ import vk; #define GLM_ENABLE_EXPERIMENTAL #include -#include - #include +#include + +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -163,8 +168,8 @@ class obj_model { vk::buffer_parameters vertex_params = { .memory_mask = p_physical.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { @@ -172,7 +177,7 @@ class obj_model { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_params); @@ -199,9 +204,9 @@ class obj_model { } } - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); + void destruct() { + m_vertex_buffer.destruct(); + m_index_buffer.destruct(); } private: @@ -235,6 +240,80 @@ get_instance_extensions() { return extension_names; } +/** + * @brief STBI-specific implementation of the vk::image interface + */ +class stb_image : public vk::image { +public: + stb_image() = delete; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + +protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + vk::image_params image_options = { + .extent = m_extent, + .format = texture_format, + .memory_mask = p_params.memory_mask, + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .mip_levels = p_params.mip_levels, + .layer_count = p_params.layer_count, + }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + +private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; +}; + int main() { //! @note Just added the some test code to test the conan-starter setup code @@ -286,20 +365,9 @@ main() { // Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - - // Specifically set for the mac m1 series platform -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -315,11 +383,6 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; @@ -332,19 +395,7 @@ main() { std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif - vk::device_features device_features{ - vk::descriptor_indexing_feature{ { - .descriptorBindingSampledImageUpdateAfterBind = true, - .descriptorBindingPartiallyBound = true, - .descriptorBindingVariableDescriptorCount = true, - } }, - vk::dynamic_rendering_feature{ { - .dynamicRendering = true, - } }, - }; - vk::device_params logical_device_params = { - .features = device_features.data(), .queue_priorities = priorities, .extensions = extensions, .queue_family_index = 0, @@ -353,21 +404,14 @@ main() { 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 = physical_device.request_surface(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 + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -397,7 +441,7 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -415,7 +459,7 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -428,7 +472,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -466,8 +510,6 @@ main() { vk::renderpass main_renderpass(logical_device, renderpass_attachments); - std::println("renderpass created!!!"); - // Setting up swapchain framebuffers std::vector swapchain_framebuffers(image_count); @@ -491,9 +533,6 @@ main() { 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, @@ -505,8 +544,6 @@ main() { // 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{ @@ -566,7 +603,7 @@ main() { std::vector entries = { vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -585,7 +622,7 @@ main() { std::vector entries_set1 = { vk::descriptor_entry{ // layout (set = 1, binding = 0) uniform sampler2D - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 0, .stage = vk::shader_stage::fragment, @@ -639,7 +676,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo = vk::uniform_buffer( logical_device, sizeof(global_uniform), uniform_params); @@ -659,14 +696,13 @@ main() { }; vk::texture_params config_texture = { - .memory_mask = - physical_device.memory_properties(static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit)), + .memory_mask = physical_device.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), }; - vk::texture texture1(logical_device, - std::filesystem::path("asset_samples/viking_room.png"), - config_texture); + + stb_image img = stb_image("asset_samples/viking_room.png", config_texture); + vk::texture texture1(logical_device, &img, config_texture); std::array samplers = { vk::write_image{ @@ -779,38 +815,37 @@ main() { // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set0_resource.destroy(); - set1_resource.destroy(); - test_ubo.destroy(); - test_model.destroy(); + texture1.destruct(); + set0_resource.destruct(); + set1_resource.destruct(); + test_ubo.destruct(); + test_model.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + depth_img.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/13-skybox/CMakeLists.txt b/demos/13-skybox/CMakeLists.txt index 50be187..6a44aa1 100644 --- a/demos/13-skybox/CMakeLists.txt +++ b/demos/13-skybox/CMakeLists.txt @@ -14,6 +14,7 @@ build_application( tinyobjloader LINK_PACKAGES + stb::stb vulkan-cpp tinyobjloader Vulkan::Vulkan diff --git a/demos/13-skybox/application.cpp b/demos/13-skybox/application.cpp index 8c1a757..1e37459 100644 --- a/demos/13-skybox/application.cpp +++ b/demos/13-skybox/application.cpp @@ -14,7 +14,6 @@ #include #include #include -import vk; #include #define GLM_FORCE_RADIANS @@ -22,8 +21,15 @@ import vk; #include #define GLM_ENABLE_EXPERIMENTAL #include +#include #include +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +import vk; import environment_map; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -116,20 +122,9 @@ main() { // Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - - // Specifically set for the mac m1 series platform -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -143,17 +138,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -167,21 +159,14 @@ main() { 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 = physical_device.request_surface(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 + .width = static_cast(width), + .height = static_cast(height), + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -210,10 +195,9 @@ main() { .format = surface_properties.format.format, .memory_mask = physical_device.memory_properties(vk::memory_property::device_local_bit), .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] = @@ -221,13 +205,15 @@ main() { // Creating Images for depth buffering vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = depth_format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -278,8 +264,6 @@ main() { vk::renderpass main_renderpass(logical_device, renderpass_attachments); - std::println("renderpass created!!!"); - // Setting up swapchain framebuffers std::vector swapchain_framebuffers(image_count); @@ -303,9 +287,6 @@ main() { 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, @@ -317,21 +298,12 @@ main() { // gets set with the renderpass std::array color = { 0.f, 0.5f, 0.5f, 1.f }; - // std::vector faces = { - // "asset_samples/skybox/right.jpg", - // "asset_samples/skybox/left.jpg", - // "asset_samples/skybox/top.jpg", - // "asset_samples/skybox/bottom.jpg", - // "asset_samples/skybox/front.jpg", - // "asset_samples/skybox/back.jpg" - // }; environment_map skybox = environment_map( logical_device, std::filesystem::path("asset_samples/skybox/monkstown_castle_4k.hdr"), physical_device, main_renderpass); - // editor camera properties float field_of_view = 45.f; glm::vec3 position = { 3.5f, 4.90f, 36.40f }; glm::vec3 scale{ 1.f }; @@ -363,25 +335,7 @@ main() { float time = std::chrono::duration( current_time - start_time) .count(); - // 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(90.f), - // (float)swapchain_extent.width / - // (float)swapchain_extent.height, - // 0.1f, - // 10.0f) - // }; - - // if(glfwGetKey(main_window, GLFW_KEY)) - // glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); - // glm::vec3 forward = glm::rotate(to_quaternion, - // atlas::math::backward()); glm::vec3 right = - // glm::rotate(to_quaternion, atlas::math::right()); + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { position.z += 1.f; } @@ -394,6 +348,7 @@ main() { if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) { position.x -= 1.f; } + global_uniform ubo = {}; ubo.proj = glm::mat4(1.f); ubo.proj = glm::perspective( @@ -426,31 +381,30 @@ main() { // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + depth_img.destruct(); } - skybox.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + skybox.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/13-skybox/environment_map.cppm b/demos/13-skybox/environment_map.cppm index f2ed59d..ada7444 100644 --- a/demos/13-skybox/environment_map.cppm +++ b/demos/13-skybox/environment_map.cppm @@ -27,6 +27,7 @@ module; #define GLM_ENABLE_EXPERIMENTAL #include #include +#include export module environment_map; import vk; @@ -51,7 +52,7 @@ public: } // ~environment_map() { - // destroy(); + // destruct(); // } void create_hdr_skybox(const std::filesystem::path& p_filename) { @@ -83,10 +84,10 @@ public: .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::transfer_src_bit), + .usage = vk::buffer_usage::transfer_src_bit, }; - vk::buffer_stream staging_buffer = vk::buffer_stream( + vk::buffer staging_buffer = vk::buffer( m_device, static_cast(image_size), staging_buffer_params); // Creating image handle to storing the HDR @@ -161,8 +162,8 @@ public: vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(graphics_queue); - upload_cmd.destroy(); - staging_buffer.destroy(); + upload_cmd.destruct(); + staging_buffer.destruct(); stbi_set_flip_vertically_on_load(false); } @@ -326,17 +327,14 @@ public: { 0.0f, 0.0f } } }; - const uint32_t property = - static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit); vk::buffer_parameters vertex_params = { .memory_mask = m_physical_device->memory_properties( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; m_skybox_vbo_size = vertices.size(); m_skybox_vbo = vk::vertex_buffer(m_device, vertices, vertex_params); @@ -408,8 +406,7 @@ public: // m_physical_device->memory_properties(static_cast(property)), .memory_mask = m_physical_device->memory_properties( vk::memory_property::host_cached_bit), - .usage = - static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; m_skybox_ubo = vk::uniform_buffer(m_device, sizeof(skybox_uniform), uniform_params); @@ -419,23 +416,20 @@ public: identity.proj_view[1][1] *= -1; std::span bytes(reinterpret_cast(&identity), 1); - std::println("Before transfer!"); - // m_skybox_ubo.transfer(bytes); - std::println("After transfer!"); // set=0 bindings: // - binding 0: UBO (vertex) // - binding 1: samplerCube (fragment) std::array entries = { vk::descriptor_entry{ - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = vk::descriptor_binding_point{ .binding = 0, .stage = vk::shader_stage::vertex }, .descriptor_count = 1, }, vk::descriptor_entry{ - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = vk::descriptor_binding_point{ .binding = 1, .stage = vk::shader_stage::fragment }, @@ -537,7 +531,8 @@ public: .dynamic_states = dyn, }; - m_skybox_pipeline = vk::pipeline(m_device, pipe_info); + m_skybox_pipeline = + std::make_optional(m_device, pipe_info); } void update_uniform(const skybox_uniform& p_ubo) { @@ -545,9 +540,9 @@ public: } void bind(vk::command_buffer p_current) { - m_skybox_pipeline.bind(p_current); + m_skybox_pipeline->bind(p_current); std::array descriptors = { m_skybox_descriptors }; - p_current.bind_descriptors(m_skybox_pipeline.layout(), + p_current.bind_descriptors(m_skybox_pipeline->layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, descriptors); // m_skybox_vbo.bind(p_current); @@ -568,16 +563,16 @@ public: //! @brief Retreving the sample image of the environment map. [[nodiscard]] vk::sample_image image() const { return m_skybox_image; } - void destroy() { + void destruct() { - m_skybox_image.destroy(); - if (m_skybox_pipeline.alive()) { - m_skybox_pipeline.destroy(); + m_skybox_image.destruct(); + if (m_skybox_pipeline->alive()) { + m_skybox_pipeline->destruct(); } - m_skybox_descriptors.destroy(); - m_skybox_ubo.destroy(); - m_skybox_shaders.destroy(); - m_skybox_vbo.destroy(); + m_skybox_descriptors.destruct(); + m_skybox_ubo.destruct(); + m_skybox_shaders.destruct(); + m_skybox_vbo.destruct(); } //! TODO: Logic for converting the HDR image handles to a skybox @@ -592,7 +587,7 @@ private: vk::shader_resource m_skybox_shaders{}; vk::uniform_buffer m_skybox_ubo{}; vk::descriptor_resource m_skybox_descriptors{}; - vk::pipeline m_skybox_pipeline{}; + std::optional m_skybox_pipeline{}; vk::vertex_buffer m_skybox_vbo; uint64_t m_skybox_vbo_size = 0; }; \ No newline at end of file diff --git a/demos/14-imgui/CMakeLists.txt b/demos/14-imgui/CMakeLists.txt index a0f1d47..e89a9ad 100644 --- a/demos/14-imgui/CMakeLists.txt +++ b/demos/14-imgui/CMakeLists.txt @@ -14,6 +14,7 @@ build_application( tinyobjloader LINK_PACKAGES + stb::stb vulkan-cpp tinyobjloader Vulkan::Vulkan diff --git a/demos/14-imgui/application.cpp b/demos/14-imgui/application.cpp index 21c07c8..e447748 100644 --- a/demos/14-imgui/application.cpp +++ b/demos/14-imgui/application.cpp @@ -14,7 +14,7 @@ #include #include #include -import vk; +#include #include #define GLM_FORCE_RADIANS @@ -23,10 +23,15 @@ import vk; #define GLM_ENABLE_EXPERIMENTAL #include -#include - #include +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +import vk; + static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, @@ -154,27 +159,40 @@ class obj_model { } m_indices_size = vertices.size(); m_indices_size = indices.size(); - vk::vertex_params vertex_info = { - .phsyical_memory_properties = p_physical.memory_properties(), + //! @brief Creating vertex/index buffers with host visibility flags + const auto property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + + vk::buffer_parameters vertex_params = { + .memory_mask = p_physical.memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; - vk::index_params index_info = { .phsyical_memory_properties = - p_physical.memory_properties() }; + vk::buffer_parameters index_params = { + .memory_mask = p_physical.memory_properties(property_flags), + .property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, + }; - m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_info); - m_index_buffer = vk::index_buffer(p_device, indices, index_info); + m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_params); + m_index_buffer = vk::index_buffer(p_device, indices, index_params); m_is_loaded = true; } [[nodiscard]] bool loaded() const { return m_is_loaded; } - void bind(const VkCommandBuffer& p_command) { - m_vertex_buffer.bind(p_command); + [[nodiscard]] VkBuffer vertex_handle() const { return m_vertex_buffer; } - if (m_has_indices) { - m_index_buffer.bind(p_command); - } - } + [[nodiscard]] VkBuffer index_handle() const { return m_index_buffer; } + + [[nodiscard]] bool has_indices() const { return m_has_indices; } + + [[nodiscard]] uint32_t indices_size() const { return m_indices_size; } void draw(const VkCommandBuffer& p_command) { if (m_has_indices) { @@ -185,9 +203,9 @@ class obj_model { } } - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); + void destruct() { + m_vertex_buffer.destruct(); + m_index_buffer.destruct(); } private: @@ -221,6 +239,80 @@ get_instance_extensions() { return extension_names; } +/** + * @brief STBI-specific implementation of the vk::image interface + */ +class stb_image : public vk::image { +public: + stb_image() = delete; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + +protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + vk::image_params image_options = { + .extent = m_extent, + .format = texture_format, + .memory_mask = p_params.memory_mask, + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .mip_levels = p_params.mip_levels, + .layer_count = p_params.layer_count, + }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + +private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; +}; + int main() { //! @note Just added the some test code to test the conan-starter setup code @@ -276,16 +368,9 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - - // Specifically set for the mac m1 series platform -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -297,19 +382,16 @@ main() { // 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); + physical_device.request_depth_format(format_support); // setting up logical device std::array priorities = { 0.f }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -323,21 +405,14 @@ main() { 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 = physical_device.request_surface(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 + .width = static_cast(width), + .height = static_cast(height), + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -360,28 +435,31 @@ main() { for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .height = swapchain_extent.height, }, .format = surface_properties.format.format, + .memory_mask = physical_device.memory_properties( + vk::memory_property::device_local_bit), .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); // Creating Images for depth buffering vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = depth_format, + .memory_mask = physical_device.memory_properties( + vk::memory_property::device_local_bit), .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); @@ -430,8 +508,6 @@ main() { vk::renderpass main_renderpass(logical_device, renderpass_attachments); - std::println("renderpass created!!!"); - // Setting up swapchain framebuffers std::vector swapchain_framebuffers(image_count); @@ -455,9 +531,6 @@ main() { 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, @@ -530,7 +603,7 @@ main() { std::vector entries = { vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -549,7 +622,7 @@ main() { std::vector entries_set1 = { vk::descriptor_entry{ // layout (set = 1, binding = 0) uniform sampler2D - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 0, .stage = vk::shader_stage::fragment, @@ -597,11 +670,17 @@ main() { physical_device); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { - .phsyical_memory_properties = physical_device.memory_properties() + vk::buffer_parameters uniform_params = { + .memory_mask = + physical_device.memory_properties(static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit)), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; - vk::uniform_buffer test_ubo = - vk::uniform_buffer(logical_device, sizeof(global_uniform), test_ubo_info); + vk::uniform_buffer test_ubo = vk::uniform_buffer( + logical_device, sizeof(global_uniform), uniform_params); // std::println("uniform_buffer.alive() = {}", test_ubo.alive()); std::array uniforms0 = { @@ -619,12 +698,14 @@ main() { }; // Loading a texture - vk::texture_info config_texture = { - .phsyical_memory_properties = physical_device.memory_properties(), + vk::texture_params config_texture = { + .memory_mask = physical_device.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), }; - vk::texture texture1(logical_device, - std::filesystem::path("asset_samples/viking_room.png"), - config_texture); + + stb_image img = stb_image("asset_samples/viking_room.png", config_texture); + vk::texture texture1(logical_device, &img, config_texture); std::array samplers = { vk::write_image{ @@ -667,8 +748,14 @@ main() { // drawing stuff to main_graphics_pipeline.bind(current); - // Must be binded before descriptor resource gets binded - test_model.bind(current); + const VkBuffer vertex = test_model.vertex_handle(); + uint64_t offset = 0; + current.bind_vertex_buffers(std::span(&vertex, 1), + std::span(&offset, 1)); + + if (test_model.has_indices()) { + current.bind_index_buffers32(test_model.index_handle()); + } static auto start_time = std::chrono::high_resolution_clock::now(); @@ -727,38 +814,37 @@ main() { // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set0_resource.destroy(); - set1_resource.destroy(); - test_ubo.destroy(); - test_model.destroy(); + texture1.destruct(); + set0_resource.destruct(); + set1_resource.destruct(); + test_ubo.destruct(); + test_model.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + depth_img.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/15-dynamic-rendering/application.cpp b/demos/15-dynamic-rendering/application.cpp index ecc065d..b05ec4a 100644 --- a/demos/15-dynamic-rendering/application.cpp +++ b/demos/15-dynamic-rendering/application.cpp @@ -14,7 +14,7 @@ #include #include #include -import vk; +#include #include #define GLM_FORCE_RADIANS @@ -23,10 +23,10 @@ import vk; #define GLM_ENABLE_EXPERIMENTAL #include -#include - #include +import vk; + static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, @@ -163,8 +163,8 @@ class obj_model { vk::buffer_parameters vertex_params = { .memory_mask = p_physical.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { @@ -172,7 +172,7 @@ class obj_model { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_params); @@ -199,9 +199,9 @@ class obj_model { } } - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); + void destruct() { + m_vertex_buffer.destruct(); + m_index_buffer.destruct(); } private: @@ -295,12 +295,9 @@ main() { } // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - vk::queue_indices queue_indices = physical_device.family_indices(); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -324,8 +321,6 @@ main() { // 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); VkFormat depth_format = physical_device.request_depth_format(format_support); @@ -339,7 +334,7 @@ main() { .features = device_features.data(), .queue_priorities = priorities, .extensions = extensions, - .queue_family_index = queue_indices.graphics, + .queue_family_index = 0, }; vk::device logical_device(physical_device, logical_device_params); @@ -352,9 +347,7 @@ main() { vk::swapchain_params enumerate_swapchain_settings = { .width = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -399,7 +392,7 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -412,7 +405,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -433,10 +426,14 @@ main() { // Loading graphics pipeline std::array shader_sources = { - vk::shader_source{ .filename = "shader_samples/sample1/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample1/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample1/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample1/test.frag.spv", + .stage = vk::shader_stage::fragment, + }, }; // To render triangle, we do not need to set any vertex attributes @@ -581,28 +578,27 @@ main() { } logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - geometry_resource.destroy(); - main_graphics_pipeline.destroy(); + geometry_resource.destruct(); + main_graphics_pipeline.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& image : swapchain_depth_images) { - image.destroy(); + image.destruct(); } - presentation_queue.destroy(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } diff --git a/demos/16-descriptor-indexing/CMakeLists.txt b/demos/16-descriptor-indexing/CMakeLists.txt index 5bd84bc..2d64cab 100644 --- a/demos/16-descriptor-indexing/CMakeLists.txt +++ b/demos/16-descriptor-indexing/CMakeLists.txt @@ -14,6 +14,7 @@ build_application( tinyobjloader LINK_PACKAGES + stb::stb vulkan-cpp tinyobjloader Vulkan::Vulkan diff --git a/demos/16-descriptor-indexing/README.md b/demos/16-descriptor-indexing/README.md index 39294d0..c618560 100644 --- a/demos/16-descriptor-indexing/README.md +++ b/demos/16-descriptor-indexing/README.md @@ -43,7 +43,7 @@ These flags are a way to indicate this specific layout binding may have a max am std::vector entries_set1 = { vk::descriptor_entry{ // layout (set = 1, binding = 0) uniform sampler2D - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 0, .stage = vk::shader_stage::fragment, diff --git a/demos/16-descriptor-indexing/application.cpp b/demos/16-descriptor-indexing/application.cpp index 60b6756..078d220 100644 --- a/demos/16-descriptor-indexing/application.cpp +++ b/demos/16-descriptor-indexing/application.cpp @@ -14,7 +14,7 @@ #include #include #include -import vk; +#include #include #define GLM_FORCE_RADIANS @@ -23,9 +23,13 @@ import vk; #define GLM_ENABLE_EXPERIMENTAL #include -#include +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif #include +import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( @@ -163,8 +167,8 @@ class obj_model { vk::buffer_parameters vertex_params = { .memory_mask = p_physical.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { @@ -172,7 +176,7 @@ class obj_model { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_params); @@ -199,9 +203,9 @@ class obj_model { } } - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); + void destruct() { + m_vertex_buffer.destruct(); + m_index_buffer.destruct(); } private: @@ -239,6 +243,80 @@ struct push_constant_data { uint32_t texture_index = 0; }; +/** + * @brief STBI-specific implementation of the vk::image interface + */ +class stb_image : public vk::image { +public: + stb_image() = delete; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + +protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + vk::image_params image_options = { + .extent = m_extent, + .format = texture_format, + .memory_mask = p_params.memory_mask, + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .mip_levels = p_params.mip_levels, + .layer_count = p_params.layer_count, + }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + +private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; +}; + int main() { //! @note Just added the some test code to test the conan-starter setup code @@ -294,17 +372,10 @@ main() { // 1. Setting up vk instance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - vk::queue_indices queue_indices = physical_device.family_indices(); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -348,7 +419,7 @@ main() { .features = device_features.data(), .queue_priorities = priorities, .extensions = extensions, - .queue_family_index = queue_indices.graphics, + .queue_family_index = 0, }; vk::device logical_device(physical_device, logical_device_params); @@ -361,9 +432,7 @@ main() { vk::swapchain_params enumerate_swapchain_settings = { .width = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -408,7 +477,7 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -421,7 +490,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -501,7 +570,7 @@ main() { std::vector entries = { vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -520,7 +589,7 @@ main() { std::vector entries_set1 = { vk::descriptor_entry{ // layout (set = 1, binding = 0) uniform sampler2D textures[]; - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 0, .stage = vk::shader_stage::fragment, @@ -596,7 +665,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo = vk::uniform_buffer( logical_device, sizeof(global_uniform), uniform_params); @@ -616,14 +685,13 @@ main() { }; vk::texture_params config_texture = { - .memory_mask = - physical_device.memory_properties(static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit)), + .memory_mask = physical_device.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), }; - vk::texture texture1(logical_device, - std::filesystem::path("asset_samples/viking_room.png"), - config_texture); + + stb_image img = stb_image("asset_samples/viking_room.png", config_texture); + vk::texture texture1(logical_device, &img, config_texture); std::array samplers = { vk::write_image{ @@ -754,7 +822,7 @@ main() { .texture_index = 0, }; main_graphics_pipeline.push_constant( - current, push, stage, 0, sizeof(push_constant_data)); + current, push, stage, 0); // We set the uniforms and then we offload that to the GPU global_uniform ubo = { @@ -808,34 +876,33 @@ main() { } logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set0_resource.destroy(); - set1_resource.destroy(); - test_ubo.destroy(); - test_model.destroy(); + texture1.destruct(); + set0_resource.destruct(); + set1_resource.destruct(); + test_ubo.destruct(); + test_model.destruct(); - geometry_resource.destroy(); - main_graphics_pipeline.destroy(); + geometry_resource.destruct(); + main_graphics_pipeline.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& image : swapchain_depth_images) { - image.destroy(); + image.destruct(); } - presentation_queue.destroy(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } diff --git a/demos/17-buffer-device-address/README.md b/demos/17-buffer-device-address/README.md index bf8e784..7fe6fce 100644 --- a/demos/17-buffer-device-address/README.md +++ b/demos/17-buffer-device-address/README.md @@ -42,9 +42,8 @@ vk::buffer_parameters uniform_params = { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = - static_cast(vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; diff --git a/demos/17-buffer-device-address/application.cpp b/demos/17-buffer-device-address/application.cpp index 3da9742..8d78a8c 100644 --- a/demos/17-buffer-device-address/application.cpp +++ b/demos/17-buffer-device-address/application.cpp @@ -169,8 +169,8 @@ class obj_model { vk::buffer_parameters vertex_params = { .memory_mask = p_physical.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { @@ -178,7 +178,7 @@ class obj_model { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_params); @@ -205,9 +205,9 @@ class obj_model { } } - void destroy() { - m_vertex_buffer.destroy(); - m_index_buffer.destroy(); + void destruct() { + m_vertex_buffer.destruct(); + m_index_buffer.destruct(); } private: @@ -294,8 +294,8 @@ class stb_image : public vk::image { .extent = m_extent, .format = texture_format, .memory_mask = p_params.memory_mask, - .usage = static_cast(vk::image_usage::transfer_dst_bit) | - static_cast(vk::image_usage::sampled_bit), + .usage = + vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, .mip_levels = p_params.mip_levels, .layer_count = p_params.layer_count, }; @@ -495,7 +495,7 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; @@ -586,7 +586,7 @@ main() { std::vector entries_set1 = { vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D textures[]; - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 1, .stage = vk::shader_stage::fragment, @@ -661,9 +661,8 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = - static_cast(vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; vk::dyn::buffer test_ubo = @@ -827,7 +826,7 @@ main() { .global_ubo_addr = ubo_address, }; main_graphics_pipeline.push_constant( - current, push, stage, 0, sizeof(push_constant_data)); + current, push, stage, 0); const VkDescriptorSet set1 = set1_resource; current.bind_descriptors(main_graphics_pipeline.layout(), @@ -853,33 +852,32 @@ main() { } logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - texture1.destroy(); - set1_resource.destroy(); + texture1.destruct(); + set1_resource.destruct(); test_ubo.reset(); - test_model.destroy(); + test_model.destruct(); - geometry_resource.destroy(); - main_graphics_pipeline.destroy(); + geometry_resource.destruct(); + main_graphics_pipeline.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } for (auto& image : swapchain_depth_images) { - image.destroy(); + image.destruct(); } - presentation_queue.destroy(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - // api_instance.destruct(); return 0; } diff --git a/demos/2-physical-device/application.cpp b/demos/2-physical-device/application.cpp index 64fb99f..278cb3a 100644 --- a/demos/2-physical-device/application.cpp +++ b/demos/2-physical-device/application.cpp @@ -13,6 +13,7 @@ #include #include #include +#include import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -103,18 +104,18 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated - }; + // Selecting a specific physical device + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); - vk::physical_device device(api_instance, enumerate_devices); + std::println("Device name: {}", physical_device.properties().deviceName); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } glfwDestroyWindow(window); - api_instance.destroy(); + api_instance.destruct(); return 0; } diff --git a/demos/3-logical-device/README.md b/demos/3-logical-device/README.md index 64f58a8..590d3b6 100644 --- a/demos/3-logical-device/README.md +++ b/demos/3-logical-device/README.md @@ -76,7 +76,7 @@ vk::device logical_device(physical_device, logical_device_params); # Last Minute Notes -When you have a logical device. When your application closes, make sure to call `.wait()` and `.destroy()`. +When you have a logical device. When your application closes, make sure to call `.wait()` and `.destruct()`. Vulkan requires that all objects you create must be destroyed, deallocated, or freed before the logical device itself gets destroyed @@ -91,8 +91,8 @@ while(!glfwWindowShouldCLose(window)) { // .wait() calls vkDeviceWaitIdle(device) under the hood logical_device.wait(); -// .destroy() ensure the resources of the logical devices are cleaned up properly -logical_device.destroy(); +// .destruct() ensure the resources of the logical devices are cleaned up properly +logical_device.destruct(); ``` # Thats it! diff --git a/demos/3-logical-device/application.cpp b/demos/3-logical-device/application.cpp index 92d9f27..05050cc 100644 --- a/demos/3-logical-device/application.cpp +++ b/demos/3-logical-device/application.cpp @@ -13,6 +13,7 @@ #include #include #include +#include import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -104,16 +105,9 @@ main() { } // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - vk::queue_indices queue_indices = physical_device.family_indices(); - std::println("Graphics Queue Family Index = {}", - (int)queue_indices.graphics); - std::println("Compute Queue Family Index = {}", queue_indices.compute); - std::println("Transfer Queue Family Index = {}", queue_indices.transfer); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -124,29 +118,28 @@ main() { std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif - vk::device_params logical_device_params = { + vk::device_params device_params = { .queue_priorities = priorities, .extensions = extensions, .queue_family_index = 0, }; - vk::device logical_device(physical_device, logical_device_params); + vk::device logical_device(physical_device, device_params); // Presentation queue family uses graphics queue vk::queue_params present_queue_enumerate = { .family = 0, - .index = queue_indices.graphics, + .index = 0, }; - vk::device_queue presesnt_queue(logical_device, present_queue_enumerate); + vk::device_queue present_queue(logical_device, present_queue_enumerate); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } logical_device.wait(); - logical_device.destroy(); + logical_device.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } diff --git a/demos/4-surface/application.cpp b/demos/4-surface/application.cpp index d09934a..049c06d 100644 --- a/demos/4-surface/application.cpp +++ b/demos/4-surface/application.cpp @@ -13,6 +13,7 @@ #include #include #include +#include import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -103,13 +104,10 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - vk::queue_indices queue_indices = physical_device.family_indices(); + // Selecting a specific physical device + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -134,7 +132,7 @@ main() { // Presentation queue family uses graphics queue vk::queue_params present_queue_enumerate = { .family = 0, - .index = queue_indices.graphics, + .index = 0, }; vk::device_queue presesnt_queue(logical_device, present_queue_enumerate); @@ -143,10 +141,9 @@ main() { } logical_device.wait(); - logical_device.destroy(); + logical_device.destruct(); - window_surface.destroy(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } diff --git a/demos/5-swapchain/README.md b/demos/5-swapchain/README.md index 3ec4b76..7de0f7e 100644 --- a/demos/5-swapchain/README.md +++ b/demos/5-swapchain/README.md @@ -118,7 +118,7 @@ for(uint32_t i = 0; i < swapchain_images.size(); i++) { .extent = { .width=swapchain_extent.width, .height=swapchain_extent.height }, .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(), diff --git a/demos/5-swapchain/application.cpp b/demos/5-swapchain/application.cpp index a91b567..fdc244d 100644 --- a/demos/5-swapchain/application.cpp +++ b/demos/5-swapchain/application.cpp @@ -13,6 +13,7 @@ #include #include #include +#include import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -107,13 +108,10 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::integrated, - }; - vk::physical_device physical_device(api_instance, enumerate_devices); - - vk::queue_indices queue_indices = physical_device.family_indices(); + // Selecting a specific physical device + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // setting up logical device std::array priorities = { 0.f }; @@ -128,7 +126,7 @@ main() { vk::device_params logical_device_params = { .queue_priorities = priorities, .extensions = extensions, - .queue_family_index = queue_indices.graphics, + .queue_family_index = 0, }; vk::device logical_device(physical_device, logical_device_params); @@ -141,9 +139,7 @@ main() { vk::swapchain_params enumerate_swapchain_settings = { .width = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -184,7 +180,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -266,30 +262,25 @@ main() { // }); (???) // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); + image.destruct(); } - // for (auto& depth_image : swapchain_depth_images) { - // depth_image.destroy(); - // } - - main_renderpass.destroy(); - presentation_queue.destroy(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } diff --git a/demos/6-graphics-pipeline/README.md b/demos/6-graphics-pipeline/README.md index e68afaa..c59f055 100644 --- a/demos/6-graphics-pipeline/README.md +++ b/demos/6-graphics-pipeline/README.md @@ -345,10 +345,10 @@ while (!glfwWindowShouldClose(window)) { } // make sure to destroy child objects of Vulkan before the actual logical device. -main_graphics_pipeline.destroy(); -geometry_resource.destroy(); +main_graphics_pipeline.destruct(); +geometry_resource.destruct(); -logical_device.destroy(); +logical_device.destruct(); ``` # Final Result diff --git a/demos/6-graphics-pipeline/application.cpp b/demos/6-graphics-pipeline/application.cpp index ac28a35..25c6262 100644 --- a/demos/6-graphics-pipeline/application.cpp +++ b/demos/6-graphics-pipeline/application.cpp @@ -14,6 +14,7 @@ #include #include #include +#include import vk; @@ -105,16 +106,10 @@ main() { std::println("\napi_instance alive and initiated!!!"); } - // setting up physical device - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + // Selecting a specific physical device + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -128,11 +123,6 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; @@ -152,21 +142,14 @@ main() { 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 = physical_device.request_surface(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 + .width = static_cast(width), + .height = static_cast(height), + .present_index = 0 }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -177,43 +160,29 @@ main() { std::span images = main_swapchain.get_images(); uint32_t image_count = static_cast(images.size()); - // Creating Images + // Creating images from vk::swapchain std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; // Setting up the images for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = surface_properties.format.format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - // Creating Depth Images for depth buffering - vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, - .format = depth_format, - .memory_mask = physical_device.memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - }; - swapchain_depth_images[i] = - vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -221,7 +190,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -229,10 +198,9 @@ main() { vk::command_buffer(logical_device, settings); } - // setting up renderpass - + // Configuring a renderpass // setting up attachments for the renderpass - std::array renderpass_attachments = { + std::array renderpass_attachments = { vk::attachment{ .format = surface_properties.format.format, .layout = vk::image_layout::color_optimal, @@ -244,23 +212,10 @@ main() { .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::depth_stencil_read_only_optimal, - }, }; 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++) { @@ -271,8 +226,7 @@ main() { // 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() }; + image_view_attachments = { swapchain_images[i].image_view() }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, @@ -283,9 +237,6 @@ main() { 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, @@ -297,14 +248,16 @@ main() { // 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/sample1/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample1/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample1/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample1/test.frag.spv", + .stage = vk::shader_stage::fragment, + }, }; // To render triangle, we do not need to set any vertex attributes @@ -315,10 +268,6 @@ main() { }; vk::shader_resource geometry_resource(logical_device, shader_info); - if (geometry_resource.is_valid()) { - std::println("geometry resource is valid!"); - } - // Setting up descriptor sets for graphics pipeline std::array color_blend_attachments = { vk::color_blend_attachment_state{}, @@ -340,11 +289,6 @@ main() { }; vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if (main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", - main_graphics_pipeline.alive()); - } - while (!glfwWindowShouldClose(window)) { glfwPollEvents(); @@ -381,32 +325,27 @@ main() { // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_image : swapchain_depth_images) { - depth_image.destroy(); + image.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/7-vertex-buffer/application.cpp b/demos/7-vertex-buffer/application.cpp index 8d8a681..61b4d4e 100644 --- a/demos/7-vertex-buffer/application.cpp +++ b/demos/7-vertex-buffer/application.cpp @@ -13,6 +13,8 @@ #include #include #include +#include + import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -103,33 +105,13 @@ main() { // 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_gpu::discrete}) - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + // Selecting a specific physical device + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // 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 @@ -140,17 +122,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -164,21 +143,14 @@ main() { 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 = physical_device.request_surface(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 = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -191,7 +163,6 @@ main() { // Creating Images std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; @@ -200,33 +171,21 @@ main() { uint32_t mip_levels = 1; for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = surface_properties.format.format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, - .format = depth_format, - .memory_mask = physical_device.memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - }; - swapchain_depth_images[i] = - vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -234,7 +193,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -242,10 +201,8 @@ main() { vk::command_buffer(logical_device, settings); } - // setting up renderpass - // setting up attachments for the renderpass - std::array renderpass_attachments = { + std::array renderpass_attachments = { vk::attachment{ .format = surface_properties.format.format, .layout = vk::image_layout::color_optimal, @@ -257,17 +214,6 @@ main() { .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::depth_stencil_read_only_optimal, - }, }; vk::renderpass main_renderpass(logical_device, renderpass_attachments); @@ -275,8 +221,6 @@ 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); - // 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 @@ -284,8 +228,9 @@ main() { // 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() }; + image_view_attachments = { + swapchain_images[i].image_view(), + }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, @@ -349,11 +294,6 @@ main() { }; vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if (main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", - main_graphics_pipeline.alive()); - } - // Setting up vertex buffer std::array vertices = { vk::vertex_input{ @@ -376,8 +316,8 @@ main() { vk::buffer_parameters vertex_params = { .memory_mask = physical_device.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::vertex_buffer test_vbo(logical_device, vertices, vertex_params); @@ -420,34 +360,29 @@ main() { // }); (???) // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - test_vbo.destroy(); + test_vbo.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + image.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ 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 3884ca5..ebc3060 100644 --- a/demos/8-index-uniform-buffers/application.cpp +++ b/demos/8-index-uniform-buffers/application.cpp @@ -14,6 +14,7 @@ #include #include #include +#include import vk; static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -104,27 +105,9 @@ main() { // 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_gpu::discrete}) - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -138,17 +121,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -162,21 +142,14 @@ main() { 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 = physical_device.request_surface(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 + .width = static_cast(width), + .height = static_cast(height), + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -189,7 +162,6 @@ main() { // Creating Images std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; @@ -204,28 +176,13 @@ main() { .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - // Creating Depth Images for depth buffering - vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, - .format = depth_format, - .memory_mask = physical_device.memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - }; - swapchain_depth_images[i] = - vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -233,7 +190,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -241,10 +198,8 @@ main() { vk::command_buffer(logical_device, settings); } - // setting up renderpass - // setting up attachments for the renderpass - std::array renderpass_attachments = { + std::array renderpass_attachments = { vk::attachment{ .format = surface_properties.format.format, .layout = vk::image_layout::color_optimal, @@ -256,17 +211,6 @@ main() { .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::depth_stencil_read_only_optimal, - }, }; vk::renderpass main_renderpass(logical_device, renderpass_attachments); @@ -280,8 +224,7 @@ main() { // 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() }; + image_view_attachments = { swapchain_images[i].image_view() }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, @@ -292,9 +235,6 @@ main() { 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, @@ -306,26 +246,30 @@ main() { // 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 + // Specifying which shaders to load into shader sources std::array shader_sources = { - vk::shader_source{ .filename = "shader_samples/sample2/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample2/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample2/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample2/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::rg32_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 = 0, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + vk::vertex_attribute_entry{ + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + } }; std::array attributes = { @@ -348,10 +292,6 @@ main() { 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!"); - } - std::array color_blend_attachments = { vk::color_blend_attachment_state{}, }; @@ -373,21 +313,24 @@ main() { }; vk::pipeline main_graphics_pipeline(logical_device, pipeline_configuration); - if (main_graphics_pipeline.alive()) { - std::println("Main graphics pipeline alive() = {}", - main_graphics_pipeline.alive()); - } - // Setting up vertex buffer std::array vertices = { - vk::vertex_input{ .position = { -0.5f, -0.5f, 0.f }, - .color = { 1.0f, 0.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, -0.5f, 0.f }, - .color = { 0.0f, 1.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, 0.5f, 0.f }, - .color = { 0.0f, 0.0f, 1.0f } }, - vk::vertex_input{ .position = { -0.5f, 0.5f, 0.f }, - .color = { 1.0f, 1.0f, 1.0f } } + vk::vertex_input{ + .position = { -0.5f, -0.5f, 0.f }, + .color = { 1.0f, 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, -0.5f, 0.f }, + .color = { 0.0f, 1.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, 0.5f, 0.f }, + .color = { 0.0f, 0.0f, 1.0f }, + }, + vk::vertex_input{ + .position = { -0.5f, 0.5f, 0.f }, + .color = { 1.0f, 1.0f, 1.0f }, + }, }; const auto property_flags = @@ -398,11 +341,10 @@ main() { vk::buffer_parameters vertex_params = { .memory_mask = physical_device.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::vertex_buffer test_vbo(logical_device, vertices, vertex_params); - std::println("vertex_buffer.alive() = {}", test_vbo.alive()); // Creating index buffer std::array indices = { 0, 1, 2, 2, 3, 0 }; @@ -411,7 +353,7 @@ main() { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; vk::index_buffer test_ibo(logical_device, indices, index_params); @@ -420,7 +362,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo( logical_device, sizeof(vk::vertex_input), uniform_params); @@ -468,41 +410,33 @@ main() { 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 + // Performing Vulkan cleanup logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - test_ubo.destroy(); - test_ibo.destroy(); - test_vbo.destroy(); + test_ubo.destruct(); + test_ibo.destruct(); + test_vbo.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + image.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/demos/9-uniforms/application.cpp b/demos/9-uniforms/application.cpp index 535aff8..0598bfe 100644 --- a/demos/9-uniforms/application.cpp +++ b/demos/9-uniforms/application.cpp @@ -13,6 +13,7 @@ #include #include #include +#include import vk; #include @@ -107,22 +108,12 @@ main() { global_extensions // .extensions also takes in std::span }; - // 1. Setting up vk instance + // Creating VkInstance vk::instance api_instance(config, debug_callback_info); - if (api_instance.alive()) { - std::println("\napi_instance alive and initiated!!!"); - } - - vk::physical_enumeration enumerate_devices{ - .device_type = vk::physical_gpu::discrete, - }; - -#if defined(__APPLE__) - enumerate_devices.device_type = vk::physical_gpu::integrated; -#endif - - vk::physical_device physical_device(api_instance, enumerate_devices); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); // selecting depth format std::array format_support = { @@ -136,17 +127,14 @@ main() { VkFormat depth_format = physical_device.request_depth_format(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 }; #if defined(__APPLE__) - std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, - "VK_KHR_portability_subset" }; + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; #else std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #endif @@ -160,21 +148,14 @@ main() { 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 = physical_device.request_surface(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 = static_cast(width), .height = static_cast(height), - .present_index = - physical_device.family_indices() - .graphics, // presentation index just uses the graphics index + .present_index = 0, }; vk::swapchain main_swapchain(logical_device, window_surface, @@ -187,7 +168,6 @@ main() { // Creating Images std::vector swapchain_images(image_count); - std::vector swapchain_depth_images(image_count); VkExtent2D swapchain_extent = surface_properties.capabilities.currentExtent; @@ -196,33 +176,21 @@ main() { uint32_t mip_levels = 1; for (uint32_t i = 0; i < swapchain_images.size(); i++) { vk::image_params swapchain_image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, + .extent = { + .width = swapchain_extent.width, + .height = swapchain_extent.height, + }, .format = surface_properties.format.format, .memory_mask = physical_device.memory_properties( vk::memory_property::device_local_bit), .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, }; swapchain_images[i] = vk::sample_image(logical_device, images[i], swapchain_image_config); - - vk::image_params image_config = { - .extent = { .width = swapchain_extent.width, - .height = swapchain_extent.height }, - .format = depth_format, - .memory_mask = physical_device.memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - }; - swapchain_depth_images[i] = - vk::sample_image(logical_device, image_config); } // setting up command buffers @@ -230,7 +198,7 @@ main() { 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, + .queue_index = 0, .flags = vk::command_pool_flags::reset, }; @@ -241,7 +209,7 @@ main() { // setting up renderpass // setting up attachments for the renderpass - std::array renderpass_attachments = { + std::array renderpass_attachments = { vk::attachment{ .format = surface_properties.format.format, .layout = vk::image_layout::color_optimal, @@ -253,23 +221,10 @@ main() { .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::depth_stencil_read_only_optimal, - }, }; vk::renderpass main_renderpass(logical_device, renderpass_attachments); - std::println("renderpass created!!!"); - // Setting up swapchain framebuffers std::vector swapchain_framebuffers(image_count); @@ -281,8 +236,7 @@ main() { // 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() }; + image_view_attachments = { swapchain_images[i].image_view() }; vk::framebuffer_params framebuffer_info = { .renderpass = main_renderpass, @@ -293,9 +247,6 @@ main() { 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, @@ -307,14 +258,16 @@ main() { // 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/sample3/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample3/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample3/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample3/test.frag.spv", + .stage = vk::shader_stage::fragment, + }, }; // Setting up vertex attributes in the test shaders @@ -351,15 +304,11 @@ main() { 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 entries for descriptor set 0 std::vector entries = { vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -402,14 +351,22 @@ main() { // Setting up vertex buffer std::array vertices = { - vk::vertex_input{ .position = { -0.5f, -0.5f, 0.f }, - .color = { 1.0f, 0.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, -0.5f, 0.f }, - .color = { 0.0f, 1.0f, 0.0f } }, - vk::vertex_input{ .position = { 0.5f, 0.5f, 0.f }, - .color = { 0.0f, 0.0f, 1.0f } }, - vk::vertex_input{ .position = { -0.5f, 0.5f, 0.f }, - .color = { 1.0f, 1.0f, 1.0f } } + vk::vertex_input{ + .position = { -0.5f, -0.5f, 0.f }, + .color = { 1.0f, 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, -0.5f, 0.f }, + .color = { 0.0f, 1.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 0.5f, 0.5f, 0.f }, + .color = { 0.0f, 0.0f, 1.0f }, + }, + vk::vertex_input{ + .position = { -0.5f, 0.5f, 0.f }, + .color = { 1.0f, 1.0f, 1.0f }, + } }; const auto property_flags = static_cast(vk::memory_property::host_visible_bit | @@ -419,8 +376,8 @@ main() { vk::buffer_parameters vertex_params = { .memory_mask = physical_device.memory_properties(property_flags), .property_flags = vk::memory_property::device_local_bit, - .usage = static_cast(vk::buffer_usage::transfer_dst_bit) | - static_cast(vk::buffer_usage::vertex_buffer_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::vertex_buffer test_vbo(logical_device, vertices, vertex_params); @@ -431,7 +388,7 @@ main() { .property_flags = static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = static_cast(vk::buffer_usage::index_buffer_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; vk::index_buffer test_ibo(logical_device, indices, index_params); @@ -441,7 +398,7 @@ main() { physical_device.memory_properties(static_cast( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)), - .usage = static_cast(vk::buffer_usage::uniform_buffer_bit), + .usage = vk::buffer_usage::uniform_buffer_bit, }; vk::uniform_buffer test_ubo = vk::uniform_buffer( logical_device, sizeof(global_uniform), uniform_params); @@ -545,37 +502,32 @@ main() { // }); (???) // this to ensure they are cleaned up in the proper order logical_device.wait(); - main_swapchain.destroy(); + main_swapchain.destruct(); - set0_resource.destroy(); - test_ubo.destroy(); - test_ibo.destroy(); - test_vbo.destroy(); + set0_resource.destruct(); + test_ubo.destruct(); + test_ibo.destruct(); + test_vbo.destruct(); for (auto& command : swapchain_command_buffers) { - command.destroy(); + command.destruct(); } for (auto& fb : swapchain_framebuffers) { - fb.destroy(); + fb.destruct(); } for (auto& image : swapchain_images) { - image.destroy(); - } - - for (auto& depth_img : swapchain_depth_images) { - depth_img.destroy(); + image.destruct(); } - main_graphics_pipeline.destroy(); - geometry_resource.destroy(); - main_renderpass.destroy(); - presentation_queue.destroy(); + main_graphics_pipeline.destruct(); + geometry_resource.destruct(); + main_renderpass.destruct(); + presentation_queue.destruct(); - logical_device.destroy(); - window_surface.destroy(); + logical_device.destruct(); + window_surface.destruct(); glfwDestroyWindow(window); - api_instance.destroy(); return 0; } \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams.cppm b/vulkan-cpp/buffer.cppm similarity index 92% rename from vulkan-cpp/buffer_streams.cppm rename to vulkan-cpp/buffer.cppm index db2e92a..8ac0ce2 100644 --- a/vulkan-cpp/buffer_streams.cppm +++ b/vulkan-cpp/buffer.cppm @@ -5,13 +5,13 @@ module; #include #include -export module vk:buffer_streams; +export module vk:buffer; export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief Represents a VkBuffer handler for creating VkBuffer handle * @@ -19,12 +19,12 @@ export namespace vk { * GPU memory * */ - class buffer_stream { + class buffer { public: - buffer_stream() = default; + buffer() = default; /** - * @brief constructs a buffer_stream to write streams of data to GPU + * @brief constructs a buffer to write streams of data to GPU * memory * * @param p_device is the logical device to construct the buffer @@ -33,11 +33,17 @@ export namespace vk { * @param p_params are additional parameters for the buffer * handles */ - buffer_stream(const VkDevice& p_device, - uint64_t p_device_size, - const buffer_parameters& p_params) + buffer(const VkDevice& p_device, + uint64_t p_device_size, + const buffer_parameters& p_params) : m_device(p_device) { + construct(p_device_size, p_params); + } + + ~buffer() = default; + void construct(uint64_t p_device_size, + const buffer_parameters& p_params) { VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -48,13 +54,13 @@ export namespace vk { }; vk_check( - vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + vkCreateBuffer(m_device, &buffer_ci, nullptr, &m_handle), "vkCreateBuffer"); // retrieving buffer memory requirements VkMemoryRequirements memory_requirements = {}; vkGetBufferMemoryRequirements( - p_device, m_handle, &memory_requirements); + m_device, m_handle, &memory_requirements); uint32_t mapped_memory_requirements = memory_requirements.memoryTypeBits & p_params.memory_mask; uint32_t memory_index = @@ -86,12 +92,12 @@ export namespace vk { #endif vk_check( vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), + m_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(m_device, m_handle, m_device_memory, 0), "vkBindBufferMemory"); } @@ -130,7 +136,7 @@ export namespace vk { * Example Usage: * * ```C++ - * buffer_streams staging_buffer(logical_device, ...); + * buffers staging_buffer(logical_device, ...); * * std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; * staging_buffer.transfer(white_color); @@ -227,7 +233,7 @@ export namespace vk { * * ```C++ * - * vk::buffer_stream staging_buffer(logical_device, {...}); + * vk::buffer staging_buffer(logical_device, {...}); * * std::array copy_regions = { * vk::buffer_image_copy{ @@ -269,7 +275,7 @@ export namespace vk { image_copies.data()); } - void destroy() { + void destruct() { if (m_handle != nullptr) { vkDestroyBuffer(m_device, m_handle, nullptr); } diff --git a/vulkan-cpp/buffer_streams16.cppm b/vulkan-cpp/buffer16.cppm similarity index 74% rename from vulkan-cpp/buffer_streams16.cppm rename to vulkan-cpp/buffer16.cppm index 7939876..8e48e01 100644 --- a/vulkan-cpp/buffer_streams16.cppm +++ b/vulkan-cpp/buffer16.cppm @@ -5,22 +5,20 @@ module; #include #include -export module vk:buffer_streams16; +export module vk:buffer16; export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief buffer stream for streaming arbitrary buffers of 32-bytes */ - class buffer_stream16 { + class buffer16 { public: - buffer_stream16() = default; - buffer_stream16(const VkDevice&, - uint64_t, - const buffer_parameters&) {} + buffer16() = default; + buffer16(const VkDevice&, uint64_t, const buffer_parameters&) {} /** * @brief write arbitrary buffer of 32-bytes to GPU-memory @@ -31,7 +29,7 @@ export namespace vk { const VkImage& p_image, image_extent p_extent) {} - void destroy() {} + void destruct() {} operator VkBuffer() { return m_handle; } diff --git a/vulkan-cpp/buffer_streams32.cppm b/vulkan-cpp/buffer32.cppm similarity index 82% rename from vulkan-cpp/buffer_streams32.cppm rename to vulkan-cpp/buffer32.cppm index d088dc1..84cb879 100644 --- a/vulkan-cpp/buffer_streams32.cppm +++ b/vulkan-cpp/buffer32.cppm @@ -6,24 +6,31 @@ module; #include #include -export module vk:buffer_streams32; +export module vk:buffer32; export import :types; export import :utilities; export import :command_buffer; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief buffer stream for streaming arbitrary buffers of 32-bytes */ - class buffer_stream32 { + class buffer32 { public: - buffer_stream32() = default; - buffer_stream32(const VkDevice& p_device, - uint64_t p_device_size, - const buffer_parameters& p_params) + buffer32() = default; + buffer32(const VkDevice& p_device, + uint64_t p_device_size, + const buffer_parameters& p_params) : m_device(p_device) { + construct(p_device_size, p_params); + } + + ~buffer32() = default; + + void construct(uint64_t p_device_size, + const buffer_parameters& p_params) { VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, @@ -34,13 +41,13 @@ export namespace vk { }; vk_check( - vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + vkCreateBuffer(m_device, &buffer_ci, nullptr, &m_handle), "vkCreateBuffer"); - // 2. retrieving buffer memory requirements + // retrieving buffer memory requirements VkMemoryRequirements memory_requirements = {}; vkGetBufferMemoryRequirements( - p_device, m_handle, &memory_requirements); + m_device, m_handle, &memory_requirements); uint32_t mapped_memory_requirements = memory_requirements.memoryTypeBits & p_params.memory_mask; uint32_t memory_index = @@ -58,8 +65,7 @@ export namespace vk { .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 + .objectHandle = reinterpret_cast(m_handle), .pObjectName = p_params.debug_name // specify what type of buffer this is }; @@ -72,19 +78,19 @@ export namespace vk { #endif vk_check( vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), + m_device, &memory_alloc_info, nullptr, &m_device_memory), "vkAllocateMemory"); - // 5. bind memory resource of this buffer handle + // bind memory resource of this buffer handle vk_check( - vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), + vkBindBufferMemory(m_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 transfer(std::span p_data) { void* mapped = nullptr; vk_check(vkMapMemory(m_device, m_device_memory, @@ -123,7 +129,7 @@ export namespace vk { &buffer_image_copy); } - void destroy() { + void destruct() { if (m_handle != nullptr) { vkDestroyBuffer(m_device, m_handle, nullptr); } diff --git a/vulkan-cpp/command_buffer.cppm b/vulkan-cpp/command_buffer.cppm index e0343e0..e73600c 100644 --- a/vulkan-cpp/command_buffer.cppm +++ b/vulkan-cpp/command_buffer.cppm @@ -11,7 +11,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { struct command_inherit_info { VkRenderPass renderpass = nullptr; uint32_t subpass_index = 0; @@ -536,8 +536,8 @@ export namespace vk { * Example Usage: * * ```C++ - * vk::buffer_stream staging_buffer(logical_device, ...); - * vk::buffer_stream vertex_buffer(logical_device, ...); + * vk::buffer staging_buffer(logical_device, ...); + * vk::buffer vertex_buffer(logical_device, ...); * * vk::command_buffer primary_command(logical_device, ...); * @@ -611,7 +611,7 @@ export namespace vk { const auto viewport = p_params[i]; viewports[i] = { .x = viewport.x, - .y = viewport.x, + .y = viewport.y, .width = viewport.width, .height = viewport.height, .minDepth = viewport.min_depth, @@ -646,7 +646,7 @@ export namespace vk { /** * @brief Explicitly API to properly do command buffer cleanup */ - void destroy() { + void destruct() { vkFreeCommandBuffers( m_device, m_command_pool, 1, &m_command_buffer); vkDestroyCommandPool(m_device, m_command_pool, nullptr); diff --git a/vulkan-cpp/descriptor_resource.cppm b/vulkan-cpp/descriptor_resource.cppm index 4ccc75a..535d1fb 100644 --- a/vulkan-cpp/descriptor_resource.cppm +++ b/vulkan-cpp/descriptor_resource.cppm @@ -13,7 +13,7 @@ export import :uniform_buffer; export import :sample_image; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @param slot is the slot specific to the number slot for the * descriptor. Ex. layout (set = 0) @@ -85,14 +85,14 @@ export namespace vk { * * std::array entries = { * vk::descriptor_entry{ - * .type = vk::buffer::uniform, .binding_point = { + * .type = vk::descriptor_type::uniform, .binding_point = { * .binding = 0, * .stage = vk::shader_stage::vertex, * }, * .descriptor_count = 1, * }, * vk::descriptor_entry{ - * .type = vk::buffer::combined_image_sampler, + * .type = vk::descriptor_type::combined_image_sampler, * .binding_point = { * .binding = 1, * .stage = vk::shader_stage::fragment, @@ -385,7 +385,7 @@ export namespace vk { return m_descriptor_layout; } - void destroy() { + void destruct() { if (m_descriptor_pool != nullptr) { vkDestroyDescriptorPool( m_device, m_descriptor_pool, nullptr); diff --git a/vulkan-cpp/device.cppm b/vulkan-cpp/device.cppm index 8310692..ade58f0 100644 --- a/vulkan-cpp/device.cppm +++ b/vulkan-cpp/device.cppm @@ -8,7 +8,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @name device * @brief represents a vulkan logical device @@ -59,7 +59,7 @@ export namespace vk { [[nodiscard]] queue_family family() const { return m_queue_family; } - void destroy() { + void destruct() { if (m_device != nullptr) { vkDestroyDevice(m_device, nullptr); } diff --git a/vulkan-cpp/device_present_queue.cppm b/vulkan-cpp/device_present_queue.cppm index 6f399e0..af16202 100644 --- a/vulkan-cpp/device_present_queue.cppm +++ b/vulkan-cpp/device_present_queue.cppm @@ -10,7 +10,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @name device_present_queue * @brief Represents a presentation queue that must have an associated @@ -152,7 +152,7 @@ export namespace vk { } } - void destroy() { + void destruct() { vkDeviceWaitIdle(m_device); vkDestroySemaphore(m_device, m_presentation_completed, nullptr); vkDestroySemaphore(m_device, m_work_completed, nullptr); diff --git a/vulkan-cpp/device_queue.cppm b/vulkan-cpp/device_queue.cppm index 846971f..77a4cf7 100644 --- a/vulkan-cpp/device_queue.cppm +++ b/vulkan-cpp/device_queue.cppm @@ -8,7 +8,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @name * @brief Represents a queue part of a specific logical device created diff --git a/vulkan-cpp/dyn/shader_objects.cppm b/vulkan-cpp/dyn/shader_objects.cppm index c300481..7203736 100644 --- a/vulkan-cpp/dyn/shader_objects.cppm +++ b/vulkan-cpp/dyn/shader_objects.cppm @@ -12,7 +12,7 @@ import :types; import :utilities; export namespace vk::dyn::experimental { - inline namespace v1 { + inline namespace v6 { struct shader_ext_params { shader_stage stage; shader_stage next_stage; @@ -172,7 +172,7 @@ export namespace vk::dyn::experimental { &m_shader_handle); } - void destroy() { + void destruct() { vkDestroyShaderEXT(m_device, m_shader_handle, nullptr); } diff --git a/vulkan-cpp/feature_extensions.cppm b/vulkan-cpp/feature_extensions.cppm index e5d4140..961b69e 100644 --- a/vulkan-cpp/feature_extensions.cppm +++ b/vulkan-cpp/feature_extensions.cppm @@ -8,223 +8,226 @@ module; export module vk:feature_extensions; export namespace vk { - - /** - * @brief ExtensionConcept being a concept - * - * Used for mainly performing compile-time checks if the features specified - * are actual valid features - * - * Because Vulkan is a C API and .pNext being a void*. This can be bug-prone - * for accidentally pointing to a type that is not a feature struct like a - * std::string, for example. - * - * VulkanChainable concept is used to verify the conditions of the type that - * is being passed to chain_features. - * - * Which is important to ensure that we only accept types that do contain - * .sType and .pNext - * - * TODO: Probably might have this be a template specialization due to being - * able to verify at compile-time if the vulkan features, we need to check - * for are valid. This way even if the struct has `.sType` and `.pNext`, we - * can at least verify the struct is a feature that is valid - * - * - * Example: - * - * ```C++ - * - * // This trait should be false by default - * // Meaning if you reach this, then it should error out - * template - * struct device_feature : public std::false_type { - * // Having this be a compiler-error by default if this struct is - * reached. - * // Users should not be allowed to supply a non vulkan feature struct - * ONLY the vulkan feature struct static_assert(*this, "Invalid vulkan - * feature specified. Only accepting valid vulkan features."); - * }; - */ - template - concept ExtensionConcept = requires(T t) { - { t.sType } -> std::convertible_to; - { t.pNext } -> std::convertible_to; - }; - - /** - * @brief a trait that can be aliased to an - */ - template - struct feature_trait : public T { - - feature_trait(T p_initialize_feature) - : T(p_initialize_feature) { - this->sType = SType; - } - }; - - using physical_device_features2 = - feature_trait; - using buffer_device_address = feature_trait< - VkPhysicalDeviceBufferDeviceAddressFeatures, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES>; - - // Descriptor indexing to access unbounded array of a given uniform - using descriptor_indexing_feature = feature_trait< - VkPhysicalDeviceDescriptorIndexingFeatures, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES>; - - //! @brief Modernized Vulkan feature that reduces state managing for - //! renderpasses + framebuffers - using dynamic_rendering_feature = feature_trait< - VkPhysicalDeviceDynamicRenderingFeatures, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES>; - - //! @brief Represent buffers as direct pointer in shaders - // using buffer_device_address_feature = feature_trait< - // VkPhysicalDeviceBufferAddressFeatures, - // VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES>; - - //! @brief Modernize approach for bindless techniques - using descriptor_buffer_feature = feature_trait< - VkPhysicalDeviceDescriptorBufferFeaturesEXT, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT>; - - //! @brief Updating descriptors similar fashion as push constants - using push_descriptors_feature = feature_trait< - VkPhysicalDevicePushDescriptorPropertiesKHR, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR>; - - //! @brief Feature that can skip monolith pipeline objects - using shader_object_feature = feature_trait< - VkPhysicalDeviceShaderObjectFeaturesEXT, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT>; - - //! @brief Handled dynamic pipeline states - using pipeline_library = feature_trait< - VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT>; - - //! @brief Clean barriers and semaphores - using sync2_feature = feature_trait< - VkPhysicalDeviceSynchronization2Features, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES>; - - template - class device_features { - public: - device_features(Features&&... p_args) - : m_data(std::forward(p_args)...) { - - // Check unpacked structures of vulkan features - // Then we chain the pNext pointer altogether for each feature we - // unpack if there are any - if constexpr (sizeof...(Features) > 0) { - std::apply([this](auto&... spec) { chain_features(spec...); }, - m_data); - } - } + inline namespace v6 { /** - * @brief We provide the chained pNext ptr - * - * This will let us directly have the chained features the user can - * specify. + * @brief ExtensionConcept being a concept * - * @return nullptr if no features are specified, returns the pNext - * feature chain otherwise. + * Used for mainly performing compile-time checks if the features + * specified are actual valid features * - * @returns the internal data of the vulkan device extensions that are - * chained altogether. + * Because Vulkan is a C API and .pNext being a void*. This can be + * bug-prone for accidentally pointing to a type that is not a feature + * struct like a std::string, for example. * - * Will return nullptr if no extensions are enabled. - */ - [[nodiscard]] void* data() noexcept { - - // At compile-time we retrieve the head pointer of the entire - // feature list chain altogether. - if constexpr (sizeof...(Features) > 0) { - return &std::get<0>(m_data); - } - - return nullptr; - } - - private: - /** - * @brief Vulkan uses a linked-list specifying lists of features to - * enable. + * VulkanChainable concept is used to verify the conditions of the type + * that is being passed to chain_features. * - * This linked-list feature is used to enable modern GPU features. This - * internal API allows to take in a collection of structs that are - * inter-connected them into a single chain the internal API's can read - * from. + * Which is important to ensure that we only accept types that do + * contain .sType and .pNext * - * The pNext used for chaining + * TODO: Probably might have this be a template specialization due to + * being able to verify at compile-time if the vulkan features, we need + * to check for are valid. This way even if the struct has `.sType` and + * `.pNext`, we can at least verify the struct is a feature that is + * valid * - * [ Feature A ] [ Feature B ] [ Feature N ] - * +------------+ +------------+ +-----------+ - * | .sType | | .sType | | .sType | - * | .pNext | --> | .pNext | -> | .pNext | - * +------------+ +------------+ +-----------+ - * ( head ) ( internal ) ( tail ) * - * Example Usage: + * Example: * * ```C++ * - * vk::device_features device_features{ - * vk::descriptor_indexing_feature{{ - * .descriptorBindingPartiallyBound = true, - * .descriptorBindingVariableDescriptorCount = true, - * .descriptorBindingSampledImageUpdateAfterBind = true, - * } }, - * vk::dynamic_rendering{ { - * .dynamicRendering = true, - * } }, + * // This trait should be false by default + * // Meaning if you reach this, then it should error out + * template + * struct device_feature : public std::false_type { + * // Having this be a compiler-error by default if this struct is + * reached. + * // Users should not be allowed to supply a non vulkan feature + * struct ONLY the vulkan feature struct static_assert(*this, "Invalid + * vulkan feature specified. Only accepting valid vulkan features."); * }; - * - * vk::device_params config_logical_device = { - * .features = device_features, - * }; - * - * ``` - * - * */ - template - void chain_features(T& head, Feature&... tail) { + template + concept ExtensionConcept = requires(T t) { + { t.sType } -> std::convertible_to; + { t.pNext } -> std::convertible_to; + }; + + /** + * @brief a trait that can be aliased to an + */ + template + struct feature_trait : public T { + + feature_trait(T p_initialize_feature) + : T(p_initialize_feature) { + this->sType = SType; + } + }; + + using physical_device_features2 = + feature_trait; + using buffer_device_address = feature_trait< + VkPhysicalDeviceBufferDeviceAddressFeatures, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES>; + + // Descriptor indexing to access unbounded array of a given uniform + using descriptor_indexing_feature = feature_trait< + VkPhysicalDeviceDescriptorIndexingFeatures, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES>; + + //! @brief Modernized Vulkan feature that reduces state managing for + //! renderpasses + framebuffers + using dynamic_rendering_feature = feature_trait< + VkPhysicalDeviceDynamicRenderingFeatures, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES>; + + //! @brief Represent buffers as direct pointer in shaders + // using buffer_device_address_feature = feature_trait< + // VkPhysicalDeviceBufferAddressFeatures, + // VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES>; + + //! @brief Modernize approach for bindless techniques + using descriptor_buffer_feature = feature_trait< + VkPhysicalDeviceDescriptorBufferFeaturesEXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT>; + + //! @brief Updating descriptors similar fashion as push constants + using push_descriptors_feature = feature_trait< + VkPhysicalDevicePushDescriptorPropertiesKHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR>; + + //! @brief Feature that can skip monolith pipeline objects + using shader_object_feature = feature_trait< + VkPhysicalDeviceShaderObjectFeaturesEXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT>; + + //! @brief Handled dynamic pipeline states + using pipeline_library = feature_trait< + VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT>; + + //! @brief Clean barriers and semaphores + using sync2_feature = feature_trait< + VkPhysicalDeviceSynchronization2Features, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES>; + + template + class device_features { + public: + device_features(Features&&... p_args) + : m_data(std::forward(p_args)...) { + + // Check unpacked structures of vulkan features + // Then we chain the pNext pointer altogether for each feature + // we unpack if there are any + if constexpr (sizeof...(Features) > 0) { + std::apply( + [this](auto&... spec) { chain_features(spec...); }, + m_data); + } + } + /** - * @brief Passing an arbitrary sequences of - * VkPhysicalDevice*Features + * @brief We provide the chained pNext ptr + * + * This will let us directly have the chained features the user can + * specify. * + * @return nullptr if no features are specified, returns the pNext + * feature chain otherwise. * - * @brief Handled using Variadic Templates - * Compiler does not generate a loop, rather it'll generate a flat - * sequence of instructions. + * @returns the internal data of the vulkan device extensions that + * are chained altogether. * - * Essentially doing something like: - * chain_features(descriptor_indexing, dynamic_rendering). + * Will return nullptr if no extensions are enabled. + */ + [[nodiscard]] void* data() noexcept { + + // At compile-time we retrieve the head pointer of the entire + // feature list chain altogether. + if constexpr (sizeof...(Features) > 0) { + return &std::get<0>(m_data); + } + + return nullptr; + } + + private: + /** + * @brief Vulkan uses a linked-list specifying lists of features to + * enable. * - * The compiler will automatically assign the chaining .pNext - * pointer per sequence: (where it will automatically assign the - * .pNext pointer per feature specified in it's sequence) + * This linked-list feature is used to enable modern GPU features. + * This internal API allows to take in a collection of structs that + * are inter-connected them into a single chain the internal API's + * can read from. + * + * The pNext used for chaining + * + * [ Feature A ] [ Feature B ] [ Feature N ] + * +------------+ +------------+ +-----------+ + * | .sType | | .sType | | .sType | + * | .pNext | --> | .pNext | -> | .pNext | + * +------------+ +------------+ +-----------+ + * ( head ) ( internal ) ( tail ) + * + * Example Usage: + * + * ```C++ + * + * vk::device_features device_features{ + * vk::descriptor_indexing_feature{{ + * .descriptorBindingPartiallyBound = true, + * .descriptorBindingVariableDescriptorCount = true, + * .descriptorBindingSampledImageUpdateAfterBind = true, + * } }, + * vk::dynamic_rendering{ { + * .dynamicRendering = true, + * } }, + * }; + * + * vk::device_params config_logical_device = { + * .features = device_features, + * }; + * + * ``` * - * 1.) current.pNext = &descriptor_indexing - * 2.) descriptor_indexing.pNext = &dynamic_rendering * */ - auto* current = reinterpret_cast(&head); - ((current->pNext = reinterpret_cast(&tail), - current = reinterpret_cast(&tail)), - ...); - current->pNext = nullptr; - } - - private: - std::tuple m_data; - }; + template + void chain_features(T& head, Feature&... tail) { + /** + * @brief Passing an arbitrary sequences of + * VkPhysicalDevice*Features + * + * + * @brief Handled using Variadic Templates + * Compiler does not generate a loop, rather it'll generate a + * flat sequence of instructions. + * + * Essentially doing something like: + * chain_features(descriptor_indexing, dynamic_rendering). + * + * The compiler will automatically assign the chaining .pNext + * pointer per sequence: (where it will automatically assign the + * .pNext pointer per feature specified in it's sequence) + * + * 1.) current.pNext = &descriptor_indexing + * 2.) descriptor_indexing.pNext = &dynamic_rendering + * + */ + auto* current = reinterpret_cast(&head); + ((current->pNext = reinterpret_cast(&tail), + current = reinterpret_cast(&tail)), + ...); + current->pNext = nullptr; + } + private: + std::tuple m_data; + }; + }; }; \ No newline at end of file diff --git a/vulkan-cpp/framebuffer.cppm b/vulkan-cpp/framebuffer.cppm index 4902ffb..e20513b 100644 --- a/vulkan-cpp/framebuffer.cppm +++ b/vulkan-cpp/framebuffer.cppm @@ -8,7 +8,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @name vk::framebuffer * @@ -45,7 +45,7 @@ export namespace vk { [[nodiscard]] bool alive() const { return m_framebuffer; } - void destroy() { + void destruct() { if (m_framebuffer != nullptr) { vkDestroyFramebuffer(m_device, m_framebuffer, nullptr); } diff --git a/vulkan-cpp/image.cppm b/vulkan-cpp/image.cppm index b417657..8587244 100644 --- a/vulkan-cpp/image.cppm +++ b/vulkan-cpp/image.cppm @@ -8,7 +8,7 @@ export module vk:image; import :types; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief interface for the purpose of acting as an interface to diff --git a/vulkan-cpp/index_buffer.cppm b/vulkan-cpp/index_buffer.cppm index 523eb81..0e78d14 100644 --- a/vulkan-cpp/index_buffer.cppm +++ b/vulkan-cpp/index_buffer.cppm @@ -8,10 +8,10 @@ export module vk:index_buffer; export import :types; export import :utilities; export import :command_buffer; -export import :buffer_streams32; +export import :buffer32; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief Test implementation for index buffers @@ -29,9 +29,18 @@ export namespace vk { : m_device(p_device) { m_index_buffer = - buffer_stream32(m_device, p_indices.size_bytes(), p_params); + buffer32(m_device, p_indices.size_bytes(), p_params); - m_index_buffer.write(p_indices); + m_index_buffer.transfer(p_indices); + } + + void construct(std::span p_indices, + const buffer_parameters& p_params) { + m_index_buffer.construct(p_indices.size_bytes(), p_params); + } + + void transfer(std::span p_data) { + m_index_buffer.transfer(p_data); } [[nodiscard]] bool alive() const { return m_index_buffer; } @@ -40,11 +49,11 @@ export namespace vk { operator VkBuffer() { return m_index_buffer; } - void destroy() { m_index_buffer.destroy(); } + void destruct() { m_index_buffer.destruct(); } private: VkDevice m_device = nullptr; - buffer_stream32 m_index_buffer{}; + buffer32 m_index_buffer{}; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/instance.cppm b/vulkan-cpp/instance.cppm index e81fe38..0fd3320 100644 --- a/vulkan-cpp/instance.cppm +++ b/vulkan-cpp/instance.cppm @@ -12,7 +12,7 @@ import :utilities; import :physical_device; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief vk::instance represents VkInstance to initialize the vulkan * API. diff --git a/vulkan-cpp/physical_device.cppm b/vulkan-cpp/physical_device.cppm index b739c53..03d59af 100644 --- a/vulkan-cpp/physical_device.cppm +++ b/vulkan-cpp/physical_device.cppm @@ -11,7 +11,7 @@ import :utilities; import :types; export namespace vk { - inline namespace v1 { + inline namespace v6 { class physical_device { public: physical_device() = diff --git a/vulkan-cpp/pipeline.cppm b/vulkan-cpp/pipeline.cppm index 0a2cf3b..81652b4 100644 --- a/vulkan-cpp/pipeline.cppm +++ b/vulkan-cpp/pipeline.cppm @@ -12,7 +12,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { struct input_assembly_state { primitive_topology topology = primitive_topology::triangle_list; @@ -149,6 +149,8 @@ export namespace vk { configure(p_params); } + ~pipeline() = default; + /** * @brief explicit API for creating a VkPipeline and * VkPipelineLayout handle @@ -530,8 +532,7 @@ export namespace vk { void push_constant(const VkCommandBuffer& p_current, const T& p_data, shader_stage p_stage, - uint32_t p_offset, - uint32_t p_range) { + uint32_t p_offset) { // Perform compile-time checks if push constant data exceeds // maximum size of data to be transferred via push constant @@ -543,7 +544,7 @@ export namespace vk { m_pipeline_layout, static_cast(p_stage), p_offset, - p_range, + sizeof(T), &p_data); } @@ -556,7 +557,7 @@ export namespace vk { } //! @brief explicit cleanup performed on vk::pipeline - void destroy() { + void destruct() { if (m_pipeline_layout != nullptr) { vkDestroyPipelineLayout( m_device, m_pipeline_layout, nullptr); diff --git a/vulkan-cpp/renderpass.cppm b/vulkan-cpp/renderpass.cppm index 4983ac4..a7e337d 100644 --- a/vulkan-cpp/renderpass.cppm +++ b/vulkan-cpp/renderpass.cppm @@ -11,7 +11,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @name renderpass * @@ -307,7 +307,7 @@ export namespace vk { vkCmdEndRenderPass(p_current); } - void destroy() { + void destruct() { vkDestroyRenderPass(m_device, m_renderpass, nullptr); } diff --git a/vulkan-cpp/sample_image.cppm b/vulkan-cpp/sample_image.cppm index 668dc55..7671d9d 100644 --- a/vulkan-cpp/sample_image.cppm +++ b/vulkan-cpp/sample_image.cppm @@ -11,7 +11,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * 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 @@ -33,7 +33,17 @@ export namespace vk { sample_image(const VkDevice& p_device, const image_params& p_image_params) : m_device(p_device) { - // 1. creating VkImage handle + construct(p_image_params); + } + + sample_image(const VkDevice& p_device, + const VkImage& p_image, + const image_params& p_image_params) + : m_device(p_device) { + construct(p_image, p_image_params); + } + + void construct(const image_params& p_image_params) { VkImageCreateInfo image_ci = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = nullptr, @@ -55,13 +65,13 @@ export namespace vk { .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED }; - vk_check(vkCreateImage(p_device, &image_ci, nullptr, &m_image), + vk_check(vkCreateImage(m_device, &image_ci, nullptr, &m_image), "vkCreateImage"); - // 2. get image memory requirements from physical device + // get image memory requirements from physical device VkMemoryRequirements memory_requirements; vkGetImageMemoryRequirements( - p_device, m_image, &memory_requirements); + m_device, m_image, &memory_requirements); uint32_t mapped_memory_requirements = memory_requirements.memoryTypeBits & @@ -81,23 +91,21 @@ export namespace vk { vk_check( vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), + m_device, &memory_alloc_info, nullptr, &m_device_memory), "vkAllocateMemory"); - // 5. bind image memory + // Binding the image memory vk_check( - vkBindImageMemory(p_device, m_image, m_device_memory, 0), + vkBindImageMemory(m_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 + // Need to bind image view to the VkDeviceMemory for the VkImage + // before using the VkImageView 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_params.view_type, .format = p_image_params.format, .components = { @@ -116,7 +124,7 @@ export namespace vk { }; vk_check(vkCreateImageView( - p_device, &image_view_ci, nullptr, &m_image_view), + m_device, &image_view_ci, nullptr, &m_image_view), "vkCreateImage"); // Create VkSampler handler @@ -145,15 +153,13 @@ export namespace vk { }; vk_check( - vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + vkCreateSampler(m_device, &sampler_info, nullptr, &m_sampler), "vkCreateSampler"); } - sample_image(const VkDevice& p_device, - const VkImage& p_image, - const image_params& p_image_params) - : m_device(p_device) - , m_image(p_image) { + void construct(const VkImage& p_image, + const image_params& p_image_params) { + m_image = p_image; VkImageViewCreateInfo image_view_ci = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, @@ -178,7 +184,7 @@ export namespace vk { }; vk_check(vkCreateImageView( - p_device, &image_view_ci, nullptr, &m_image_view), + m_device, &image_view_ci, nullptr, &m_image_view), "vkCreateImage"); // Create VkSampler handler @@ -207,7 +213,7 @@ export namespace vk { }; vk_check( - vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + vkCreateSampler(m_device, &sampler_info, nullptr, &m_sampler), "vkCreateSampler"); m_only_destroy_image_view = true; @@ -510,7 +516,7 @@ export namespace vk { &image_memory_barrier); } - void destroy() { + void destruct() { if (m_image_view != nullptr) { vkDestroyImageView(m_device, m_image_view, nullptr); } diff --git a/vulkan-cpp/shader_resource.cppm b/vulkan-cpp/shader_resource.cppm index 09bf2b4..56b4a70 100644 --- a/vulkan-cpp/shader_resource.cppm +++ b/vulkan-cpp/shader_resource.cppm @@ -12,7 +12,7 @@ export import :types; export import :utilities; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @param sources holds data the shader source and stage the source it @@ -131,7 +131,7 @@ export namespace vk { } //! @brief used for explicit cleanup for this resource - void destroy() { + void destruct() { for (auto& handle : m_shader_module_handlers) { if (handle.module != nullptr) { vkDestroyShaderModule(m_device, handle.module, nullptr); diff --git a/vulkan-cpp/surface.cppm b/vulkan-cpp/surface.cppm index 963170e..49e4200 100644 --- a/vulkan-cpp/surface.cppm +++ b/vulkan-cpp/surface.cppm @@ -19,7 +19,7 @@ export import :utilities; export import :instance; export namespace vk { - inline namespace v1 { + inline namespace v6 { class surface { public: @@ -33,7 +33,7 @@ export namespace vk { [[nodiscard]] bool alive() const { return m_surface_handler; } - void destroy() { + void destruct() { if (m_surface_handler != nullptr) { vkDestroySurfaceKHR(m_instance, m_surface_handler, nullptr); } diff --git a/vulkan-cpp/swapchain.cppm b/vulkan-cpp/swapchain.cppm index 28051d5..c55c61e 100644 --- a/vulkan-cpp/swapchain.cppm +++ b/vulkan-cpp/swapchain.cppm @@ -12,7 +12,7 @@ export import :utilities; export import :device_queue; export namespace vk { - inline namespace v1 { + inline namespace v6 { class swapchain { public: @@ -91,7 +91,7 @@ export namespace vk { return m_images; } - void destroy() { + void destruct() { vkDestroySwapchainKHR(m_device, m_swapchain_handler, nullptr); } diff --git a/vulkan-cpp/texture.cppm b/vulkan-cpp/texture.cppm index d7a332b..787548b 100644 --- a/vulkan-cpp/texture.cppm +++ b/vulkan-cpp/texture.cppm @@ -9,13 +9,13 @@ export module vk:texture; import :types; import :utilities; -import :buffer_streams; +import :buffer; import :sample_image; import :command_buffer; import :image; export namespace vk { - inline namespace v1 { + inline namespace v6 { class texture { public: @@ -60,30 +60,26 @@ export namespace vk { .format = texture_format, .memory_mask = p_memory_mask, .usage = - static_cast(image_usage::transfer_dst_bit) | - static_cast(image_usage::sampled_bit), + image_usage::transfer_dst_bit | image_usage::sampled_bit, .mip_levels = p_mip_levels, .layer_count = p_layer_count, }; m_image = sample_image(m_device, img_options); - // Setup staging buffer - uint32_t property_flag = memory_property::host_visible_bit | - memory_property::host_cached_bit; - + // Performing staging transfers buffer_parameters staging_options = { .memory_mask = img_options.memory_mask, - .property_flags = - static_cast(property_flag), - .usage = - static_cast(buffer_usage::transfer_src_bit), + .property_flags = memory_property::host_visible_bit | + memory_property::host_cached_bit, + .usage = buffer_usage::transfer_src_bit, }; - buffer_stream staging(m_device, p_data.size(), staging_options); + buffer staging(m_device, p_data.size(), staging_options); staging.transfer(p_data); - // 5. Creating temporary command buffer for texture + // Performing transfers as a command to GPU memory for + // preparations command_params copy_command_params = { .levels = command_levels::primary, .queue_index = 0, @@ -137,8 +133,8 @@ export namespace vk { vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(temp_graphics_queue); - temp_command_buffer.destroy(); - staging.destroy(); + temp_command_buffer.destruct(); + staging.destruct(); } void construct(image* p_image, @@ -147,15 +143,13 @@ export namespace vk { const VkFormat texture_format = static_cast(format::r8g8b8a8_unorm); - // NOTE To Self: Essentially passed to p_config parameter in - // create_texture_with_data + image_params img_options = { .extent = p_image->extent(), .format = texture_format, .memory_mask = p_texture_params.memory_mask, .usage = - static_cast(image_usage::transfer_dst_bit) | - static_cast(image_usage::sampled_bit), + image_usage::transfer_dst_bit | image_usage::sampled_bit, .mip_levels = p_texture_params.mip_levels, .layer_count = p_texture_params.layer_count, }; @@ -170,10 +164,9 @@ export namespace vk { .memory_mask = img_options.memory_mask, .property_flags = static_cast(property_flag), - .usage = - static_cast(buffer_usage::transfer_src_bit), + .usage = buffer_usage::transfer_src_bit, }; - buffer_stream staging( + buffer staging( m_device, p_image->read().size(), staging_options); staging.transfer(p_image->read()); @@ -232,8 +225,8 @@ export namespace vk { vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(temp_graphics_queue); - temp_command_buffer.destroy(); - staging.destroy(); + temp_command_buffer.destruct(); + staging.destruct(); } //! @return true if image loaded, false if texture did not load @@ -244,7 +237,7 @@ export namespace vk { [[nodiscard]] image_extent extent() const { return m_extent; } - void destroy() { m_image.destroy(); } + void destruct() { m_image.destruct(); } private: VkDevice m_device = nullptr; diff --git a/vulkan-cpp/types.cppm b/vulkan-cpp/types.cppm index 316123f..676047a 100644 --- a/vulkan-cpp/types.cppm +++ b/vulkan-cpp/types.cppm @@ -13,7 +13,7 @@ export module vk:types; import :feature_extensions; export namespace vk { - inline namespace v1 { + inline namespace v6 { enum format : uint32_t { // Core Formats undefined = VK_FORMAT_UNDEFINED, @@ -1050,7 +1050,7 @@ export namespace vk { depth_clamp_range_ext = VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT }; - enum buffer : uint8_t { + enum descriptor_type : uint8_t { uniform = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // represents // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER @@ -1065,7 +1065,7 @@ export namespace vk { // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE }; - enum image_usage : uint32_t { + enum class 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, @@ -1548,7 +1548,7 @@ export namespace vk { }; struct descriptor_entry { - buffer type; + descriptor_type type; descriptor_binding_point binding_point; uint32_t descriptor_count; descriptor_bind_flags flags; @@ -1589,7 +1589,7 @@ export namespace vk { memory_property property = memory_property::device_local_bit; uint32_t memory_mask = 0; image_aspect_flags aspect = image_aspect_flags::color_bit; - uint32_t usage; + image_usage usage; VkImageCreateFlags image_flags = 0; VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; uint32_t mip_levels = 1; @@ -1626,7 +1626,7 @@ export namespace vk { struct buffer_parameters { uint32_t memory_mask = 0; memory_property property_flags; - uint32_t usage; + buffer_usage usage; memory_allocate_flags allocate_flags; VkSharingMode share_mode = VK_SHARING_MODE_EXCLUSIVE; const char* debug_name = nullptr; diff --git a/vulkan-cpp/uniform_buffer.cppm b/vulkan-cpp/uniform_buffer.cppm index a9a311d..a7f024f 100644 --- a/vulkan-cpp/uniform_buffer.cppm +++ b/vulkan-cpp/uniform_buffer.cppm @@ -10,10 +10,10 @@ export module vk:uniform_buffer; export import :types; export import :utilities; export import :command_buffer; -export import :buffer_streams; +export import :buffer; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief represents a vulkan uniform buffer * @@ -28,7 +28,7 @@ export namespace vk { : m_device(p_device) , m_size_bytes(p_size_bytes) { m_uniform_handle = - buffer_stream(m_device, p_size_bytes, p_uniform_params); + buffer(m_device, p_size_bytes, p_uniform_params); } [[nodiscard]] bool alive() const { return m_uniform_handle; } @@ -48,12 +48,12 @@ export namespace vk { operator VkBuffer() { return m_uniform_handle; } - void destroy() { m_uniform_handle.destroy(); } + void destruct() { m_uniform_handle.destruct(); } private: uint64_t m_size_bytes; VkDevice m_device = nullptr; - buffer_stream m_uniform_handle{}; + buffer m_uniform_handle{}; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/utilities.cppm b/vulkan-cpp/utilities.cppm index 7805bcc..0272de9 100644 --- a/vulkan-cpp/utilities.cppm +++ b/vulkan-cpp/utilities.cppm @@ -12,7 +12,7 @@ export module vk:utilities; import :types; export namespace vk { - inline namespace v1 { + inline namespace v6 { void vk_check(const VkResult& p_result, const std::string& p_name) { if (p_result != VK_SUCCESS) { @@ -117,6 +117,14 @@ export namespace vk { static_cast(p_rhs)); } + inline image_usage operator|(image_usage p_lhs, image_usage p_rhs) { + // Lets us truncate the underlying type of the enum (class) to allow + // it to be bitwise OR'd + using T = std::underlying_type_t; + return static_cast(static_cast(p_lhs) | + static_cast(p_rhs)); + } + inline image_aspect_flags operator|(image_aspect_flags p_lhs, image_aspect_flags p_rhs) { // Lets us truncate the underlying type of the enum (class) to allow @@ -197,7 +205,7 @@ export namespace vk { vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(temp_graphics_queue); - temp_command_buffer.destroy(); + temp_command_buffer.destruct(); } */ diff --git a/vulkan-cpp/vertex_buffer.cppm b/vulkan-cpp/vertex_buffer.cppm index 5ff3d0c..7e713af 100644 --- a/vulkan-cpp/vertex_buffer.cppm +++ b/vulkan-cpp/vertex_buffer.cppm @@ -9,10 +9,10 @@ export module vk:vertex_buffer; export import :types; export import :utilities; export import :command_buffer; -export import :buffer_streams; +export import :buffer; export namespace vk { - inline namespace v1 { + inline namespace v6 { /** * @brief vulkan implementation for loading in vertices to a vulkan * buffer handle @@ -32,6 +32,72 @@ export namespace vk { const buffer_parameters& p_params) : m_device(p_device) { + // Staging buffer operations + buffer_parameters staging_buffer_params = { + .memory_mask = p_params.memory_mask, + .property_flags = static_cast( + memory_property::host_visible_bit | + memory_property::host_cached_bit), + .usage = buffer_usage::transfer_src_bit | + buffer_usage::storage_buffer_bit, + .debug_name = p_params.debug_name, + .vkSetDebugUtilsObjectNameEXT = + p_params.vkSetDebugUtilsObjectNameEXT + }; + buffer staging_buffer( + m_device, p_vertices.size_bytes(), staging_buffer_params); + staging_buffer.transfer(p_vertices); + + // Creating vertex buffer handle + m_vertex_handler = + buffer(m_device, p_vertices.size_bytes(), p_params); + + // 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); + + copy_command_buffer.copy_buffer( + staging_buffer, m_vertex_handler, p_vertices.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); + + copy_command_buffer.destruct(); + + // Cleaning up staging buffer after using it + staging_buffer.destruct(); + } + + ~vertex_buffer() = default; + + void construct(const VkDevice& p_device, + std::span p_vertices, + const buffer_parameters& p_params) { + + // Can be used to invalidate 3D mesh vertices // Staging buffer const uint32_t transfer = static_cast(buffer_usage::transfer_src_bit); @@ -43,20 +109,20 @@ export namespace vk { .property_flags = static_cast( memory_property::host_visible_bit | memory_property::host_cached_bit), - .usage = - static_cast(buffer_usage::transfer_src_bit) | - static_cast(buffer_usage::storage_buffer_bit), + .usage = buffer_usage::transfer_src_bit | + buffer_usage::storage_buffer_bit, .debug_name = p_params.debug_name, .vkSetDebugUtilsObjectNameEXT = p_params.vkSetDebugUtilsObjectNameEXT }; - buffer_stream staging_buffer( + buffer staging_buffer( m_device, p_vertices.size_bytes(), staging_buffer_params); staging_buffer.transfer(p_vertices); // Creating vertex buffer handle - m_vertex_handler = - buffer_stream(m_device, p_vertices.size_bytes(), p_params); + // m_vertex_handler = + // buffer(m_device, p_vertices.size_bytes(), p_params); + m_vertex_handler.construct(p_vertices.size_bytes(), p_params); // 1. Retrieve the first queue // TODO: Use vk::device_queue for this @@ -68,7 +134,7 @@ export namespace vk { queue_index, &temp_graphics_queue); - // command_buffer_info + // creating command to copy data to GPU for available accessing command_params enumerate_command_info = { .levels = command_levels::primary, .queue_index = 0, @@ -91,27 +157,27 @@ export namespace vk { vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(temp_graphics_queue); - copy_command_buffer.destroy(); + copy_command_buffer.destruct(); - // 5. cleanup staging buffer -- no longer used - staging_buffer.destroy(); + // cleanup staging buffer -- no longer used + staging_buffer.destruct(); } + void destruct() { m_vertex_handler.destruct(); } + [[nodiscard]] bool alive() const { return m_vertex_handler; } - // TODO: Probably handle flushing in vk::buffer_stream to give - // support for this...? - // void write(std::span p_vertices) {} + void transfer(std::span p_vertices) { + m_vertex_handler.transfer(p_vertices); + } operator VkBuffer() const { return m_vertex_handler; } operator VkBuffer() { return m_vertex_handler; } - void destroy() { m_vertex_handler.destroy(); } - private: VkDevice m_device = nullptr; - buffer_stream m_vertex_handler; + buffer m_vertex_handler; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/vk.cppm b/vulkan-cpp/vk.cppm index ac285de..19dfbb1 100644 --- a/vulkan-cpp/vk.cppm +++ b/vulkan-cpp/vk.cppm @@ -15,8 +15,8 @@ export import :framebuffer; export import :sample_image; export import :shader_resource; export import :pipeline; -export import :buffer_streams; -export import :buffer_streams32; +export import :buffer; +export import :buffer32; export import :vertex_buffer; export import :index_buffer; export import :uniform_buffer; @@ -26,5 +26,5 @@ export import :buffer_device_address; export import :image; namespace vk { - inline namespace v1 {}; + inline namespace v6 {}; }; \ No newline at end of file