diff --git a/.github/workflows/clang-format-deploy.yml b/.github/workflows/clang-format-deploy.yml index ac9f391..1e3234f 100644 --- a/.github/workflows/clang-format-deploy.yml +++ b/.github/workflows/clang-format-deploy.yml @@ -5,14 +5,11 @@ jobs: name: Formatting Check runs-on: ubuntu-latest steps: - - - name: 🌐 Downloading .clang-format from TheAtlasEngine - run: wget https://github.com/engine3d-dev/TheAtlasEngine/blob/main/.clang-format -O .clang-format - - uses: actions/checkout@v4 - name: Run clang-format style check for C/C++/Protobuf programs. uses: jidicula/clang-format-action@v4.14.0 with: - clang-format-version: 19 + clang-format-version: 20 check-path: '.' + include-regex: '.*\.(cpp|cppm)$' fallback-style: 'LLVM' # optional diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index e971a69..ea89922 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -1,25 +1,32 @@ -name: C++ Linter +name: cpp-linter on: [pull_request] -jobs: - linux-build: - name: "Linter" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: cpp-linter/cpp-linter-action@main - id: linter - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - style: '.clang-format' # Use .clang-format config file - version: 19 # Using clang-tidy19 - tidy-checks: '.clang-tidy' # Use .clang-tidy config file - # only 'update' a single comment in a pull request thread. - thread-comments: ${{ github.event_name == 'pull_request' && 'update' }} +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 + 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' - - name: Fail fast?! - if: steps.linter.outputs.checks-failed > 0 - run: exit 1 + - name: Fail fast?! + if: ${{ steps.linter.outputs.checks-failed > 0 }} + run: | + echo "some linter checks failed. ${{ steps.linter.outputs.checks-failed }}" + # for actual deployment + exit 1 \ No newline at end of file diff --git a/conanfile.py b/conanfile.py index e17b42b..c4fc71e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -9,7 +9,7 @@ class VulkanCppRecipe(ConanFile): name = "vulkan-cpp" - version = "5.0" + version = "6.0" license = "Apache-2.0" url = "https://github.com/engine3d-dev/vulkan-cpp" homepage = "https://github.com/engine3d-dev/vulkan-cpp" diff --git a/demos/12-loading-models/application.cpp b/demos/12-loading-models/application.cpp index e83eef5..1715152 100644 --- a/demos/12-loading-models/application.cpp +++ b/demos/12-loading-models/application.cpp @@ -23,6 +23,8 @@ import vk; #define GLM_ENABLE_EXPERIMENTAL #include +#include + #include static VKAPI_ATTR VkBool32 VKAPI_CALL @@ -144,15 +146,23 @@ class obj_model { indices.push_back(unique_vertices[vertex]); } } - vk::vertex_params vertex_info = { .phsyical_memory_properties = - p_physical.memory_properties(), - .vertices = vertices }; + + m_has_indices = (indices.size() > 0) ? true : false; + + if (m_has_indices) { + m_indices_size = indices.size(); + } + m_indices_size = vertices.size(); + m_indices_size = indices.size(); + vk::vertex_params vertex_info = { + .phsyical_memory_properties = p_physical.memory_properties(), + }; vk::index_params index_info = { .phsyical_memory_properties = - p_physical.memory_properties(), - .indices = indices }; - m_vertex_buffer = vk::vertex_buffer(p_device, vertex_info); - m_index_buffer = vk::index_buffer(p_device, index_info); + p_physical.memory_properties() }; + + m_vertex_buffer = vk::vertex_buffer(p_device, vertices, vertex_info); + m_index_buffer = vk::index_buffer(p_device, indices, index_info); m_is_loaded = true; } @@ -160,22 +170,18 @@ class obj_model { void bind(const VkCommandBuffer& p_command) { m_vertex_buffer.bind(p_command); - if (m_index_buffer.size() > 0) { + + if (m_has_indices) { m_index_buffer.bind(p_command); } } void draw(const VkCommandBuffer& p_command) { - if (m_index_buffer.size() > 0) { - vkCmdDrawIndexed(p_command, - static_cast(m_index_buffer.size()), - 1, - 0, - 0, - 0); + if (m_has_indices) { + vkCmdDrawIndexed(p_command, m_indices_size, 1, 0, 0, 0); } else { - vkCmdDraw(p_command, m_vertex_buffer.size(), 1, 0, 0); + vkCmdDraw(p_command, m_indices_size, 1, 0, 0); } } @@ -186,6 +192,8 @@ class obj_model { private: bool m_is_loaded = false; + bool m_has_indices = false; + uint32_t m_indices_size = 0; vk::vertex_buffer m_vertex_buffer{}; vk::index_buffer m_index_buffer{}; }; @@ -465,10 +473,14 @@ main() { // Now creating a vulkan graphics pipeline for the shader loading std::array shader_sources = { - vk::shader_source{ .filename = "shader_samples/sample5/test.vert.spv", - .stage = vk::shader_stage::vertex }, - vk::shader_source{ .filename = "shader_samples/sample5/test.frag.spv", - .stage = vk::shader_stage::fragment }, + vk::shader_source{ + .filename = "shader_samples/sample5/test.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "shader_samples/sample5/test.frag.spv", + .stage = vk::shader_stage::fragment, + }, }; // Setting up vertex attributes in the test shaders @@ -571,25 +583,34 @@ main() { physical_device); // Setting up descriptor sets for handling uniforms - vk::uniform_params test_ubo_info = { .phsyical_memory_properties = - physical_device.memory_properties(), - .size_bytes = sizeof(global_uniform) }; + vk::uniform_params test_ubo_info = { + .phsyical_memory_properties = physical_device.memory_properties() + }; vk::uniform_buffer test_ubo = - vk::uniform_buffer(logical_device, test_ubo_info); + vk::uniform_buffer(logical_device, sizeof(global_uniform), test_ubo_info); // std::println("uniform_buffer.alive() = {}", test_ubo.alive()); - std::array uniforms0 = { vk::write_buffer{ - .buffer = test_ubo, .offset = 0, .range = test_ubo.size_bytes() } }; + std::array uniforms0 = { + vk::write_buffer{ + .buffer = test_ubo, + .offset = 0, + .range = static_cast(test_ubo.size_bytes()), + }, + }; std::array uniforms = { - vk::write_buffer_descriptor{ .dst_binding = 0, .uniforms = uniforms0 } + vk::write_buffer_descriptor{ + .dst_binding = 0, + .uniforms = uniforms0, + }, }; // Loading a texture vk::texture_info config_texture = { .phsyical_memory_properties = physical_device.memory_properties(), - .filepath = std::filesystem::path("asset_samples/viking_room.png") }; - vk::texture texture1(logical_device, config_texture); + vk::texture texture1(logical_device, + std::filesystem::path("asset_samples/viking_room.png"), + config_texture); std::array samplers = { vk::write_image{ @@ -656,7 +677,9 @@ main() { 10.0f) }; ubo.proj[1][1] *= -1; - test_ubo.update(&ubo); + + std::array ubo_arr = { ubo }; + test_ubo.transfer(ubo_arr); // Before we can send stuff to the GPU, since we already updated the // descriptor set 0 beforehand, we must bind that descriptor resource diff --git a/demos/12-loading-models/conanfile.py b/demos/12-loading-models/conanfile.py index 708fb66..eb977f5 100644 --- a/demos/12-loading-models/conanfile.py +++ b/demos/12-loading-models/conanfile.py @@ -22,7 +22,7 @@ def requirements(self): self.requires("glm/1.0.1") self.requires("stb/cci.20230920") self.requires("tinyobjloader/2.0.0-rc10") - self.requires("vulkan-cpp/5.0") + self.requires("vulkan-cpp/6.0") def build(self): cmake = CMake(self) diff --git a/vulkan-cpp/buffer_streams.cppm b/vulkan-cpp/buffer_streams.cppm index bf1c172..fa99415 100644 --- a/vulkan-cpp/buffer_streams.cppm +++ b/vulkan-cpp/buffer_streams.cppm @@ -3,6 +3,7 @@ module; #include #include #include +#include export module vk:buffer_streams; @@ -13,93 +14,146 @@ export namespace vk { inline namespace v1 { /** * @brief Represents a VkBuffer handler for creating VkBuffer handle - * - * Purpose for using VkBuffer handle to streaming bytes of data into the GPU memory - * + * + * Purpose for using VkBuffer handle to streaming bytes of data into the + * GPU memory + * */ class buffer_stream { public: buffer_stream() = default; + + /** + * @brief constructs a buffer_stream to write streams of data to GPU + * memory + * + * @param p_device is the logical device to construct the buffer + * handles + * @param p_device_size is size in bytes of the buffer to be created + * @param p_settings are additional parameters for the buffer + * handles + */ buffer_stream(const VkDevice& p_device, - const buffer_parameters& p_settings) : m_device(p_device) { - m_allocation_size = p_settings.device_size; + uint64_t p_device_size, + const buffer_parameters& p_settings) + : m_device(p_device) { VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = m_allocation_size, // size in bytes + .size = p_device_size, // size in bytes .usage = p_settings.usage, .sharingMode = p_settings.share_mode, }; - vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), - "vkCreateBuffer"); + vk_check( + vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + "vkCreateBuffer"); // 2. retrieving buffer memory requirements VkMemoryRequirements memory_requirements = {}; - vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); - - // 3. selects the required memory requirements for this specific buffer - // allocations - uint32_t memory_index = - select_memory_requirements(p_settings.physical_memory_properties, - memory_requirements, - p_settings.property_flags); - - // 4. allocatring the necessary memory based on memory requirements for - // the buffer handles + vkGetBufferMemoryRequirements( + p_device, m_handle, &memory_requirements); + + // 3. selects the required memory requirements for this specific + // buffer allocations + uint32_t memory_index = select_memory_requirements( + p_settings.physical_memory_properties, + memory_requirements, + p_settings.property_flags); + + // 4. allocatring the necessary memory based on memory + // requirements for the buffer handles VkMemoryAllocateInfo memory_alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = memory_requirements.size, .memoryTypeIndex = memory_index }; - #if _DEBUG +#if _DEBUG // 1. Define the structure VkDebugUtilsObjectNameInfoEXT debug_info = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .pNext = nullptr, .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is - .pObjectName = p_settings.debug_name // specify what type of buffer this is + .objectHandle = (uint64_t) + m_handle, // specify vulkan to what object handle this is + .pObjectName = + p_settings + .debug_name // specify what type of buffer this is }; - if(p_settings.vkSetDebugUtilsObjectNameEXT != nullptr) { + if (p_settings.vkSetDebugUtilsObjectNameEXT != nullptr) { // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - p_settings.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + p_settings.vkSetDebugUtilsObjectNameEXT(m_device, + &debug_info); } - #endif - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); +#endif + vk_check( + vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); // 5. bind memory resource of this buffer handle - vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), - "vkBindBufferMemory"); + vk_check( + vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), + "vkBindBufferMemory"); } /** - * @param span writes some buffer data in the GPU's memory using - * vkMapMemory/vkUnmapMemory + * @brief writes an arbitrary amount of uniforms of type T + * + * Performs runtime assertion checks if the bytes of type T are + * valid before mapping the uniforms for GPU to access + * + * Example Usage: + * + * ```C++ + * vk::uniform_buffer test_ubo(...); + * std::array ubo = { ... }; + * + * test_ubo.transfer(ubo); + * ``` */ template - void write(std::span p_in_data) { - VkDeviceSize buffer_size = p_in_data.size_bytes(); + void transfer(std::span p_in_data, uint32_t p_offset = 0) { void* mapped = nullptr; - vk_check(vkMapMemory( - m_device, m_device_memory, 0, buffer_size, 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_in_data.data(), buffer_size); + vk_check(vkMapMemory(m_device, + m_device_memory, + p_offset, + p_in_data.size_bytes(), + 0, + &mapped), + "vkMapMemory"); + memcpy(mapped, p_in_data.data(), p_in_data.size_bytes()); vkUnmapMemory(m_device, m_device_memory); } - void write(const void* p_in_data, uint32_t p_size_bytes) { + /** + * @brief writing uniforms that are represented into bytes + * @param p_data are the bytes to allow GPU to access + * Example Usage: + * + * ```C++ + * buffer_streams staging_buffer(logical_device, ...); + * + * std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; + * staging_buffer.transfer(white_color); + * ``` + * + */ + void transfer(std::span p_data, + uint32_t p_offset = 0) { void* mapped = nullptr; - vk_check(vkMapMemory( - m_device, m_device_memory, 0, p_size_bytes, 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_in_data, p_size_bytes); + vk_check(vkMapMemory(m_device, + m_device_memory, + p_offset, + p_data.size_bytes(), + 0, + &mapped), + "vkMapMemory"); + memcpy(mapped, p_data.data(), p_data.size_bytes()); vkUnmapMemory(m_device, m_device_memory); } @@ -108,63 +162,44 @@ export namespace vk { * @brief This function automatically assumes the destination image * layout is going to be set to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL * - * @param p_command is the current command buffer to perform and store - * this operation into + * @param p_command is the current command buffer to perform and + * store this operation into * @param p_image is the destination to copy data from the buffer to * @param p_extent is the size of the image that is being copied * * ```C++ - * + * * buffer_streams texture_image(logical_device, ...); - * - * texture_image.copy(temp_command_buffer, texture_image, texture_format, old_layout, new_layout); + * + * texture_image.copy(temp_command_buffer, texture_image, + * texture_format, old_layout, new_layout); * ``` - * + * */ void copy_to_image(const VkCommandBuffer& p_command, - const VkImage& p_image, - image_extent p_extent) { - VkBufferImageCopy buffer_image_copy = { + const VkImage& p_image, + image_extent p_extent) { + VkBufferImageCopy buffer_image_copy = { .bufferOffset = 0, .bufferRowLength = 0, .bufferImageHeight = 0, - .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1 }, + .imageSubresource = { .aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 }, .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } + .imageExtent = { .width = p_extent.width, + .height = p_extent.height, + .depth = 1 } }; vkCmdCopyBufferToImage(p_command, - m_handle, - p_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &buffer_image_copy); - } - - /** - * @param p_data is the bytes to write into the GPU's memory through the - * Vulkan vkMapMemory/vkUnmapMemory API's. - * - * ```C++ - * - * buffer_streams staging_buffer(logical_device, ...); - * - * std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; - * staging_buffer.write(white_color); - * ``` - * - */ - void write(std::span p_data) { - void* mapped = nullptr; - vk_check( - vkMapMemory( - m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), - "vkMapMemory"); - memcpy(mapped, p_data.data(), p_data.size_bytes()); - vkUnmapMemory(m_device, m_device_memory); + m_handle, + p_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &buffer_image_copy); } void destroy() { @@ -185,7 +220,6 @@ export namespace vk { VkDevice m_device = nullptr; VkBuffer m_handle; VkDeviceMemory m_device_memory; - uint32_t m_allocation_size = 0; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams16.cppm b/vulkan-cpp/buffer_streams16.cppm index 050da88..7939876 100644 --- a/vulkan-cpp/buffer_streams16.cppm +++ b/vulkan-cpp/buffer_streams16.cppm @@ -7,38 +7,40 @@ module; export module vk:buffer_streams16; - export import :types; export import :utilities; - export namespace vk { inline namespace v1 { /** * @brief buffer stream for streaming arbitrary buffers of 32-bytes - */ + */ class buffer_stream16 { public: buffer_stream16() = default; - buffer_stream16(const VkDevice& p_device, const buffer_parameters& p_params); + buffer_stream16(const VkDevice&, + uint64_t, + const buffer_parameters&) {} /** * @brief write arbitrary buffer of 32-bytes to GPU-memory - */ - void write(std::span p_data); + */ + void write(std::span) {} - void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent); + void copy_to_image(const VkCommandBuffer& p_command, + const VkImage& p_image, + image_extent p_extent) {} - void destroy(); + void destroy() {} operator VkBuffer() { return m_handle; } operator VkBuffer() const { return m_handle; } private: - VkDevice m_device=nullptr; - VkDeviceMemory m_device_memory=nullptr; - VkBuffer m_handle=nullptr; + VkDevice m_device = nullptr; + VkDeviceMemory m_device_memory = nullptr; + VkBuffer m_handle = nullptr; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/buffer_streams32.cppm b/vulkan-cpp/buffer_streams32.cppm index 2c958b2..2442195 100644 --- a/vulkan-cpp/buffer_streams32.cppm +++ b/vulkan-cpp/buffer_streams32.cppm @@ -7,108 +7,124 @@ module; export module vk:buffer_streams32; - export import :types; export import :utilities; export import :command_buffer; - export namespace vk { inline namespace v1 { /** * @brief buffer stream for streaming arbitrary buffers of 32-bytes - */ + */ class buffer_stream32 { public: buffer_stream32() = default; - buffer_stream32(const VkDevice& p_device, const buffer_parameters& p_params) : m_device(p_device) { + buffer_stream32(const VkDevice& p_device, + uint64_t p_device_size, + const buffer_parameters& p_params) + : m_device(p_device) { VkBufferCreateInfo buffer_ci = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, - .size = p_params.device_size, // size in bytes + .size = p_device_size, // size in bytes .usage = p_params.usage, .sharingMode = p_params.share_mode, }; - vk_check(vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), - "vkCreateBuffer"); + vk_check( + vkCreateBuffer(p_device, &buffer_ci, nullptr, &m_handle), + "vkCreateBuffer"); // 2. retrieving buffer memory requirements VkMemoryRequirements memory_requirements = {}; - vkGetBufferMemoryRequirements(p_device, m_handle, &memory_requirements); - - // 3. selects the required memory requirements for this specific buffer - // allocations - uint32_t memory_index = - select_memory_requirements(p_params.physical_memory_properties, - memory_requirements, - p_params.property_flags); - - // 4. allocatring the necessary memory based on memory requirements for - // the buffer handles + vkGetBufferMemoryRequirements( + p_device, m_handle, &memory_requirements); + + // 3. selects the required memory requirements for this specific + // buffer allocations + uint32_t memory_index = select_memory_requirements( + p_params.physical_memory_properties, + memory_requirements, + p_params.property_flags); + + // 4. allocatring the necessary memory based on memory + // requirements for the buffer handles VkMemoryAllocateInfo memory_alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, .allocationSize = memory_requirements.size, .memoryTypeIndex = memory_index }; - #if _DEBUG +#if _DEBUG // 1. Define the structure VkDebugUtilsObjectNameInfoEXT debug_info = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, .pNext = nullptr, .objectType = VK_OBJECT_TYPE_BUFFER, - .objectHandle = (uint64_t)m_handle, // specify vulkan to what object handle this is - .pObjectName = p_params.debug_name // specify what type of buffer this is + .objectHandle = (uint64_t) + m_handle, // specify vulkan to what object handle this is + .pObjectName = + p_params.debug_name // specify what type of buffer this is }; - if(p_params.vkSetDebugUtilsObjectNameEXT != nullptr) { + if (p_params.vkSetDebugUtilsObjectNameEXT != nullptr) { // vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); - p_params.vkSetDebugUtilsObjectNameEXT(m_device, &debug_info); + p_params.vkSetDebugUtilsObjectNameEXT(m_device, + &debug_info); } - #endif - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); +#endif + vk_check( + vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); // 5. bind memory resource of this buffer handle - vk_check(vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), - "vkBindBufferMemory"); + vk_check( + vkBindBufferMemory(p_device, m_handle, m_device_memory, 0), + "vkBindBufferMemory"); } /** * @brief write arbitrary buffer of 32-bytes to GPU-memory - */ + */ void write(std::span p_data) { void* mapped = nullptr; - vk_check( - vkMapMemory( - m_device, m_device_memory, 0, p_data.size_bytes(), 0, &mapped), - "vkMapMemory"); + vk_check(vkMapMemory(m_device, + m_device_memory, + 0, + p_data.size_bytes(), + 0, + &mapped), + "vkMapMemory"); memcpy(mapped, p_data.data(), p_data.size_bytes()); vkUnmapMemory(m_device, m_device_memory); } - void copy_to_image(const VkCommandBuffer& p_command, const VkImage& p_image, image_extent p_extent) { + void copy_to_image(const VkCommandBuffer& p_command, + const VkImage& p_image, + image_extent p_extent) { VkBufferImageCopy buffer_image_copy = { .bufferOffset = 0, .bufferRowLength = 0, .bufferImageHeight = 0, - .imageSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1 }, + .imageSubresource = { .aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1 }, .imageOffset = { .x = 0, .y = 0, .z = 0 }, - .imageExtent = { .width = p_extent.width, .height = p_extent.height, .depth = 1 } + .imageExtent = { .width = p_extent.width, + .height = p_extent.height, + .depth = 1 } }; vkCmdCopyBufferToImage(p_command, - m_handle, - p_image, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, - &buffer_image_copy); + m_handle, + p_image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &buffer_image_copy); } void destroy() { @@ -126,9 +142,9 @@ export namespace vk { operator VkBuffer() const { return m_handle; } private: - VkDevice m_device=nullptr; - VkDeviceMemory m_device_memory=nullptr; - VkBuffer m_handle=nullptr; + VkDevice m_device = nullptr; + VkDeviceMemory m_device_memory = nullptr; + VkBuffer m_handle = nullptr; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/command_buffer.cppm b/vulkan-cpp/command_buffer.cppm index f1c7ff9..1830088 100644 --- a/vulkan-cpp/command_buffer.cppm +++ b/vulkan-cpp/command_buffer.cppm @@ -6,7 +6,6 @@ module; export module vk:command_buffer; - export import :types; export import :utilities; @@ -19,61 +18,72 @@ export namespace vk { }; /** - * @brief vk::command_buffer represents the wrapper around VkCommandBuffer - * - * Defines the command buffer and provides API's to directly interact with how - * the command buffer may be utilized based on the needs of the application that uses it - * - */ + * @brief vk::command_buffer represents the wrapper around + * VkCommandBuffer + * + * Defines the command buffer and provides API's to directly interact + * with how the command buffer may be utilized based on the needs of the + * application that uses it + * + */ class command_buffer { public: command_buffer() = default; - command_buffer(const VkDevice& p_device, const command_params& p_enumerate_command_info) : m_device(p_device) { + command_buffer(const VkDevice& p_device, + const command_params& p_enumerate_command_info) + : m_device(p_device) { VkCommandPoolCreateInfo pool_ci = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .pNext = nullptr, - // .flags = - // (VkCommandPoolCreateFlags)p_enumerate_command_info.pool_flag, - .flags = static_cast(p_enumerate_command_info.flags), - .queueFamilyIndex = p_enumerate_command_info.queue_index - }; - - vk_check( - vkCreateCommandPool(m_device, &pool_ci, nullptr, &m_command_pool), - "vkCreateCommandPool"); - - VkCommandBufferAllocateInfo command_buffer_alloc_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .pNext = nullptr, - .commandPool = m_command_pool, - .level = - static_cast(p_enumerate_command_info.levels), - .commandBufferCount = 1 - }; - - vk_check(vkAllocateCommandBuffers( - m_device, &command_buffer_alloc_info, &m_command_buffer), - "vkAllocateCommandBuffers"); + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .pNext = nullptr, + // .flags = + // (VkCommandPoolCreateFlags)p_enumerate_command_info.pool_flag, + .flags = static_cast( + p_enumerate_command_info.flags), + .queueFamilyIndex = p_enumerate_command_info.queue_index + }; + + vk_check(vkCreateCommandPool( + m_device, &pool_ci, nullptr, &m_command_pool), + "vkCreateCommandPool"); + + VkCommandBufferAllocateInfo command_buffer_alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .pNext = nullptr, + .commandPool = m_command_pool, + .level = static_cast( + p_enumerate_command_info.levels), + .commandBufferCount = 1 + }; + + vk_check(vkAllocateCommandBuffers(m_device, + &command_buffer_alloc_info, + &m_command_buffer), + "vkAllocateCommandBuffers"); } /** - * @brief begins the recording operation of the particular command buffer - * - * @param p_usage are flags to specify the behavior of the command buffer - * @param p_inherit_info is if this command buffer is created and used as a secondary command buffer, then - * this defines any state that will be inherited from the primary command buffer - * - * + * @brief begins the recording operation of the particular command + * buffer + * + * @param p_usage are flags to specify the behavior of the command + * buffer + * @param p_inherit_info is if this command buffer is created and + * used as a secondary command buffer, then this defines any state + * that will be inherited from the primary command buffer + * + * * ```C++ - * + * * vk::command_buffer temp_command(logical_device, ....); - * + * * temp_command.begin(command_usage::one_time_submit); * temp_command.end(); // required whenever .begin is called * ``` - * - */ - void begin(command_usage p_usage, std::span p_inherit_info = {}) { + * + */ + void begin( + command_usage p_usage, + std::span p_inherit_info = {}) { // Resets to zero if get called every frame if (m_begin_end_count == 2) { m_begin_end_count = 0; @@ -81,11 +91,12 @@ export namespace vk { m_begin_end_count++; std::vector inheritance_infos( - p_inherit_info.size()); + p_inherit_info.size()); for (size_t i = 0; i < inheritance_infos.size(); i++) { inheritance_infos[i] = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + .sType = + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, .renderPass = p_inherit_info[i].renderpass, .subpass = p_inherit_info[i].subpass_index, .framebuffer = p_inherit_info[i].framebuffer @@ -97,55 +108,65 @@ export namespace vk { .pNext = nullptr, .flags = static_cast(p_usage) }; - vk_check(vkBeginCommandBuffer(m_command_buffer, &command_begin_info), - "vkBeginCommandBuffer"); + vk_check( + vkBeginCommandBuffer(m_command_buffer, &command_begin_info), + "vkBeginCommandBuffer"); } /** * @brief ends command buffer recording operation - */ + */ void end() { m_begin_end_count++; vkEndCommandBuffer(m_command_buffer); } /** - * - * @brief Copy from the source buffer to a destination specified buffer - * - * - * Command buffer records this and expects a staging buffer to map chunks of data in GPU memory - * - * Then calling this API to handle copying the sources in staging buffer to its final destination buffer, moving those chunks into the final buffer handle - * - * + * + * @brief Copy from the source buffer to a destination specified + * buffer + * + * + * Command buffer records this and expects a staging buffer to map + * chunks of data in GPU memory + * + * Then calling this API to handle copying the sources in staging + * buffer to its final destination buffer, moving those chunks into + * the final buffer handle + * + * * @param p_src is the buffer to copy its region from * @param p_dst is the buffer to copy that region into - * @param p_size_bytes is the amount of bytes stored in the buffer that is being copied into the destination buffer - * - * + * @param p_size_bytes is the amount of bytes stored in the buffer + * that is being copied into the destination buffer + * + * * ```C++ - * - * // staging buffer to make sure we copy data regions chunks to vertex buffer correctly - * vk::buffer_stream staging_buffer(logical_device, ...); - * + * + * // staging buffer to make sure we copy data regions chunks to + * vertex buffer correctly vk::buffer_stream + * staging_buffer(logical_device, ...); + * * // vertex_buffer handle is the destination to copy the regions to * vk::buffer_stream vertex_buffer(logical_device, ...); - * + * * vk::command_buffer temp_command(logical_device, ...); - * + * * temp_command.begin(command_usage::one_time_submit); * temp_command.copy(staging_buffer, vertex_buffer, size_bytes); * temp_command.end(); - * - * + * + * * ``` - * - */ - void copy_buffer(const VkBuffer& p_src, const VkBuffer& p_dst, uint64_t p_size_bytes) { + * + */ + void copy_buffer(const VkBuffer& p_src, + const VkBuffer& p_dst, + uint64_t p_size_bytes) { VkBufferCopy copy_region{}; copy_region.size = p_size_bytes; - vkCmdCopyBuffer(m_command_buffer, p_src, p_dst, 1, ©_region); + vkCmdCopyBuffer( + m_command_buffer, p_src, p_dst, 1, ©_region); } [[nodiscard]] bool alive() const { return m_command_buffer; } @@ -156,17 +177,18 @@ export namespace vk { * The command buffer that is executing these commands must be a * specified primary command buffer * - * @param p_commands is the secondary command buffer that gets executed - * if the command buffer itself is a primary command buffer + * @param p_commands is the secondary command buffer that gets + * executed if the command buffer itself is a primary command buffer */ void execute(std::span p_commands) { vkCmdExecuteCommands(m_command_buffer, - static_cast(p_commands.size()), - p_commands.data()); + static_cast(p_commands.size()), + p_commands.data()); } void destroy() { - vkFreeCommandBuffers(m_device, m_command_pool, 1, &m_command_buffer); + 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 78dd88f..08828fb 100644 --- a/vulkan-cpp/descriptor_resource.cppm +++ b/vulkan-cpp/descriptor_resource.cppm @@ -7,7 +7,6 @@ module; export module vk:descriptor_resource; - export import :types; export import :utilities; export import :uniform_buffer; @@ -16,8 +15,8 @@ export import :sample_image; export namespace vk { inline namespace v1 { /** - * @param slot is the slot specific to the number slot for the descriptor. - * Ex. layout (set = 0) + * @param slot is the slot specific to the number slot for the + * descriptor. Ex. layout (set = 0) */ struct descriptor_layout { uint32_t slot = 0; @@ -28,17 +27,24 @@ export namespace vk { class descriptor_resource { public: descriptor_resource() = default; - descriptor_resource(const VkDevice& p_device, const descriptor_layout& p_info) : m_device(p_device), m_slot(p_info.slot) { - std::vector pool_sizes(p_info.entries.size()); - std::vector descriptor_layout_bindings(p_info.entries.size()); + descriptor_resource(const VkDevice& p_device, + const descriptor_layout& p_info) + : m_device(p_device) + , m_slot(p_info.slot) { + std::vector pool_sizes( + p_info.entries.size()); + std::vector + descriptor_layout_bindings(p_info.entries.size()); for (size_t i = 0; i < pool_sizes.size(); i++) { - VkDescriptorType descriptor_type = static_cast(p_info.entries[i].type); + VkDescriptorType descriptor_type = + static_cast(p_info.entries[i].type); pool_sizes[i] = { .type = descriptor_type, .descriptorCount = - static_cast(p_info.entries[i].descriptor_count) * - p_info.max_sets, + static_cast( + p_info.entries[i].descriptor_count) * + p_info.max_sets, }; } @@ -46,13 +52,15 @@ export namespace vk { descriptor_entry entry = p_info.entries[i]; descriptor_binding_point bind = entry.binding_point; - VkDescriptorType type = static_cast(entry.type); + VkDescriptorType type = + static_cast(entry.type); descriptor_layout_bindings[i] = { .binding = bind.binding, .descriptorType = type, .descriptorCount = entry.descriptor_count, - .stageFlags = static_cast(bind.stage), + .stageFlags = + static_cast(bind.stage), }; } @@ -66,22 +74,24 @@ export namespace vk { }; vk_check(vkCreateDescriptorPool( - m_device, &pool_ci, nullptr, &m_descriptor_pool), - "vkCreateDescriptorPool"); + m_device, &pool_ci, nullptr, &m_descriptor_pool), + "vkCreateDescriptorPool"); VkDescriptorSetLayoutCreateInfo descriptor_layout_ci = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .sType = + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .pNext = nullptr, .flags = 0, .bindingCount = - static_cast(descriptor_layout_bindings.size()), + static_cast(descriptor_layout_bindings.size()), .pBindings = descriptor_layout_bindings.data() }; - vk_check( - vkCreateDescriptorSetLayout( - m_device, &descriptor_layout_ci, nullptr, &m_descriptor_layout), - "vkCreateDescriptorSetLayout"); + vk_check(vkCreateDescriptorSetLayout(m_device, + &descriptor_layout_ci, + nullptr, + &m_descriptor_layout), + "vkCreateDescriptorSetLayout"); VkDescriptorSetAllocateInfo descriptor_set_alloc_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, .pNext = nullptr, @@ -91,42 +101,50 @@ export namespace vk { }; vk_check(vkAllocateDescriptorSets(m_device, - &descriptor_set_alloc_info, - &m_descriptor_set), - "vkAllocateDescriptorSets"); + &descriptor_set_alloc_info, + &m_descriptor_set), + "vkAllocateDescriptorSets"); } - void bind(const VkCommandBuffer& p_current, const VkPipelineLayout& p_pipeline_layout) { + void bind(const VkCommandBuffer& p_current, + const VkPipelineLayout& p_pipeline_layout) { vkCmdBindDescriptorSets(p_current, - VK_PIPELINE_BIND_POINT_GRAPHICS, - p_pipeline_layout, - m_slot, - 1, - &m_descriptor_set, - 0, - nullptr); + VK_PIPELINE_BIND_POINT_GRAPHICS, + p_pipeline_layout, + m_slot, + 1, + &m_descriptor_set, + 0, + nullptr); } - - void update(std::span p_uniforms, std::span p_images={}) { + + void update(std::span p_uniforms, + std::span p_images = {}) { std::vector write_descriptors; - // uint32_t represent the destination bindings to those resources (uniforms and sample images) - std::unordered_map> buffer_infos; - std::unordered_map> image_infos; + // uint32_t represent the destination bindings to those + // resources (uniforms and sample images) + std::unordered_map> + buffer_infos; + std::unordered_map> + image_infos; // handle uniforms - for(const auto& ubo : p_uniforms) { - for(const auto& uniform : ubo.uniforms) { - buffer_infos[ubo.dst_binding].emplace_back(uniform.buffer, uniform.offset, uniform.range); + for (const auto& ubo : p_uniforms) { + for (const auto& uniform : ubo.uniforms) { + buffer_infos[ubo.dst_binding].emplace_back( + uniform.buffer, uniform.offset, uniform.range); } VkWriteDescriptorSet write_descriptor = { - . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .pNext = nullptr, .dstSet = m_descriptor_set, .dstBinding = ubo.dst_binding, .dstArrayElement = 0, - .descriptorCount = static_cast(buffer_infos[ubo.dst_binding].size()), + .descriptorCount = static_cast( + buffer_infos[ubo.dst_binding].size()), .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .pBufferInfo = buffer_infos[ubo.dst_binding].data(), }; @@ -134,10 +152,13 @@ export namespace vk { write_descriptors.emplace_back(write_descriptor); } - for(const auto& ubo : p_images) { + for (const auto& ubo : p_images) { - for(const auto& sample_image : ubo.sample_images) { - image_infos[ubo.dst_binding].emplace_back(sample_image.sampler, sample_image.view, static_cast(sample_image.layout)); + for (const auto& sample_image : ubo.sample_images) { + image_infos[ubo.dst_binding].emplace_back( + sample_image.sampler, + sample_image.view, + static_cast(sample_image.layout)); } VkWriteDescriptorSet write_descriptor = { @@ -146,8 +167,10 @@ export namespace vk { .dstSet = m_descriptor_set, .dstBinding = ubo.dst_binding, .dstArrayElement = 0, - .descriptorCount = static_cast(image_infos[ubo.dst_binding].size()), - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = static_cast( + image_infos[ubo.dst_binding].size()), + .descriptorType = + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .pImageInfo = image_infos[ubo.dst_binding].data(), }; @@ -155,13 +178,15 @@ export namespace vk { } vkUpdateDescriptorSets( - m_device, - static_cast(write_descriptors.size()), - write_descriptors.data(), - 0, - nullptr); - - // Ensures to clear up so we dont have any existing handles because they only need to exist until we've updated the descriptors + m_device, + static_cast(write_descriptors.size()), + write_descriptors.data(), + 0, + nullptr); + + // Ensures to clear up so we dont have any existing handles + // because they only need to exist until we've updated the + // descriptors buffer_infos.clear(); image_infos.clear(); } @@ -172,12 +197,13 @@ export namespace vk { void destroy() { if (m_descriptor_pool != nullptr) { - vkDestroyDescriptorPool(m_device, m_descriptor_pool, nullptr); + vkDestroyDescriptorPool( + m_device, m_descriptor_pool, nullptr); } if (m_descriptor_layout != nullptr) { vkDestroyDescriptorSetLayout( - m_device, m_descriptor_layout, nullptr); + m_device, m_descriptor_layout, nullptr); } } diff --git a/vulkan-cpp/device.cppm b/vulkan-cpp/device.cppm index 311a184..1a3f199 100644 --- a/vulkan-cpp/device.cppm +++ b/vulkan-cpp/device.cppm @@ -7,7 +7,6 @@ export module vk:device; export import :types; export import :utilities; - export namespace vk { inline namespace v1 { /** @@ -22,14 +21,15 @@ export namespace vk { }; public: - device(const VkPhysicalDevice& p_physical, const device_params& p_config) { + device(const VkPhysicalDevice& p_physical, + const device_params& p_config) { VkDeviceQueueCreateInfo device_queue_ci = { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .pNext = nullptr, .flags = 0, .queueFamilyIndex = p_config.queue_family_index, .queueCount = - static_cast(p_config.queue_priorities.size()), + static_cast(p_config.queue_priorities.size()), .pQueuePriorities = p_config.queue_priorities.data(), }; @@ -42,7 +42,7 @@ export namespace vk { .enabledLayerCount = 0, .ppEnabledLayerNames = nullptr, .enabledExtensionCount = - static_cast(p_config.extensions.size()), + static_cast(p_config.extensions.size()), .ppEnabledExtensionNames = p_config.extensions.data(), }; @@ -51,8 +51,9 @@ export namespace vk { features.robustBufferAccess = false; create_info.pEnabledFeatures = &features; - vk_check(vkCreateDevice(p_physical, &create_info, nullptr, &m_device), - "vkCreateDevice"); + vk_check( + vkCreateDevice(p_physical, &create_info, nullptr, &m_device), + "vkCreateDevice"); } [[nodiscard]] queue_family family() const { return m_queue_family; } @@ -63,9 +64,7 @@ export namespace vk { } } - void wait() { - vkDeviceWaitIdle(m_device); - } + void wait() { vkDeviceWaitIdle(m_device); } operator VkDevice() const { return m_device; } diff --git a/vulkan-cpp/device_present_queue.cppm b/vulkan-cpp/device_present_queue.cppm index 0d795a8..67311c1 100644 --- a/vulkan-cpp/device_present_queue.cppm +++ b/vulkan-cpp/device_present_queue.cppm @@ -24,35 +24,36 @@ export namespace vk { public: device_present_queue() = default; device_present_queue(const VkDevice& p_device, - const VkSwapchainKHR& p_swapchain_context, - const queue_params& p_config) - : m_device(p_device), m_swapchain(p_swapchain_context) { - - vkGetDeviceQueue( - m_device, p_config.family, p_config.index, &m_queue_handler); + const VkSwapchainKHR& p_swapchain_context, + const queue_params& p_config) + : m_device(p_device) + , m_swapchain(p_swapchain_context) { + + vkGetDeviceQueue( + m_device, p_config.family, p_config.index, &m_queue_handler); m_work_completed = create_semaphore(m_device); m_presentation_completed = create_semaphore(m_device); m_out_of_date = false; } - void wait_idle() { - vkQueueWaitIdle(m_queue_handler); - } + void wait_idle() { vkQueueWaitIdle(m_queue_handler); } //! @return true if this queue is out of date - // Can occur when acquired_next_image or present_frame are out of date - // indication swapchain resizeability. - // TODO: Change this to using C++'s exceptions for handling out-of-date invalidation cases + // Can occur when acquired_next_image or present_frame are out of + // date indication swapchain resizeability. + // TODO: Change this to using C++'s exceptions for handling + // out-of-date invalidation cases bool out_of_date(bool p_is_reset = true) { // The return value we return bool return_value = false; // If the bool is set to true meaning its out of date - // Then we set the internal variable tracking the acquired next image - // state to false, and return false This is for ensuring that we do not - // need to set the boolean ourselves. Should we handle this state to - // reset to false if checked or user should set the state??? + // Then we set the internal variable tracking the acquired next + // image state to false, and return false This is for ensuring + // that we do not need to set the boolean ourselves. Should we + // handle this state to reset to false if checked or user should + // set the state??? if (m_out_of_date) { return_value = m_out_of_date; if (p_is_reset) { @@ -69,7 +70,7 @@ export namespace vk { uint32_t image_acquired; VkResult acquired_next_image_res = - vkAcquireNextImageKHR(m_device, + vkAcquireNextImageKHR(m_device, m_swapchain, std::numeric_limits::max(), m_presentation_completed, @@ -94,35 +95,40 @@ export namespace vk { .waitSemaphoreCount = 0, .pWaitSemaphores = nullptr, .pWaitDstStageMask = nullptr, - .commandBufferCount = static_cast(p_commands.size()), + .commandBufferCount = + static_cast(p_commands.size()), .pCommandBuffers = p_commands.data(), .signalSemaphoreCount = 0, .pSignalSemaphores = nullptr, }; - VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); + VkResult res = + vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); vk_check(res, "vkQueueSubmit"); } //! @brief Submit commands to this specific present queue //! (asynchronously) void submit_async(std::span p_commands, - pipeline_stage_flags p_flags = + pipeline_stage_flags p_flags = pipeline_stage_flags::color_attachment_output) { - VkPipelineStageFlags flags = static_cast(p_flags); + VkPipelineStageFlags flags = + static_cast(p_flags); VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 1, .pWaitSemaphores = &m_presentation_completed, .pWaitDstStageMask = &flags, - .commandBufferCount = static_cast(p_commands.size()), + .commandBufferCount = + static_cast(p_commands.size()), .pCommandBuffers = p_commands.data(), .signalSemaphoreCount = 1, .pSignalSemaphores = &m_work_completed, }; - VkResult res = vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); + VkResult res = + vkQueueSubmit(m_queue_handler, 1, &submit_info, nullptr); vk_check(res, "vkQueueSubmit"); } @@ -139,9 +145,11 @@ export namespace vk { .pImageIndices = &p_frame_idx, }; - VkResult res = vkQueuePresentKHR(m_queue_handler, &present_info); + VkResult res = + vkQueuePresentKHR(m_queue_handler, &present_info); vk_check(res, "vkQueuePresentKHR"); - if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) { + if (res == VK_ERROR_OUT_OF_DATE_KHR || + res == VK_SUBOPTIMAL_KHR) { m_out_of_date = true; } } diff --git a/vulkan-cpp/device_queue.cppm b/vulkan-cpp/device_queue.cppm index 4daecfc..846971f 100644 --- a/vulkan-cpp/device_queue.cppm +++ b/vulkan-cpp/device_queue.cppm @@ -7,7 +7,6 @@ export module vk:device_queue; export import :types; export import :utilities; - export namespace vk { inline namespace v1 { /** @@ -18,8 +17,10 @@ export namespace vk { public: device_queue() = default; - device_queue(const VkDevice& p_device, const queue_params& p_config) { - vkGetDeviceQueue(p_device, p_config.family, p_config.index, &m_queue_handler); + device_queue(const VkDevice& p_device, + const queue_params& p_config) { + vkGetDeviceQueue( + p_device, p_config.family, p_config.index, &m_queue_handler); } [[nodiscard]] bool alive() const { return m_queue_handler; } diff --git a/vulkan-cpp/framebuffer.cppm b/vulkan-cpp/framebuffer.cppm index 76731ea..4902ffb 100644 --- a/vulkan-cpp/framebuffer.cppm +++ b/vulkan-cpp/framebuffer.cppm @@ -14,30 +14,33 @@ export namespace vk { * * @param p_device is logical device that creates and manages the * destruction of vulkan framebuffer handles. - * @param p_setting are specifications to configure the creation of vulkan - * VkFramebuffer handles. + * @param p_setting are specifications to configure the creation of + * vulkan VkFramebuffer handles. */ class framebuffer { public: framebuffer() = default; framebuffer(const VkDevice& p_device, - const framebuffer_params& p_setting) : m_device(p_device) { - + const framebuffer_params& p_setting) + : m_device(p_device) { + VkFramebufferCreateInfo framebuffer_ci = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .pNext = nullptr, .flags = 0, .renderPass = p_setting.renderpass, - .attachmentCount = static_cast(p_setting.views.size()), + .attachmentCount = + static_cast(p_setting.views.size()), .pAttachments = p_setting.views.data(), .width = p_setting.extent.width, .height = p_setting.extent.height, .layers = 1 }; - vk::vk_check(vkCreateFramebuffer( - m_device, &framebuffer_ci, nullptr, &m_framebuffer), - "vkCreateFramebuffer"); + vk::vk_check( + vkCreateFramebuffer( + m_device, &framebuffer_ci, nullptr, &m_framebuffer), + "vkCreateFramebuffer"); } [[nodiscard]] bool alive() const { return m_framebuffer; } diff --git a/vulkan-cpp/index_buffer.cppm b/vulkan-cpp/index_buffer.cppm index 558a372..15300b4 100644 --- a/vulkan-cpp/index_buffer.cppm +++ b/vulkan-cpp/index_buffer.cppm @@ -5,7 +5,6 @@ module; export module vk:index_buffer; - export import :types; export import :utilities; export import :command_buffer; @@ -17,43 +16,44 @@ export namespace vk { public: index_buffer() = default; index_buffer(const VkDevice& p_device, - const index_params& p_info) : m_device(p_device) { - m_indices_count = p_info.indices.size(); + std::span p_indices, + const index_params& p_info) + : m_device(p_device) { buffer_parameters index_params = { - .device_size = p_info.indices.size_bytes(), - .physical_memory_properties = p_info.phsyical_memory_properties, - .property_flags = static_cast(memory_property::host_visible_bit | memory_property::host_cached_bit), - .usage = static_cast(buffer_usage::index_buffer_bit), + .physical_memory_properties = + p_info.phsyical_memory_properties, + .property_flags = static_cast( + memory_property::host_visible_bit | + memory_property::host_cached_bit), + .usage = static_cast( + buffer_usage::index_buffer_bit), .debug_name = p_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_info.vkSetDebugUtilsObjectNameEXT + .vkSetDebugUtilsObjectNameEXT = + p_info.vkSetDebugUtilsObjectNameEXT }; - m_index_buffer = buffer_stream32(m_device, index_params); + m_index_buffer = buffer_stream32( + m_device, p_indices.size_bytes(), index_params); - m_index_buffer.write(p_info.indices); + m_index_buffer.write(p_indices); } [[nodiscard]] bool alive() const { return m_index_buffer; } - [[nodiscard]] uint32_t size() const { return m_indices_count; } - void bind(const VkCommandBuffer& p_current, uint64_t p_offset = 0) { vkCmdBindIndexBuffer( - p_current, m_index_buffer, p_offset, VK_INDEX_TYPE_UINT32); + p_current, m_index_buffer, p_offset, VK_INDEX_TYPE_UINT32); } operator VkBuffer() const { return m_index_buffer; } operator VkBuffer() { return m_index_buffer; } - void destroy() { - m_index_buffer.destroy(); - } + void destroy() { m_index_buffer.destroy(); } private: VkDevice m_device = nullptr; - uint32_t m_indices_count = 0; buffer_stream32 m_index_buffer{}; }; }; diff --git a/vulkan-cpp/instance.cppm b/vulkan-cpp/instance.cppm index 4375c90..6769cd7 100644 --- a/vulkan-cpp/instance.cppm +++ b/vulkan-cpp/instance.cppm @@ -12,10 +12,11 @@ export import :utilities; export namespace vk { inline namespace v1 { /** - * @brief vk::instance represents VkInstance to initialize the vulkan API. + * @brief vk::instance represents VkInstance to initialize the vulkan + * API. * - * Provides configuration settings that can be applied to the application - * and the vulkan debug utility for the validation layers + * Provides configuration settings that can be applied to the + * application and the vulkan debug utility for the validation layers */ class instance { public: @@ -26,7 +27,7 @@ export namespace vk { * tooling for debugging and enabling validation layers */ instance(const application_params& p_config, - const debug_message_utility& p_debug_message_utils) { + const debug_message_utility& p_debug_message_utils) { VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pNext = nullptr, @@ -50,60 +51,76 @@ export namespace vk { // std::vector layer_properties(layer_count); layer_properties.resize(layer_count); vkEnumerateInstanceLayerProperties(&layer_count, - layer_properties.data()); + layer_properties.data()); for (const VkLayerProperties property : layer_properties) { - m_layer_properties.emplace_back(property.layerName, - property.specVersion, - property.implementationVersion, - property.description); + m_layer_properties.emplace_back( + property.layerName, + property.specVersion, + property.implementationVersion, + property.description); } // Setting up instance extensions instance_ci.enabledExtensionCount = - static_cast(p_config.extensions.size()); - instance_ci.ppEnabledExtensionNames = p_config.extensions.data(); + static_cast(p_config.extensions.size()); + instance_ci.ppEnabledExtensionNames = + p_config.extensions.data(); - #if defined(__APPLE__) - instance_ci.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - #endif +#if defined(__APPLE__) + instance_ci.flags |= + VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; +#endif - // Only execute this if we are in the debug build - #if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) + // Only execute this if we are in the debug build +#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) // Setting up validation layers instance_ci.enabledLayerCount = - static_cast(p_config.validations.size()); + static_cast(p_config.validations.size()); instance_ci.ppEnabledLayerNames = p_config.validations.data(); VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = static_cast(p_debug_message_utils.severity), - .messageType = static_cast(p_debug_message_utils.message_type), + .sType = + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, + .messageSeverity = + static_cast( + p_debug_message_utils.severity), + .messageType = static_cast( + p_debug_message_utils.message_type), .pfnUserCallback = p_debug_message_utils.callback, }; - // This is to invoke the vulkan debug utils if it is a valid callback - // To ensure that we are not using an invalid debug callback + // This is to invoke the vulkan debug utils if it is a valid + // callback To ensure that we are not using an invalid debug + // callback if (p_debug_message_utils.callback != nullptr) { - // instance_ci.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; - instance_ci.pNext = reinterpret_cast(&debug_create_info); + // instance_ci.pNext = + // (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; + instance_ci.pNext = + reinterpret_cast( + &debug_create_info); } else { instance_ci.pNext = nullptr; } - #else +#else instance_ci.enabledLayerCount = 0; instance_ci.ppEnabledLayerNames = nullptr; instance_ci.pNext = nullptr; - #endif +#endif vk_check(vkCreateInstance(&instance_ci, nullptr, &m_instance), - "vkCreateInstance"); - - // Set the debug utility function pointer if we are in the debug build. - #if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - // This needs to be created after the VkInstance is or else it wont be applied the debug information during validation layer error message execution - m_vk_set_debug_utils_object_name_ext = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkSetDebugUtilsObjectNameEXT")); - #endif + "vkCreateInstance"); + +// Set the debug utility function pointer if we are in the debug build. +#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) + // This needs to be created after the VkInstance is or else it + // wont be applied the debug information during validation layer + // error message execution + m_vk_set_debug_utils_object_name_ext = + reinterpret_cast( + vkGetInstanceProcAddr(m_instance, + "vkSetDebugUtilsObjectNameEXT")); +#endif } //! @return true if a valid VkInstance @@ -115,15 +132,20 @@ export namespace vk { } /** - * @brief returns function pointer to allow for setting debug object name - * - * - * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug builds - * - * This allows for setting up object names that is useful to the programmer when a validation layer error message occurs unexpectedly - * - */ - [[nodiscard]] PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() const { + * @brief returns function pointer to allow for setting debug object + * name + * + * + * This allows for utilizing vkSetDebugUtilsObjectNameEXT during + * debug builds + * + * This allows for setting up object names that is useful to the + * programmer when a validation layer error message occurs + * unexpectedly + * + */ + [[nodiscard]] PFN_vkSetDebugUtilsObjectNameEXT + get_debug_object_name() const { return m_vk_set_debug_utils_object_name_ext; } @@ -138,7 +160,8 @@ export namespace vk { VkInstance m_instance = nullptr; std::vector m_layer_properties{}; // This needs to be set or else it becomes nullptr - PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; + PFN_vkSetDebugUtilsObjectNameEXT + m_vk_set_debug_utils_object_name_ext; }; }; }; \ No newline at end of file diff --git a/vulkan-cpp/physical_device.cppm b/vulkan-cpp/physical_device.cppm index c9aeeb5..c266b71 100644 --- a/vulkan-cpp/physical_device.cppm +++ b/vulkan-cpp/physical_device.cppm @@ -9,25 +9,28 @@ export module vk:physical_device; export import :utilities; export import :types; - export namespace vk { inline namespace v1 { class physical_device { public: physical_device() = default; - physical_device(const VkInstance& p_instance, const physical_enumeration& p_physical_enumeration) { - m_physical_device = enumerate_physical_devices(p_instance, p_physical_enumeration.device_type); + physical_device( + const VkInstance& p_instance, + const physical_enumeration& p_physical_enumeration) { + m_physical_device = enumerate_physical_devices( + p_instance, p_physical_enumeration.device_type); if (m_physical_device == nullptr) { return; } m_queue_family_properties = - enumerate_queue_family_properties(m_physical_device); + enumerate_queue_family_properties(m_physical_device); - // This makes sure that we get the graphics, compute, and transfer queue - // indices from the physical queue family assigned + // This makes sure that we get the graphics, compute, and + // transfer queue indices from the physical queue family + // assigned uint32_t queue_index = 0; for (const auto& queue_family : m_queue_family_properties) { if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { @@ -72,8 +75,8 @@ export namespace vk { uint32_t i = 0; for (const auto& queue_family : m_queue_family_properties) { vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( - m_physical_device, i, p_surface, &compatible), - "vkGetPhysicalDeviceSurfaceSupportKHR"); + m_physical_device, i, p_surface, &compatible), + "vkGetPhysicalDeviceSurfaceSupportKHR"); if (compatible) { presentation_index = i; @@ -84,10 +87,11 @@ export namespace vk { } //! @return physical device memory requirements - [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() const { + [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() + const { VkPhysicalDeviceMemoryProperties physical_memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_device, - &physical_memory_properties); + vkGetPhysicalDeviceMemoryProperties( + m_physical_device, &physical_memory_properties); return physical_memory_properties; } @@ -95,11 +99,10 @@ export namespace vk { operator VkPhysicalDevice() const { return m_physical_device; } - private: VkPhysicalDevice enumerate_physical_devices( - const VkInstance& p_instance, - const physical_gpu& p_physical_device_type) { + const VkInstance& p_instance, + const physical_gpu& p_physical_device_type) { uint32_t device_count = 0; vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); @@ -107,11 +110,11 @@ export namespace vk { return nullptr; } - - // TODO: Turn this into map + // TODO: Turn this into map std::vector physical_devices(device_count); vkEnumeratePhysicalDevices( - p_instance, &device_count, physical_devices.data()); + p_instance, &device_count, physical_devices.data()); VkPhysicalDevice physical_device = nullptr; for (const auto& device : physical_devices) { @@ -119,12 +122,13 @@ export namespace vk { vkGetPhysicalDeviceProperties(device, &device_properties); if (device_properties.deviceType == - static_cast(p_physical_device_type)) { + static_cast( + p_physical_device_type)) { physical_device = device; } } return physical_device; - } + } private: VkPhysicalDevice m_physical_device = nullptr; diff --git a/vulkan-cpp/pipeline.cppm b/vulkan-cpp/pipeline.cppm index dfecade..ff61146 100644 --- a/vulkan-cpp/pipeline.cppm +++ b/vulkan-cpp/pipeline.cppm @@ -20,7 +20,7 @@ export namespace vk { }; struct viewport_state { - uint8_t viewport_count= 1; + uint8_t viewport_count = 1; uint8_t scissor_count = 1; }; @@ -30,7 +30,7 @@ export namespace vk { polygon_mode polygon_mode = polygon_mode::fill; cull_mode cull_mode = cull_mode::none; front_face front_face = front_face::counter_clockwise; - bool depth_bias_enabled=false; + bool depth_bias_enabled = false; float depth_bias_constant = 0.f; float depth_bias_clamp = 0.f; float depth_bias_slope = 0.f; @@ -38,27 +38,30 @@ export namespace vk { }; struct multisample_state { - sample_bit rasterization_samples=sample_bit::count_1; - bool shading_enabled=false; - float min_shading = 1.f; // optional - std::span p_sample_masks={}; // optional - bool alpha_to_coverage_enable=false; // optional - bool alpha_to_one_enable=false; // optional + sample_bit rasterization_samples = sample_bit::count_1; + bool shading_enabled = false; + float min_shading = 1.f; // optional + std::span p_sample_masks = {}; // optional + bool alpha_to_coverage_enable = false; // optional + bool alpha_to_one_enable = false; // optional }; struct color_blend_attachment_state { bool blend_enabled = true; - blend_factor src_color_blend_factor=blend_factor::src_alpha; - blend_factor dst_color_blend_factor = blend_factor::one_minus_src_alpha; + blend_factor src_color_blend_factor = blend_factor::src_alpha; + blend_factor dst_color_blend_factor = + blend_factor::one_minus_src_alpha; blend_op color_blend_op = blend_op::add; blend_factor src_alpha_blend_factor = blend_factor::one; blend_factor dst_alpha_blend_factor = blend_factor::zero; blend_op alpha_blend_op = blend_op::add; - uint32_t color_write_mask = color_component::red | color_component::green | color_component::blue | color_component::alpha; + uint32_t color_write_mask = + color_component::red | color_component::green | + color_component::blue | color_component::alpha; }; struct color_blend_state { - bool logic_op_enable=false; + bool logic_op_enable = false; logical_op logical_op = logical_op::copy; std::span attachments; std::span blend_constants; @@ -72,27 +75,36 @@ export namespace vk { bool stencil_test_enable = false; }; - /** * @param renderpass is required for a VkPipeline to know up front - * @param shader_modules is a std::span of the loaded shader - * sources for the pipeline to correspond to - * @param descriptor_layouts are the VkDescriptorSetLayout that you pass up - * front to the graphics pipeline if there are any provided - * @param input_assembly is for configuring the state of the input assembly for the graphics pipeline - * @param viewport_state is for configuring state of the viewport for this graphics pipeline - * @param rasterization_state is to configure how the topology and rasterization with this graphics pipeline is configured. - * @param multisample is to configure the graphics pipeline's multisample state - * @param color_blend is configuring the graphics pipeline state for specifying color blending - * @param depth_stencil_enable is used to toggle to use this graphics pipeline with an additional of depth stencil or just the color blend. - * @param depth_stencil is for specifying to this graphics pipeline configuring the depth stencil configurations. - * @param dynamic_states is specifying the dynamic state of the viewport and scissor to configure for this graphics pipeline + * @param shader_modules is a std::span of the loaded + * shader sources for the pipeline to correspond to + * @param descriptor_layouts are the VkDescriptorSetLayout that you pass + * up front to the graphics pipeline if there are any provided + * @param input_assembly is for configuring the state of the input + * assembly for the graphics pipeline + * @param viewport_state is for configuring state of the viewport for + * this graphics pipeline + * @param rasterization_state is to configure how the topology and + * rasterization with this graphics pipeline is configured. + * @param multisample is to configure the graphics pipeline's + * multisample state + * @param color_blend is configuring the graphics pipeline state for + * specifying color blending + * @param depth_stencil_enable is used to toggle to use this graphics + * pipeline with an additional of depth stencil or just the color blend. + * @param depth_stencil is for specifying to this graphics pipeline + * configuring the depth stencil configurations. + * @param dynamic_states is specifying the dynamic state of the viewport + * and scissor to configure for this graphics pipeline */ struct pipeline_params { VkRenderPass renderpass = nullptr; std::span shader_modules{}; - std::span vertex_attributes; - std::span vertex_bind_attributes; + std::span + vertex_attributes; + std::span + vertex_bind_attributes; std::span descriptor_layouts; input_assembly_state input_assembly; @@ -114,85 +126,98 @@ export namespace vk { /** * @brief constructs the graphics pipeline handle - * - * @param p_device is logical device to create the graphics pipeline handles + * + * @param p_device is logical device to create the graphics pipeline + * handles * @param p_info are the parameters for creating the pipelines with - */ - pipeline(const VkDevice& p_device, const pipeline_params& p_info) : m_device(p_device) { + */ + pipeline(const VkDevice& p_device, const pipeline_params& p_info) + : m_device(p_device) { invalidate(p_info); } /** - * @brief explicit API for creating a VkPipeline and VkPipelineLayout - * handle - * + * @brief explicit API for creating a VkPipeline and + * VkPipelineLayout handle + * * Code Usage Example - * + * * ```C++ - * + * * vk::pipeline_params pipeline_params = { * .renderpass = main_renderpass // pass in VkRenderPass handle - * .shader_modules = shader_resource.handles() // sets the std::span - * .vertex_attributes = shader_resource.vertex_attributes(), - * .vertex_bind_attributes = shader_resource.vertex_bind_attributes(), - * .descriptor_layouts = layouts + * .shader_modules = shader_resource.handles() // sets the + * std::span .vertex_attributes = + * shader_resource.vertex_attributes(), .vertex_bind_attributes = + * shader_resource.vertex_bind_attributes(), .descriptor_layouts = + * layouts * }; - * + * * vk::pipeline graphics_pipeline(logical_device, pipeline_params); - * + * * // or when need to invalidate, explicitly call create * graphics_pipeline.create(pipeline_params); - * + * * ``` * - * @param p_info is the parameters required to set the graphics pipeline handles - * - * More info on vulkan's official + * @param p_info is the parameters required to set the graphics + * pipeline handles + * + * More info on vulkan's official * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCreateGraphicsPipelines.html) */ void invalidate(const pipeline_params& p_info) { - std::vector pipeline_shader_stages(p_info.shader_modules.size()); + std::vector + pipeline_shader_stages(p_info.shader_modules.size()); uint32_t shader_src_index = 0; - // 1. Load in and setup the VKShaderModule handlers for VkPipeline + // 1. Load in and setup the VKShaderModule handlers for + // VkPipeline for (const shader_handle& src : p_info.shader_modules) { - VkShaderStageFlags stage = static_cast(src.stage); + VkShaderStageFlags stage = + static_cast(src.stage); pipeline_shader_stages[shader_src_index] = - VkPipelineShaderStageCreateInfo{ - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = (VkShaderStageFlagBits)stage, - .module = src.module, - .pName = "main" - }; + VkPipelineShaderStageCreateInfo{ + .sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = (VkShaderStageFlagBits)stage, + .module = src.module, + .pName = "main" + }; shader_src_index++; } // 2. Setting up the vertex attribute details for VkPipeline - std::span bind_attributes = - p_info.vertex_bind_attributes; + std::span + bind_attributes = p_info.vertex_bind_attributes; std::span attributes = - p_info.vertex_attributes; + p_info.vertex_attributes; VkPipelineVertexInputStateCreateInfo vertex_input_info = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .sType = + VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .vertexBindingDescriptionCount = - static_cast(bind_attributes.size()), + static_cast(bind_attributes.size()), .pVertexBindingDescriptions = bind_attributes.data(), .vertexAttributeDescriptionCount = - static_cast(attributes.size()), + static_cast(attributes.size()), .pVertexAttributeDescriptions = attributes.data() }; VkPipelineInputAssemblyStateCreateInfo input_assembly = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = static_cast(p_info.input_assembly.topology), - .primitiveRestartEnable = p_info.input_assembly.primitive_restart_enable, + .sType = + VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .topology = static_cast( + p_info.input_assembly.topology), + .primitiveRestartEnable = + p_info.input_assembly.primitive_restart_enable, }; VkPipelineViewportStateCreateInfo viewport_state = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .sType = + VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, .viewportCount = p_info.viewport.viewport_count, .scissorCount = p_info.viewport.scissor_count, }; @@ -200,96 +225,146 @@ export namespace vk { // if lineWidth is zero, validation layers will occur // because cant be zero. Must be set to 1.0f VkPipelineRasterizationStateCreateInfo rasterizer_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .depthClampEnable = p_info.rasterization.depth_clamp_enabled, - .rasterizerDiscardEnable = p_info.rasterization.rasterizer_discard_enabled, - .polygonMode = static_cast(p_info.rasterization.polygon_mode), - .cullMode = static_cast(p_info.rasterization.cull_mode), - .frontFace = static_cast(p_info.rasterization.front_face), + .sType = + VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .depthClampEnable = + p_info.rasterization.depth_clamp_enabled, + .rasterizerDiscardEnable = + p_info.rasterization.rasterizer_discard_enabled, + .polygonMode = static_cast( + p_info.rasterization.polygon_mode), + .cullMode = static_cast( + p_info.rasterization.cull_mode), + .frontFace = + static_cast(p_info.rasterization.front_face), .depthBiasEnable = p_info.rasterization.depth_bias_enabled, - .depthBiasConstantFactor = p_info.rasterization.depth_bias_constant, + .depthBiasConstantFactor = + p_info.rasterization.depth_bias_constant, .depthBiasClamp = p_info.rasterization.depth_bias_clamp, - .depthBiasSlopeFactor = p_info.rasterization.depth_bias_slope, + .depthBiasSlopeFactor = + p_info.rasterization.depth_bias_slope, .lineWidth = p_info.rasterization.line_width }; VkPipelineMultisampleStateCreateInfo multisampling_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .rasterizationSamples = static_cast(p_info.multisample.rasterization_samples), + .sType = + VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .rasterizationSamples = static_cast( + p_info.multisample.rasterization_samples), .sampleShadingEnable = p_info.multisample.shading_enabled, .minSampleShading = p_info.multisample.min_shading, .pSampleMask = p_info.multisample.p_sample_masks.data(), - .alphaToCoverageEnable = p_info.multisample.alpha_to_coverage_enable, + .alphaToCoverageEnable = + p_info.multisample.alpha_to_coverage_enable, .alphaToOneEnable = p_info.multisample.alpha_to_one_enable, }; - std::vector color_blend_attachments(p_info.color_blend.attachments.size()); + std::vector + color_blend_attachments( + p_info.color_blend.attachments.size()); - for(size_t i = 0; i < color_blend_attachments.size(); i++) { + for (size_t i = 0; i < color_blend_attachments.size(); i++) { color_blend_attachments[i] = { - .blendEnable = p_info.color_blend.attachments[i].blend_enabled, - .srcColorBlendFactor = static_cast(p_info.color_blend.attachments[i].src_color_blend_factor), // Enabled: alpha blending - .dstColorBlendFactor = static_cast(p_info.color_blend.attachments[i].dst_color_blend_factor), // Enabled: alpha blending - .colorBlendOp = static_cast(p_info.color_blend.attachments[i].color_blend_op), // Enabled: alpha blending - .srcAlphaBlendFactor = static_cast(p_info.color_blend.attachments[i].src_alpha_blend_factor), // Enabled: alpha blending - .dstAlphaBlendFactor = static_cast(p_info.color_blend.attachments[i].dst_alpha_blend_factor), // Enabled: alpha blending - .alphaBlendOp = static_cast(p_info.color_blend.attachments[i].alpha_blend_op), // Enabled: alpha blending - .colorWriteMask = static_cast(p_info.color_blend.attachments[i].color_write_mask), + .blendEnable = + p_info.color_blend.attachments[i].blend_enabled, + .srcColorBlendFactor = static_cast( + p_info.color_blend.attachments[i] + .src_color_blend_factor), // Enabled: alpha blending + .dstColorBlendFactor = static_cast( + p_info.color_blend.attachments[i] + .dst_color_blend_factor), // Enabled: alpha blending + .colorBlendOp = static_cast( + p_info.color_blend.attachments[i] + .color_blend_op), // Enabled: alpha blending + .srcAlphaBlendFactor = static_cast( + p_info.color_blend.attachments[i] + .src_alpha_blend_factor), // Enabled: alpha blending + .dstAlphaBlendFactor = static_cast( + p_info.color_blend.attachments[i] + .dst_alpha_blend_factor), // Enabled: alpha blending + .alphaBlendOp = static_cast( + p_info.color_blend.attachments[i] + .alpha_blend_op), // Enabled: alpha blending + .colorWriteMask = static_cast( + p_info.color_blend.attachments[i].color_write_mask), }; } - VkPipelineColorBlendStateCreateInfo color_blending_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .sType = + VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, .logicOpEnable = p_info.color_blend.logic_op_enable, - .logicOp = static_cast(p_info.color_blend.logical_op), // Optional - .attachmentCount = static_cast(color_blend_attachments.size()), + .logicOp = static_cast( + p_info.color_blend.logical_op), // Optional + .attachmentCount = + static_cast(color_blend_attachments.size()), .pAttachments = color_blend_attachments.data(), // these are optional - .blendConstants = {0.f, 0.f, 0.f, 0.f} // optional -- set to default in being 0.0f's + .blendConstants = { 0.f, 0.f, 0.f, 0.f } + // optional -- set to default in being 0.0f's }; - // Using ranges to load in the floats from an arbitrary array into this. Though it should only be valid to accept only 4 floats rather then N arbitrary floats in this buffer. - if(!p_info.color_blend.blend_constants.empty()) { + // Using ranges to load in the floats from an arbitrary array + // into this. Though it should only be valid to accept only 4 + // floats rather then N arbitrary floats in this buffer. + if (!p_info.color_blend.blend_constants.empty()) { // Get the first 4 elements in the span as those are // the data we are to set the .blendConstants to. - // As .blendConstants only take up to 4 elements in the array. - std::span color_blend_constants = p_info.color_blend.blend_constants.first<4>(); - std::ranges::copy(color_blend_constants.begin(), color_blend_constants.end(), color_blending_ci.blendConstants); + // As .blendConstants only take up to 4 elements in the + // array. + std::span color_blend_constants = + p_info.color_blend.blend_constants.first<4>(); + std::ranges::copy(color_blend_constants.begin(), + color_blend_constants.end(), + color_blending_ci.blendConstants); } - VkPipelineDepthStencilStateCreateInfo pipeline_deth_stencil_state_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .depthTestEnable = p_info.depth_stencil.depth_test_enable, - .depthWriteEnable = p_info.depth_stencil.depth_write_enable, - .depthCompareOp = static_cast(p_info.depth_stencil.depth_compare_op), - .depthBoundsTestEnable = p_info.depth_stencil.depth_bounds_test_enable, - .stencilTestEnable = p_info.depth_stencil.stencil_test_enable, - }; - - //! @note -- pipeline states needs to be baked into the pipeline state + VkPipelineDepthStencilStateCreateInfo + pipeline_deth_stencil_state_ci = { + .sType = + VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .depthTestEnable = p_info.depth_stencil.depth_test_enable, + .depthWriteEnable = + p_info.depth_stencil.depth_write_enable, + .depthCompareOp = static_cast( + p_info.depth_stencil.depth_compare_op), + .depthBoundsTestEnable = + p_info.depth_stencil.depth_bounds_test_enable, + .stencilTestEnable = + p_info.depth_stencil.stencil_test_enable, + }; + + //! @note -- pipeline states needs to be baked into the pipeline + //! state VkPipelineDynamicStateCreateInfo dynamic_state_ci = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - .dynamicStateCount = static_cast(p_info.dynamic_states.size()), - .pDynamicStates = reinterpret_cast(p_info.dynamic_states.data()) + .sType = + VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = + static_cast(p_info.dynamic_states.size()), + .pDynamicStates = reinterpret_cast( + p_info.dynamic_states.data()) }; - // Specifies layout of the uniforms (data resources) to be used by this specified graphics pipeline + // Specifies layout of the uniforms (data resources) to be used + // by this specified graphics pipeline VkPipelineLayoutCreateInfo pipeline_layout_ci = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = static_cast(p_info.descriptor_layouts.size()), + .setLayoutCount = + static_cast(p_info.descriptor_layouts.size()), .pSetLayouts = p_info.descriptor_layouts.data(), }; - vk_check(vkCreatePipelineLayout( - m_device, &pipeline_layout_ci, nullptr, &m_pipeline_layout), - "vkCreatePipelineLayout"); + vk_check( + vkCreatePipelineLayout( + m_device, &pipeline_layout_ci, nullptr, &m_pipeline_layout), + "vkCreatePipelineLayout"); VkGraphicsPipelineCreateInfo graphics_pipeline_ci = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, .flags = 0, - .stageCount = static_cast(pipeline_shader_stages.size()), + .stageCount = + static_cast(pipeline_shader_stages.size()), .pStages = pipeline_shader_stages.data(), .pVertexInputState = &vertex_input_info, .pInputAssemblyState = &input_assembly, @@ -298,7 +373,9 @@ export namespace vk { .pMultisampleState = &multisampling_ci, .pDepthStencilState = &pipeline_deth_stencil_state_ci, .pColorBlendState = &color_blending_ci, - .pDynamicState = (p_info.depth_stencil_enabled) ? &dynamic_state_ci : nullptr, + .pDynamicState = (p_info.depth_stencil_enabled) + ? &dynamic_state_ci + : nullptr, .layout = m_pipeline_layout, .renderPass = p_info.renderpass, .subpass = 0, @@ -306,10 +383,13 @@ export namespace vk { .basePipelineIndex = -1 }; - vk::vk_check( - vkCreateGraphicsPipelines( - m_device, nullptr, 1, &graphics_pipeline_ci, nullptr, &m_pipeline), - "vkCreateGraphicsPipelines"); + vk::vk_check(vkCreateGraphicsPipelines(m_device, + nullptr, + 1, + &graphics_pipeline_ci, + nullptr, + &m_pipeline), + "vkCreateGraphicsPipelines"); } /** @@ -322,40 +402,48 @@ export namespace vk { * * ```C++ * - * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_params is specified*); + * vk::pipeline graphics_pipeline(logical_device, *assume + * pipeline_params is specified*); * * // bound to current command buffer - * // in this example we set binding point to VK_PIPELINE_BIND_POINT_GRAPHICS + * // in this example we set binding point to + * VK_PIPELINE_BIND_POINT_GRAPHICS * graphics_pipeline.bind(current_command, * pipeline_bind_point::graphics); * ``` * - * @param p_command is the current command buffer the graphics pipeline - * is bound to - * @param p_bind_point is the specified bind point graphics pipeline is - * bound to. - * - * More info on vulkan's official + * @param p_command is the current command buffer the graphics + * pipeline is bound to + * @param p_bind_point is the specified bind point graphics pipeline + * is bound to. + * + * More info on vulkan's official * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdBindPipeline.html) */ - void bind(const VkCommandBuffer& p_command, pipeline_bind_point p_bind_point = pipeline_bind_point::graphics) { - vkCmdBindPipeline(p_command, static_cast(p_bind_point), m_pipeline); + void bind(const VkCommandBuffer& p_command, + pipeline_bind_point p_bind_point = + pipeline_bind_point::graphics) { + vkCmdBindPipeline( + p_command, + static_cast(p_bind_point), + m_pipeline); } /** * @brief Update values of push constants - * + * * Push constants let us send small amount of data with a small * limited size to the shader * - * Push constants only accept up to a max of 128 bytes of push constant - * data + * Push constants only accept up to a max of 128 bytes of push + * constant data * * They allow for sending data to any specified shader stage (both - * vertex and fragment) that are stored within the command buffer itself + * vertex and fragment) that are stored within the command buffer + * itself * - * Using push constants are commonly used when you have chunks of data - * that may be changed every frame. + * Using push constants are commonly used when you have chunks of + * data that may be changed every frame. * * Data that may need to be updated every frame such as camera * projection/view and model matrices. @@ -363,40 +451,47 @@ export namespace vk { * Example Code Usage: * * ```C++ - * - * vk::pipeline graphics_pipeline(logical_device, *assume pipeline_params is specified*); - * + * + * vk::pipeline graphics_pipeline(logical_device, *assume + * pipeline_params is specified*); + * * m_pipeline.push_constants(current, shader_stage::vertex, 0, 1, * &global_data); - * + * * ``` * - * @param p_current current command to push constants directly to the - * shader - * @param p_stage is specifying what stage of the push constants are at - * @param p_offset is specified of the beginning of the offset to start - * from - * @param p_range is the range of bytes of the specified push constant - * data + * @param p_current current command to push constants directly to + * the shader + * @param p_stage is specifying what stage of the push constants are + * at + * @param p_offset is specified of the beginning of the offset to + * start from + * @param p_range is the range of bytes of the specified push + * constant data * @param p_data is the data that is represented into bytes to push * constants * - * More info on vulkan's official + * More info on vulkan's official * [docs](https://docs.vulkan.org/refpages/latest/refpages/source/vkCmdPushConstants.html) */ void push_constant(const VkCommandBuffer& p_current, - shader_stage p_stage, - uint32_t p_offset, - uint32_t p_range, - const void* p_data) { - vkCmdPushConstants(p_current, m_pipeline_layout, static_cast(p_stage), p_offset, p_range, p_data); + shader_stage p_stage, + uint32_t p_offset, + uint32_t p_range, + const void* p_data) { + vkCmdPushConstants(p_current, + m_pipeline_layout, + static_cast(p_stage), + p_offset, + p_range, + p_data); } //! @return true if m_pipeline is valid, false if invalid [[nodiscard]] bool alive() const { return m_pipeline; } - //! @return VkPipelineLayout that has been created with the vk::pipeline - //! handle + //! @return VkPipelineLayout that has been created with the + //! vk::pipeline handle [[nodiscard]] VkPipelineLayout layout() const { return m_pipeline_layout; } @@ -404,15 +499,16 @@ export namespace vk { //! @brief explicit cleanup performed on vk::pipeline void destroy() { if (m_pipeline_layout != nullptr) { - vkDestroyPipelineLayout(m_device, m_pipeline_layout, nullptr); + vkDestroyPipelineLayout( + m_device, m_pipeline_layout, nullptr); } if (m_pipeline != nullptr) { vkDestroyPipeline(m_device, m_pipeline, nullptr); } } - //! @brief allows for treating vk::pipeline as a VkPipeline handle for - //! simple use + //! @brief allows for treating vk::pipeline as a VkPipeline handle + //! for simple use operator VkPipeline() const { return m_pipeline; } operator VkPipeline() { return m_pipeline; } diff --git a/vulkan-cpp/renderpass.cppm b/vulkan-cpp/renderpass.cppm index f9ec230..5bcf6d0 100644 --- a/vulkan-cpp/renderpass.cppm +++ b/vulkan-cpp/renderpass.cppm @@ -19,31 +19,36 @@ export namespace vk { * renderpasses * @param p_renderpass_attachment is a vk::attachment to specify the * individual attachment operation that handle in creating - * VkAttachmentDescription, VkAttachmentReference, and VkSubpassDescription + * VkAttachmentDescription, VkAttachmentReference, and + * VkSubpassDescription * - * @param p_enable_subpass because subpasses are optional, this is a boolean - * to enable if we want to apply subpasses + * @param p_enable_subpass because subpasses are optional, this is a + * boolean to enable if we want to apply subpasses */ class renderpass { public: renderpass() = default; renderpass(const VkDevice& p_device, - std::span p_renderpass_attachments, - bool p_enable_subpasses = true) : m_device(p_device) { + std::span p_renderpass_attachments, + bool p_enable_subpasses = true) + : m_device(p_device) { create(p_renderpass_attachments, p_enable_subpasses); } - void create(std::span p_renderpass_attachments, bool p_enable_subpasses = true) { + void create(std::span p_renderpass_attachments, + bool p_enable_subpasses = true) { // 1. Specifically for setting up the attachment description std::vector attachment_description( - p_renderpass_attachments.size()); + p_renderpass_attachments.size()); // color attachment reference slots to set to help the - // VkAttachmentReference know which color attachment they correspond to + // VkAttachmentReference know which color attachment they + // correspond to std::vector color_attachment_indices; // depth attachment reference slots to set to help the - // VkAttachmentReference know which depth attachment they correspond to + // VkAttachmentReference know which depth attachment they + // correspond to std::vector depth_attachment_indices; for (size_t i = 0; i < attachment_description.size(); i++) { @@ -52,22 +57,28 @@ export namespace vk { .flags = 0, .format = attachment_spec.format, // .samples = VK_SAMPLE_COUNT_1_BIT, - .samples = static_cast(attachment_spec.samples), + .samples = static_cast( + attachment_spec.samples), // .loadOp = to_attachment_load(attachment_spec.load), - .loadOp = static_cast(attachment_spec.load), - // .storeOp = to_attachment_store(attachment_spec.store), - .storeOp = static_cast(attachment_spec.store), - .stencilLoadOp = - static_cast(attachment_spec.stencil_load), - .stencilStoreOp = - static_cast(attachment_spec.stencil_store), - .initialLayout = static_cast(attachment_spec.initial_layout), - .finalLayout = static_cast(attachment_spec.final_layout) + .loadOp = + static_cast(attachment_spec.load), + // .storeOp = + // to_attachment_store(attachment_spec.store), + .storeOp = static_cast( + attachment_spec.store), + .stencilLoadOp = static_cast( + attachment_spec.stencil_load), + .stencilStoreOp = static_cast( + attachment_spec.stencil_store), + .initialLayout = static_cast( + attachment_spec.initial_layout), + .finalLayout = static_cast( + attachment_spec.final_layout) }; // I do a check here to save the slots for specifying the - // VkAttachmentReference Since .attachment is the slot index for - // corresponding which attachment layout is to which + // VkAttachmentReference Since .attachment is the slot index + // for corresponding which attachment layout is to which if (has_depth_specified(attachment_spec.layout)) { depth_attachment_indices.emplace_back(i); } @@ -76,49 +87,56 @@ export namespace vk { } } - // 2. Setting up the color attachment reference to specifying specific - // attachments they correspond to (using the indices) + // 2. Setting up the color attachment reference to specifying + // specific attachments they correspond to (using the indices) std::vector color_attachment_references( - color_attachment_indices.size()); + color_attachment_indices.size()); for (size_t i = 0; i < color_attachment_indices.size(); i++) { uint32_t slot = color_attachment_indices[i]; color_attachment_references[i] = { .attachment = slot, - // .layout = to_image_layout(p_renderpass_attachments[slot].layout) - .layout = static_cast(p_renderpass_attachments[slot].layout) + // .layout = + // to_image_layout(p_renderpass_attachments[slot].layout) + .layout = static_cast( + p_renderpass_attachments[slot].layout) }; } - // 3. Setting up the depth attachment reference to specifying specific - // attachments they correspond to (using the indices) + // 3. Setting up the depth attachment reference to specifying + // specific attachments they correspond to (using the indices) std::vector depth_attachment_references( - depth_attachment_indices.size()); + depth_attachment_indices.size()); for (size_t i = 0; i < depth_attachment_indices.size(); i++) { uint32_t slot = depth_attachment_indices[i]; depth_attachment_references[i] = { .attachment = slot, - // .layout = to_image_layout(p_renderpass_attachments[slot].layout) - .layout = static_cast(p_renderpass_attachments[slot].layout) + // .layout = + // to_image_layout(p_renderpass_attachments[slot].layout) + .layout = static_cast( + p_renderpass_attachments[slot].layout) }; } - // 4. Setting up subpass descriptions that may/may not be applied to - // this renderpass based on the p_enable_subpass is set to true - // TODO: VkSubpassDescription is deprecated in vulkan 1.2+, we should - // change to VkSubpassDescription2 - // TODO: Change from VkRenderPassCreateInfo to VkRenderPassCreateInfo2 - // since they have different parameter modifications + // 4. Setting up subpass descriptions that may/may not be + // applied to this renderpass based on the p_enable_subpass is + // set to true + // TODO: VkSubpassDescription is deprecated in vulkan 1.2+, we + // should change to VkSubpassDescription2 + // TODO: Change from VkRenderPassCreateInfo to + // VkRenderPassCreateInfo2 since they have different parameter + // modifications VkSubpassDescription subpass_description = { .flags = 0, .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .inputAttachmentCount = 0, .pInputAttachments = nullptr, .colorAttachmentCount = - static_cast(color_attachment_references.size()), + static_cast(color_attachment_references.size()), .pColorAttachments = color_attachment_references.data(), .pResolveAttachments = nullptr, - .pDepthStencilAttachment = depth_attachment_references.data(), + .pDepthStencilAttachment = + depth_attachment_references.data(), .preserveAttachmentCount = 0, .pPreserveAttachments = nullptr }; @@ -134,7 +152,7 @@ export namespace vk { .pNext = nullptr, .flags = 0, .attachmentCount = - static_cast(attachment_description.size()), + static_cast(attachment_description.size()), .pAttachments = attachment_description.data(), .subpassCount = static_cast(subpasses.size()), .pSubpasses = subpasses.data(), @@ -142,16 +160,16 @@ export namespace vk { .pDependencies = nullptr }; - vk_check( - vkCreateRenderPass(m_device, &renderpass_ci, nullptr, &m_renderpass), - "vkCreateRenderPass"); + vk_check(vkCreateRenderPass( + m_device, &renderpass_ci, nullptr, &m_renderpass), + "vkCreateRenderPass"); } [[nodiscard]] bool alive() const { return m_renderpass; } void begin(const renderpass_begin_params& p_begin_info) { - // TODO: Move VkViewport and VkScissor to vk::swapchain since these are - // information more closely set by the swapchain + // TODO: Move VkViewport and VkScissor to vk::swapchain since + // these are information more closely set by the swapchain VkViewport viewport = { .x = 0.0f, .y = 0.0f, @@ -165,16 +183,19 @@ export namespace vk { VkRect2D scissor = { .offset = { 0, 0 }, - .extent = { p_begin_info.extent.width, p_begin_info.extent.height }, + .extent = { p_begin_info.extent.width, + p_begin_info.extent.height }, }; vkCmdSetScissor(p_begin_info.current_command, 0, 1, &scissor); // setting color for this specific renderpass - VkClearColorValue renderpass_color = { { p_begin_info.color.at(0), - p_begin_info.color.at(1), - p_begin_info.color.at(2), - p_begin_info.color.at(3) } }; + VkClearColorValue renderpass_color = { + { p_begin_info.color.at(0), + p_begin_info.color.at(1), + p_begin_info.color.at(2), + p_begin_info.color.at(3) } + }; std::array clear_values = {}; clear_values[0].color = renderpass_color; @@ -199,9 +220,10 @@ export namespace vk { .pClearValues = clear_values.data(), }; - vkCmdBeginRenderPass(p_begin_info.current_command, - &renderpass_begin_params, - static_cast(p_begin_info.subpass)); + vkCmdBeginRenderPass( + p_begin_info.current_command, + &renderpass_begin_params, + static_cast(p_begin_info.subpass)); } void end(const VkCommandBuffer& p_current) { diff --git a/vulkan-cpp/sample_image.cppm b/vulkan-cpp/sample_image.cppm index 70f7787..00fee2a 100644 --- a/vulkan-cpp/sample_image.cppm +++ b/vulkan-cpp/sample_image.cppm @@ -12,19 +12,26 @@ export import :utilities; export namespace vk { inline namespace v1 { /** - * We shift 32-bits to the high 32-bits for the old layout and OR the new layout lsb 32-bits additional to the shifted 32-bits - * - * This is to ensure the image layouts do not overlap and can be used to directly jump to set specific image loyouts rather then doing an if-statement originally to check for that - */ - constexpr uint64_t image_layout(VkImageLayout p_old, VkImageLayout p_new) { - // Shift the old_layout into the high 32 bits, and combine with new_layout in the low 32 bits. - return (static_cast(p_old) << 32) | static_cast(p_new); + * We shift 32-bits to the high 32-bits for the old layout and OR the + * new layout lsb 32-bits additional to the shifted 32-bits + * + * This is to ensure the image layouts do not overlap and can be used to + * directly jump to set specific image loyouts rather then doing an + * if-statement originally to check for that + */ + constexpr uint64_t image_layout(VkImageLayout p_old, + VkImageLayout p_new) { + // Shift the old_layout into the high 32 bits, and combine with + // new_layout in the low 32 bits. + return (static_cast(p_old) << 32) | + static_cast(p_new); } class sample_image { public: sample_image() = default; sample_image(const VkDevice& p_device, - const image_params& p_image_properties) : m_device(p_device) { + const image_params& p_image_properties) + : m_device(p_device) { // 1. creating VkImage handle VkImageCreateInfo image_ci = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, @@ -39,7 +46,8 @@ export namespace vk { .arrayLayers = p_image_properties.array_layers, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = static_cast(p_image_properties.usage), + .usage = + static_cast(p_image_properties.usage), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, @@ -47,18 +55,19 @@ export namespace vk { }; vk_check(vkCreateImage(p_device, &image_ci, nullptr, &m_image), - "vkCreateImage"); + "vkCreateImage"); // 2. get image memory requirements from physical device VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(p_device, m_image, &memory_requirements); + vkGetImageMemoryRequirements( + p_device, m_image, &memory_requirements); // uint32_t memory_type_index = // vk::image_memory_requirements(p_image_properties.physical_device, // p_device, m_image); uint32_t memory_index = select_memory_requirements( - p_image_properties.phsyical_memory_properties, - memory_requirements, - p_image_properties.property); + p_image_properties.phsyical_memory_properties, + memory_requirements, + p_image_properties.property); // 4. Allocate info VkMemoryAllocateInfo memory_alloc_info = { @@ -68,13 +77,15 @@ export namespace vk { .memoryTypeIndex = memory_index }; - vk_check(vkAllocateMemory( - p_device, &memory_alloc_info, nullptr, &m_device_memory), - "vkAllocateMemory"); + vk_check( + vkAllocateMemory( + p_device, &memory_alloc_info, nullptr, &m_device_memory), + "vkAllocateMemory"); // 5. bind image memory - vk_check(vkBindImageMemory(p_device, m_image, m_device_memory, 0), - "vkBindImageMemory"); + vk_check( + vkBindImageMemory(p_device, m_image, m_device_memory, 0), + "vkBindImageMemory"); // Needs to create VkImageView after VkImage // because VkImageView expects a VkImage to be binded to a singl @@ -91,18 +102,19 @@ export namespace vk { .g = VK_COMPONENT_SWIZZLE_IDENTITY, .b = VK_COMPONENT_SWIZZLE_IDENTITY, .a = VK_COMPONENT_SWIZZLE_IDENTITY }, - .subresourceRange = { .aspectMask = static_cast( - p_image_properties.aspect), - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = + .subresourceRange = { .aspectMask = + static_cast( + p_image_properties.aspect), + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = p_image_properties.layer_count }, }; - vk_check( - vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), - "vkCreateImage"); + vk_check(vkCreateImageView( + p_device, &image_view_ci, nullptr, &m_image_view), + "vkCreateImage"); // Create VkSampler handler VkSamplerCreateInfo sampler_info = { @@ -112,9 +124,12 @@ export namespace vk { .magFilter = p_image_properties.range.min, .minFilter = p_image_properties.range.max, .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = static_cast(p_image_properties.address_mode_u), - .addressModeV = static_cast(p_image_properties.addrses_mode_v), - .addressModeW = static_cast(p_image_properties.addrses_mode_w), + .addressModeU = static_cast( + p_image_properties.address_mode_u), + .addressModeV = static_cast( + p_image_properties.addrses_mode_v), + .addressModeW = static_cast( + p_image_properties.addrses_mode_w), .mipLodBias = 0.0f, .anisotropyEnable = false, .maxAnisotropy = 1, @@ -126,15 +141,16 @@ export namespace vk { .unnormalizedCoordinates = false }; - vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), - "vkCreateSampler"); + vk_check( + vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + "vkCreateSampler"); } - + sample_image(const VkDevice& p_device, - const VkImage& p_image, - const image_params& p_image_properties) - : m_device(p_device), - m_image(p_image) { + const VkImage& p_image, + const image_params& p_image_properties) + : m_device(p_device) + , m_image(p_image) { // Needs to create VkImageView after VkImage // because VkImageView expects a VkImage to be binded to a singl // VkDeviceMemory beforehand @@ -149,18 +165,20 @@ export namespace vk { .g = VK_COMPONENT_SWIZZLE_IDENTITY, .b = VK_COMPONENT_SWIZZLE_IDENTITY, .a = VK_COMPONENT_SWIZZLE_IDENTITY }, - .subresourceRange = { .aspectMask = static_cast( - p_image_properties.aspect), - .baseMipLevel = 0, - .levelCount = p_image_properties.mip_levels, - .baseArrayLayer = 0, - .layerCount = + .subresourceRange = { .aspectMask = + static_cast( + p_image_properties.aspect), + .baseMipLevel = 0, + .levelCount = + p_image_properties.mip_levels, + .baseArrayLayer = 0, + .layerCount = p_image_properties.layer_count }, }; - vk_check( - vkCreateImageView(p_device, &image_view_ci, nullptr, &m_image_view), - "vkCreateImage"); + vk_check(vkCreateImageView( + p_device, &image_view_ci, nullptr, &m_image_view), + "vkCreateImage"); // Create VkSampler handler VkSamplerCreateInfo sampler_info = { @@ -170,9 +188,12 @@ export namespace vk { .magFilter = p_image_properties.range.min, .minFilter = p_image_properties.range.max, .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = static_cast(p_image_properties.address_mode_u), - .addressModeV = static_cast(p_image_properties.addrses_mode_v), - .addressModeW = static_cast(p_image_properties.addrses_mode_w), + .addressModeU = static_cast( + p_image_properties.address_mode_u), + .addressModeV = static_cast( + p_image_properties.addrses_mode_v), + .addressModeW = static_cast( + p_image_properties.addrses_mode_w), .mipLodBias = 0.0f, .anisotropyEnable = false, .maxAnisotropy = 1, @@ -184,43 +205,55 @@ export namespace vk { .unnormalizedCoordinates = false }; - vk_check(vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), - "vkCreateSampler"); + vk_check( + vkCreateSampler(p_device, &sampler_info, nullptr, &m_sampler), + "vkCreateSampler"); m_only_destroy_image_view = true; } [[nodiscard]] VkSampler sampler() const { return m_sampler; } - [[nodiscard]] VkImageView image_view() const { return m_image_view; } - + [[nodiscard]] VkImageView image_view() const { + return m_image_view; + } /** - * @brief performs vkCmdPipelineBarrier to handle transitioning image layouts - * - * @param p_command is the current command buffer to record the image layout transition - * @param p_format is the image format to make sure if there is a depth format available then request the aspect mask to include the stencil bit + * @brief performs vkCmdPipelineBarrier to handle transitioning + * image layouts + * + * @param p_command is the current command buffer to record the + * image layout transition + * @param p_format is the image format to make sure if there is a + * depth format available then request the aspect mask to include + * the stencil bit * @param p_old is the source image layout transition from * @param p_new is the destination image layout transition to. - * - * + * + * * ```C++ - * + * * sample_image texture_image(logical_device, ...); - * - * - * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - * + * + * + * texture_image.memory_barrier(temp_command, some_vk_format, + * VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + * * // do some operation during this transition image layout * // such as copying from an buffer data to an image * // staging_buffer.copy_to_image(...); - * - * texture_image.memory_barrier(temp_command, some_vk_format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - * + * + * texture_image.memory_barrier(temp_command, some_vk_format, + * VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + * * ``` - * - */ - void memory_barrier(const VkCommandBuffer& p_command, VkFormat p_format, VkImageLayout p_old, VkImageLayout p_new) { + * + */ + void memory_barrier(const VkCommandBuffer& p_command, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new) { /* VkImageMemoryBarrier image_memory_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, @@ -232,9 +265,8 @@ export namespace vk { .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = m_image, - .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, + .subresourceRange = { .aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, .baseArrayLayer = 0, .layerCount = 1 } }; @@ -265,7 +297,8 @@ export namespace vk { if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; @@ -273,7 +306,8 @@ export namespace vk { else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && p_new == VK_IMAGE_LAYOUT_GENERAL) { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; @@ -282,29 +316,32 @@ export namespace vk { if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; } // Convert back from read-only to updateable else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && p_new == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; image_memory_barrier.dstAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; } // Convert from updateable texture to shader read-only else if (p_old == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.srcAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; image_memory_barrier.dstAccessMask + = VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert depth texture from undefined state to depth-stencil buffer - else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && - p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + } // Convert depth texture from undefined state to depth-stencil + buffer else if (p_old == VK_IMAGE_LAYOUT_UNDEFINED && p_new == + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { image_memory_barrier.srcAccessMask = 0; image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | @@ -321,13 +358,14 @@ export namespace vk { source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dst_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert back from read-only to color attachment - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = + source_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dst_stages = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; } // Convert back from + read-only to color attachment else if (p_old == + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && p_new == + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; @@ -337,25 +375,29 @@ export namespace vk { p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - } // Convert back from read-only to depth attachment - else if (p_old == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + + source_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dst_stages = + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; } // Convert back from + read-only to depth attachment else if (p_old == + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL && p_new == + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } // Convert from updateable depth texture to shader read-only - else if (p_old == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && - p_new == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + else if (p_old == + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL && p_new == + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { image_memory_barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; @@ -372,7 +414,8 @@ export namespace vk { 1, &image_memory_barrier); */ - // 1. Image Memory Barrier Initialization (using C++ Designated Initializers - C++20) + // 1. Image Memory Barrier Initialization (using C++ Designated + // Initializers - C++20) VkImageMemoryBarrier image_memory_barrier = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, @@ -383,134 +426,195 @@ export namespace vk { .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .image = m_image, - .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1 } + .subresourceRange = { .aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1 } }; VkPipelineStageFlags source_stage = VK_PIPELINE_STAGE_NONE; VkPipelineStageFlags dst_stages = VK_PIPELINE_STAGE_NONE; - // 2. Aspect Mask Logic (Keep as if/else, but use helper function) - if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || has_stencil_attachment(p_format)) { - - image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + // 2. Aspect Mask Logic (Keep as if/else, but use helper + // function) + if (p_new == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL || + has_stencil_attachment(p_format)) { - // Assuming has_stencil_attachment(p_format) is defined elsewhere - // works as the same as the if-statement, leaving it here for testing purposes - // image_memory_barrier.subresourceRange.aspectMask |= has_stencil_attachment(p_format) ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; + image_memory_barrier.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_DEPTH_BIT; + + // Assuming has_stencil_attachment(p_format) is defined + // elsewhere works as the same as the if-statement, leaving + // it here for testing purposes + // image_memory_barrier.subresourceRange.aspectMask |= + // has_stencil_attachment(p_format) ? + // VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; if (has_stencil_attachment(p_format)) { - image_memory_barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + image_memory_barrier.subresourceRange.aspectMask |= + VK_IMAGE_ASPECT_STENCIL_BIT; } } else { - image_memory_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + image_memory_barrier.subresourceRange.aspectMask = + VK_IMAGE_ASPECT_COLOR_BIT; } // 3. Main Transition Logic using Combined Switch const uint64_t current_layout = image_layout(p_old, p_new); switch (current_layout) { - + // UNDEFINED -> SHADER_READ_ONLY_OPTIMAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + case image_layout( + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } // UNDEFINED -> GENERAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL): { + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_GENERAL): { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } // UNDEFINED -> TRANSFER_DST_OPTIMAL - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { + case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; } - - // SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL (Convert back from read-only to transferr) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + // SHADER_READ_ONLY_OPTIMAL -> TRANSFER_DST_OPTIMAL (Convert + // back from read-only to transferr) + case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; } - // TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable texture to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + // TRANSFER_DST_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert + // from updateable texture to shader read-only) + case image_layout( + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_TRANSFER_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } - // UNDEFINED -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert depth texture from undefined state) - case image_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { + // UNDEFINED -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert + // depth texture from undefined state) + case image_layout( + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; dst_stages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; break; } - // SHADER_READ_ONLY_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Wait for render pass to complete - Note: This case is unusual but kept as per your original logic) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - // Note: Your original code had conflicting re-assignments for source_stage/dst_stages here. - // The last pair of assignments is used. - image_memory_barrier.srcAccessMask = 0; + // SHADER_READ_ONLY_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL + // (Wait for render pass to complete - Note: This case is + // unusual but kept as per your original logic) + case image_layout( + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + // Note: Your original code had conflicting + // re-assignments for source_stage/dst_stages here. The + // last pair of assignments is used. + image_memory_barrier.srcAccessMask = 0; image_memory_barrier.dstAccessMask = 0; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + source_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } - - // SHADER_READ_ONLY_OPTIMAL -> COLOR_ATTACHMENT_OPTIMAL (Convert back from read-only to color attachment) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + // SHADER_READ_ONLY_OPTIMAL -> COLOR_ATTACHMENT_OPTIMAL + // (Convert back from read-only to color attachment) + case image_layout( + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - dst_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dst_stages = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break; } - - // COLOR_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable color to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + + // COLOR_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL + // (Convert from updateable color to shader read-only) + case image_layout( + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + source_stage = + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } - // SHADER_READ_ONLY_OPTIMAL -> DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert back from read-only to depth attachment) - case image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + // SHADER_READ_ONLY_OPTIMAL -> + // DEPTH_STENCIL_ATTACHMENT_OPTIMAL (Convert back from + // read-only to depth attachment) + case image_layout( + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_SHADER_READ_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; source_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; dst_stages = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break; } - // DEPTH_STENCIL_ATTACHMENT_OPTIMAL -> SHADER_READ_ONLY_OPTIMAL (Convert from updateable depth texture to shader read-only) - case image_layout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { - image_memory_barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - source_stage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + // DEPTH_STENCIL_ATTACHMENT_OPTIMAL -> + // SHADER_READ_ONLY_OPTIMAL (Convert from updateable depth + // texture to shader read-only) + case image_layout( + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL): { + image_memory_barrier.srcAccessMask = + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + image_memory_barrier.dstAccessMask = + VK_ACCESS_SHADER_READ_BIT; + source_stage = + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; dst_stages = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break; } @@ -520,15 +624,17 @@ export namespace vk { break; } } - - vkCmdPipelineBarrier( - p_command, - source_stage, - dst_stages, - 0, // dependencyFlags - 0, nullptr, - 0, nullptr, - 1, &image_memory_barrier); + + vkCmdPipelineBarrier(p_command, + source_stage, + dst_stages, + 0, // dependencyFlags + 0, + nullptr, + 0, + nullptr, + 1, + &image_memory_barrier); } void destroy() { diff --git a/vulkan-cpp/shader_resource.cppm b/vulkan-cpp/shader_resource.cppm index fe3a2d3..18e204f 100644 --- a/vulkan-cpp/shader_resource.cppm +++ b/vulkan-cpp/shader_resource.cppm @@ -17,8 +17,8 @@ export namespace vk { /** * @param sources holds data the shader source and stage the source it * corresponds to. - * @param vertex_attributes are the vertex attributes that are used to setup - * vulkan vertex attributes and the binding attributes. + * @param vertex_attributes are the vertex attributes that are used to + * setup vulkan vertex attributes and the binding attributes. */ struct shader_resource_info { std::span sources{}; @@ -32,7 +32,8 @@ export namespace vk { * Every graphics pipeline as an associated group of shader sources with * their own specific shader stages they are apart of. * - * @param p_device is the logical device for creating the vulkan handlers + * @param p_device is the logical device for creating the vulkan + * handlers * @param p_info is the shader_resource properties for providing shader * sources to load and what vertex attributes to return from this shader * resource @@ -41,12 +42,15 @@ export namespace vk { class shader_resource { public: shader_resource() = default; - shader_resource(const VkDevice& p_device, const shader_resource_info& p_info) : m_device(p_device) { + shader_resource(const VkDevice& p_device, + const shader_resource_info& p_info) + : m_device(p_device) { m_shader_module_handlers.resize(p_info.sources.size()); for (size_t i = 0; i < p_info.sources.size(); i++) { const shader_source shader_src = p_info.sources[i]; - std::vector blob = compile_binary_shader_source(shader_src); + std::vector blob = + compile_binary_shader_source(shader_src); if (blob.empty()) { m_is_resource_valid = false; @@ -63,11 +67,12 @@ export namespace vk { // Setting m_shader_module_handlers[i]'s stage and the // VkShaderModule handle altogether - vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_shader_module_handlers[i].module), - "vkCreateShaderModule"); + vk_check( + vkCreateShaderModule(m_device, + &shader_module_ci, + nullptr, + &m_shader_module_handlers[i].module), + "vkCreateShaderModule"); m_shader_module_handlers[i].stage = shader_src.stage; } @@ -76,10 +81,12 @@ export namespace vk { [[nodiscard]] bool is_valid() const { return m_is_resource_valid; } - void vertex_attributes(std::span p_attributes) { + void vertex_attributes( + std::span p_attributes) { m_vertex_binding_attributes.resize(p_attributes.size()); - for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { + for (size_t i = 0; i < m_vertex_binding_attributes.size(); + i++) { // setting up vertex binding const vertex_attribute attribute = p_attributes[i]; m_vertex_attributes.resize(attribute.entries.size()); @@ -89,9 +96,11 @@ export namespace vk { .inputRate = to_input_rate(attribute.input_rate), }; - // then setting up the vertex attributes for the vertex data layouts + // then setting up the vertex attributes for the vertex data + // layouts for (size_t j = 0; j < attribute.entries.size(); j++) { - const vertex_attribute_entry entry = attribute.entries[j]; + const vertex_attribute_entry entry = + attribute.entries[j]; m_vertex_attributes[j] = { .location = entry.location, .binding = attribute.binding, @@ -102,8 +111,8 @@ export namespace vk { } } - //! @return the handlers of vulkan shader modules for each individual - //! shader source loaded altogether + //! @return the handlers of vulkan shader modules for each + //! individual shader source loaded altogether [[nodiscard]] std::span handles() const { return m_shader_module_handlers; } @@ -146,12 +155,14 @@ export namespace vk { return out_buffer; } - //! @brief Ensure file reads are valid before reading raw .spv binaries + //! @brief Ensure file reads are valid before reading raw .spv + //! binaries std::vector compile_binary_shader_source( - const shader_source& p_shader_source) { + const shader_source& p_shader_source) { std::vector binary_blob{}; - if (std::filesystem::is_regular_file(p_shader_source.filename)) { + if (std::filesystem::is_regular_file( + p_shader_source.filename)) { binary_blob = read(p_shader_source.filename); } @@ -163,7 +174,7 @@ export namespace vk { bool m_is_resource_valid = false; std::vector m_vertex_attributes; std::vector - m_vertex_binding_attributes; + m_vertex_binding_attributes; std::vector m_shader_module_handlers; }; }; diff --git a/vulkan-cpp/surface.cppm b/vulkan-cpp/surface.cppm index ad55854..963170e 100644 --- a/vulkan-cpp/surface.cppm +++ b/vulkan-cpp/surface.cppm @@ -14,7 +14,6 @@ module; export module vk:surface; - export import :types; export import :utilities; export import :instance; @@ -24,8 +23,12 @@ export namespace vk { class surface { public: - surface(const VkInstance& p_instance, GLFWwindow* p_window_handle) : m_instance(p_instance) { - vk_check(glfwCreateWindowSurface( m_instance, p_window_handle, nullptr, &m_surface_handler), "glfwCreateWindowSurface"); + surface(const VkInstance& p_instance, GLFWwindow* p_window_handle) + : m_instance(p_instance) { + vk_check( + glfwCreateWindowSurface( + m_instance, p_window_handle, nullptr, &m_surface_handler), + "glfwCreateWindowSurface"); } [[nodiscard]] bool alive() const { return m_surface_handler; } diff --git a/vulkan-cpp/swapchain.cppm b/vulkan-cpp/swapchain.cppm index 0401ad0..e52978e 100644 --- a/vulkan-cpp/swapchain.cppm +++ b/vulkan-cpp/swapchain.cppm @@ -16,10 +16,14 @@ export namespace vk { class swapchain { public: swapchain(const VkDevice& p_device, - const VkSurfaceKHR& p_surface, - const swapchain_params& p_settings, - const surface_params& p_surface_properties) : m_device(p_device), m_surface_handler(p_surface), m_surface_params(p_surface_properties) { - m_image_size = surface_image_size(m_surface_params.capabilities); + const VkSurfaceKHR& p_surface, + const swapchain_params& p_settings, + const surface_params& p_surface_properties) + : m_device(p_device) + , m_surface_handler(p_surface) + , m_surface_params(p_surface_properties) { + m_image_size = + surface_image_size(m_surface_params.capabilities); std::println("Surface Image Size = {}", m_image_size); @@ -33,46 +37,51 @@ export namespace vk { .minImageCount = m_image_size, .imageFormat = m_surface_params.format.format, .imageColorSpace = m_surface_params.format.colorSpace, - // use physical device surface formats to getting the right formats - // in vulkan + // use physical device surface formats to getting the right + // formats in vulkan .imageExtent = m_surface_params.capabilities.currentExtent, .imageArrayLayers = 1, .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT), + VK_IMAGE_USAGE_TRANSFER_DST_BIT), .queueFamilyIndexCount = 1, .pQueueFamilyIndices = &p_settings.present_index, - .preTransform = m_surface_params.capabilities.currentTransform, + .preTransform = + m_surface_params.capabilities.currentTransform, .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = static_cast(p_settings.present_mode), + .presentMode = + static_cast(p_settings.present_mode), .clipped = p_settings.clipped, }; - vk_check(vkCreateSwapchainKHR( - m_device, &swapchain_ci, nullptr, &m_swapchain_handler), - "vkCreateSwapchainKHR"); + vk_check( + vkCreateSwapchainKHR( + m_device, &swapchain_ci, nullptr, &m_swapchain_handler), + "vkCreateSwapchainKHR"); } - /** * @brief gets the presentable images from this associated swapchain - * - * @return std::span which are the presentable available images that can be presented to the swapchain - * + * + * @return std::span which are the presentable + * available images that can be presented to the swapchain + * * ```C++ - * + * * vk::swapchain main_swapchain(logical_device, ...); - * + * * std::span images = main_swapchain.get_images(); - * + * * ``` - * - */ + * + */ std::span get_images() { - uint32_t image_count=0; - vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, nullptr); + uint32_t image_count = 0; + vkGetSwapchainImagesKHR( + m_device, m_swapchain_handler, &image_count, nullptr); m_images.resize(image_count); - vkGetSwapchainImagesKHR(m_device, m_swapchain_handler, &image_count, m_images.data()); + vkGetSwapchainImagesKHR( + m_device, m_swapchain_handler, &image_count, m_images.data()); return m_images; } diff --git a/vulkan-cpp/texture.cppm b/vulkan-cpp/texture.cppm index a5f2fa5..cfabdea 100644 --- a/vulkan-cpp/texture.cppm +++ b/vulkan-cpp/texture.cppm @@ -12,7 +12,6 @@ module; export module vk:texture; - export import :types; export import :utilities; export import :buffer_streams; @@ -21,7 +20,10 @@ export import :command_buffer; export namespace vk { inline namespace v1 { - sample_image create_texture_with_data(const VkDevice& p_device, const image_params& p_config, const void* p_data) { + + sample_image create_texture_with_data(const VkDevice& p_device, + const image_params& p_config, + std::span p_data) { // 1. Creating temporary command buffer for texture command_params copy_command_params = { .levels = command_levels::primary, @@ -29,91 +31,60 @@ export namespace vk { .flags = command_pool_flags::reset, }; command_buffer temp_command_buffer = - command_buffer(p_device, copy_command_params); + command_buffer(p_device, copy_command_params); // 2. loading texture - sample_image texture_image = sample_image(p_device, p_config); - int bytes_per_pixel = bytes_per_texture_format(p_config.format); - // 3. getting layer size - uint32_t layer_size_with_bytes = - p_config.extent.width * p_config.extent.height * bytes_per_pixel; - uint32_t layer_count = 1; - uint32_t image_size = layer_size_with_bytes * layer_count; - - // 4. transfer data from staging buffer - uint32_t property_flag = - memory_property::host_visible_bit | memory_property::host_cached_bit; - // buffer_configuration staging_buffer_config = { - // .device_size = (uint32_t)image_size, - // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - // .property_flags = (memory_property)property_flag, - // .physical = p_config.physical_device - // }; + // 3. transfer data from staging buffer + uint32_t property_flag = memory_property::host_visible_bit | + memory_property::host_cached_bit; buffer_parameters staging_buffer_config = { - .device_size = (uint32_t)image_size, - .physical_memory_properties = p_config.phsyical_memory_properties, - .property_flags = (memory_property)property_flag, + .physical_memory_properties = + p_config.phsyical_memory_properties, + .property_flags = static_cast(property_flag), .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - // .physical = p_config.physical_device }; + buffer_stream staging( + p_device, p_data.size(), staging_buffer_config); - // buffer_handle staging_buffer = create_buffer(p_device, - // staging_buffer_config); - buffer_stream staging(p_device, staging_buffer_config); - - // 5. write data to the staging buffer with specific size specified - // write(p_device, staging, p_data, image_size); - staging.write(p_data, image_size); + // 4. write data to the staging buffer with specific size specified + staging.transfer(p_data); - // 6. start recording to this command buffer + // 5. start recording to this command buffer VkImageLayout old_layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; VkFormat texture_format = p_config.format; temp_command_buffer.begin(command_usage::one_time_submit); - // 6.1 -- transition image layout - // image_memory_barrier(temp_command_buffer, - // texture_image, - // texture_format, - // old_layout, - // new_layout); - texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); - - // 6.2 -- copy buffer to image handles - // copy(temp_command_buffer, - // texture_image, - // staging, - // p_config.extent.width, - // p_config.extent.height); - staging.copy_to_image(temp_command_buffer, texture_image, p_config.extent); - - // 6.3 -- transition image layout back to the layout specification + // 6. transition image layout + // Ensure that we are transferring our image data and correcting the + // format to ensure we do not lose any data in the process + texture_image.memory_barrier( + temp_command_buffer, texture_format, old_layout, new_layout); + staging.copy_to_image( + temp_command_buffer, texture_image, p_config.extent); old_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; new_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - // image_memory_barrier(temp_command_buffer, - // texture_image, - // texture_format, - // old_layout, - // new_layout); - texture_image.memory_barrier(temp_command_buffer, texture_format, old_layout, new_layout); + texture_image.memory_barrier( + temp_command_buffer, texture_format, old_layout, new_layout); temp_command_buffer.end(); - // 7. Create temporary graphics queue to offload the texture image into - // GPU memory - //! TODO: Do this better then just retrieving graphics queue 0 + // 8. Getting graphics queue to store the texture data for GPU + // access + // TODO: Extend vk::device_queue to enable perform command + // submission to the GPU uint32_t queue_family_index = 0; uint32_t queue_index = 0; VkQueue temp_graphics_queue; vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); + p_device, queue_family_index, queue_index, &temp_graphics_queue); // 8. now submit that texture data to be stored in GPU memory - VkCommandBuffer handle = temp_command_buffer; + const VkCommandBuffer handle = temp_command_buffer; VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = 1, @@ -124,12 +95,12 @@ export namespace vk { vkQueueWaitIdle(temp_graphics_queue); temp_command_buffer.destroy(); - // free_buffer(p_device, staging_buffer); staging.destroy(); return texture_image; } + // TODO: Remove redundant struct and replace with vk::image_params struct texture_info { // for getting image memory requirements for the texture VkPhysicalDeviceMemoryProperties phsyical_memory_properties; @@ -138,63 +109,62 @@ export namespace vk { uint32_t layer_count = 1; }; - struct texture_extent { - uint32_t width=0; - uint32_t height=0; - }; - class texture { public: texture() = default; - - texture(const VkDevice& p_device, const image_extent& p_extent, VkPhysicalDeviceMemoryProperties p_property) : m_device(p_device) { - command_params settings = { - .levels = command_levels::primary, - .queue_index = 0, - .flags = command_pool_flags::reset, - }; + + // TODO: Replace these current parameters to using vk::image_params + // to make the API's consistent. + texture(const VkDevice& p_device, + const image_extent& p_extent, + VkPhysicalDeviceMemoryProperties p_property) + : m_device(p_device) { // 1.) Load in extent dimensions - // Loading in raw white pixels for our texture. - // TODO: Take in a std::span for pixels that will then be - // written to the texture + // White pixels for storing texture. std::array white_color = { 0xFF, 0xFF, 0xFF, 0xFF }; m_width = p_extent.width; m_height = p_extent.height; - // texture_properties properties = { - // .width = m_width, - // .height = m_height, - // .usage = (VkImageUsageFlagBits)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT), - // .property = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - // // .format = VK_FORMAT_R8G8B8A8_UNORM, - // .format = VK_FORMAT_R8G8B8A8_SRGB - // // .format = VK_FORMAT_R64G64B64A64_SFLOAT - // }; image_params config_image = { - .extent = { .width = p_extent.width, .height = p_extent.height }, - .format = VK_FORMAT_R8G8B8A8_UNORM, - .property = memory_property::device_local_bit, - .aspect = image_aspect_flags::color_bit, - // .usage = (VkImageUsageFlags)(VK_IMAGE_USAGE_TRANSFER_DST_BIT | - // VK_IMAGE_USAGE_SAMPLED_BIT), - .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, - // .physical_device = p_texture_info.physical + .extent = p_extent, + // .format = VK_FORMAT_R8G8B8A8_UNORM, + .format = static_cast(format::r8g8b8a8_unorm), + .usage = + image_usage::transfer_dst_bit | image_usage::sampled_bit, .phsyical_memory_properties = p_property }; + int bytes_per_pixel = + bytes_per_texture_format(config_image.format); + + // Ensuring we get pass in the correct image size with bytes per + // pixel + uint32_t layer_size_with_bytes = config_image.extent.width * + config_image.extent.height * + bytes_per_pixel; + uint32_t layer_count = 1; + uint32_t image_size = layer_size_with_bytes * layer_count; + + std::span bytes(white_color.data(), image_size); m_image = - create_texture_with_data(m_device, config_image, white_color.data()); + create_texture_with_data(m_device, config_image, bytes); m_texture_loaded = true; } - texture(const VkDevice& p_device, const texture_info& p_texture_info) : m_device(p_device) { + // TODO: Replace these current parameters to using vk::image_params + // to make the API's consistent. + texture(const VkDevice& p_device, + const std::filesystem::path& p_filename, + const texture_info& p_texture_info) + : m_device(p_device) { // 1. load from file int w, h; int channels; + // TODO: Make passing in the filepath an explicit parameter for + // loading in a texture stbi_uc* image_pixel_data = - stbi_load(p_texture_info.filepath.string().c_str(), + stbi_load(p_filename.string().c_str(), &w, &h, &channels, @@ -212,17 +182,34 @@ export namespace vk { uint32_t property_flag = memory_property::device_local_bit; image_params config_image = { - .extent = { .width = (uint32_t)w, .height = (uint32_t)h }, - .format = VK_FORMAT_R8G8B8A8_UNORM, - .property = (memory_property)property_flag, - .aspect = image_aspect_flags::color_bit, - .usage = image_usage::transfer_dst_bit | image_usage::sampled_bit, + .extent = { .width = static_cast(w), + .height = static_cast(h) }, + // .format = VK_FORMAT_R8G8B8A8_UNORM, + .format = static_cast(format::r8g8b8a8_unorm), + .usage = + image_usage::transfer_dst_bit | image_usage::sampled_bit, .mip_levels = p_texture_info.mip_levels, .layer_count = p_texture_info.layer_count, - .phsyical_memory_properties = p_texture_info.phsyical_memory_properties, + .phsyical_memory_properties = + p_texture_info.phsyical_memory_properties, }; - - m_image = create_texture_with_data(p_device, config_image, image_pixel_data); + int bytes_per_pixel = + bytes_per_texture_format(config_image.format); + + // Ensuring we get pass in the correct image size with bytes per + // pixel + uint32_t layer_size_with_bytes = config_image.extent.width * + config_image.extent.height * + bytes_per_pixel; + uint32_t layer_count = 1; + uint32_t image_size = layer_size_with_bytes * layer_count; + + // Validating the correct amount of data to creating the texture + // with + std::span bytes( + as_bytes(image_pixel_data, image_size)); + m_image = + create_texture_with_data(p_device, config_image, bytes); m_texture_loaded = true; } @@ -235,14 +222,11 @@ export namespace vk { [[nodiscard]] uint32_t height() const { return m_height; } - void destroy() { - m_image.destroy(); - } + void destroy() { m_image.destroy(); } private: VkDevice m_device = nullptr; bool m_texture_loaded = false; - // sampled_image m_image_handle{}; sample_image m_image{}; uint32_t m_width = 0; uint32_t m_height = 0; diff --git a/vulkan-cpp/types.cppm b/vulkan-cpp/types.cppm index 3a1569a..95acac8 100644 --- a/vulkan-cpp/types.cppm +++ b/vulkan-cpp/types.cppm @@ -492,10 +492,14 @@ export namespace vk { * types to select according to your hardware specs * * @param other - device does not match any other available types - * @param integrated - the device is typically embedded in or tightly coupled with the host. - * @param discrete - the device is typically a separate processor connected to the host via an interlink. - * @param virtual - the device is typically a virtual node in a virtualization environment. - * @param type_cpu - the device is typically running on the same processor as the host + * @param integrated - the device is typically embedded in or tightly + * coupled with the host. + * @param discrete - the device is typically a separate processor + * connected to the host via an interlink. + * @param virtual - the device is typically a virtual node in a + * virtualization environment. + * @param type_cpu - the device is typically running on the same + * processor as the host */ enum class physical_gpu : uint8_t { other = VK_PHYSICAL_DEVICE_TYPE_OTHER, @@ -658,8 +662,10 @@ export namespace vk { mailbox_khr = VK_PRESENT_MODE_MAILBOX_KHR, fifo_khr = VK_PRESENT_MODE_FIFO_KHR, fifo_relaxed_khr = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - shared_demand_refresh_khr = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, - shared_continuous_refresh_khr = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR + shared_demand_refresh_khr = + VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, + shared_continuous_refresh_khr = + VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR }; struct swapchain_params { @@ -748,10 +754,14 @@ export namespace vk { triangle_list = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, triangle_strip = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, triangle_fan = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, - line_list_with_adjacent = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, - line_strip_with_adjacent = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, - triangle_list_with_adjacent = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, - triangle_strip_with_adjacent = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, + line_list_with_adjacent = + VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, + line_strip_with_adjacent = + VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, + triangle_list_with_adjacent = + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, + triangle_strip_with_adjacent = + VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, patch_list = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST }; @@ -775,10 +785,10 @@ export namespace vk { }; enum class blend_factor : uint8_t { - zero=VK_BLEND_FACTOR_ZERO, - one=VK_BLEND_FACTOR_ONE, - src_color=VK_BLEND_FACTOR_SRC_COLOR, - one_minus_src_color=VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, + zero = VK_BLEND_FACTOR_ZERO, + one = VK_BLEND_FACTOR_ONE, + src_color = VK_BLEND_FACTOR_SRC_COLOR, + one_minus_src_color = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, dst_color = VK_BLEND_FACTOR_DST_COLOR, one_minus_dst_color = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, src_alpha = VK_BLEND_FACTOR_SRC_ALPHA, @@ -805,84 +815,98 @@ export namespace vk { index_buffer_bit = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, vertex_buffer_bit = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, indirect_buffer_bit = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, - shader_device_address_bit = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + shader_device_address_bit = + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, video_decode_src_bit_khr = VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, video_decode_dst_bit_khr = VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR, - transform_feedback_buffer_bit_ext = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT, - transform_feedback_counter_buffer_bit_ext = VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, - conditoinal_rendering_bit_ext = VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT, - #ifdef VK_ENABLE_BETA_EXTENSIONS - execution_graph_scratch_bit_amdx = VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX, - #endif - acceleration_structure_build_input_read_only_bit_khr = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, - acceleration_structure_storage_bit_khr = VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, - shader_binding_table_bit_khr = VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, + transform_feedback_buffer_bit_ext = + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT, + transform_feedback_counter_buffer_bit_ext = + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, + conditoinal_rendering_bit_ext = + VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT, +#ifdef VK_ENABLE_BETA_EXTENSIONS + execution_graph_scratch_bit_amdx = + VK_BUFFER_USAGE_EXECUTION_GRAPH_SCRATCH_BIT_AMDX, +#endif + acceleration_structure_build_input_read_only_bit_khr = + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR, + acceleration_structure_storage_bit_khr = + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, + shader_binding_table_bit_khr = + VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR, video_encode_dst_bit_khr = VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR, encode_src_bit_khr = VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, - sampler_descriptor_buffer_bit_ext = VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT, - descriptor_buffer_bit_ext = VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, - descriptors_descriptor_buffer_bit_ext = VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT, - micromap_build_input_read_only_bit_ext = VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT, + sampler_descriptor_buffer_bit_ext = + VK_BUFFER_USAGE_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT, + descriptor_buffer_bit_ext = + VK_BUFFER_USAGE_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT, + descriptors_descriptor_buffer_bit_ext = + VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT, + micromap_build_input_read_only_bit_ext = + VK_BUFFER_USAGE_MICROMAP_BUILD_INPUT_READ_ONLY_BIT_EXT, micromap_storage_bit_ext = VK_BUFFER_USAGE_MICROMAP_STORAGE_BIT_EXT, // tile_memory_bit_qcom = VK_BUFFER_USAGE_TILE_MEMORY_BIT_QCOM, ray_tracing_bit_nv = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, - shader_device_address_bit_ext = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT, - shader_device_address_bit_khr = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, + shader_device_address_bit_ext = + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT, + shader_device_address_bit_khr = + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, flags_bit_max_enum = VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM }; enum class blend_op : uint32_t { - add = VK_BLEND_OP_ADD, - subtract = VK_BLEND_OP_SUBTRACT, - reverse_subtract = VK_BLEND_OP_REVERSE_SUBTRACT, - min = VK_BLEND_OP_MIN, - max = VK_BLEND_OP_MAX, - zero_ext = VK_BLEND_OP_ZERO_EXT, - src_ext = VK_BLEND_OP_SRC_EXT, - dst_ext = VK_BLEND_OP_DST_EXT, - src_over_ext = VK_BLEND_OP_SRC_OVER_EXT, - dst_over_ext = VK_BLEND_OP_DST_OVER_EXT, - src_in_ext = VK_BLEND_OP_SRC_IN_EXT, - dst_in_ext = VK_BLEND_OP_DST_IN_EXT, - src_out_ext = VK_BLEND_OP_SRC_OUT_EXT, - dst_out_ext = VK_BLEND_OP_DST_OUT_EXT, - src_atop_ext = VK_BLEND_OP_SRC_ATOP_EXT, - dst_atop_ext = VK_BLEND_OP_DST_ATOP_EXT, - xor_ext = VK_BLEND_OP_XOR_EXT, - multiply_ext = VK_BLEND_OP_MULTIPLY_EXT, - screen_ext = VK_BLEND_OP_SCREEN_EXT, - overlay_ext = VK_BLEND_OP_OVERLAY_EXT, - darken_ext = VK_BLEND_OP_DARKEN_EXT, - lighten_ext = VK_BLEND_OP_LIGHTEN_EXT, - colordodge_ext = VK_BLEND_OP_COLORDODGE_EXT, - colorburn_ext = VK_BLEND_OP_COLORBURN_EXT, - hardlight_ext = VK_BLEND_OP_HARDLIGHT_EXT, - softlight_ext = VK_BLEND_OP_SOFTLIGHT_EXT, - difference_ext = VK_BLEND_OP_DIFFERENCE_EXT, - exclusion_ext = VK_BLEND_OP_EXCLUSION_EXT, - invert_ext = VK_BLEND_OP_INVERT_EXT, - invert_rgb_ext = VK_BLEND_OP_INVERT_RGB_EXT, - lineardodge_ext = VK_BLEND_OP_LINEARDODGE_EXT, - linearburn_ext = VK_BLEND_OP_LINEARBURN_EXT, - vividlight_ext = VK_BLEND_OP_VIVIDLIGHT_EXT, - linearlight_ext = VK_BLEND_OP_LINEARLIGHT_EXT, - pinlight_ext = VK_BLEND_OP_PINLIGHT_EXT, - hardmix_ext = VK_BLEND_OP_HARDMIX_EXT, - hsl_hue_ext = VK_BLEND_OP_HSL_HUE_EXT, - hsl_saturation_ext = VK_BLEND_OP_HSL_SATURATION_EXT, - hsl_color_ext = VK_BLEND_OP_HSL_COLOR_EXT, - hsl_luminosity_ext = VK_BLEND_OP_HSL_LUMINOSITY_EXT, - plus_ext = VK_BLEND_OP_PLUS_EXT, - plus_clamped_ext = VK_BLEND_OP_PLUS_CLAMPED_EXT, + add = VK_BLEND_OP_ADD, + subtract = VK_BLEND_OP_SUBTRACT, + reverse_subtract = VK_BLEND_OP_REVERSE_SUBTRACT, + min = VK_BLEND_OP_MIN, + max = VK_BLEND_OP_MAX, + zero_ext = VK_BLEND_OP_ZERO_EXT, + src_ext = VK_BLEND_OP_SRC_EXT, + dst_ext = VK_BLEND_OP_DST_EXT, + src_over_ext = VK_BLEND_OP_SRC_OVER_EXT, + dst_over_ext = VK_BLEND_OP_DST_OVER_EXT, + src_in_ext = VK_BLEND_OP_SRC_IN_EXT, + dst_in_ext = VK_BLEND_OP_DST_IN_EXT, + src_out_ext = VK_BLEND_OP_SRC_OUT_EXT, + dst_out_ext = VK_BLEND_OP_DST_OUT_EXT, + src_atop_ext = VK_BLEND_OP_SRC_ATOP_EXT, + dst_atop_ext = VK_BLEND_OP_DST_ATOP_EXT, + xor_ext = VK_BLEND_OP_XOR_EXT, + multiply_ext = VK_BLEND_OP_MULTIPLY_EXT, + screen_ext = VK_BLEND_OP_SCREEN_EXT, + overlay_ext = VK_BLEND_OP_OVERLAY_EXT, + darken_ext = VK_BLEND_OP_DARKEN_EXT, + lighten_ext = VK_BLEND_OP_LIGHTEN_EXT, + colordodge_ext = VK_BLEND_OP_COLORDODGE_EXT, + colorburn_ext = VK_BLEND_OP_COLORBURN_EXT, + hardlight_ext = VK_BLEND_OP_HARDLIGHT_EXT, + softlight_ext = VK_BLEND_OP_SOFTLIGHT_EXT, + difference_ext = VK_BLEND_OP_DIFFERENCE_EXT, + exclusion_ext = VK_BLEND_OP_EXCLUSION_EXT, + invert_ext = VK_BLEND_OP_INVERT_EXT, + invert_rgb_ext = VK_BLEND_OP_INVERT_RGB_EXT, + lineardodge_ext = VK_BLEND_OP_LINEARDODGE_EXT, + linearburn_ext = VK_BLEND_OP_LINEARBURN_EXT, + vividlight_ext = VK_BLEND_OP_VIVIDLIGHT_EXT, + linearlight_ext = VK_BLEND_OP_LINEARLIGHT_EXT, + pinlight_ext = VK_BLEND_OP_PINLIGHT_EXT, + hardmix_ext = VK_BLEND_OP_HARDMIX_EXT, + hsl_hue_ext = VK_BLEND_OP_HSL_HUE_EXT, + hsl_saturation_ext = VK_BLEND_OP_HSL_SATURATION_EXT, + hsl_color_ext = VK_BLEND_OP_HSL_COLOR_EXT, + hsl_luminosity_ext = VK_BLEND_OP_HSL_LUMINOSITY_EXT, + plus_ext = VK_BLEND_OP_PLUS_EXT, + plus_clamped_ext = VK_BLEND_OP_PLUS_CLAMPED_EXT, plus_clamped_alpha_ext = VK_BLEND_OP_PLUS_CLAMPED_ALPHA_EXT, - plus_darker_ext = VK_BLEND_OP_PLUS_DARKER_EXT, - minus_ext = VK_BLEND_OP_MINUS_EXT, - minus_clamped_ext = VK_BLEND_OP_MINUS_CLAMPED_EXT, - contrast_ext = VK_BLEND_OP_CONTRAST_EXT, - invert_ovg_ext = VK_BLEND_OP_INVERT_OVG_EXT, - red_ext = VK_BLEND_OP_RED_EXT, - green_ext = VK_BLEND_OP_GREEN_EXT, - blue_ext = VK_BLEND_OP_BLUE_EXT + plus_darker_ext = VK_BLEND_OP_PLUS_DARKER_EXT, + minus_ext = VK_BLEND_OP_MINUS_EXT, + minus_clamped_ext = VK_BLEND_OP_MINUS_CLAMPED_EXT, + contrast_ext = VK_BLEND_OP_CONTRAST_EXT, + invert_ovg_ext = VK_BLEND_OP_INVERT_OVG_EXT, + red_ext = VK_BLEND_OP_RED_EXT, + green_ext = VK_BLEND_OP_GREEN_EXT, + blue_ext = VK_BLEND_OP_BLUE_EXT }; // VkColorComponentFlags @@ -894,109 +918,142 @@ export namespace vk { }; enum class logical_op : uint8_t { - clear = VK_LOGIC_OP_CLEAR, - bit_and = VK_LOGIC_OP_AND, - and_reverse = VK_LOGIC_OP_AND_REVERSE, - copy = VK_LOGIC_OP_COPY, - and_inverted = VK_LOGIC_OP_AND_INVERTED, - no_op = VK_LOGIC_OP_NO_OP, - bit_xor = VK_LOGIC_OP_XOR, - bit_or = VK_LOGIC_OP_OR, - nor = VK_LOGIC_OP_NOR, - equivalent = VK_LOGIC_OP_EQUIVALENT, - invert = VK_LOGIC_OP_INVERT, - or_reverse = VK_LOGIC_OP_OR_REVERSE, - copy_inverted = VK_LOGIC_OP_COPY_INVERTED, - or_inverted = VK_LOGIC_OP_OR_INVERTED, - nand = VK_LOGIC_OP_NAND, - set = VK_LOGIC_OP_SET + clear = VK_LOGIC_OP_CLEAR, + bit_and = VK_LOGIC_OP_AND, + and_reverse = VK_LOGIC_OP_AND_REVERSE, + copy = VK_LOGIC_OP_COPY, + and_inverted = VK_LOGIC_OP_AND_INVERTED, + no_op = VK_LOGIC_OP_NO_OP, + bit_xor = VK_LOGIC_OP_XOR, + bit_or = VK_LOGIC_OP_OR, + nor = VK_LOGIC_OP_NOR, + equivalent = VK_LOGIC_OP_EQUIVALENT, + invert = VK_LOGIC_OP_INVERT, + or_reverse = VK_LOGIC_OP_OR_REVERSE, + copy_inverted = VK_LOGIC_OP_COPY_INVERTED, + or_inverted = VK_LOGIC_OP_OR_INVERTED, + nand = VK_LOGIC_OP_NAND, + set = VK_LOGIC_OP_SET }; enum class compare_op : uint8_t { - never = VK_COMPARE_OP_NEVER, - less = VK_COMPARE_OP_LESS, - equal = VK_COMPARE_OP_EQUAL, - less_or_equal = VK_COMPARE_OP_LESS_OR_EQUAL, - greater = VK_COMPARE_OP_GREATER, - not_equal = VK_COMPARE_OP_NOT_EQUAL, + never = VK_COMPARE_OP_NEVER, + less = VK_COMPARE_OP_LESS, + equal = VK_COMPARE_OP_EQUAL, + less_or_equal = VK_COMPARE_OP_LESS_OR_EQUAL, + greater = VK_COMPARE_OP_GREATER, + not_equal = VK_COMPARE_OP_NOT_EQUAL, greater_or_equal = VK_COMPARE_OP_GREATER_OR_EQUAL, - always = VK_COMPARE_OP_ALWAYS + always = VK_COMPARE_OP_ALWAYS }; - // VkDynamicState + // VkDynamicState enum class dynamic_state : uint32_t { - viewport = VK_DYNAMIC_STATE_VIEWPORT, - scissor = VK_DYNAMIC_STATE_SCISSOR, - line_width = VK_DYNAMIC_STATE_LINE_WIDTH, - depth_bias = VK_DYNAMIC_STATE_DEPTH_BIAS, - blend_constants = VK_DYNAMIC_STATE_BLEND_CONSTANTS, - depth_bounds = VK_DYNAMIC_STATE_DEPTH_BOUNDS, - stencil_compare_mask = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, - stencil_write_mask = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, - stencil_reference = VK_DYNAMIC_STATE_STENCIL_REFERENCE, - cull_mode = VK_DYNAMIC_STATE_CULL_MODE, - front_face = VK_DYNAMIC_STATE_FRONT_FACE, - primitive_topology = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, - viewport_with_count = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, - scissor_with_count = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, - vertex_input_binding_stride = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE, - depth_test_enable = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, - depth_write_enable = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, - depth_compare_op = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, - depth_bounds_test_enable = VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, - stencil_test_enable = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, - stencil_op = VK_DYNAMIC_STATE_STENCIL_OP, - rasterizer_discard_enable = VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, - depth_bias_enable = VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, - primitive_restart_enable = VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, - line_stipple = VK_DYNAMIC_STATE_LINE_STIPPLE, - patch_control_points_ext = VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, - logic_op_ext = VK_DYNAMIC_STATE_LOGIC_OP_EXT, - color_write_enable_ext = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT, - depth_clamp_enable_ext = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, - polygon_mode_ext = VK_DYNAMIC_STATE_POLYGON_MODE_EXT, - rasterization_samples_ext = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT, - sample_mask_ext = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT, - alpha_to_coverage_enable_ext = VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT, - alpha_to_one_enable_ext = VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT, - logic_op_enable_ext = VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT, - color_blend_enable_ext = VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, - color_blend_equation_ext = VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, - color_write_mask_ext = VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, - tessellation_domain_origin_ext = VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT, - rasterization_stream_ext = VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT, - conservative_raster_mode_ext = VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT, - extra_primitive_overestim_ext = VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT, - depth_clip_enable_ext = VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT, - sample_locations_enable_ext = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT, - color_blend_advanced_ext = VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT, - provoking_vertex_mode_ext = VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT, - line_rasterization_mode_ext = VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT, - line_stipple_enable_ext = VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT, - depth_clip_negative_one_ext = VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT, - viewport_w_scaling_nv = VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, - discard_rectangle_ext = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, - discard_rectangle_enable_ext = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT, - discard_rectangle_mode_ext = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT, - sample_locations_ext = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, - ray_tracing_stack_size_khr = VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR, - shading_rate_palette_nv = VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV, - coarse_sample_order_nv = VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV, - exclusive_scissor_enable_nv = VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV, - exclusive_scissor_nv = VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV, - fragment_shading_rate_khr = VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR, - vertex_input_ext = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, - viewport_swizzle_nv = VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV, - coverage_to_color_enable_nv = VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV, - coverage_to_color_location_nv = VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV, - coverage_modulation_mode_nv = VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV, - coverage_modulation_table_en_nv = VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV, - coverage_modulation_table_nv = VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV, - shading_rate_image_enable_nv = VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV, - representative_frag_test_nv = VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV, - coverage_reduction_mode_nv = VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV, - attachment_feedback_loop_ext = VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT, - depth_clamp_range_ext = VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT + viewport = VK_DYNAMIC_STATE_VIEWPORT, + scissor = VK_DYNAMIC_STATE_SCISSOR, + line_width = VK_DYNAMIC_STATE_LINE_WIDTH, + depth_bias = VK_DYNAMIC_STATE_DEPTH_BIAS, + blend_constants = VK_DYNAMIC_STATE_BLEND_CONSTANTS, + depth_bounds = VK_DYNAMIC_STATE_DEPTH_BOUNDS, + stencil_compare_mask = VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, + stencil_write_mask = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, + stencil_reference = VK_DYNAMIC_STATE_STENCIL_REFERENCE, + cull_mode = VK_DYNAMIC_STATE_CULL_MODE, + front_face = VK_DYNAMIC_STATE_FRONT_FACE, + primitive_topology = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, + viewport_with_count = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT, + scissor_with_count = VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, + vertex_input_binding_stride = + VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE, + depth_test_enable = VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, + depth_write_enable = VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE, + depth_compare_op = VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, + depth_bounds_test_enable = + VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, + stencil_test_enable = VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, + stencil_op = VK_DYNAMIC_STATE_STENCIL_OP, + rasterizer_discard_enable = + VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, + depth_bias_enable = VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE, + primitive_restart_enable = + VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE, + line_stipple = VK_DYNAMIC_STATE_LINE_STIPPLE, + patch_control_points_ext = + VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, + logic_op_ext = VK_DYNAMIC_STATE_LOGIC_OP_EXT, + color_write_enable_ext = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT, + depth_clamp_enable_ext = VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT, + polygon_mode_ext = VK_DYNAMIC_STATE_POLYGON_MODE_EXT, + rasterization_samples_ext = + VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT, + sample_mask_ext = VK_DYNAMIC_STATE_SAMPLE_MASK_EXT, + alpha_to_coverage_enable_ext = + VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT, + alpha_to_one_enable_ext = VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT, + logic_op_enable_ext = VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT, + color_blend_enable_ext = VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT, + color_blend_equation_ext = + VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, + color_write_mask_ext = VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT, + tessellation_domain_origin_ext = + VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT, + rasterization_stream_ext = + VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT, + conservative_raster_mode_ext = + VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT, + extra_primitive_overestim_ext = + VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT, + depth_clip_enable_ext = VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT, + sample_locations_enable_ext = + VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT, + color_blend_advanced_ext = + VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT, + provoking_vertex_mode_ext = + VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT, + line_rasterization_mode_ext = + VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT, + line_stipple_enable_ext = VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT, + depth_clip_negative_one_ext = + VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT, + viewport_w_scaling_nv = VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, + discard_rectangle_ext = VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, + discard_rectangle_enable_ext = + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT, + discard_rectangle_mode_ext = + VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT, + sample_locations_ext = VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, + ray_tracing_stack_size_khr = + VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR, + shading_rate_palette_nv = + VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV, + coarse_sample_order_nv = + VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV, + exclusive_scissor_enable_nv = + VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV, + exclusive_scissor_nv = VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV, + fragment_shading_rate_khr = + VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR, + vertex_input_ext = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, + viewport_swizzle_nv = VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV, + coverage_to_color_enable_nv = + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV, + coverage_to_color_location_nv = + VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV, + coverage_modulation_mode_nv = + VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV, + coverage_modulation_table_en_nv = + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV, + coverage_modulation_table_nv = + VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV, + shading_rate_image_enable_nv = + VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV, + representative_frag_test_nv = + VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV, + coverage_reduction_mode_nv = + VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV, + attachment_feedback_loop_ext = + VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT, + depth_clamp_range_ext = VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT }; enum buffer : uint8_t { @@ -1404,7 +1461,6 @@ export namespace vk { struct vertex_params { VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - std::span vertices; std::string debug_name; PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; @@ -1412,16 +1468,13 @@ export namespace vk { struct index_params { VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - std::span indices; std::string debug_name; PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; }; struct uniform_params { - // VkPhysicalDevice physical_handle=nullptr; VkPhysicalDeviceMemoryProperties phsyical_memory_properties; - uint32_t size_bytes = 0; std::string debug_name; PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr; @@ -1467,11 +1520,10 @@ export namespace vk { }; struct image_params { - image_extent extent; - VkFormat format; + image_extent extent{}; + VkFormat format = VK_FORMAT_UNDEFINED; memory_property property = memory_property::device_local_bit; image_aspect_flags aspect = image_aspect_flags::color_bit; - // VkImageUsageFlags usage; uint32_t usage; VkImageCreateFlags image_flags = 0; VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; @@ -1483,18 +1535,12 @@ export namespace vk { .min = VK_FILTER_LINEAR, .max = VK_FILTER_LINEAR, }; - // VkSamplerAddressMode address_mode_u = - // VK_SAMPLER_ADDRESS_MODE_REPEAT; VkSamplerAddressMode - // addrses_mode_v = VK_SAMPLER_ADDRESS_MODE_REPEAT; - // VkSamplerAddressMode addrses_mode_w = - // VK_SAMPLER_ADDRESS_MODE_REPEAT; uint32_t address_mode_u = sampler_address_mode::repeat; uint32_t addrses_mode_v = sampler_address_mode::repeat; uint32_t addrses_mode_w = sampler_address_mode::repeat; }; struct buffer_parameters { - VkDeviceSize device_size = 0; VkPhysicalDeviceMemoryProperties physical_memory_properties; memory_property property_flags; VkBufferUsageFlags usage; diff --git a/vulkan-cpp/uniform_buffer.cppm b/vulkan-cpp/uniform_buffer.cppm index c266b65..a276c7f 100644 --- a/vulkan-cpp/uniform_buffer.cppm +++ b/vulkan-cpp/uniform_buffer.cppm @@ -3,10 +3,10 @@ module; #include #include #include +#include export module vk:uniform_buffer; - export import :types; export import :utilities; export import :command_buffer; @@ -23,40 +23,47 @@ export namespace vk { public: uniform_buffer() = default; uniform_buffer(const VkDevice& p_device, - const uniform_params& p_uniform_info) : m_device(p_device), m_size_bytes(p_uniform_info.size_bytes) { - - uint32_t property_flags = memory_property::host_visible_bit | - memory_property::host_coherent_bit; + uint64_t p_size_bytes, + const uniform_params& p_uniform_info) + : m_device(p_device) + , m_size_bytes(p_size_bytes) { buffer_parameters uniform_info = { - .device_size = m_size_bytes, .physical_memory_properties = - p_uniform_info.phsyical_memory_properties, - .property_flags = (memory_property)property_flags, + p_uniform_info.phsyical_memory_properties, + // .property_flags = (memory_property)property_flags, + .property_flags = static_cast( + memory_property::host_visible_bit | + memory_property::host_coherent_bit), .usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, .debug_name = p_uniform_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_uniform_info.vkSetDebugUtilsObjectNameEXT + .vkSetDebugUtilsObjectNameEXT = + p_uniform_info.vkSetDebugUtilsObjectNameEXT }; - m_uniform_handle = buffer_stream(m_device, uniform_info); + m_uniform_handle = + buffer_stream(m_device, p_size_bytes, uniform_info); } [[nodiscard]] bool alive() const { return m_uniform_handle; } - void update(const void* p_data) { - m_uniform_handle.write(p_data, m_size_bytes); + template + void transfer(std::span p_uniform_data) { + m_uniform_handle.transfer(p_uniform_data); + } + + void transfer(std::span p_uniforms) { + m_uniform_handle.transfer(p_uniforms); } + [[nodiscard]] uint64_t size_bytes() const { return m_size_bytes; } + operator VkBuffer() const { return m_uniform_handle; } operator VkBuffer() { return m_uniform_handle; } - [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } - - void destroy() { - m_uniform_handle.destroy(); - } + void destroy() { m_uniform_handle.destroy(); } private: - uint32_t m_size_bytes = 0; + uint64_t m_size_bytes; VkDevice m_device = nullptr; buffer_stream m_uniform_handle{}; }; diff --git a/vulkan-cpp/utilities.cppm b/vulkan-cpp/utilities.cppm index b9005a5..01fa528 100644 --- a/vulkan-cpp/utilities.cppm +++ b/vulkan-cpp/utilities.cppm @@ -14,312 +14,300 @@ export import :types; export namespace vk { inline namespace v1 { - void vk_check(const VkResult& p_result, - const std::string& p_name, - const std::source_location& p_source={}) { - if (p_result != VK_SUCCESS) { - std::println( - "File {} on line {} failed VkResult check", - std::filesystem::relative(p_source.file_name()).string(), - p_source.line()); - std::println("Current Function Location = {}", - p_source.function_name()); - std::println("{} VkResult returned: {}", p_name, (int)p_result); + void vk_check(const VkResult& p_result, + const std::string& p_name, + const std::source_location& p_source = {}) { + if (p_result != VK_SUCCESS) { + std::println( + "File {} on line {} failed VkResult check", + std::filesystem::relative(p_source.file_name()).string(), + p_source.line()); + std::println("Current Function Location = {}", + p_source.function_name()); + std::println("{} VkResult returned: {}", p_name, (int)p_result); + } + } + + std::vector enumerate_queue_family_properties( + const VkPhysicalDevice& p_physical) { + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties( + p_physical, &queue_family_count, nullptr); + std::vector queue_family_properties( + queue_family_count); + + vkGetPhysicalDeviceQueueFamilyProperties( + p_physical, &queue_family_count, queue_family_properties.data()); + + return queue_family_properties; } - } - - std::vector enumerate_queue_family_properties( - const VkPhysicalDevice& p_physical) { - uint32_t queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( - p_physical, &queue_family_count, nullptr); - std::vector queue_family_properties( - queue_family_count); - - vkGetPhysicalDeviceQueueFamilyProperties( - p_physical, &queue_family_count, queue_family_properties.data()); - - return queue_family_properties; - } - - VkFormat select_compatible_formats( - const VkPhysicalDevice& p_physical, - std::span p_format_selection, - VkImageTiling p_tiling, - VkFormatFeatureFlags p_feature_flag) { - VkFormat format = VK_FORMAT_UNDEFINED; - - for (size_t i = 0; i < p_format_selection.size(); i++) { - VkFormat current_format = static_cast(p_format_selection[i]); - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties( - p_physical, current_format, &format_properties); - - if (p_tiling == VK_IMAGE_TILING_LINEAR) { - if (format_properties.linearTilingFeatures & p_feature_flag) { + + VkFormat select_compatible_formats( + const VkPhysicalDevice& p_physical, + std::span p_format_selection, + VkImageTiling p_tiling, + VkFormatFeatureFlags p_feature_flag) { + VkFormat format = VK_FORMAT_UNDEFINED; + + for (size_t i = 0; i < p_format_selection.size(); i++) { + VkFormat current_format = + static_cast(p_format_selection[i]); + VkFormatProperties format_properties; + vkGetPhysicalDeviceFormatProperties( + p_physical, current_format, &format_properties); + + if (p_tiling == VK_IMAGE_TILING_LINEAR) { + if (format_properties.linearTilingFeatures & + p_feature_flag) { + format = current_format; + } + } + else if (p_tiling == VK_IMAGE_TILING_OPTIMAL and + format_properties.optimalTilingFeatures & + p_feature_flag) { format = current_format; } } - else if (p_tiling == VK_IMAGE_TILING_OPTIMAL and - format_properties.optimalTilingFeatures & p_feature_flag) { - format = current_format; - } + + return format; } - return format; - } - - VkFormat select_depth_format(const VkPhysicalDevice& p_physical, - std::span p_format_selection) { - - VkFormat format = select_compatible_formats( - p_physical, - p_format_selection, - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - return format; - } - - uint32_t physical_memory_properties(const VkPhysicalDevice& p_physical, - uint32_t p_type_filter, - VkMemoryPropertyFlags p_property_flag) { - VkPhysicalDeviceMemoryProperties mem_props; - vkGetPhysicalDeviceMemoryProperties(p_physical, &mem_props); - - for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { - if ((p_type_filter & (1 << i)) and - (mem_props.memoryTypes[i].propertyFlags & p_property_flag) == - p_property_flag) { - return i; - } + VkFormat select_depth_format( + const VkPhysicalDevice& p_physical, + std::span p_format_selection) { + + VkFormat format = select_compatible_formats( + p_physical, + p_format_selection, + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); + return format; } - return -1; - } - - // VkMemoryPropertyFlags to_memory_property_flags(memory_property p_flag) { - // VkMemoryPropertyFlags flags = 0; - // if (p_flag & memory_property::device_local_bit) { - // flags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - // } - // if (p_flag & memory_property::host_visible_bit) { - // flags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; - // } - // if (p_flag & memory_property::host_coherent_bit) { - // flags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - // } - // if (p_flag & memory_property::host_cached_bit) { - // flags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - // } - // if (p_flag & memory_property::lazily_allocated_bit) { - // flags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; - // } - // if (p_flag & memory_property::device_protected_bit) { - // flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT; - // } - // if (p_flag & memory_property::device_coherent_bit_amd) { - // flags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD; - // } - // if (p_flag & memory_property::device_uncached_bit_amd) { - // flags |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD; - // } - // if (p_flag & memory_property::rdma_capable_bit_nv) { - // flags |= VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV; - // } - - // return flags; - // } - - surface_params enumerate_surface(const VkPhysicalDevice& p_physical, - const VkSurfaceKHR& p_surface) { - surface_params enumerate_surface_properties{}; - vk_check( - vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - p_physical, p_surface, &enumerate_surface_properties.capabilities), - "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - - uint32_t format_count = 0; - std::vector formats; - vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( - p_physical, p_surface, &format_count, nullptr), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - formats.resize(format_count); - - vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( - p_physical, p_surface, &format_count, formats.data()), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - for (const auto& format : formats) { - if (format.format == VK_FORMAT_B8G8R8A8_SRGB && - format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - enumerate_surface_properties.format = format; + uint32_t physical_memory_properties( + const VkPhysicalDevice& p_physical, + uint32_t p_type_filter, + VkMemoryPropertyFlags p_property_flag) { + VkPhysicalDeviceMemoryProperties mem_props; + vkGetPhysicalDeviceMemoryProperties(p_physical, &mem_props); + + for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { + if ((p_type_filter & (1 << i)) and + (mem_props.memoryTypes[i].propertyFlags & + p_property_flag) == p_property_flag) { + return i; + } } + + return -1; } - if(enumerate_surface_properties.format.format == VK_FORMAT_UNDEFINED) { - enumerate_surface_properties.format = formats[0]; + surface_params enumerate_surface(const VkPhysicalDevice& p_physical, + const VkSurfaceKHR& p_surface) { + surface_params enumerate_surface_properties{}; + vk_check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR( + p_physical, + p_surface, + &enumerate_surface_properties.capabilities), + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + + uint32_t format_count = 0; + std::vector formats; + vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( + p_physical, p_surface, &format_count, nullptr), + "vkGetPhysicalDeviceSurfaceFormatsKHR"); + + formats.resize(format_count); + + vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( + p_physical, p_surface, &format_count, formats.data()), + "vkGetPhysicalDeviceSurfaceFormatsKHR"); + + for (const auto& format : formats) { + if (format.format == VK_FORMAT_B8G8R8A8_SRGB && + format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + enumerate_surface_properties.format = format; + } + } + + if (enumerate_surface_properties.format.format == + VK_FORMAT_UNDEFINED) { + enumerate_surface_properties.format = formats[0]; + } + + return enumerate_surface_properties; } - return enumerate_surface_properties; - } + uint32_t surface_image_size( + const VkSurfaceCapabilitiesKHR& p_capabilities) { + uint32_t requested_images = p_capabilities.minImageCount + 1; - uint32_t surface_image_size( - const VkSurfaceCapabilitiesKHR& p_capabilities) { - uint32_t requested_images = p_capabilities.minImageCount + 1; + uint32_t final_image_count = 0; - uint32_t final_image_count = 0; + if ((p_capabilities.maxImageCount > 0) and + (requested_images > p_capabilities.maxImageCount)) { + final_image_count = p_capabilities.maxImageCount; + } + else { + final_image_count = requested_images; + } - if ((p_capabilities.maxImageCount > 0) and - (requested_images > p_capabilities.maxImageCount)) { - final_image_count = p_capabilities.maxImageCount; + return final_image_count; } - else { - final_image_count = requested_images; + + VkSampler create_sampler(const VkDevice& p_device, + const filter_range& p_range, + VkSamplerAddressMode p_address_mode) { + VkSamplerCreateInfo sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .magFilter = p_range.min, + .minFilter = p_range.max, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = p_address_mode, + .addressModeV = p_address_mode, + .addressModeW = p_address_mode, + .mipLodBias = 0.0f, + .anisotropyEnable = false, + .maxAnisotropy = 1, + .compareEnable = false, + .compareOp = VK_COMPARE_OP_ALWAYS, + .minLod = 0.0f, + .maxLod = 0.0f, + .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, + .unnormalizedCoordinates = false + }; + + VkSampler sampler = nullptr; + VkResult res = + vkCreateSampler(p_device, &sampler_info, nullptr, &sampler); + vk_check(res, "vkCreateSampler"); + return sampler; } - return final_image_count; - } - - VkSampler create_sampler(const VkDevice& p_device, - const filter_range& p_range, - VkSamplerAddressMode p_address_mode) { - VkSamplerCreateInfo sampler_info = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .magFilter = p_range.min, - .minFilter = p_range.max, - .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = p_address_mode, - .addressModeV = p_address_mode, - .addressModeW = p_address_mode, - .mipLodBias = 0.0f, - .anisotropyEnable = false, - .maxAnisotropy = 1, - .compareEnable = false, - .compareOp = VK_COMPARE_OP_ALWAYS, - .minLod = 0.0f, - .maxLod = 0.0f, - .borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK, - .unnormalizedCoordinates = false - }; - - VkSampler sampler = nullptr; - VkResult res = - vkCreateSampler(p_device, &sampler_info, nullptr, &sampler); - vk_check(res, "vkCreateSampler"); - return sampler; - } - - VkSemaphore create_semaphore(const VkDevice& p_device) { - // creating semaphores - VkSemaphoreCreateInfo semaphore_ci = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = nullptr, - .flags = 0 - }; - - VkSemaphore semaphore; - vk_check( - vkCreateSemaphore(p_device, &semaphore_ci, nullptr, &semaphore), - "vkCreateSemaphore"); - return semaphore; - } - - uint32_t image_memory_requirements(const VkPhysicalDevice& p_physical, - const VkDevice& p_device, - const VkImage& p_image, - memory_property p_property) { - VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(p_device, p_image, &memory_requirements); - - uint32_t type_filter = memory_requirements.memoryTypeBits; - VkMemoryPropertyFlags property_flag = static_cast(p_property); - - VkPhysicalDeviceMemoryProperties mem_props; - vkGetPhysicalDeviceMemoryProperties(p_physical, &mem_props); - - for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { - if ((type_filter & (1 << i)) and - (mem_props.memoryTypes[i].propertyFlags & property_flag) == - property_flag) { - return i; - } + VkSemaphore create_semaphore(const VkDevice& p_device) { + // creating semaphores + VkSemaphoreCreateInfo semaphore_ci = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = nullptr, + .flags = 0 + }; + + VkSemaphore semaphore; + vk_check( + vkCreateSemaphore(p_device, &semaphore_ci, nullptr, &semaphore), + "vkCreateSemaphore"); + return semaphore; } - return -1; - } - - VkVertexInputRate to_input_rate(input_rate p_input_rate) { - switch (p_input_rate) { - case input_rate::vertex: - return VK_VERTEX_INPUT_RATE_VERTEX; - case input_rate::instance: - return VK_VERTEX_INPUT_RATE_INSTANCE; - default: - return VK_VERTEX_INPUT_RATE_MAX_ENUM; + uint32_t image_memory_requirements(const VkPhysicalDevice& p_physical, + const VkDevice& p_device, + const VkImage& p_image, + memory_property p_property) { + VkMemoryRequirements memory_requirements; + vkGetImageMemoryRequirements( + p_device, p_image, &memory_requirements); + + uint32_t type_filter = memory_requirements.memoryTypeBits; + VkMemoryPropertyFlags property_flag = + static_cast(p_property); + + VkPhysicalDeviceMemoryProperties mem_props; + vkGetPhysicalDeviceMemoryProperties(p_physical, &mem_props); + + for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { + if ((type_filter & (1 << i)) and + (mem_props.memoryTypes[i].propertyFlags & property_flag) == + property_flag) { + return i; + } + } + + return -1; } - } - bool has_depth_specified(image_layout p_layout) { - if (p_layout == image_layout::depth_stencil_optimal) { - return true; + VkVertexInputRate to_input_rate(input_rate p_input_rate) { + switch (p_input_rate) { + case input_rate::vertex: + return VK_VERTEX_INPUT_RATE_VERTEX; + case input_rate::instance: + return VK_VERTEX_INPUT_RATE_INSTANCE; + default: + return VK_VERTEX_INPUT_RATE_MAX_ENUM; + } } - if (p_layout == image_layout::depth_stencil_read_only_optimal) { - return true; + bool has_depth_specified(image_layout p_layout) { + if (p_layout == image_layout::depth_stencil_optimal) { + return true; + } + + if (p_layout == image_layout::depth_stencil_read_only_optimal) { + return true; + } + return false; } - return false; - } - - int bytes_per_texture_format(VkFormat p_format) { - switch (p_format) { - case VK_FORMAT_R8_SINT: - case VK_FORMAT_R8_UNORM: - return 1; - case VK_FORMAT_R16_SFLOAT: - return 2; - case VK_FORMAT_R16G16_SFLOAT: - case VK_FORMAT_B8G8R8A8_UNORM: - case VK_FORMAT_R8G8B8A8_UNORM: - return 4; - case VK_FORMAT_R16G16B16A16_SFLOAT: - return 4 * sizeof(uint16_t); - case VK_FORMAT_R32G32B32A32_SFLOAT: - return 4 * sizeof(float); - case VK_FORMAT_R8G8B8A8_SRGB: - return 4 * sizeof(uint8_t); - default: - return 0; + + uint32_t select_memory_requirements( + VkPhysicalDeviceMemoryProperties p_physical_memory_props, + VkMemoryRequirements p_memory_requirements, + memory_property p_property) { + uint32_t memory_bits = p_memory_requirements.memoryTypeBits; + VkMemoryPropertyFlags property_flag = + static_cast(p_property); + + for (uint32_t i = 0; i < p_physical_memory_props.memoryTypeCount; + i++) { + if ((memory_bits & (1 << i)) and + (p_physical_memory_props.memoryTypes[i].propertyFlags & + property_flag) == property_flag) { + return i; + } + } + + return -1; } - return 0; - } - - bool has_stencil_attachment(VkFormat p_format) { - return ((p_format == VK_FORMAT_D32_SFLOAT_S8_UINT) || - (p_format == VK_FORMAT_D24_UNORM_S8_UINT)); - } - - uint32_t select_memory_requirements( - VkPhysicalDeviceMemoryProperties p_physical_memory_props, - VkMemoryRequirements p_memory_requirements, - memory_property p_property) { - uint32_t memory_bits = p_memory_requirements.memoryTypeBits; - VkMemoryPropertyFlags property_flag = - static_cast(p_property); - - for (uint32_t i = 0; i < p_physical_memory_props.memoryTypeCount; i++) { - if ((memory_bits & (1 << i)) and - (p_physical_memory_props.memoryTypes[i].propertyFlags & - property_flag) == property_flag) { - return i; + int bytes_per_texture_format(VkFormat p_format) { + switch (p_format) { + case VK_FORMAT_R8_SINT: + case VK_FORMAT_R8_UNORM: + return 1; + case VK_FORMAT_R16_SFLOAT: + return 2; + case VK_FORMAT_R16G16_SFLOAT: + case VK_FORMAT_B8G8R8A8_UNORM: + case VK_FORMAT_R8G8B8A8_UNORM: + return 4; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return 4 * sizeof(uint16_t); + case VK_FORMAT_R32G32B32A32_SFLOAT: + return 4 * sizeof(float); + case VK_FORMAT_R8G8B8A8_SRGB: + return 4 * sizeof(uint8_t); + default: + return 0; } + + return 0; } - return -1; - } + bool has_stencil_attachment(VkFormat p_format) { + return ((p_format == VK_FORMAT_D32_SFLOAT_S8_UINT) || + (p_format == VK_FORMAT_D24_UNORM_S8_UINT)); + } + + template + std::span to_bytes(T p_data) { + return std::span(reinterpret_cast(&p_data), + sizeof(p_data)); + } + + std::span as_bytes(const void* p_data, uint32_t p_size) { + const auto* bytes = reinterpret_cast(p_data); + return std::span(bytes, p_size); + } -}; // end of v1 namespace + }; // end of v1 namespace }; \ No newline at end of file diff --git a/vulkan-cpp/vertex_buffer.cppm b/vulkan-cpp/vertex_buffer.cppm index e3ce41f..fc3536d 100644 --- a/vulkan-cpp/vertex_buffer.cppm +++ b/vulkan-cpp/vertex_buffer.cppm @@ -6,7 +6,6 @@ module; export module vk:vertex_buffer; - export import :types; export import :utilities; export import :command_buffer; @@ -15,53 +14,57 @@ export import :buffer_streams; export namespace vk { inline namespace v1 { /** - * @brief vulkan implementation for loading in vertices to a vulkan buffer handle - * - * This implementation automates handle in loading the vertices and its memories for it + * @brief vulkan implementation for loading in vertices to a vulkan + * buffer handle + * + * This implementation automates handle in loading the vertices and its + * memories for it */ class vertex_buffer { public: vertex_buffer() = default; vertex_buffer(const VkDevice& p_device, - const vertex_params& p_vertex_info) : m_device(p_device) { - m_size = p_vertex_info.vertices.size(); - m_size_bytes = p_vertex_info.vertices.size_bytes(); - - VkBufferUsageFlags usage = - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + std::span p_vertices, + const vertex_params& p_vertex_info) + : m_device(p_device) { // 1. creating staging buffer - uint32_t property_flags = - memory_property::host_visible_bit | memory_property::host_cached_bit; + // uint32_t property_flags = memory_property::host_visible_bit | + // memory_property::host_cached_bit; uint32_t buffer_usage = + // buffer_usage::transfer_src_bit | + // buffer_usage::storage_buffer_bit; - buffer_parameters new_staging_buffer_settings = { - .device_size = m_size_bytes, + buffer_parameters staging_buffer_params = { .physical_memory_properties = - p_vertex_info.phsyical_memory_properties, - .property_flags = (memory_property)property_flags, + p_vertex_info.phsyical_memory_properties, + // .property_flags = (memory_property)property_flags, + .property_flags = static_cast( + memory_property::host_visible_bit | + memory_property::host_cached_bit), .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, .debug_name = p_vertex_info.debug_name.c_str(), - .vkSetDebugUtilsObjectNameEXT = p_vertex_info.vkSetDebugUtilsObjectNameEXT + .vkSetDebugUtilsObjectNameEXT = + p_vertex_info.vkSetDebugUtilsObjectNameEXT }; - buffer_stream staging_buffer(m_device, new_staging_buffer_settings); - std::span vertices = p_vertex_info.vertices; - staging_buffer.write(vertices); + buffer_stream staging_buffer( + m_device, p_vertices.size_bytes(), staging_buffer_params); + staging_buffer.transfer(p_vertices); // 3.) Now creating our actual vertex buffer handler buffer_parameters vertex_params = { - .device_size = m_size_bytes, .physical_memory_properties = - p_vertex_info.phsyical_memory_properties, + p_vertex_info.phsyical_memory_properties, .property_flags = memory_property::device_local_bit, .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, }; - m_vertex_handler = buffer_stream(m_device, vertex_params); + m_vertex_handler = buffer_stream( + m_device, p_vertices.size_bytes(), vertex_params); - // 4. Copy data from staging buffer to the actual vertex buffer itself! - buffer_copy_info info = { .src = staging_buffer, - .dst = m_vertex_handler }; + // 4. Copy data from staging buffer to the actual vertex buffer + // itself! buffer_copy_info info = { .src = staging_buffer, + // .dst = m_vertex_handler }; // copy(m_device, info, m_size_bytes); // 1. Retrieve the first queue @@ -69,22 +72,27 @@ export namespace vk { 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); + 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); + command_buffer copy_command_buffer(p_device, + enumerate_command_info); copy_command_buffer.begin(command_usage::one_time_submit); // VkBufferCopy copy_region{}; // copy_region.size = (VkDeviceSize)m_size_bytes; // vkCmdCopyBuffer( - // copy_command_buffer, staging_buffer, m_vertex_handler, 1, ©_region); - copy_command_buffer.copy_buffer(staging_buffer, m_vertex_handler, m_size_bytes); + // copy_command_buffer, staging_buffer, m_vertex_handler, 1, + // ©_region); + 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{}; @@ -103,30 +111,27 @@ export namespace vk { staging_buffer.destroy(); } - [[nodiscard]] uint32_t size_bytes() const { return m_size_bytes; } - - [[nodiscard]] uint32_t size() const { return m_size; } - [[nodiscard]] bool alive() const { return m_vertex_handler; } void bind(const VkCommandBuffer& p_current) { std::array handlers = { m_vertex_handler }; VkDeviceSize offsets[] = { 0 }; - vkCmdBindVertexBuffers(p_current, 0, 1, handlers.data(), offsets); + vkCmdBindVertexBuffers( + p_current, 0, 1, handlers.data(), offsets); } + // TODO: Probably handle flushing in vk::buffer_stream to give + // support for this...? + // void write(std::span p_vertices) {} + operator VkBuffer() const { return m_vertex_handler; } operator VkBuffer() { return m_vertex_handler; } - void destroy() { - m_vertex_handler.destroy(); - } + void destroy() { m_vertex_handler.destroy(); } private: VkDevice m_device = nullptr; - uint32_t m_size_bytes = 0; - uint32_t m_size = 0; buffer_stream m_vertex_handler; }; }; diff --git a/vulkan-cpp/vk.cppm b/vulkan-cpp/vk.cppm index 8170de9..08e7609 100644 --- a/vulkan-cpp/vk.cppm +++ b/vulkan-cpp/vk.cppm @@ -23,6 +23,5 @@ export import :descriptor_resource; export import :texture; namespace vk { - inline namespace v1 { - }; + inline namespace v1 {}; }; \ No newline at end of file