diff --git a/.gitignore b/.gitignore index 34aeb90..99c2920 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ old shaders stb_image.h *.log -vk.xml textures tiny_obj_loader.h vk_enum_string.h diff --git a/compile.sh b/compile.sh index 46e9a64..5a1f797 100755 --- a/compile.sh +++ b/compile.sh @@ -1,16 +1,12 @@ #!/bin/sh WDIR=$HOME/c++/vulkan -SHADER_DIR=$WDIR/shaders -SOURCE_DIR=$WDIR/src/shaders -mkdir -p "${SHADER_DIR}" +mkdir -p $WDIR/shaders -for file in $(ls ${SOURCE_DIR}); do - ext="${file##*.}" - if [[ $ext == "vert" ]] || [[ $ext == "frag" ]]; then - echo "compiling ${file}" - glslc ${SOURCE_DIR}/${file} -o ${SHADER_DIR}/$(basename ${file}).spv - fi -done +glslc $WDIR/shader.vert -o $WDIR/shaders/vert.spv +glslc $WDIR/shader.frag -o $WDIR/shaders/frag.spv + +glslc $WDIR/shader2D.vert -o $WDIR/shaders/vert2D.spv +glslc $WDIR/shader2D.frag -o $WDIR/shaders/frag2D.spv diff --git a/src/Makefile b/src/Makefile index 0c7ddf7..37a3497 100755 --- a/src/Makefile +++ b/src/Makefile @@ -48,10 +48,7 @@ $(OBJECT_DIRS): # Extras Options # # with debug flags -.PHONY += shader debug run gdb pch clean docs -shader: - sh ../compile.sh - +.PHONY += debug run gdb pch clean docs debug: CXXFLAGS += -g # -DDEBUG debug: default diff --git a/src/main.cpp b/src/main.cpp index 10aab26..e8d392d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,31 +1,30 @@ +#include "main.hpp" + #include "shape.hpp" #include "vulkan_instance.hpp" #include "renderer2D.hpp" #include "renderer3D.hpp" -#include "vulkan_settings.hpp" #include #include #include -namespace gz::vlk { +namespace gz::vk { int mainLoop() { - LogCreateInfo logCI { - .logfile = "main.log", - .storeLog = false, - .prefix = "Main", - .prefixColor = Color::BG_RED, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "main.log"; + logCI.storeLog = false; + logCI.prefix = "Main"; + logCI.prefixColor = Color::BG_RED; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; Log log(std::move(logCI)); - gz::SettingsManagerCreateInfo smCI { - .filepath = settings::CONFIG_FILE, - .initialValues = settings::INITIAL_SETTINGS, - .readFileOnCreation = true, - .writeFileOnExit = true, - .throwExceptionWhenNewValueNotAllowed = true, - }; + gz::SettingsManagerCreateInfo smCI{}; + smCI.filepath = gz::vk::CONFIG_FILE; + smCI.readFileOnCreation = true; + smCI.writeFileOnExit = true; + smCI.initialValues = gz::vk::INITIAL_SETTINGS; + smCI.throwExceptionWhenNewValueNotAllowed = true; VulkanInstance vulkanInstance(smCI); vulkanInstance.init(); @@ -91,5 +90,5 @@ namespace gz::vlk { int main() { - return gz::vlk::mainLoop(); + return gz::vk::mainLoop(); } diff --git a/src/main.hpp b/src/main.hpp new file mode 100644 index 0000000..d914d89 --- /dev/null +++ b/src/main.hpp @@ -0,0 +1,19 @@ +#pragma once + + +namespace gz::vk { + + + + + + + + + + + + + + +} // namespace gz::vk diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index 7e53fdf..6e91db5 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -2,7 +2,7 @@ #include "vulkan_instance.hpp" -namespace gz::vlk { +namespace gz::vk { void Renderer::cleanup_(){ vk.destroyCommandBuffers(commandBuffers); diff --git a/src/renderer/renderer.hpp b/src/renderer/renderer.hpp index 1a6a3f6..d4f22a6 100644 --- a/src/renderer/renderer.hpp +++ b/src/renderer/renderer.hpp @@ -1,22 +1,16 @@ #pragma once -#define VULKAN_HPP_NO_CONSTRUCTORS -#define VULKAN_HPP_NO_EXCEPTIONS -#include - // includes for child classes -#include "vulkan_util.hpp" -#include - #include "texture_manager.hpp" #include "vertex.hpp" #include "vulkan_allocator.hpp" +#include - +#include #include -namespace gz::vlk { +namespace gz::vk { /// Defined in texture_manager.hpp class TextureManager; /// Defined in vulkan_instance.hpp @@ -37,13 +31,13 @@ namespace gz::vlk { VulkanInstance& vk; TextureManager& textureManager; - std::vector commandBuffers; + std::vector commandBuffers; /// On device local memory - vk::Buffer vertexBuffer; + VkBuffer vertexBuffer; MemoryInfo vertexBufferMemory; - vk::DeviceSize vertexBufferSize; - vk::Buffer indexBuffer; + VkDeviceSize vertexBufferSize; + VkBuffer indexBuffer; MemoryInfo indexBufferMemory; - vk::DeviceSize indexBufferSize; + VkDeviceSize indexBufferSize; }; // class RendererBase -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/renderer/renderer2D.cpp b/src/renderer/renderer2D.cpp index b1e4e52..25f9aa6 100644 --- a/src/renderer/renderer2D.cpp +++ b/src/renderer/renderer2D.cpp @@ -1,16 +1,17 @@ #include "renderer2D.hpp" #include "exceptions.hpp" +#include "vk_enum_string.h" #include "vulkan_allocator.hpp" #include "vulkan_instance.hpp" #include "texture_manager.hpp" -#include #include -#include #include +#include -namespace gz::vlk { + +namespace gz::vk { // // INIT & CLEANUP @@ -18,13 +19,12 @@ namespace gz::vlk { Renderer2D::Renderer2D(VulkanInstance& instance, TextureManager& textureManager) : Renderer(instance, textureManager) { - LogCreateInfo logCI { - .logfile = "renderer2D.log", - .storeLog = false, - .prefix = "2D-Renderer", - .prefixColor = Color::LI_MAGENTA, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "renderer2D.log"; + logCI.storeLog = false; + logCI.prefix = "2D-Renderer"; + logCI.prefixColor = Color::LI_MAGENTA; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; rLog = Log(std::move(logCI)); vk.registerCleanupCallback(std::bind(&Renderer2D::cleanup, this)); @@ -59,19 +59,8 @@ namespace gz::vlk { createRenderPass(); createImages(); vk.createFramebuffers(framebuffers, imageViews, renderPass); - std::vector descriptorSetLayouts = { textureManager.getDescriptorSetLayout() }; - - // specialization constant for sampler2D array length = atlas count - vk::SpecializationMapEntry specME { - .constantID = 0, - .offset = 0, - .size = sizeof(uint32_t), - }; - uint32_t atlasCount = textureManager.getAtlasCount(); - vk::SpecializationInfo specI; - specI.setData(atlasCount); - specI.setMapEntries(specME); - vk.createGraphicsPipeline("shaders/vert2D.spv", "shaders/frag2D.spv", descriptorSetLayouts, false, renderPass, pipelines[PL_2D], &specI); + std::vector descriptorSetLayouts = { textureManager.getDescriptorSetLayout() }; + vk.createGraphicsPipeline("shaders/vert2D.spv", "shaders/frag2D.spv", descriptorSetLayouts, false, renderPass, pipelines[PL_2D]); } @@ -85,7 +74,7 @@ namespace gz::vlk { vk.destroyImageView(imageViews[i]); vk.destroyImage(images[i], imageMemory[i]); } - vk.getDevice().destroyRenderPass(renderPass, nullptr); + vkDestroyRenderPass(vk.getDevice(), renderPass, nullptr); } @@ -104,10 +93,10 @@ namespace gz::vlk { images.resize(vk.getScImages().size()); imageMemory.resize(vk.getScImages().size()); imageViews.resize(vk.getScImages().size()); - vk::ImageUsageFlags usage= vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc; + VkImageUsageFlags usage= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; for (size_t i = 0; i < images.size(); i++) { - vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, images[i], imageMemory[i]); - vk.createImageView(vk.getScImageFormat(), images[i], imageViews[i], vk::ImageAspectFlagBits::eColor); + vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), VK_IMAGE_TILING_OPTIMAL, usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, images[i], imageMemory[i]); + vk.createImageView(vk.getScImageFormat(), images[i], imageViews[i], VK_IMAGE_ASPECT_COLOR_BIT); } } @@ -115,80 +104,87 @@ namespace gz::vlk { // RENDER PASS // void Renderer2D::createRenderPass() { - vk::AttachmentDescription2 colorBlendAttachment { - .format = vk.getScImageFormat(), - .samples = vk::SampleCountFlagBits::e1, - .loadOp = vk::AttachmentLoadOp::eClear, - .storeOp = vk::AttachmentStoreOp::eStore, - .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, - .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, - .initialLayout = vk::ImageLayout::eUndefined, - .finalLayout = vk::ImageLayout::eTransferSrcOptimal, - }; + VkAttachmentDescription2 colorBlendAttachment{}; + colorBlendAttachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; + colorBlendAttachment.format = vk.getScImageFormat(); + colorBlendAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorBlendAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorBlendAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorBlendAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorBlendAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorBlendAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorBlendAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - vk::AttachmentReference2 colorAttachmentRef { - .attachment = 0, - .layout = vk::ImageLayout::eColorAttachmentOptimal, - }; + VkAttachmentReference2 colorAttachmentRef{}; + colorAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - /* vk::AttachmentDescription depthAttachment { */ + /* VkAttachmentDescription depthAttachment{}; */ /* depthAttachment.format = findDepthFormat(); */ - /* depthAttachment.samples = vk::SampleCountFlagBits::e1; */ - /* depthAttachment.loadOp = vk::AttachmentLoadOp::eClear; */ - /* depthAttachment.storeOp = vk::AttachmentStoreOp::eDontCare; */ - /* depthAttachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare; */ - /* depthAttachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare; */ - /* depthAttachment.initialLayout = vk::ImageLayout::eUndefined; */ - /* depthAttachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal; */ + /* depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; */ + /* depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; */ + /* depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; */ + /* depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; */ + /* depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; */ + /* depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; */ + /* depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; */ - /* vk::AttachmentReference depthAttachmentRef { */ + /* VkAttachmentReference depthAttachmentRef{}; */ /* depthAttachmentRef.attachment = 1; */ - /* depthAttachmentRef.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal; */ + /* depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; */ - vk::SubpassDescription2 subpass { - .pipelineBindPoint = vk::PipelineBindPoint::eGraphics, - .colorAttachmentCount = 1, - .pColorAttachments = &colorAttachmentRef, - /* .pDepthStencilAttachment = &depthAttachmentRef, */ - }; + VkSubpassDescription2 subpass{}; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + /* subpass.pDepthStencilAttachment = &depthAttachmentRef; */ - vk::SubpassDependency2 colorAttachmentSD { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, - .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, - .srcAccessMask = NO_ACC_FLAGS, - .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, - }; + VkSubpassDependency2 colorAttachmentSD{}; + colorAttachmentSD.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; + colorAttachmentSD.srcSubpass = VK_SUBPASS_EXTERNAL; + colorAttachmentSD.dstSubpass = 0; + colorAttachmentSD.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorAttachmentSD.srcAccessMask = 0; + colorAttachmentSD.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorAttachmentSD.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; // dependecy for the image layout transition to transfer dst - vk::SubpassDependency2 layoutTransitionSD { - .srcSubpass = 0, - .dstSubpass = VK_SUBPASS_EXTERNAL, - .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, - .dstStageMask = vk::PipelineStageFlagBits::eTransfer, - .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead, - .dependencyFlags = vk::DependencyFlagBits::eByRegion, - }; - /* vk::SubpassDependency dependency { */ + VkSubpassDependency2 layoutTransitionSD{}; + layoutTransitionSD.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; + layoutTransitionSD.srcSubpass = 0; + layoutTransitionSD.dstSubpass = VK_SUBPASS_EXTERNAL; + layoutTransitionSD.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + layoutTransitionSD.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; + layoutTransitionSD.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + layoutTransitionSD.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; + layoutTransitionSD.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + /* VkSubpassDependency dependency{}; */ /* dependency.srcSubpass = VK_SUBPASS_EXTERNAL; */ /* dependency.dstSubpass = 0; */ - /* dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */ + /* dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; */ /* dependency.srcAccessMask = 0; */ - /* dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */ - /* dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite; */ + /* dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; */ + /* dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; */ - /* std::array attachments = { colorBlendAttachment, depthAttachment }; */ - std::vector attachments = { colorBlendAttachment }; - std::vector dependencies = { colorAttachmentSD, layoutTransitionSD }; - vk::RenderPassCreateInfo2 renderPassCI; - renderPassCI.setDependencies(dependencies); - renderPassCI.setAttachments(attachments); - renderPassCI.setSubpasses(subpass); - - vk::Result result = vk.getDevice().createRenderPass2(&renderPassCI, nullptr, &renderPass); - if (result != vk::Result::eSuccess) { + /* std::array attachments = { colorBlendAttachment, depthAttachment }; */ + std::vector attachments = { colorBlendAttachment }; + std::vector dependencies = { colorAttachmentSD, layoutTransitionSD }; + VkRenderPassCreateInfo2 renderPassCI{}; + renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2; + renderPassCI.attachmentCount = static_cast(attachments.size()); + renderPassCI.pAttachments = attachments.data(); + renderPassCI.subpassCount = 1; + renderPassCI.pSubpasses = &subpass; + renderPassCI.dependencyCount = dependencies.size(); + renderPassCI.pDependencies = dependencies.data(); + /* renderPassCI.dependencyCount = 0; */ + /* renderPassCI.pDependencies = nullptr; */ + /* renderPassCI.correlatedViewMaskCount = 0; */ + /* renderPassCI.pCorrelatedViewMasks = nullptr; */ + VkResult result = vkCreateRenderPass2(vk.getDevice(), &renderPassCI, nullptr, &renderPass); + if (result != VK_SUCCESS) { throw getVkException(result, "Could not create render pass", "Renderer2D::createRenderPass"); } rLog("createRenderPass: Created render pass."); @@ -200,55 +196,54 @@ namespace gz::vlk { // RENDERING // void Renderer2D::recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame) { - vk::CommandBufferBeginInfo commandBufferBI { - /* .flags = 0, */ - /* .pInheritanceInfo = nullptr, */ - }; - vk::Result result = commandBuffers[currentFrame].begin(&commandBufferBI); - if (result != vk::Result::eSuccess) { + VkCommandBufferBeginInfo commandBufferBI{}; + commandBufferBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + /* commandBufferBI.flags = 0; */ + /* commandBufferBI.pInheritanceInfo = nullptr; */ + VkResult result = vkBeginCommandBuffer(commandBuffers[currentFrame], &commandBufferBI); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to begin 2D command buffer", "Renderer2D::recordCommandBuffer"); } + VkRenderPassBeginInfo renderPassBI{}; + renderPassBI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassBI.renderPass = renderPass; + renderPassBI.framebuffer = framebuffers[imageIndex]; + renderPassBI.renderArea.offset = { 0, 0 }; + renderPassBI.renderArea.extent = vk.getScExtent(); // clear - std::array clearValues{}; - vk::ClearColorValue clearColor{}; - clearColor.setFloat32({ 0.0f, 0.0f, 0.1f, 0.5f }); - clearValues[0].setColor(std::move(clearColor)); + std::array clearValues{}; + clearValues[0].color = {{1.0f, 0.0f, 0.0f, 1.0f}}; /* clearValues[1].depthStencil = {1.0f, 0}; */ - vk::RenderPassBeginInfo renderPassBI { - .renderPass = renderPass, - .framebuffer = framebuffers[imageIndex], - .renderArea { .offset = { 0, 0 }, .extent = vk.getScExtent(), } - }; - renderPassBI.setClearValues(clearValues); + renderPassBI.clearValueCount = static_cast(clearValues.size()); + renderPassBI.pClearValues = clearValues.data(); - commandBuffers[currentFrame].beginRenderPass(&renderPassBI, vk::SubpassContents::eInline); + vkCmdBeginRenderPass(commandBuffers[currentFrame], &renderPassBI, VK_SUBPASS_CONTENTS_INLINE); - commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines[PL_2D].pipeline); - vk::Buffer vertexBuffers[] = { vertexBuffer }; - vk::DeviceSize offsets[] = {0}; + vkCmdBindPipeline(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[PL_2D].pipeline); + VkBuffer vertexBuffers[] = { vertexBuffer }; + VkDeviceSize offsets[] = {0}; uint32_t bindingCount = 1; - uint32_t binding = 0; - commandBuffers[currentFrame].bindVertexBuffers(binding, bindingCount, vertexBuffers, offsets); + vkCmdBindVertexBuffers(commandBuffers[currentFrame], BINDING, bindingCount, vertexBuffers, offsets); // TODO use correct index type! - commandBuffers[currentFrame].bindIndexBuffer(indexBuffer, NO_OFFSET, vk::IndexType::eUint32); + vkCmdBindIndexBuffer(commandBuffers[currentFrame], indexBuffer, NO_OFFSET, VK_INDEX_TYPE_UINT32); uint32_t descriptorCount = 1; uint32_t firstSet = 0; uint32_t dynamicOffsetCount = 0; uint32_t* dynamicOffsets = nullptr; - commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[PL_2D].layout, firstSet, descriptorCount, &textureManager.getDescriptorSet(), dynamicOffsetCount, dynamicOffsets); + vkCmdBindDescriptorSets(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[PL_2D].layout, firstSet, descriptorCount, &textureManager.getDescriptorSet(), dynamicOffsetCount, dynamicOffsets); int instanceCount = 1; int firstIndex = 0; int firstInstance = 0; - commandBuffers[currentFrame].drawIndexed(static_cast(shapesIndicesCount), instanceCount, firstIndex, NO_OFFSET, firstInstance); - commandBuffers[currentFrame].endRenderPass(); + vkCmdDrawIndexed(commandBuffers[currentFrame], static_cast(shapesIndicesCount), instanceCount, firstIndex, NO_OFFSET, firstInstance); + vkCmdEndRenderPass(commandBuffers[currentFrame]); vk.copyImageToImage(commandBuffers[currentFrame], images[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent()); - result = commandBuffers[currentFrame].end(); - if (result != vk::Result::eSuccess) { - rLog.error("Failed to record 2D - command buffer", "VkResult:", result); + result = vkEndCommandBuffer(commandBuffers[currentFrame]); + if (result != VK_SUCCESS) { + rLog.error("Failed to record 2D - command buffer", "VkResult:", STR_VK_RESULT(result)); throw getVkException(result, "Failed to record 2D - command buffer", "Renderer2D::recordCommandBufferWithTexture"); } vk.submitThisFrame(commandBuffers[currentFrame]); @@ -262,24 +257,21 @@ namespace gz::vlk { } // create staging buffer - vk::Buffer stagingBuffer; + VkBuffer stagingBuffer; MemoryInfo stagingBufferMemory; - vk.createBuffer(vertexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); + vk.createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); // fill staging buffer void* data; - vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, vertexBufferSize, NO_MEM_FLAGS, &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer", "Renderer3D::fillVertexBufferWithShapes"); - } + vkMapMemory(vk.getDevice(), stagingBufferMemory.memory, stagingBufferMemory.offset, vertexBufferSize, NO_FLAGS, &data); Vertex2D* vdata = reinterpret_cast(data); size_t offset = 0; for (auto it = shapes.begin(); it != shapes.end(); it++) { - rLog.log0("fillVertexBufferWithShapes: copying vertex buffer nr", it - shapes.begin(), "-", it->getVertices(), "to address:", long(vdata + offset), " offset:", offset); + rLog("fillVertexBufferWithShapes: copying vertex buffer nr", it - shapes.begin(), "-", it->getVertices(), "to address:", long(vdata + offset), " offset:", offset); memcpy(vdata+offset, it->getVertices().data(), it->getVertices().size() * sizeof(Vertex2D)); offset += it->getVertices().size(); } - vk.getDevice().unmapMemory(stagingBufferMemory.memory); + vkUnmapMemory(vk.getDevice(), stagingBufferMemory.memory); // fill vertex buffer vk.copyBuffer(stagingBuffer, vertexBuffer, vertexBufferSize); vk.destroyBuffer(stagingBuffer, stagingBufferMemory); @@ -291,16 +283,13 @@ namespace gz::vlk { } // create staging buffer - vk::Buffer stagingBuffer; + VkBuffer stagingBuffer; MemoryInfo stagingBufferMemory; - vk.createBuffer(indexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); + vk.createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); // fill staging buffer void* data; - vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, indexBufferSize, NO_MEM_FLAGS, &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer", "Renderer2D::fillIndexBufferWithShapes"); - } + vkMapMemory(vk.getDevice(), stagingBufferMemory.memory, stagingBufferMemory.offset, indexBufferSize, NO_FLAGS, &data); uint32_t* idata = reinterpret_cast(data); size_t offset = 0; for (auto it = shapes.begin(); it != shapes.end(); it++) { @@ -308,8 +297,8 @@ namespace gz::vlk { memcpy(idata+offset, it->getIndices().data(), it->getIndices().size() * sizeof(uint32_t)); offset += it->getIndices().size(); } - rLog.log0("fillIndexBufferWithShapes: indices count:", shapesIndicesCount); - vk.getDevice().unmapMemory(stagingBufferMemory.memory); + rLog("fillIndexBufferWithShapes: indices count:", shapesIndicesCount); + vkUnmapMemory(vk.getDevice(), stagingBufferMemory.memory); // fill index buffer vk.copyBuffer(stagingBuffer, indexBuffer, indexBufferSize); @@ -331,11 +320,11 @@ namespace gz::vlk { void Renderer2D::drawFrame(uint32_t imageIndex) { - commandBuffers[vk.getCurrentFrame()].reset(); + vkResetCommandBuffer(commandBuffers[vk.getCurrentFrame()], NO_FLAGS); /* recordCommandBuffer(imageIndex, vk.getCurrentFrame()); */ recordCommandBuffer(imageIndex, vk.getCurrentFrame()); } -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/renderer/renderer2D.hpp b/src/renderer/renderer2D.hpp index f63b931..0fc283f 100644 --- a/src/renderer/renderer2D.hpp +++ b/src/renderer/renderer2D.hpp @@ -6,7 +6,7 @@ #include "vulkan_allocator.hpp" #include "vulkan_util.hpp" -namespace gz::vlk { +namespace gz::vk { class Renderer2D : public Renderer { public: /** @@ -49,13 +49,13 @@ namespace gz::vlk { * @details * As of now, this does (in the same command buffer from graphicsPool) * -# begin render pass - * - image layout: vk::ImageLayout::eColorAttachmentOptimal + * - image layout: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL * - clear image * -# bind 2d pipeline, vertex and index buffer * -# bind texture sampler * -# draw indexed: draw the shapes from shapes vector * -# end render pass - * - image layout: vk::ImageLayout::eTransferSrcOptimal + * - image layout: VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL * -# copy image to swapChain image with same imageIndex */ void recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame); @@ -67,9 +67,9 @@ namespace gz::vlk { * The images are used as render targets. After rendering, the current image gets blitted onto the current swap chain image. * @{ */ - std::vector images; + std::vector images; std::vector imageMemory; - std::vector imageViews; + std::vector imageViews; /** * @brief Creates the images (on imageMemory) and imageViews with the format of the VulkanInstance::swapChain images */ @@ -81,10 +81,10 @@ namespace gz::vlk { * @details * Attachments: * - color blend: - * - loadOp = vk::AttachmentLoadOp::eClear - * - storeOp = vk::AttachmentStoreOp::eStore - * - initialLayout = vk::ImageLayout::eColorAttachmentOptimal - * - finalLayout = vk::ImageLayout::eColorAttachmentOptimal + * - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR + * - storeOp = VK_ATTACHMENT_STORE_OP_STORE + * - initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + * - finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL * - stencil load/store = dont care */ /// @{ @@ -92,10 +92,10 @@ namespace gz::vlk { * @brief Create a render pass */ void createRenderPass(); - vk::RenderPass renderPass; + VkRenderPass renderPass; /// @} - std::vector framebuffers; + std::vector framebuffers; // PIPELINE PipelineContainer pipelines; @@ -130,4 +130,4 @@ namespace gz::vlk { Log rLog; }; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/renderer/renderer3D.cpp b/src/renderer/renderer3D.cpp index a02ded1..ca3622a 100644 --- a/src/renderer/renderer3D.cpp +++ b/src/renderer/renderer3D.cpp @@ -6,24 +6,23 @@ #include "texture_manager.hpp" #include "exceptions.hpp" #include "vk_enum_string.h" -#include "vulkan_settings.hpp" #include +#include #include -namespace gz::vlk { +namespace gz::vk { // // INIT & CLEANUP // Renderer3D::Renderer3D(VulkanInstance& instance, TextureManager& textureManager) : Renderer(instance, textureManager) { - LogCreateInfo logCI{ - .logfile = "renderer3D.log", - .storeLog = false, - .prefix = "3D-Renderer", - .prefixColor = Color::LI_CYAN, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "renderer3D.log"; + logCI.storeLog = false; + logCI.prefix = "3D-Renderer"; + logCI.prefixColor = Color::LI_CYAN; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; rLog = Log(std::move(logCI)); vk.registerCleanupCallback(std::bind(&Renderer3D::cleanup, this)); @@ -34,6 +33,7 @@ namespace gz::vlk { const size_t indexCount = 10000; vk.createVertexBuffer(vertexCount, vertexBuffer, vertexBufferMemory, vertexBufferSize); vk.createIndexBuffer(indexCount, indexBuffer, indexBufferMemory, indexBufferSize); + rLog("Created Renderer3D"); // TODO loadModel(); @@ -46,7 +46,7 @@ namespace gz::vlk { &descriptorSetLayout, &descriptorPool, }, { &framebuffers, &images, &imageMemory, &imageViews, &commandBuffers, &descriptorSets })); - rLog.log1("Created Renderer3D"); + rLog("Created Renderer3D"); } void Renderer3D::cleanup() { @@ -55,8 +55,8 @@ namespace gz::vlk { for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) { vk.destroyBuffer(uniformBuffers[i], uniformBuffersMemory[i]); } - vk.getDevice().destroyDescriptorSetLayout(descriptorSetLayout, NO_ALLOC); - vk.getDevice().destroyDescriptorPool(descriptorPool, NO_ALLOC); + vkDestroyDescriptorSetLayout(vk.getDevice(), descriptorSetLayout, NO_ALLOC); + vkDestroyDescriptorPool(vk.getDevice(), descriptorPool, NO_ALLOC); cleanupSwapChainDependantResources(); cleanup_(); @@ -67,13 +67,11 @@ namespace gz::vlk { // SWAPCHAIN DEPENDANT // void Renderer3D::initSwapChainDependantResources() { - // UPDATE DOC ON CHANGES! createRenderPass(); createImages(); - createDepthImage(); - vk.createFramebuffers(framebuffers, imageViews, renderPass, depthImageView); - std::vector descriptorSetLayouts = { descriptorSetLayout }; - vk.createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", descriptorSetLayouts, true, renderPass, pipelines[PL_3D]); + vk.createFramebuffers(framebuffers, imageViews, renderPass); + std::vector descriptorSetLayouts = { descriptorSetLayout }; + vk.createGraphicsPipeline("shaders/vert.spv", "shaders/frag.spv", descriptorSetLayouts, false, renderPass, pipelines[PL_3D]); } @@ -83,14 +81,13 @@ namespace gz::vlk { vk.destroyFramebuffers(framebuffers); - vk.destroyImageView(depthImageView); - vk.destroyImage(depthImage, depthImageMemory); - for (size_t i = 0; i < images.size(); i++) { vk.destroyImageView(imageViews[i]); vk.destroyImage(images[i], imageMemory[i]); } - vk.getDevice().destroyRenderPass(renderPass, nullptr); + vkDestroyRenderPass(vk.getDevice(), renderPass, nullptr); + + } @@ -107,120 +104,99 @@ namespace gz::vlk { images.resize(vk.getScImages().size()); imageMemory.resize(vk.getScImages().size()); imageViews.resize(vk.getScImages().size()); - vk::ImageUsageFlags usage= vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc; + VkImageUsageFlags usage= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; for (size_t i = 0; i < images.size(); i++) { - vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), vk::ImageTiling::eOptimal, usage, vk::MemoryPropertyFlagBits::eDeviceLocal, images[i], imageMemory[i]); - vk.createImageView(vk.getScImageFormat(), images[i], imageViews[i], vk::ImageAspectFlagBits::eColor); + vk.createImage(vk.getScExtent().width, vk.getScExtent().height, vk.getScImageFormat(), VK_IMAGE_TILING_OPTIMAL, usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, images[i], imageMemory[i]); + vk.createImageView(vk.getScImageFormat(), images[i], imageViews[i], VK_IMAGE_ASPECT_COLOR_BIT); } } -// -// DEPTH -// - void Renderer3D::createDepthImage() { - vk::MemoryPropertyFlags memoryProperties = vk::MemoryPropertyFlagBits::eDeviceLocal; - vk::ImageUsageFlags imageUsage = vk::ImageUsageFlagBits::eDepthStencilAttachment; - vk::ImageTiling tiling = vk::ImageTiling::eOptimal; - vk::Format depthFormat = vk.getDepthFormat(); - - vk.createImage(vk.getScExtent().width, vk.getScExtent().height, depthFormat, tiling, imageUsage, memoryProperties, depthImage, depthImageMemory); - vk.createImageView(depthFormat, depthImage, depthImageView, vk::ImageAspectFlagBits::eDepth); - - vk.transitionImageLayout(depthImage, depthFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eDepthStencilAttachmentOptimal); - } - // // RENDER PASS // void Renderer3D::createRenderPass() { - vk::AttachmentDescription2 colorBlendAD { - .format = vk.getScImageFormat(), - .samples = vk::SampleCountFlagBits::e1, - .loadOp = vk::AttachmentLoadOp::eClear, - .storeOp = vk::AttachmentStoreOp::eStore, - .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, - .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, - .initialLayout = vk::ImageLayout::eUndefined, - .finalLayout = vk::ImageLayout::eTransferSrcOptimal, - }; + VkAttachmentDescription2 colorBlendAttachment{}; + colorBlendAttachment.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; + colorBlendAttachment.format = vk.getScImageFormat(); + colorBlendAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorBlendAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorBlendAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorBlendAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorBlendAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorBlendAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorBlendAttachment.finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - vk::AttachmentReference2 colorBlendAR { - .attachment = 0, - .layout = vk::ImageLayout::eColorAttachmentOptimal, - }; + VkAttachmentReference2 colorAttachmentRef{}; + colorAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - vk::AttachmentDescription2 depthAD { - .format = vk.getDepthFormat(), - .samples = vk::SampleCountFlagBits::e1, - .loadOp = vk::AttachmentLoadOp::eClear, - .storeOp = vk::AttachmentStoreOp::eDontCare, - .stencilLoadOp = vk::AttachmentLoadOp::eDontCare, - .stencilStoreOp = vk::AttachmentStoreOp::eDontCare, - .initialLayout = vk::ImageLayout::eUndefined, - .finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal, - }; + /* VkAttachmentDescription depthAttachment{}; */ + /* depthAttachment.format = findDepthFormat(); */ + /* depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; */ + /* depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; */ + /* depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; */ + /* depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; */ + /* depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; */ + /* depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; */ + /* depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; */ - vk::AttachmentReference2 depthAR { - .attachment = 1, - .layout = vk::ImageLayout::eDepthStencilAttachmentOptimal, - }; + /* VkAttachmentReference depthAttachmentRef{}; */ + /* depthAttachmentRef.attachment = 1; */ + /* depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; */ - vk::SubpassDescription2 subpass { - .pipelineBindPoint = vk::PipelineBindPoint::eGraphics, - .colorAttachmentCount = 1, - .pColorAttachments = &colorBlendAR, - .pDepthStencilAttachment = &depthAR, - }; + VkSubpassDescription2 subpass{}; + subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + /* subpass.pDepthStencilAttachment = &depthAttachmentRef; */ - // wait until image is available - vk::SubpassDependency2 colorAttachmentSD { - .srcSubpass = VK_SUBPASS_EXTERNAL, - .dstSubpass = 0, - .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, - .dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests, - .srcAccessMask = NO_ACC_FLAGS, - .dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite, - }; + VkSubpassDependency2 colorAttachmentSD{}; + colorAttachmentSD.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; + colorAttachmentSD.srcSubpass = VK_SUBPASS_EXTERNAL; + colorAttachmentSD.dstSubpass = 0; + colorAttachmentSD.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorAttachmentSD.srcAccessMask = 0; + colorAttachmentSD.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + colorAttachmentSD.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; - // image layout transition to transfer dst - vk::SubpassDependency2 layoutTransitionSD { - .srcSubpass = 0, - .dstSubpass = VK_SUBPASS_EXTERNAL, - .srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput, - .dstStageMask = vk::PipelineStageFlagBits::eTransfer, - .srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite, - .dstAccessMask = vk::AccessFlagBits::eTransferRead, - .dependencyFlags = vk::DependencyFlagBits::eByRegion, - }; + // dependecy for the image layout transition to transfer dst + VkSubpassDependency2 layoutTransitionSD{}; + layoutTransitionSD.sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2; + layoutTransitionSD.srcSubpass = 0; + layoutTransitionSD.dstSubpass = VK_SUBPASS_EXTERNAL; + layoutTransitionSD.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; + layoutTransitionSD.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT; + layoutTransitionSD.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + layoutTransitionSD.dstAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; + layoutTransitionSD.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - /* vk::SubpassDependency2 dependency { */ - /* dependency.srcSubpass = VK_SUBPASS_EXTERNAL; */ - /* dependency.dstSubpass = 0; */ - /* dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */ - /* dependency.srcAccessMask = 0; */ - /* dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests; */ - /* dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite; */ - - std::vector attachments = { colorBlendAD, depthAD, }; - std::vector dependencies = { colorAttachmentSD, layoutTransitionSD }; - vk::RenderPassCreateInfo2 renderPassCI { - /* .attachmentCount = static_cast(attachments.size()), */ - /* .pAttachments = attachments.data(), */ - /* .subpassCount = 1, */ - /* .pSubpasses = &subpass, */ - /* .dependencyCount = static_cast(dependencies.size()), */ - /* .pDependencies = dependencies.data(), */ - /* .dependencyCount = 0, */ - /* .pDependencies = nullptr, */ - /* .correlatedViewMaskCount = 0, */ - /* .pCorrelatedViewMasks = nullptr, */ - }; - renderPassCI.setAttachments(attachments); - renderPassCI.setDependencies(dependencies); - renderPassCI.setSubpasses(subpass); - vk::Result result = vk.getDevice().createRenderPass2(&renderPassCI, nullptr, &renderPass); - if (result != vk::Result::eSuccess) { + /* std::array attachments = { colorBlendAttachment, depthAttachment }; */ + std::vector attachments = { colorBlendAttachment }; + std::vector dependencies = { colorAttachmentSD, layoutTransitionSD }; + VkRenderPassCreateInfo2 renderPassCI{}; + renderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2; + renderPassCI.attachmentCount = static_cast(attachments.size()); + renderPassCI.pAttachments = attachments.data(); + renderPassCI.subpassCount = 1; + renderPassCI.pSubpasses = &subpass; + renderPassCI.dependencyCount = dependencies.size(); + renderPassCI.pDependencies = dependencies.data(); + /* renderPassCI.dependencyCount = 0; */ + /* renderPassCI.pDependencies = nullptr; */ + /* renderPassCI.correlatedViewMaskCount = 0; */ + /* renderPassCI.pCorrelatedViewMasks = nullptr; */ + VkResult result = vkCreateRenderPass2(vk.getDevice(), &renderPassCI, nullptr, &renderPass); + if (result != VK_SUCCESS) { throw getVkException(result, "Could not create render pass", "Renderer3D::createRenderPass"); } rLog.log0("createRenderPass: Created render pass."); @@ -234,90 +210,91 @@ namespace gz::vlk { void Renderer3D::createDescriptorResources() { // LAYOUT // 1) uniform buffer object - vk::DescriptorSetLayoutBinding uboLayoutBinding { - .binding = 0, - .descriptorType = vk::DescriptorType::eUniformBuffer, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eVertex, - /* .pImmutableSamplers = nullptr, */ - }; + VkDescriptorSetLayoutBinding uboLayoutBinding{}; + uboLayoutBinding.binding = 0; + uboLayoutBinding.descriptorCount = 1; + uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + /* uboLayoutBinding.pImmutableSamplers = nullptr; */ // 2) combined image sampler - vk::DescriptorSetLayoutBinding samplerLayoutBinding { - .binding = 1, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eFragment, - /* .pImmutableSamplers = nullptr, */ - }; + VkDescriptorSetLayoutBinding samplerLayoutBinding{}; + samplerLayoutBinding.binding = 1; + samplerLayoutBinding.descriptorCount = 1; + samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + /* samplerLayoutBinding.pImmutableSamplers = nullptr; */ - std::vector bindings = { uboLayoutBinding, samplerLayoutBinding }; + std::vector bindings = { uboLayoutBinding, samplerLayoutBinding }; vk.createDescriptorSetLayout(bindings, descriptorSetLayout); // POOL - std::array poolSizes; - poolSizes[0].type = vk::DescriptorType::eUniformBuffer; + std::array poolSizes; + poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; poolSizes[0].descriptorCount = static_cast(vk.getMaxFramesInFlight()); - poolSizes[1].type = vk::DescriptorType::eCombinedImageSampler; + poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; poolSizes[1].descriptorCount = static_cast(vk.getMaxFramesInFlight()); - vk::DescriptorPoolCreateInfo poolCI { - .maxSets = static_cast(vk.getMaxFramesInFlight()), - }; - poolCI.setPoolSizes(poolSizes); - - vk::Result result; - std::tie(result, descriptorPool) = vk.getDevice().createDescriptorPool(poolCI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create descriptor pool", "Renderer3D::createDescriptorResources"); - } + VkDescriptorPoolCreateInfo poolCI{}; + poolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolCI.poolSizeCount = static_cast(poolSizes.size()); + poolCI.pPoolSizes = poolSizes.data(); + poolCI.maxSets = static_cast(vk.getMaxFramesInFlight()); + VkResult result = vkCreateDescriptorPool(vk.getDevice(), &poolCI, nullptr, &descriptorPool); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create descriptor pool", "Renderer3D::createDescriptorResources"); + } // SETS - std::vector layouts(vk.getMaxFramesInFlight(), descriptorSetLayout); - vk::DescriptorSetAllocateInfo setAI { - .descriptorPool = descriptorPool, - }; - setAI.setSetLayouts(layouts); + std::vector layouts(vk.getMaxFramesInFlight(), descriptorSetLayout); + VkDescriptorSetAllocateInfo setAI{}; + setAI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + setAI.descriptorPool = descriptorPool; + setAI.descriptorSetCount = static_cast(layouts.size()); + setAI.pSetLayouts = layouts.data(); - // TODO is resize needed? - /* descriptorSets.resize(vk.getMaxFramesInFlight()); */ - std::tie(result, descriptorSets) = vk.getDevice().allocateDescriptorSets(setAI); - if (result != vk::Result::eSuccess) { + descriptorSets.resize(vk.getMaxFramesInFlight()); + result = vkAllocateDescriptorSets(vk.getDevice(), &setAI, descriptorSets.data()); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to create descriptor sets", "Renderer3D::createDescriptorResources"); } // configure sets for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) { - vk::DescriptorBufferInfo bufferI { - .buffer = uniformBuffers[i], - .offset = 0, - .range = VK_WHOLE_SIZE, // sizeof(UniformBufferObject), - }; + VkDescriptorBufferInfo bufferI{}; + bufferI.buffer = uniformBuffers[i]; + bufferI.offset = 0; + bufferI.range = VK_WHOLE_SIZE; // sizeof(UniformBufferObject); - vk::DescriptorImageInfo imageI { - .sampler = textureManager.getTextureAtlas().getTextureSampler(), - .imageView = textureManager.getTextureAtlas().getTextureImageView(), - .imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal, - }; + VkDescriptorImageInfo imageI{}; + imageI.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageI.imageView = textureManager.getTextureAtlas().getTextureImageView(); + imageI.sampler = textureManager.getTextureAtlas().getTextureSampler(); - std::array descriptorW{}; + std::array descriptorW{}; + descriptorW[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorW[0].dstSet = descriptorSets[i]; descriptorW[0].dstBinding = bindingUniformBuffer; descriptorW[0].dstArrayElement = 0; - descriptorW[0].descriptorType = vk::DescriptorType::eUniformBuffer; - descriptorW[0].setBufferInfo(bufferI); + descriptorW[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptorW[0].descriptorCount = 1; + descriptorW[0].pBufferInfo = &bufferI; /* descriptorW[0].pImageInfo = nullptr; */ /* descriptorW[0].pTexelBufferView = nullptr; */ + descriptorW[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorW[1].dstSet = descriptorSets[i]; descriptorW[1].dstBinding = bindingCombinedImageSampler; descriptorW[1].dstArrayElement = 0; - descriptorW[1].descriptorType = vk::DescriptorType::eCombinedImageSampler; - descriptorW[1].setImageInfo(imageI); + descriptorW[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorW[1].descriptorCount = 1; + /* descriptorW[1].pBufferInfo = &bufferI; */ + descriptorW[1].pImageInfo = &imageI; /* descriptorW[1].pTexelBufferView = nullptr; */ - // write 1, copy 0 - vk.getDevice().updateDescriptorSets(descriptorW, nullptr); + uint32_t descriptorWriteCount = static_cast(descriptorW.size()); + uint32_t descriptorCopyCount = 0; + vkUpdateDescriptorSets(vk.getDevice(), descriptorWriteCount, descriptorW.data(), descriptorCopyCount, nullptr); } rLog.log0("createDescriptorResources: Created descriptor layouts, pool and sets."); } @@ -328,10 +305,10 @@ namespace gz::vlk { void Renderer3D::loadModel() { // load model into VerticesAndIndices struct rLog.log1("Renderer3D: loadModel: loading model"); - vk.loadModel(settings::MODEL_PATH, model); + vk.loadModel(model); // TODO use correct type - vk::DeviceSize requiredVertexBufferSize = model.vertices.size() * sizeof(Vertex3D); - vk::DeviceSize requiredIndexBufferSize = model.indices.size() * sizeof(uint32_t); + VkDeviceSize requiredVertexBufferSize = model.vertices.size() * sizeof(Vertex3D); + VkDeviceSize requiredIndexBufferSize = model.indices.size() * sizeof(uint32_t); if (requiredVertexBufferSize > vertexBufferSize) { throw VkException("Renderer3D::loadModel: vertex buffer too small"); } if (requiredIndexBufferSize > indexBufferSize) { throw VkException("Renderer3D::loadModel: index buffer too small"); } @@ -339,18 +316,14 @@ namespace gz::vlk { rLog.log0("Renderer3D: loadModel: filling vertex buffer"); // copy to vertexBuffer // create staging buffer - vk::Buffer stagingBuffer; + VkBuffer stagingBuffer; MemoryInfo stagingBufferMemory; - vk.createBuffer(requiredVertexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); + vk.createBuffer(requiredVertexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); // fill staging buffer void* data; - vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, requiredVertexBufferSize, NO_MEM_FLAGS, &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer for vertices", "Renderer3D::loadModel"); - } - + vkMapMemory(vk.getDevice(), stagingBufferMemory.memory, stagingBufferMemory.offset, requiredVertexBufferSize, NO_FLAGS, &data); memcpy(data, model.vertices.data(), requiredVertexBufferSize); - vk.getDevice().unmapMemory(stagingBufferMemory.memory); + vkUnmapMemory(vk.getDevice(), stagingBufferMemory.memory); // fill vertex buffer vk.copyBuffer(stagingBuffer, vertexBuffer, requiredVertexBufferSize); vk.destroyBuffer(stagingBuffer, stagingBufferMemory); @@ -358,14 +331,11 @@ namespace gz::vlk { rLog.log0("Renderer3D: loadModel: filling index buffer"); data = nullptr; // copy to index buffer - vk.createBuffer(requiredIndexBufferSize, vk::BufferUsageFlagBits::eTransferSrc, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, stagingBuffer, stagingBufferMemory); + vk.createBuffer(requiredIndexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); // fill staging buffer - result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, requiredIndexBufferSize, NO_MEM_FLAGS, &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer for indices", "Renderer3D::loadModel"); - } + vkMapMemory(vk.getDevice(), stagingBufferMemory.memory, stagingBufferMemory.offset, requiredIndexBufferSize, NO_FLAGS, &data); memcpy(data, model.indices.data(), requiredIndexBufferSize); - vk.getDevice().unmapMemory(stagingBufferMemory.memory); + vkUnmapMemory(vk.getDevice(), stagingBufferMemory.memory); // fill index buffer vk.copyBuffer(stagingBuffer, indexBuffer, requiredIndexBufferSize); vk.destroyBuffer(stagingBuffer, stagingBufferMemory); @@ -375,50 +345,54 @@ namespace gz::vlk { // RENDERING // void Renderer3D::recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame) { - vk::CommandBufferBeginInfo commandBufferBI; - vk::Result result = commandBuffers[currentFrame].begin(commandBufferBI); - if (result != vk::Result::eSuccess) { + VkCommandBufferBeginInfo commandBufferBI{}; + commandBufferBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + commandBufferBI.flags = 0; + commandBufferBI.pInheritanceInfo = nullptr; + VkResult result = vkBeginCommandBuffer(commandBuffers[currentFrame], &commandBufferBI); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to begin 3D command buffer", "Renderer3D::recordCommandBuffer"); } + VkRenderPassBeginInfo renderPassBI{}; + renderPassBI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassBI.renderPass = renderPass; + renderPassBI.framebuffer = framebuffers[imageIndex]; + renderPassBI.renderArea.offset = { 0, 0 }; + renderPassBI.renderArea.extent = vk.getScExtent(); // clear - std::array clearValues{}; - vk::ClearColorValue clearColor{}; - clearColor.setFloat32({0.1f, 0.0f, 0.0f, 0.5f}); - clearValues[0].setColor(std::move(clearColor)); - clearValues[1].setDepthStencil({1.0f, 0}); + std::array clearValues{}; + clearValues[0].color = {{1.0f, 0.0f, 0.0f, 1.0f}}; + /* clearValues[1].depthStencil = {1.0f, 0}; */ + renderPassBI.clearValueCount = static_cast(clearValues.size()); + renderPassBI.pClearValues = clearValues.data(); - vk::RenderPassBeginInfo renderPassBI { - .renderPass = renderPass, - .framebuffer = framebuffers[imageIndex], - .renderArea { .offset = { 0, 0 }, .extent = vk.getScExtent() } - }; - renderPassBI.setClearValues(clearValues); + vkCmdBeginRenderPass(commandBuffers[currentFrame], &renderPassBI, VK_SUBPASS_CONTENTS_INLINE); - commandBuffers[currentFrame].beginRenderPass(renderPassBI, vk::SubpassContents::eInline); - - commandBuffers[currentFrame].bindPipeline(vk::PipelineBindPoint::eGraphics, pipelines[PL_3D].pipeline); - vk::Buffer vertexBuffers[] = { vertexBuffer }; - vk::DeviceSize offsets[] = {0}; + vkCmdBindPipeline(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[PL_3D].pipeline); + VkBuffer vertexBuffers[] = { vertexBuffer }; + VkDeviceSize offsets[] = {0}; uint32_t bindingCount = 1; - uint32_t firstBinding = 0; - commandBuffers[currentFrame].bindVertexBuffers(firstBinding, bindingCount, vertexBuffers, offsets); + vkCmdBindVertexBuffers(commandBuffers[currentFrame], BINDING, bindingCount, vertexBuffers, offsets); // TODO use correct index type! - commandBuffers[currentFrame].bindIndexBuffer(indexBuffer, NO_OFFSET, vk::IndexType::eUint32); + vkCmdBindIndexBuffer(commandBuffers[currentFrame], indexBuffer, NO_OFFSET, VK_INDEX_TYPE_UINT32); + uint32_t descriptorCount = 1; uint32_t firstSet = 0; - commandBuffers[currentFrame].bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelines[PL_3D].layout, firstSet, descriptorSets[currentFrame], {}); + uint32_t dynamicOffsetCount = 0; + uint32_t* dynamicOffsets = nullptr; + vkCmdBindDescriptorSets(commandBuffers[currentFrame], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[PL_3D].layout, firstSet, descriptorCount, &descriptorSets[currentFrame], dynamicOffsetCount, dynamicOffsets); int instanceCount = 1; int firstIndex = 0; int firstInstance = 0; - commandBuffers[currentFrame].drawIndexed(static_cast(model.indices.size()), instanceCount, firstIndex, NO_OFFSET, firstInstance); - commandBuffers[currentFrame].endRenderPass(); + vkCmdDrawIndexed(commandBuffers[currentFrame], static_cast(model.indices.size()), instanceCount, firstIndex, NO_OFFSET, firstInstance); + vkCmdEndRenderPass(commandBuffers[currentFrame]); vk.copyImageToImage(commandBuffers[currentFrame], images[imageIndex], vk.getScImages()[imageIndex], vk.getScExtent()); - result = commandBuffers[currentFrame].end(); - if (result != vk::Result::eSuccess) { - rLog.error("Failed to record 3D - command buffer", "VkResult:", result); + result = vkEndCommandBuffer(commandBuffers[currentFrame]); + if (result != VK_SUCCESS) { + rLog.error("Failed to record 3D - command buffer", "VkResult:", STR_VK_RESULT(result)); throw getVkException(result, "Failed to record 3D - command buffer", "Renderer3D::recordCommandBuffer"); } vk.submitThisFrame(commandBuffers[currentFrame]); @@ -427,7 +401,7 @@ namespace gz::vlk { // RENDERING // void Renderer3D::drawFrame(uint32_t imageIndex) { - commandBuffers[vk.getCurrentFrame()].reset(NO_CMD_RESET_FLAGS); + vkResetCommandBuffer(commandBuffers[vk.getCurrentFrame()], NO_FLAGS); /* recordCommandBuffer(imageIndex, vk.getCurrentFrame()); */ updateUniformBuffer(); recordCommandBuffer(imageIndex, vk.getCurrentFrame()); @@ -435,13 +409,13 @@ namespace gz::vlk { void Renderer3D::createUniformBuffers() { - vk::DeviceSize bufferSize = sizeof(UniformBufferObject); + VkDeviceSize bufferSize = sizeof(UniformBufferObject); uniformBuffers.resize(vk.getMaxFramesInFlight()); uniformBuffersMemory.resize(vk.getMaxFramesInFlight()); for (size_t i = 0; i < vk.getMaxFramesInFlight(); i++) { - vk.createBuffer(bufferSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, uniformBuffers[i], uniformBuffersMemory[i]); + vk.createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]); } } @@ -462,12 +436,9 @@ namespace gz::vlk { /* ubo.projection[1][1] *= -1; // y coordinate inverted in opengl */ MemoryInfo& uniformBufferMI = uniformBuffersMemory[vk.getCurrentFrame()]; void* data; - vk::Result result = vk.getDevice().mapMemory(uniformBufferMI.memory, uniformBufferMI.offset, sizeof(ubo), NO_MEM_FLAGS, &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer", "Renderer3D::updateUniformBuffer"); - } + vkMapMemory(vk.getDevice(), uniformBufferMI.memory, uniformBufferMI.offset, sizeof(ubo), NO_FLAGS, &data); memcpy(data, &ubo, sizeof(ubo)); - vk.getDevice().unmapMemory(uniformBufferMI.memory); + vkUnmapMemory(vk.getDevice(), uniformBufferMI.memory); } @@ -475,4 +446,4 @@ namespace gz::vlk { -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/renderer/renderer3D.hpp b/src/renderer/renderer3D.hpp index 07f6df8..3f66c68 100644 --- a/src/renderer/renderer3D.hpp +++ b/src/renderer/renderer3D.hpp @@ -5,7 +5,7 @@ #include "vulkan_allocator.hpp" #include "vulkan_util.hpp" -namespace gz::vlk { +namespace gz::vk { struct UniformBufferObject { alignas(16) glm::mat4 model; alignas(16) glm::mat4 view; @@ -34,7 +34,7 @@ namespace gz::vlk { /// @} private: void recordCommandBuffer(uint32_t imageIndex, uint32_t currentFrame); - std::vector uniformBuffers; + std::vector uniformBuffers; std::vector uniformBuffersMemory; void createUniformBuffers(); void updateUniformBuffer(); @@ -45,36 +45,24 @@ namespace gz::vlk { * The images are used as render targets. After rendering, the current image gets blitted onto the current swap chain image. */ /// @{ - std::vector images; + std::vector images; std::vector imageMemory; - std::vector imageViews; + std::vector imageViews; /** * @brief Creates the images (on imageMemory) and imageViews with the format of the VulkanInstance::swapChain images */ void createImages(); /// @} - /** - * @name Depth - */ - /// @{ - vk::Image depthImage; - MemoryInfo depthImageMemory; - vk::ImageView depthImageView; - /** - * @brief Create depth image and view with a @ref VulkanInstance::getDepthFormat() "depth format" - */ - void createDepthImage(); - /// @} /** * @name Render pass * @details * Attachments: * - color blend: - * - loadOp = vk::AttachmentLoadOp::eClear - * - storeOp = vk::AttachmentStoreOp::eStore - * - initialLayout = vk::ImageLayout::eColorAttachmentOptimal - * - finalLayout = vk::ImageLayout::eColorAttachmentOptimal + * - loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR + * - storeOp = VK_ATTACHMENT_STORE_OP_STORE + * - initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + * - finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL * - stencil load/store = dont care */ /// @{ @@ -82,10 +70,10 @@ namespace gz::vlk { * @brief Create a render pass */ void createRenderPass(); - vk::RenderPass renderPass; + VkRenderPass renderPass; /// @} - std::vector framebuffers; + std::vector framebuffers; // PIPELINE PipelineContainer pipelines; @@ -96,9 +84,9 @@ namespace gz::vlk { * -# Combined Image Sampler (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) */ /// @{ - vk::DescriptorPool descriptorPool; - vk::DescriptorSetLayout descriptorSetLayout; - std::vector descriptorSets; + VkDescriptorPool descriptorPool; + VkDescriptorSetLayout descriptorSetLayout; + std::vector descriptorSets; /** * @brief Create a descriptor layout binding for the MVP uniform buffer object * @details Create a desciptor set layout with bindings for @@ -128,11 +116,10 @@ namespace gz::vlk { /** * @brief Sets up resources that depend on the swap chain or its attributes * @details - * Initializes: - * - @ref createRenderPass() "render pass" - * - @ref createImages() "images and imageViews" - * - @ref createDepthImage() "depth image and view" - * - @ref VulkanInstance::createFramebuffers() "framebuffers" + * Initializes up: + * - images, imageMemory, imageViews + * - framebuffers + * - render pass * - pipeline */ void initSwapChainDependantResources(); diff --git a/src/shader/shader.frag b/src/shader/shader.frag new file mode 100644 index 0000000..6bf4554 --- /dev/null +++ b/src/shader/shader.frag @@ -0,0 +1,16 @@ +#version 450 +#extension GL_EXT_debug_printf : enable + +layout(binding = 1) uniform sampler2D textureSampler; + +layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragTextureCoordinate; + +layout(location = 0) out vec4 outColor; + +void main() { + /* outColor = vec4(fragColor, 1.0); */ + /* debugPrintfEXT("outColor %v3f", fragColor); */ + outColor = vec4(fragTextureCoordinate, 0.0, 1.0); + /* outColor = vec4(fragColor * texture(textureSampler, fragTextureCoordinate).rgb, 1.0); */ +} diff --git a/src/shader/shader.vert b/src/shader/shader.vert new file mode 100644 index 0000000..351875e --- /dev/null +++ b/src/shader/shader.vert @@ -0,0 +1,25 @@ +#version 450 +#extension GL_EXT_debug_printf : enable + +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +} ubo; + +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inColor; +layout(location = 2) in vec2 inTextureCoordinate; + +layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragTextureCoordinate; + + +void main() { + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + /* gl_Position = vec4(inPosition, 1.0); */ + + /* debugPrintfEXT("inPosition %v3f, inColor %v3f", inPosition, inColor); */ + fragColor = inColor; + fragTextureCoordinate = inTextureCoordinate; +} diff --git a/src/shader/shader2D.frag b/src/shader/shader2D.frag new file mode 100644 index 0000000..5ac53ff --- /dev/null +++ b/src/shader/shader2D.frag @@ -0,0 +1,17 @@ +#version 450 +#extension GL_EXT_debug_printf : enable + +layout(binding = 0) uniform sampler2D textureSampler; + +layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragTextureCoordinate; + +layout(location = 0) out vec4 outColor; + +void main() { + /* outColor = vec4(fragColor, 1.0); */ + /* outColor = vec4(fragTextureCoordinate, 0.0, 1.0); */ + /* outColor = vec4(fragColor * texture(textureSampler, fragTextureCoordinate).rgb, 1.0); */ + outColor = texture(textureSampler, fragTextureCoordinate); + /* debugPrintfEXT("outColor %v3f", outColor); */ +} diff --git a/src/shader/shader2D.vert b/src/shader/shader2D.vert new file mode 100644 index 0000000..d48fa9a --- /dev/null +++ b/src/shader/shader2D.vert @@ -0,0 +1,25 @@ +#version 450 +#extension GL_EXT_debug_printf : enable + +/* layout(binding = 0) uniform UniformBufferObject { */ +/* mat4 model; */ +/* mat4 view; */ +/* mat4 proj; */ +/* } ubo; */ + +layout(location = 0) in vec2 inPosition; +layout(location = 1) in vec3 inColor; +layout(location = 2) in vec2 inTextureCoordinate; + +layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragTextureCoordinate; + + +void main() { + /* gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); */ + gl_Position = vec4(inPosition, 0.0, 1.0); + + /* debugPrintfEXT("inPosition %v2f, inColor %v3f", inPosition, inColor); */ + fragColor = inColor; + fragTextureCoordinate = inTextureCoordinate; +} diff --git a/src/shape.cpp b/src/shape.cpp index e7e629c..88ddce4 100644 --- a/src/shape.cpp +++ b/src/shape.cpp @@ -2,7 +2,7 @@ #include "texture_manager.hpp" -namespace gz::vlk { +namespace gz::vk { Rectangle::Rectangle(float top, float left, uint32_t width, uint32_t height, glm::vec3 color, std::string&& texture) : top(top), left(left), width(width), height(height), color(color) { @@ -55,4 +55,4 @@ namespace gz::vlk { } -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/shape.hpp b/src/shape.hpp index ab8bbb3..4a0da76 100644 --- a/src/shape.hpp +++ b/src/shape.hpp @@ -3,7 +3,7 @@ #include "vertex.hpp" #include -namespace gz::vlk { +namespace gz::vk { // defined in texture_manager.hpp class TextureManager; class Shape { @@ -46,4 +46,4 @@ namespace gz::vlk { glm::vec3 color; void generateVertices(); }; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/utility/exceptions.cpp b/src/utility/exceptions.cpp index 7c88b40..828fb3d 100644 --- a/src/utility/exceptions.cpp +++ b/src/utility/exceptions.cpp @@ -1,9 +1,9 @@ #include "exceptions.hpp" -#include "vulkan_util.hpp" +#include "vk_enum_string.h" namespace gz { - VkException getVkException(vk::Result result, std::string&& what, std::string&& functionName) { + VkException getVkException(VkResult result, std::string&& what, std::string&& functionName) { std::string whatStr; if (!functionName.empty()) { whatStr += "Error in function: " + functionName + ": "; @@ -15,7 +15,7 @@ namespace gz { whatStr += what + ": "; } whatStr += "VkResult="; - whatStr += ::toString(result); + whatStr += STR_VK_RESULT(result); return VkException(whatStr); } } diff --git a/src/utility/exceptions.hpp b/src/utility/exceptions.hpp index b653469..e467c67 100644 --- a/src/utility/exceptions.hpp +++ b/src/utility/exceptions.hpp @@ -2,8 +2,7 @@ #include -#define VULKAN_HPP_NO_CONSTRUCTORS -#include +#include #include #include @@ -32,8 +31,7 @@ namespace gz { /** * @brief Return a VkException with a formatted string - * @todo Return different Exceptions depending in result or make this a constructor of VkException */ - VkException getVkException(vk::Result result, std::string&& what="", std::string&& functionName=""); + VkException getVkException(VkResult result, std::string&& what="", std::string&& functionName=""); } diff --git a/src/utility/texture_atlas.cpp b/src/utility/texture_atlas.cpp index 63ad7bb..d1b7946 100644 --- a/src/utility/texture_atlas.cpp +++ b/src/utility/texture_atlas.cpp @@ -12,10 +12,10 @@ #include #include #include - +#include #include -namespace gz::vlk { +namespace gz::vk { std::string TextureImageArea::toString() const { return "<(" + gz::toString(x) + "," + gz::toString(y) + "), (" + gz::toString(width) + "x" + gz::toString(height) + ")>"; } @@ -29,13 +29,12 @@ TextureAtlas::TextureAtlas(VulkanInstance& instance, uint16_t slotWidth, uint16_ slotCountX(slotCountX), slotCountY(slotCountY) { #ifdef LOG_LEVEL_0 - LogCreateInfo logCI{ - .logfile = "textureAtlas.log", - .storeLog = false, - .prefix = "TextureAtlas (" + gz::toString(slotCountX) + "x" + gz::toString(slotCountY) + ")X(" + gz::toString(slotWidth) + "x" + gz::toString(slotHeight) + ")", - .prefixColor = Color::GREEN, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "textureAtlas.log"; + logCI.storeLog = false; + logCI.prefix = "TextureAtlas (" + gz::toString(slotCountX) + "x" + gz::toString(slotCountY) + ")X(" + gz::toString(slotWidth) + "x" + gz::toString(slotHeight) + ")"; + logCI.prefixColor = Color::GREEN; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; tLog = Log(std::move(logCI)); #endif @@ -60,24 +59,23 @@ void TextureAtlas::cleanup() { void TextureAtlas::createImageResources() { - vk.createImage(slotWidth * slotCountX, slotHeight * slotCountY, vk::Format::eR8G8B8A8Srgb, vk::ImageTiling::eLinear, - vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled, - vk::MemoryPropertyFlagBits::eDeviceLocal, + vk.createImage(slotWidth * slotCountX, slotHeight * slotCountY, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_TILING_LINEAR, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, textureImage, textureImageMemory); - vk::CommandBuffer cmdBuffer = vk.beginSingleTimeCommands(POOL_GRAPHICS); - vk.transitionImageLayout(textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, &cmdBuffer); - vk::ImageSubresourceRange subresourceRange { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }; - cmdBuffer.clearColorImage(textureImage, vk::ImageLayout::eTransferDstOptimal, &settings::missingTextureColor, 1, &subresourceRange); - vk.transitionImageLayout(textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, &cmdBuffer); + VkCommandBuffer cmdBuffer = vk.beginSingleTimeCommands(POOL_GRAPHICS); + vk.transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &cmdBuffer); + VkImageSubresourceRange subresourceRange{}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = 1; + subresourceRange.baseArrayLayer = 0; + subresourceRange.layerCount = 1; + vkCmdClearColorImage(cmdBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &missingTextureColor, 1, &subresourceRange); + vk.transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, &cmdBuffer); vk.endSingleTimeCommands(cmdBuffer, POOL_GRAPHICS); - vk.createImageView(vk::Format::eR8G8B8A8Srgb, textureImage, textureImageView, vk::ImageAspectFlagBits::eColor); + vk.createImageView(VK_FORMAT_R8G8B8A8_SRGB, textureImage, textureImageView, VK_IMAGE_ASPECT_COLOR_BIT); vk.createTextureSampler(textureSampler); } @@ -163,26 +161,22 @@ std::pair TextureAtlas::addTexture(uint8_t* pixels, uint16 void TextureAtlas::blitTextureOnImage(uint8_t* pixels, uint16_t slotX, uint16_t slotY, uint16_t textureWidth, uint16_t textureHeight) { constexpr size_t BYTES_PER_PIXEL = 4; - vk::DeviceSize imageSize = textureWidth * textureHeight * BYTES_PER_PIXEL; - vk::Buffer stagingBuffer; + VkDeviceSize imageSize = textureWidth * textureHeight * BYTES_PER_PIXEL; + VkBuffer stagingBuffer; MemoryInfo stagingBufferMemory; - vk.createBuffer(imageSize, vk::BufferUsageFlagBits::eTransferSrc, - vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, + vk.createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); void* data; - vk::Result result = vk.getDevice().mapMemory(stagingBufferMemory.memory, stagingBufferMemory.offset, imageSize, vk::MemoryMapFlags(), &data); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to map staging buffer", "TextureAtlas::blitTextureOnImage"); - } - + vkMapMemory(vk.getDevice(), stagingBufferMemory.memory, stagingBufferMemory.offset, imageSize, NO_FLAGS, &data); memcpy(data, pixels, static_cast(imageSize)); - vk.getDevice().unmapMemory(stagingBufferMemory.memory); + vkUnmapMemory(vk.getDevice(), stagingBufferMemory.memory); - vk.transitionImageLayout(textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eTransferDstOptimal); + vk.transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vk.copyBufferToImage(stagingBuffer, textureImage, static_cast(slotWidth * slotX), static_cast(slotHeight * slotY), // offset static_cast(textureWidth), static_cast(textureHeight)); // dimensions - vk.transitionImageLayout(textureImage, vk::Format::eR8G8B8A8Srgb, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal); + vk.transitionImageLayout(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); vk.destroyBuffer(stagingBuffer, stagingBufferMemory); } diff --git a/src/utility/texture_atlas.hpp b/src/utility/texture_atlas.hpp index 01f4d06..e9063c5 100644 --- a/src/utility/texture_atlas.hpp +++ b/src/utility/texture_atlas.hpp @@ -3,8 +3,7 @@ #include "vulkan_allocator.hpp" #include #include -#define VULKAN_HPP_NO_CONSTRUCTORS -#include +#include #include #include @@ -15,7 +14,7 @@ #include #endif -namespace gz::vlk { +namespace gz::vk { /** * @brief Describes an area in the textureImage that is not in use */ @@ -62,8 +61,8 @@ namespace gz::vlk { * @throws Exception when there is no space in the atlas to add the texture */ std::pair addTexture(uint8_t* pixels, uint16_t textureWidth, uint16_t textureHeight); - const vk::ImageView& getTextureImageView() const { return textureImageView; } - const vk::Sampler& getTextureSampler() const { return textureSampler; } + const VkImageView& getTextureImageView() const { return textureImageView; } + const VkSampler& getTextureSampler() const { return textureSampler; } std::string toString() const; @@ -82,10 +81,10 @@ namespace gz::vlk { * the textureImage is created with missingTextureColor and then transitioned to SHADER_READ_ONLY_OPTIMAL layout. */ void createImageResources(); - vk::Image textureImage; + VkImage textureImage; MemoryInfo textureImageMemory; - vk::ImageView textureImageView; - vk::Sampler textureSampler; + VkImageView textureImageView; + VkSampler textureSampler; std::set freeAreas; /** @@ -104,4 +103,4 @@ namespace gz::vlk { Log tLog; #endif }; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/utility/texture_manager.cpp b/src/utility/texture_manager.cpp index 480e219..b3fe585 100644 --- a/src/utility/texture_manager.cpp +++ b/src/utility/texture_manager.cpp @@ -3,22 +3,22 @@ #include "vulkan_instance.hpp" #include +#include -namespace gz::vlk { +namespace gz::vk { TextureManager::TextureManager(VulkanInstance& instance) : vk(instance) { - LogCreateInfo logCI{ - .logfile = "textureManager.log", - .storeLog = false, - .prefix = "Texture", - .prefixColor = Color::GREEN, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "textureManager.log"; + logCI.storeLog = false; + logCI.prefix = "Texture"; + logCI.prefixColor = Color::GREEN; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; tLog = Log(std::move(logCI)); vk.registerCleanupCallback(std::bind(&TextureManager::cleanup, this)); - atlases.emplace_back(TextureAtlas(vk, 24, 24, 24, 24)); + atlases.insert({ 0, TextureAtlas(vk, 24, 24, 24, 24) }); createDescriptorSetLayout(); createDescriptorPool(); createDescriptorSet(); @@ -30,10 +30,12 @@ namespace gz::vlk { void TextureManager::cleanup() { tLog.log0("cleanup: cleaning up"); - vk.getDevice().destroyDescriptorSetLayout(descriptorSetLayout, NO_ALLOC); - vk.getDevice().destroyDescriptorPool(descriptorPool, NO_ALLOC); - for (auto& atlas : atlases) { + /* vkFreeDescriptorSets(vk.getDevice(), descriptorPool, 1, &descriptorSet); */ + vkDestroyDescriptorSetLayout(vk.getDevice(), descriptorSetLayout, NO_ALLOC); + vkDestroyDescriptorPool(vk.getDevice(), descriptorPool, NO_ALLOC); + for (auto& [i, atlas] : atlases) { atlas.cleanup(); + } } @@ -44,6 +46,8 @@ namespace gz::vlk { } TextureInfo& texI = textureInfos[textureName]; tLog.log0("getTexCoords", texCoords, "textureInfo: topleft", texI.texCoordTopLeft, "botright", texI.texCoordBottomRight); + /* texCoords.x = texI.texCoordTopLeft.x + texCoords.x * (texI.texCoordBottomRight.x - texI.texCoordTopLeft.x); */ + /* texCoords.y = texI.texCoordTopLeft.y + texCoords.y * (texI.texCoordBottomRight.y - texI.texCoordTopLeft.y); */ texCoords = texI.texCoordTopLeft + texCoords * (texI.texCoordBottomRight - texI.texCoordTopLeft); } @@ -56,12 +60,11 @@ namespace gz::vlk { } TextureInfo& texI = textureInfos[textureName]; texI.atlas = 0; - // TODO auto texCoords = atlases.at(0).addTexture(pixels, textureWidth, textureHeight); stbi_image_free(pixels); tLog.log0("TextureManager::loadTextureFromFile: TexCoords of new image:", texCoords.first, texCoords.second); - texI.texCoordTopLeft = std::move(texCoords.first), - texI.texCoordBottomRight = std::move(texCoords.second), + texI.texCoordTopLeft = std::move(texCoords.first); + texI.texCoordBottomRight = std::move(texCoords.second); tLog.log0("TextureManager::loadTextureFromFile: After loading:", atlases.at(0)); } @@ -71,20 +74,20 @@ namespace gz::vlk { // void TextureManager::createDescriptorSetLayout() { // combined image sampler - std::vector samplerLayoutBindings(atlases.size(), { - .binding = 0, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eFragment, - /* .pImmutableSamplers = nullptr, */ - } - ); + VkDescriptorSetLayoutBinding samplerLayoutBinding{}; + samplerLayoutBinding.binding = 0; + samplerLayoutBinding.descriptorCount = 1; + samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + /* samplerLayoutBinding.pImmutableSamplers = nullptr; */ - vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCI; - descriptorSetLayoutCI.setBindings(samplerLayoutBindings); + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI{}; + descriptorSetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorSetLayoutCI.bindingCount = 1; + descriptorSetLayoutCI.pBindings = &samplerLayoutBinding; - vk::Result result = vk.getDevice().createDescriptorSetLayout(&descriptorSetLayoutCI, nullptr, &descriptorSetLayout); - if (result != vk::Result::eSuccess) { + VkResult result = vkCreateDescriptorSetLayout(vk.getDevice(), &descriptorSetLayoutCI, nullptr, &descriptorSetLayout); + if (result != VK_SUCCESS) { throw getVkException(result, "Could not create descriptorSetLayout", "TextureManager::createDescriptorSetLayout"); } /* vLog("createDescriptorSetLayout: Created descriptor set layout."); */ @@ -92,56 +95,64 @@ void TextureManager::createDescriptorSetLayout() { void TextureManager::createDescriptorPool() { - std::vector poolSizes { - vk::DescriptorPoolSize { - .type = vk::DescriptorType::eCombinedImageSampler, - .descriptorCount = static_cast(vk.getMaxFramesInFlight()) - } - }; + std::array poolSizes; + /* poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; */ + /* poolSizes[0].descriptorCount = static_cast(vk.getMaxFramesInFlight()); */ + poolSizes[0].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + poolSizes[0].descriptorCount = static_cast(vk.getMaxFramesInFlight()); - vk::DescriptorPoolCreateInfo poolCI { .maxSets = 1 }; - poolCI.setPoolSizes(poolSizes); - - vk::Result result; - std::tie(result, descriptorPool) = vk.getDevice().createDescriptorPool(poolCI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create descriptor pool", "TextureManager::createDescriptorPool"); - } + VkDescriptorPoolCreateInfo poolCI{}; + poolCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + poolCI.poolSizeCount = static_cast(poolSizes.size()); + poolCI.pPoolSizes = poolSizes.data(); + poolCI.maxSets = 1; + VkResult result = vkCreateDescriptorPool(vk.getDevice(), &poolCI, nullptr, &descriptorPool); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create descriptor pool", "TextureManager::createDescriptorPool"); + } /* vLog("createDescriptorPool: Created descriptor pool."); */ } void TextureManager::createDescriptorSet() { - vk::DescriptorSetAllocateInfo setAI { - .descriptorPool = descriptorPool, - }; - setAI.setSetLayouts(descriptorSetLayout); + /* std::vector layouts(vk.getMaxFramesInFlight(), descriptorSetLayout); */ + VkDescriptorSetAllocateInfo setAI{}; + setAI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + setAI.descriptorPool = descriptorPool; + /* setAI.descriptorSetCount = static_cast(vk.getMaxFramesInFlight()); */ + /* setAI.pSetLayouts = layouts.data(); */ + setAI.descriptorSetCount = 1; + setAI.pSetLayouts = &descriptorSetLayout; - auto [result, descriptorSetV] = vk.getDevice().allocateDescriptorSets(setAI); - descriptorSet = descriptorSetV.front(); - if (result != vk::Result::eSuccess) { + /* descriptorSets.resize(vk.getMaxFramesInFlight()); */ + /* VkResult result = vkAllocateDescriptorSets(vk.getDevice(), &setAI, descriptorSets.data()); */ + VkResult result = vkAllocateDescriptorSets(vk.getDevice(), &setAI, &descriptorSet); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to create descriptor set", "TextureManager::createDescriptorPool"); } // configure sets - std::vector imageInfos; + std::vector imageInfos; for (auto it = atlases.cbegin(); it != atlases.cend(); it++) { imageInfos.emplace_back(); - imageInfos.back().imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal; - imageInfos.back().imageView = it->getTextureImageView(); - imageInfos.back().sampler = it->getTextureSampler(); + imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfos.back().imageView = it->second.getTextureImageView(); + imageInfos.back().sampler = it->second.getTextureSampler(); } - vk::WriteDescriptorSet descriptorW { - .dstSet = descriptorSet, - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorType = vk::DescriptorType::eCombinedImageSampler, - }; - descriptorW.setImageInfo(imageInfos); + std::array descriptorW{}; + descriptorW[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorW[0].dstSet = descriptorSet; + descriptorW[0].dstBinding = 0; + descriptorW[0].dstArrayElement = 0; + descriptorW[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorW[0].descriptorCount = static_cast(imageInfos.size()); + descriptorW[0].pImageInfo = imageInfos.data(); - // 1 write, no copies - vk.getDevice().updateDescriptorSets(descriptorW, nullptr); - tLog.log0("createDescriptorSets: Created descriptor sets."); + uint32_t descriptorWriteCount = static_cast(descriptorW.size()); + uint32_t descriptorCopyCount = 0; + vkUpdateDescriptorSets(vk.getDevice(), descriptorWriteCount, descriptorW.data(), descriptorCopyCount, nullptr); + /* } */ + /* vLog("createDescriptorSets: Created descriptor sets."); */ } -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/utility/texture_manager.hpp b/src/utility/texture_manager.hpp index 389ccff..417f371 100644 --- a/src/utility/texture_manager.hpp +++ b/src/utility/texture_manager.hpp @@ -10,7 +10,7 @@ #include -namespace gz::vlk { +namespace gz::vk { struct TextureInfo { uint32_t atlas; glm::vec2 texCoordTopLeft; @@ -28,35 +28,30 @@ namespace gz::vlk { */ TextureManager(VulkanInstance& instance); void getTexCoords(const std::string& textureName, glm::vec2& texCoords); - const vk::DescriptorSet& getDescriptorSet() const { return descriptorSet; } - const vk::DescriptorSetLayout& getDescriptorSetLayout() const { return descriptorSetLayout; } + const VkDescriptorSet& getDescriptorSet() const { return descriptorSet; } + const VkDescriptorSetLayout& getDescriptorSetLayout() const { return descriptorSetLayout; } // TODO /// @todo take texture as argument - const TextureAtlas& getTextureAtlas() const { return atlases.at(0); } - uint32_t getAtlasCount() const { return static_cast(atlases.size()); } + const TextureAtlas& getTextureAtlas() const { return atlases.at(0); }; private: void cleanup(); void loadTextureFromFile(const std::string& textureName); - // TODO index currently has no meaning - std::vector atlases; - /** - * @brief Contains textureName : TextureInfo pairs - */ + std::unordered_map atlases; util::unordered_string_map textureInfos; VulkanInstance& vk; Log tLog; /** * @name Create desciptors * @details These functions create a desciptor with bindings for - * -# Array of combined image samplers (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) at binding 0. Array length is atlas count + * -# Combined Image Sampler (DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) at binding 0 * @{ */ - vk::DescriptorSetLayout descriptorSetLayout; - vk::DescriptorPool descriptorPool; - vk::DescriptorSet descriptorSet; - /* std::vector descriptorSets; */ + VkDescriptorSetLayout descriptorSetLayout; + VkDescriptorPool descriptorPool; + VkDescriptorSet descriptorSet; + /* std::vector descriptorSets; */ /** * @brief Create a descriptor set layout * @details @@ -74,4 +69,4 @@ namespace gz::vlk { }; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/utility/vulkan_util.cpp b/src/utility/vulkan_util.cpp index 8be2a38..11922f3 100644 --- a/src/utility/vulkan_util.cpp +++ b/src/utility/vulkan_util.cpp @@ -1,13 +1,9 @@ #include "vulkan_util.hpp" #include #include -#include -#include -#define VULKAN_HPP_NO_CONSTRUCTORS -#include -namespace gz::vlk { +namespace gz::vk { // // CONVENIENCE // @@ -20,9 +16,6 @@ namespace gz::vlk { f11.pNext = &f12; f12.pNext = &f13; } - - /* static_assert(sizeof(VkStructureType) != sizeof(vk::StructureType), "Objects do not have same size"); */ - /* static_assert(sizeof(VkPhysicalDeviceFeatures) != sizeof(vk::PhysicalDeviceFeatures), "Objects do not have same size"); */ bool PhysicalDeviceFeatures::requiredFeaturesAvailable(const PhysicalDeviceFeatures& requiredFeatures) const { // iterate over all the features in the structs // VkPhysicalDeviceFeatures2 @@ -75,47 +68,53 @@ namespace gz::vlk { return true; } - void PipelineContainer::erase(const PipelineT& key, const vk::Device& device, const vk::AllocationCallbacks* pAllocator) { - device.destroyPipeline(pipelines[key].pipeline, pAllocator); - device.destroyPipelineLayout(pipelines[key].layout, pAllocator); + void PipelineContainer::erase(const PipelineT& key, const VkDevice& device, const VkAllocationCallbacks* pAllocator) { + vkDestroyPipeline(device, pipelines[key].pipeline, pAllocator); + vkDestroyPipelineLayout(device, pipelines[key].layout, pAllocator); pipelines.erase(pipelines.find(key)); } - PipelineContainer::iterator PipelineContainer::erase(const PipelineContainer::iterator& it, const vk::Device& device, const vk::AllocationCallbacks* pAllocator) { - device.destroyPipeline(it->second.pipeline, pAllocator); - device.destroyPipelineLayout(it->second.layout, pAllocator); + PipelineContainer::iterator PipelineContainer::erase(const PipelineContainer::iterator& it, const VkDevice& device, const VkAllocationCallbacks* pAllocator) { + vkDestroyPipeline(device, it->second.pipeline, pAllocator); + vkDestroyPipelineLayout(device, it->second.layout, pAllocator); return pipelines.erase(it); } - void PipelineContainer::destroy(const vk::Device& device, const vk::AllocationCallbacks* pAllocator) { + void PipelineContainer::destroy(const VkDevice& device, const VkAllocationCallbacks* pAllocator) { auto it = pipelines.begin(); while (it != pipelines.end()) { it = erase(it, device); } } - vk::DependencyInfo getDepInfo(const vk::ImageMemoryBarrier2& barrier) { - vk::DependencyInfo depI { - .imageMemoryBarrierCount = 1, - .pImageMemoryBarriers = &barrier, - }; + VkDependencyInfo getDepInfo(const VkImageMemoryBarrier2& barrier) { + VkDependencyInfo depI{}; + depI.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO; + depI.imageMemoryBarrierCount = 1; + depI.pImageMemoryBarriers = &barrier; return depI; } - /* void getBufferMemoryRequirements(const vk::Device& device, const vk::Buffer& buffer, vk::BufferMemoryRequirementsInfo2& bufMemReq, vk::MemoryRequirements2& memReq) { */ - /* bufMemReq.pNext = nullptr; */ - /* bufMemReq.buffer = buffer; */ + void getBufferMemoryRequirements(const VkDevice& device, const VkBuffer& buffer, VkBufferMemoryRequirementsInfo2& bufMemReq, VkMemoryRequirements2& memReq) { + bufMemReq.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; + bufMemReq.pNext = nullptr; + bufMemReq.buffer = buffer; - /* memReq.pNext = nullptr; */ - /* vk::getBufferMemoryRequirements2(device, &bufMemReq, &memReq); */ - /* } */ + memReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + memReq.pNext = nullptr; + vkGetBufferMemoryRequirements2(device, &bufMemReq, &memReq); + } - /* void getImageMemoryRequirements(const vk::Device& device, const vk::Image& image, vk::ImageMemoryRequirementsInfo2& imMemReq, vk::MemoryRequirements2& memReq) { */ - /* imMemReq.image = image; */ + void getImageMemoryRequirements(const VkDevice& device, const VkImage& image, VkImageMemoryRequirementsInfo2& imMemReq, VkMemoryRequirements2& memReq) { + imMemReq.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; + imMemReq.pNext = nullptr; + imMemReq.image = image; - /* memReq = device.getImageMemoryRequirements2(imMemReq); */ - /* } */ + memReq.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + memReq.pNext = nullptr; + vkGetImageMemoryRequirements2(device, &imMemReq, &memReq); + } // @@ -143,7 +142,7 @@ namespace gz::vlk { } -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/utility/vulkan_util.hpp b/src/utility/vulkan_util.hpp index 2d6448b..0e53fa7 100644 --- a/src/utility/vulkan_util.hpp +++ b/src/utility/vulkan_util.hpp @@ -5,25 +5,9 @@ #include #include #include -#define VULKAN_HPP_NO_CONSTRUCTORS -#define VULKAN_HPP_NO_EXCEPTIONS -#include +#include -#ifdef GZ_UTIL_STRING_CONCEPTS - static_assert(false, "gz-util/util/string_conversion.hpp is included before vulkan_util.hpp!"); -#endif - -template -concept VkToString = requires(const T& t) { - { vk::to_string(t) }; -}; - -template -inline std::string toString(const T& t) { - return vk::to_string(t); -} - -namespace gz::vlk { +namespace gz::vk { /** * @name Convenience structs * @details @@ -34,14 +18,13 @@ namespace gz::vlk { * @brief Struct containing all physical device features structs * @details * Make sure to call vkGetPhysicalDeviceFeatures2 with the f member, not this struct itself - * @todo Redo with vulkan.hpp and vk::StructureChain */ struct PhysicalDeviceFeatures { /** * @brief Initialize the structs with sType and pNext chain f -> f11 -> f12 -> f13 */ PhysicalDeviceFeatures(); - VkPhysicalDeviceFeatures2 f {}; + VkPhysicalDeviceFeatures2 f{}; VkPhysicalDeviceVulkan11Features f11{}; VkPhysicalDeviceVulkan12Features f12{}; VkPhysicalDeviceVulkan13Features f13{}; @@ -55,8 +38,8 @@ namespace gz::vlk { PL_3D, PL_2D }; struct Pipeline { - vk::Pipeline pipeline; - vk::PipelineLayout layout; + VkPipeline pipeline; + VkPipelineLayout layout; void operator=(const Pipeline& other) = delete; }; @@ -70,15 +53,15 @@ namespace gz::vlk { /** * @brief Destroy the pipeline+layout and then remove the handles from the underlying map */ - void erase(const PipelineT& key, const vk::Device& device, const vk::AllocationCallbacks* pAllocator=nullptr); + void erase(const PipelineT& key, const VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr); /** * @brief Destroy the pipeline+layout and then remove the handles from the underlying map */ - iterator erase(const iterator& it, const vk::Device& device, const vk::AllocationCallbacks* pAllocator=nullptr); + iterator erase(const iterator& it, const VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr); /** * @brief Destroy all pipelines#layouts and then remove the handles from the underlying map */ - void destroy(const vk::Device& device, const vk::AllocationCallbacks* pAllocator=nullptr); + void destroy(const VkDevice& device, const VkAllocationCallbacks* pAllocator=nullptr); iterator begin() { return pipelines.begin(); } iterator end() { return pipelines.end(); } size_t size() const { return pipelines.size(); } @@ -88,9 +71,9 @@ namespace gz::vlk { }; struct SwapChainSupport { - vk::SurfaceCapabilities2KHR capabilities; - std::vector formats; - std::vector presentModes; + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector presentModes; }; @@ -101,12 +84,12 @@ namespace gz::vlk { struct VerticesAndIndices { std::vector vertices; std::vector indices; - constexpr vk::IndexType getIndexType() const { + constexpr VkIndexType getIndexType() const { if (std::same_as) { - return vk::IndexType::eUint16; + return VK_INDEX_TYPE_UINT16; } else if (std::same_as) { - return vk::IndexType::eUint32; + return VK_INDEX_TYPE_UINT32; } } }; @@ -141,30 +124,30 @@ namespace gz::vlk { /** - * @brief Get a vk::DependencyInfo struct for a single image memory barrier + * @brief Get a VkDependencyInfo struct for a single image memory barrier */ - vk::DependencyInfo getDepInfo(const vk::ImageMemoryBarrier2& barrier); + VkDependencyInfo getDepInfo(const VkImageMemoryBarrier2& barrier); /** * @brief Fill bufMeqReq and memReq * @details * Fill the structs and call vkGetBufferMemoryRequirements2() */ - /* void getBufferMemoryRequirements(const vk::Device& device, const vk::Buffer& buffer, vk::BufferMemoryRequirementsInfo2& bufMemReq, vk::MemoryRequirements2& memReq); */ + void getBufferMemoryRequirements(const VkDevice& device, const VkBuffer& buffer, VkBufferMemoryRequirementsInfo2& bufMemReq, VkMemoryRequirements2& memReq); /** * @brief Fill imMemReq and memReq * @details * Fill the structs and call vkGetImageMemoryRequirements2() */ - /* void getImageMemoryRequirements(const vk::Device& device, const vk::Image& image, vk::ImageMemoryRequirementsInfo2& imMemReq, vk::MemoryRequirements2& memReq); */ + void getImageMemoryRequirements(const VkDevice& device, const VkImage& image, VkImageMemoryRequirementsInfo2& imMemReq, VkMemoryRequirements2& memReq); /// @} /** * @brief Used for debugging * @see VulkanInstance::debugLog * @details - * Handles like vk::Device are pointers to the actual handle. + * Handles like VkDevice are pointers to the actual handle. * Register the handle to a vulkan object with this struct and call updateHandles(). * The handles set will then contain the actual address of the handle, as printed by the validation layers. * That means you can check a handle returned by a validation layer @@ -186,33 +169,4 @@ namespace gz::vlk { }; - - /** - * @brief Check if all required extensions are available - */ - template - bool areExtensionsAvailable(const RE& requiredExtensions, const AE& availableExtensions) - requires std::same_as, const char*&> and std::same_as, vk::ExtensionProperties&> - { - bool extensionAvailable; - for (const auto& requiredExtension : requiredExtensions) { - extensionAvailable = false; - for (const auto& extension : availableExtensions) { - if (strcmp(requiredExtension, extension.extensionName) == 0) { - extensionAvailable = true; - break; - } - } - if (!extensionAvailable) { - return false; - } - } - return true; - } - - /** - * @file - * @brief Various utility structs and functions, as well as toString() overload for vk objects - */ - -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/vertex.cpp b/src/vertex.cpp index 1882631..a6b7f31 100644 --- a/src/vertex.cpp +++ b/src/vertex.cpp @@ -1,21 +1,20 @@ #include "vertex.hpp" -#define VULKAN_HPP_NO_CONSTRUCTORS -#include +#include #include #include -namespace gz::vlk { +namespace gz::vk { const uint32_t BINDING = 0; template -vk::Format getVkFormat() { +VkFormat getVkFormat() { if (std::same_as) { - return vk::Format::eR32G32B32Sfloat; + return VK_FORMAT_R32G32B32_SFLOAT; } else if (std::same_as) { - return vk::Format::eR32G32Sfloat; + return VK_FORMAT_R32G32_SFLOAT; } } @@ -30,29 +29,28 @@ vk::Format getVkFormat() { template - vk::VertexInputBindingDescription Vertex::getBindingDescription() { - vk::VertexInputBindingDescription bindingD { - .binding = BINDING, - .stride = sizeof(Vertex), - .inputRate = vk::VertexInputRate::eVertex, - }; + VkVertexInputBindingDescription Vertex::getBindingDescription() { + VkVertexInputBindingDescription bindingD{}; + bindingD.binding = BINDING; + bindingD.stride = sizeof(Vertex); + bindingD.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; return bindingD; } template - std::array Vertex::getAttributeDescriptions() { - std::array inputAttributeD{}; + std::array Vertex::getAttributeDescriptions() { + std::array inputAttributeD{}; inputAttributeD[0].binding = BINDING; inputAttributeD[0].location = 0; inputAttributeD[0].format = getVkFormat(); inputAttributeD[0].offset = offsetof(Vertex, pos); inputAttributeD[1].binding = BINDING; inputAttributeD[1].location = 1; - inputAttributeD[1].format = vk::Format::eR32G32B32Sfloat; + inputAttributeD[1].format = VK_FORMAT_R32G32B32_SFLOAT; inputAttributeD[1].offset = offsetof(Vertex, color); inputAttributeD[2].binding = BINDING; inputAttributeD[2].location = 2; - inputAttributeD[2].format = vk::Format::eR32G32Sfloat; + inputAttributeD[2].format = VK_FORMAT_R32G32_SFLOAT; inputAttributeD[2].offset = offsetof(Vertex, texCoord); return inputAttributeD; @@ -65,11 +63,11 @@ vk::Format getVkFormat() { template std::string Vertex::toString() const; template std::string Vertex::toString() const; - template vk::VertexInputBindingDescription Vertex::getBindingDescription(); - template vk::VertexInputBindingDescription Vertex::getBindingDescription(); - template std::array Vertex::getAttributeDescriptions(); - template std::array Vertex::getAttributeDescriptions(); + template VkVertexInputBindingDescription Vertex::getBindingDescription(); + template VkVertexInputBindingDescription Vertex::getBindingDescription(); + template std::array Vertex::getAttributeDescriptions(); + template std::array Vertex::getAttributeDescriptions(); template bool Vertex::operator==(const Vertex& other) const; template bool Vertex::operator==(const Vertex& other) const; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/vertex.hpp b/src/vertex.hpp index b797ad6..d6b2b9f 100644 --- a/src/vertex.hpp +++ b/src/vertex.hpp @@ -6,19 +6,17 @@ #include #include +/* #include */ -// defined in vulkan/vulkan.hpp -namespace vk { - struct VertexInputBindingDescription; - struct VertexInputAttributeDescription; -} +struct VkVertexInputBindingDescription; +struct VkVertexInputAttributeDescription; -namespace gz::vlk { +namespace gz::vk { template concept VertexType = requires { - requires std::same_as; + requires std::same_as; requires std::ranges::forward_range; - requires std::same_as, vk::VertexInputAttributeDescription>; + requires std::same_as, VkVertexInputAttributeDescription>; }; template @@ -37,12 +35,12 @@ namespace gz::vlk { glm::vec2 texCoord = { 0, 0 }; std::string toString() const; bool operator==(const Vertex& other) const; - static vk::VertexInputBindingDescription getBindingDescription(); - static std::array getAttributeDescriptions(); + static VkVertexInputBindingDescription getBindingDescription(); + static std::array getAttributeDescriptions(); }; // struct Vertex using Vertex3D = Vertex; using Vertex2D = Vertex; -} // namespace gz::vlk +} // namespace gz::vk @@ -50,9 +48,9 @@ namespace gz::vlk { // HASHES // namespace std { - template - struct hash> { - size_t operator()(gz::vlk::Vertex const& vertex) const { + template + struct hash> { + size_t operator()(gz::vk::Vertex const& vertex) const { return ((hash()(vertex.pos)) ^ (hash()(vertex.color) << 1) >> 1 ) ^ (hash()(vertex.texCoord) << 1); diff --git a/src/vk_convert.cpp b/src/vk_convert.cpp index e0e9f3a..ba4e83c 100644 --- a/src/vk_convert.cpp +++ b/src/vk_convert.cpp @@ -1,6 +1,6 @@ #include "vk_convert.hpp" -bool vkBool2Bool(const vk::Bool32& b) { +bool vkBool2Bool(const VkBool32& b) { if (b == VK_TRUE) { return true; } @@ -9,7 +9,7 @@ bool vkBool2Bool(const vk::Bool32& b) { } }; -vk::Bool32 bool2VkBool(const bool& b) { +VkBool32 bool2VkBool(const bool& b) { if (b) { return VK_TRUE; } @@ -18,7 +18,7 @@ vk::Bool32 bool2VkBool(const bool& b) { } } -std::string vkBool2String(const vk::Bool32& b) { +std::string vkBool2String(const VkBool32& b) { if (b == VK_TRUE) { return "true"; } @@ -27,7 +27,7 @@ std::string vkBool2String(const vk::Bool32& b) { } }; -vk::Bool32 string2VkBool(const std::string& s) { +VkBool32 string2VkBool(const std::string& s) { if (s == "true") { return VK_TRUE; } diff --git a/src/vk_convert.hpp b/src/vk_convert.hpp index 6d0be7d..a7dd343 100644 --- a/src/vk_convert.hpp +++ b/src/vk_convert.hpp @@ -1,10 +1,9 @@ -#define VULKAN_HPP_NO_CONSTRUCTORS -#include +#include #include -vk::Bool32 bool2VkBool(const bool& b); -bool vkBool2Bool(const vk::Bool32& b); +VkBool32 bool2VkBool(const bool& b); +bool vkBool2Bool(const VkBool32& b); -vk::Bool32 string2VkBool(const std::string& s); -std::string vkBool2String(const vk::Bool32& b); +VkBool32 string2VkBool(const std::string& s); +std::string vkBool2String(const VkBool32& b); diff --git a/src/vulkan_allocator.cpp b/src/vulkan_allocator.cpp index 165bd0d..68f9fa6 100644 --- a/src/vulkan_allocator.cpp +++ b/src/vulkan_allocator.cpp @@ -5,14 +5,15 @@ #include #include +#include -namespace gz::vlk { +namespace gz::vk { std::string MemoryBlock::toString() const { return std::string(""); } - DeviceMemory::DeviceMemory(vk::DeviceSize size_) { + DeviceMemory::DeviceMemory(VkDeviceSize size_) { size = size_; memory = VK_NULL_HANDLE; blocks.emplace_back(MemoryBlock{size, 0, true}); @@ -22,18 +23,17 @@ namespace gz::vlk { VulkanAllocator::VulkanAllocator(VulkanInstance& instance) : vk(instance) { - LogCreateInfo logCI { - .logfile = "vulkan_allocator.log", - .storeLog = false, - .prefix = "Allocator", - .prefixColor = Color::BLACK, - .timeColor = settings::VULKAN_MESSAGE_TIME_COLOR, - }; + LogCreateInfo logCI{}; + logCI.logfile = "vulkan_allocator.log"; + logCI.storeLog = false; + logCI.prefix = "Allocator"; + logCI.prefixColor = Color::BLACK; + logCI.timeColor = VULKAN_MESSAGE_TIME_COLOR; aLog = Log(std::move(logCI)); } - void VulkanAllocator::allocate(const vk::MemoryAllocateInfo& allocI, const vk::MemoryRequirements2& memReq, MemoryInfo& memoryInfo) { + void VulkanAllocator::allocate(const VkMemoryAllocateInfo& allocI, const VkMemoryRequirements2& memReq, MemoryInfo& memoryInfo) { aLog.log0("allocate: Requesting memory with ( size", toHexString(allocI.allocationSize), "), ( memoryTypeIndex", allocI.memoryTypeIndex, "), ( alignment", toHexString(memReq.memoryRequirements.alignment), ")"); @@ -72,7 +72,7 @@ namespace gz::vlk { memoryInfo.offset = block->offset; memoryInfo.memoryTypeIndex = allocI.memoryTypeIndex; - /* aLog.log0("allocate: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(deviceMemory - memory[memoryInfo.memoryTypeIndex].begin()) + ") Blocks:", deviceMemory->blocks); */ + aLog.log0("allocate: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(deviceMemory - memory[memoryInfo.memoryTypeIndex].begin()) + ") Blocks:", deviceMemory->blocks); return; } } @@ -80,12 +80,13 @@ namespace gz::vlk { // if nothing is found, allocate new memory memory[allocI.memoryTypeIndex].emplace_back(DeviceMemory(allocI.allocationSize * TODO_ALLOCATION_SIZE_MULTIPLIIER)); - vk::MemoryAllocateInfo allocI_{}; + VkMemoryAllocateInfo allocI_{}; + allocI_.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocI_.memoryTypeIndex = allocI.memoryTypeIndex; allocI_.allocationSize = memory[allocI.memoryTypeIndex].back().size; aLog.log0("allocate: Allocating new memory of size:", gz::toHexString(allocI_.allocationSize, 0), "(memory", memoryInfo.memoryTypeIndex, "-", gz::toString(memory[memoryInfo.memoryTypeIndex].size()) + ")"); - vk::Result result = vk.getDevice().allocateMemory(&allocI_, NO_ALLOC, &memory[allocI.memoryTypeIndex].back().memory); - if (result != vk::Result::eSuccess) { + VkResult result = vkAllocateMemory(vk.getDevice(), &allocI_, NO_ALLOC, &memory[allocI.memoryTypeIndex].back().memory); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to allocate memory", "VulkanAllocator::allocate"); } @@ -95,11 +96,11 @@ namespace gz::vlk { deviceMemory.blocks.front().size -= allocI.allocationSize; deviceMemory.blocks.emplace_front(MemoryBlock{ allocI.allocationSize, 0, false }); - // alignment always satisfied with vk::allocateMemory() and offset 0 + // alignment always satisfied with vkAllocateMemory() and offset 0 memoryInfo.memory = deviceMemory.memory; memoryInfo.offset = 0; memoryInfo.memoryTypeIndex = allocI.memoryTypeIndex; - /* aLog.log0("allocate: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(memory[memoryInfo.memoryTypeIndex].size()) + ") Blocks:", deviceMemory.blocks); */ + aLog.log0("allocate: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(memory[memoryInfo.memoryTypeIndex].size()) + ") Blocks:", deviceMemory.blocks); } @@ -135,11 +136,11 @@ namespace gz::vlk { memoryInfo.memory = VK_NULL_HANDLE; memoryInfo.offset = 0; - /* aLog.log0("free: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(deviceMemory - memory[memoryInfo.memoryTypeIndex].begin()) + ") Blocks:", deviceMemory->blocks); */ + aLog.log0("free: (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(deviceMemory - memory[memoryInfo.memoryTypeIndex].begin()) + ") Blocks:", deviceMemory->blocks); // if now there is only one free block, everything is free -> deallocate memory if (deviceMemory->blocks.size() == 1) { aLog.log0("free: Deallocating (memory", memoryInfo.memoryTypeIndex, "-", gz::toString(deviceMemory - memory[memoryInfo.memoryTypeIndex].begin()) + ") of size:", gz::toHexString(deviceMemory->size, 0)); - vk.getDevice().freeMemory(deviceMemory->memory, NO_ALLOC); + vkFreeMemory(vk.getDevice(), deviceMemory->memory, NO_ALLOC); memory[memoryInfo.memoryTypeIndex].erase(deviceMemory); } return; @@ -159,11 +160,11 @@ namespace gz::vlk { aLog.warning("cleanup: (memory", memType->first, "-", gz::toString(deviceMemory - memType->second.begin()) + ") Block not freed: ", *block); } aLog.log0("free: Deallocating (memory", memType->first, "-", gz::toString(deviceMemory - memType->second.begin()) + ") of size:", gz::toHexString(deviceMemory->size, 0)); - vk.getDevice().freeMemory(deviceMemory->memory, NO_ALLOC); + vkFreeMemory(vk.getDevice(), deviceMemory->memory, NO_ALLOC); } } memory.clear(); } -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/vulkan_allocator.hpp b/src/vulkan_allocator.hpp index 015fe51..72947b9 100644 --- a/src/vulkan_allocator.hpp +++ b/src/vulkan_allocator.hpp @@ -4,28 +4,27 @@ #include #include - -#define VULKAN_HPP_NO_EXCEPTIONS -#define VULKAN_HPP_NO_CONSTRUCTORS #include +#include #include #include +/* #include */ -namespace gz::vlk { +namespace gz::vk { /** - * @brief Contains information about a subsection (block) of a vk::DeviceMemory + * @brief Contains information about a subsection (block) of a VkDeviceMemory */ struct MemoryInfo { /** * @brief Handle of the memory */ - vk::DeviceMemory memory = VK_NULL_HANDLE; + VkDeviceMemory memory = VK_NULL_HANDLE; /** * @brief Offset into memory */ - vk::DeviceSize offset = 0; + VkDeviceSize offset = 0; /** * @brief The memoryTypeIndex memory was allocated from. Needed for VulkanAllocator::free() */ @@ -43,20 +42,20 @@ namespace gz::vlk { }; /** - * @brief Manage a single vk::DeviceMemory chunk + * @brief Manage a single VkDeviceMemory chunk */ struct DeviceMemory { DeviceMemory() = delete; - DeviceMemory(vk::DeviceSize size_); + DeviceMemory(VkDeviceSize size_); - vk::DeviceSize size; - vk::DeviceMemory memory; + VkDeviceSize size; + VkDeviceMemory memory; std::list blocks; }; // if no memory is available, allocate a chunk of multiplier * requested size - constexpr vk::DeviceSize TODO_ALLOCATION_SIZE_MULTIPLIIER = 10; + constexpr VkDeviceSize TODO_ALLOCATION_SIZE_MULTIPLIIER = 10; // defined in vulkan_instance.hpp @@ -65,7 +64,7 @@ namespace gz::vlk { /** * @brief Allocator for device local memory * @details - * Allocates larger chunks of vk::DeviceMemory from which blocks can be @ref allocate() "allocated". + * Allocates larger chunks of VkDeviceMemory from which blocks can be @ref allocate() "allocated". * * This class is for device local memory only, not for host memory. * You can not use it for vulkan memory allocation callbacks (pAllocator). @@ -74,34 +73,34 @@ namespace gz::vlk { * The usage is explained with the example of creating and destroying a single buffer. * @code * // Create buffer handle - * vk::Buffer buffer; + * VkBuffer buffer; * // Create empty memory info struct * MemoryInfo bufferMI; * - * vk::BufferCreateInfo bufferCI{} + * VkBufferCreateInfo bufferCI{} * ... - * vk::createBuffer(...); + * vkCreateBuffer(...); * * // get memory requirements - * vk::MemoryRequirements2 memReq; - * vk::BufferMemoryRequirementsInfo2 bufMemReq; + * VkMemoryRequirements2 memReq; + * VkBufferMemoryRequirementsInfo2 bufMemReq; * // from vulkan_util.hpp, same exists for imageMemoryRequirements * getBufferMemoryRequirements(device, buffer, bufMemReq, memReq); * * // set allocation info - * vk::MemoryAllocateInfo memAI { + * VkMemoryAllocateInfo memAI{}; * ... - * .memoryTypeIndex = VulkanInstance::findMemoryType(memReq.memoryRequirements.memoryTypeBits, wantedProperties), + * memAI.memoryTypeIndex = VulkanInstance::findMemoryType(memReq.memoryRequirements.memoryTypeBits, wantedProperties); * * // allocate memory for the buffer * VulkanAllocator::allocate(memAI, memReq, bufferMI); * * // bind the buffer to the memory - * device.bindBufferMemory(buffer, bufferMI.memory, bufferMI.offset); + * vkBindBufferMemory(device, buffer, bufferMI.memory, bufferMI.offset); * * ... * - * device.destroyBuffer(buffer); + * vkDestroyBuffer(device, buffer); * VulkanAllocator::free(bufferMemoryInfo); * @endcode * @@ -111,23 +110,23 @@ namespace gz::vlk { public: VulkanAllocator(VulkanInstance& instance); /** - * @brief Get a block from a vk::DeviceMemory + * @brief Get a block from a VkDeviceMemory * @details - * Get a block of allocI.allocationSize of a vk::DeviceMemory that was allocated with allocI.memoryTypeIndex. + * Get a block of allocI.allocationSize of a VkDeviceMemory that was allocated with allocI.memoryTypeIndex. * * When this function returns, memoryInfo will contain the information about the available block. * You can then bind something of size allocI.allocationSize to memoryInfo.memory at offset memoryInfo.offset. - * @throws vk::Exception when a call to vkAllocateMemory is needed and fails + * @throws VkException when a call to vkAllocateMemory is needed and fails * @todo Determine the size of new allocations - * @todo alignment, maybe use vk::MemoryRequirements instead of vk::MemoryAllocateInfo? + * @todo alignment, maybe use VkMemoryRequirements instead of VkMemoryAllocateInfo? * @todo maybe increase the block size of the allocated block so that the following blocks is already 16-aligned? */ - void allocate(const vk::MemoryAllocateInfo& allocI, const vk::MemoryRequirements2& memReq, MemoryInfo& memoryInfo); + void allocate(const VkMemoryAllocateInfo& allocI, const VkMemoryRequirements2& memReq, MemoryInfo& memoryInfo); /** * @brief Free a block allocated with allocate() * * When this function returns, memoryInfo will be reset to default values - * @throws vk::UserError if memoryInfo was not allocated from this allocator + * @throws VkUserError if memoryInfo was not allocated from this allocator */ void free(MemoryInfo& memoryInfo); @@ -148,4 +147,4 @@ namespace gz::vlk { VulkanInstance& vk; }; // class VulkanAllocator -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/vulkan_instance.cpp b/src/vulkan_instance.cpp index c27f4da..db8b3cd 100644 --- a/src/vulkan_instance.cpp +++ b/src/vulkan_instance.cpp @@ -1,17 +1,20 @@ #include "vulkan_instance.hpp" #include "exceptions.hpp" -/* #include "font.hpp" */ +#include "font.hpp" +#include "vk_enum_string.h" +#include "vulkan_allocator.hpp" #include "vulkan_util.hpp" - +#include +#include +#include #include #include #include +#include +#include #include -#include -#include - #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" @@ -19,14 +22,14 @@ #include "tiny_obj_loader.h" #include +#include #include #include #include #include -#define VULKAN_HPP_NO_CONSTRUCTORS -#include +#include -namespace gz::vlk { +namespace gz::vk { using std::uint32_t; @@ -35,22 +38,150 @@ using std::uint32_t; // const unsigned int WIDTH = 600; const unsigned int HEIGHT = 600; - // DEBUG -#ifdef NDEBUG - constexpr bool enableValidationLayers = false; -#else - constexpr bool enableValidationLayers = true; -#endif - // TODO: why needed at two separate places? - constexpr vk::DebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCI { - .pNext = &settings::validationFeatures, - .messageSeverity = settings::debugMessageSevereties, - .messageType = settings::debugMessageTypes, - .pfnUserCallback = VulkanInstance::debugLog, - .pUserData = nullptr, + const std::vector extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + /* VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME */ + }; + const std::vector instanceExtensions = { }; + // + // DEBUG + // + const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation", + }; +#ifdef NDEBUG + constexpr bool enableValidationLayers = false; +#else + constexpr bool enableValidationLayers = true; +#endif + + constexpr VkDebugUtilsMessageSeverityFlagsEXT debugMessageSevereties = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + + constexpr VkDebugUtilsMessageTypeFlagsEXT debugMessageTypes = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + const std::vector validationFeaturesEnable { + VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT, + VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, + VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT + }; + const VkValidationFeaturesEXT validationFeatures { + VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT, // sType + nullptr, // pNext + static_cast(validationFeaturesEnable.size()), // enabled feature count + validationFeaturesEnable.data(), // enable features + 0, // disabled feature count + nullptr // disabled features + }; + + /* constexpr VkDebugUtilsMessageTypeFlagsEXT debugFlags = */ + /* VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT | */ + /* VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT; */ + + constexpr VkDebugUtilsMessengerCreateInfoEXT debugUtilsMessengerCI { + VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, // sType + &validationFeatures, // pNext + /* nullptr, // pNext */ + NO_FLAGS, // flags + debugMessageSevereties, // messageSeverety + debugMessageTypes, // messageType + VulkanInstance::debugLog, // pfnUserCallback + nullptr, // pUserData + + }; + + +// +// UTILITY FUNCTIONS +// + // + // EXTENSIONS + // + bool checkRequiredExtensionsAvailable(const std::vector& requiredExtensions, const std::vector& availableExtensions) { + bool extensionAvailable; + for (const auto& requiredExtension : requiredExtensions) { + extensionAvailable = false; + for (const auto& extension : availableExtensions) { + if (strcmp(requiredExtension, extension.extensionName) == 0) { + extensionAvailable = true; + break; + } + } + if (!extensionAvailable) { + return false; + } + } + return true; + } + + + std::vector getRequiredExtensions() { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector requiredExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + + if (enableValidationLayers) { + requiredExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + return requiredExtensions; + } + + + // check if all extensions are supported by device + bool deviceExtensionsSupported(VkPhysicalDevice device) { + uint32_t extensionCount; + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + std::vector availableExtensions(extensionCount); + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); + + bool extensionAvailable; + for (const char* requiredExtension : extensions) { + extensionAvailable = false; + for (const auto& extensionProperties : availableExtensions) { + if (strcmp(requiredExtension, extensionProperties.extensionName) == 0) { + extensionAvailable = true; + break; + } + } + if (!extensionAvailable) { return false; } + } + return true; + } + + // + // VALIDATION LAYERS + // + // check if validation layers are supported/installed + bool validationLayersSupported() { + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + bool layerAvailable; + for (const char* requiredLayer : validationLayers) { + layerAvailable = false; + for (const auto& layerProperties : availableLayers) { + if (strcmp(requiredLayer, layerProperties.layerName) == 0) { + layerAvailable = true; + break; + } + } + if (!layerAvailable) { return false; } + } + return true; + } + + +// // // IMPLEMENTATION OF VULKANINSTANCE // @@ -89,10 +220,7 @@ using std::uint32_t; void VulkanInstance::cleanup() { - vk::Result result = device.waitIdle(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to wait for device idle", "VulkanInstance::cleanup"); - } + vkDeviceWaitIdle(device); // call callbacks in reverse order for (auto it = cleanupCallbacks.rbegin(); it != cleanupCallbacks.rend(); it++) { (*it)(); @@ -102,91 +230,86 @@ using std::uint32_t; destroyCommandBuffers(commandBuffersBegin); destroyCommandBuffers(commandBuffersEnd); - /* device.destroyImageView(textureImageView, nullptr); */ - /* device.destroySampler(textureSampler, nullptr); */ - /* device.destroyImage(textureImage, nullptr); */ - /* device.freeMemory(textureImageMemory, nullptr); */ + /* vkDestroyImageView(device, textureImageView, nullptr); */ + /* vkDestroySampler(device, textureSampler, nullptr); */ + /* vkDestroyImage(device, textureImage, nullptr); */ + /* vkFreeMemory(device, textureImageMemory, nullptr); */ cleanupSwapChain(); for (size_t i = 0; i < getMaxFramesInFlight(); i++) { - device.destroySemaphore(imageAvailableSemaphores[i], nullptr); - device.destroySemaphore(renderFinishedSemaphores[i], nullptr); - device.destroyFence(inFlightFences[i], nullptr); + vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); + vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); + vkDestroyFence(device, inFlightFences[i], nullptr); } - /* device.freeCommandBuffers(commandPoolGraphics, static_cast(commandBuffers2D.size()), commandBuffers2D.data()); */ - /* device.freeCommandBuffers(commandPoolGraphics, static_cast(commandBuffers3D.size()), commandBuffers3D.data()); */ + /* vkFreeCommandBuffers(device, commandPoolGraphics, static_cast(commandBuffers2D.size()), commandBuffers2D.data()); */ + /* vkFreeCommandBuffers(device, commandPoolGraphics, static_cast(commandBuffers3D.size()), commandBuffers3D.data()); */ - device.destroyCommandPool(commandPoolGraphics, nullptr); - device.destroyCommandPool(commandPoolTransfer, nullptr); + vkDestroyCommandPool(device, commandPoolGraphics, nullptr); + vkDestroyCommandPool(device, commandPoolTransfer, nullptr); allocator.cleanup(); - device.destroy(); - instance.destroySurfaceKHR(surface); + vkDestroyDevice(device, nullptr); + vkDestroySurfaceKHR(instance, surface, nullptr); cleanupDebugMessenger(); - instance.destroy(); + vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); } uint32_t VulkanInstance::beginFrameDraw() { - vk::Result result = device.waitForFences(inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to wait for fence", "VulkanInstance::beginFrameDraw"); - } + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); uint32_t imageIndex; uint32_t blockFor = 0; /* uint64_t blockFor = UINT64_MAX; */ - result = device.acquireNextImageKHR(swapChain, blockFor, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - if (result == vk::Result::eErrorOutOfDateKHR or frameBufferResized) { // result == VK_SUBOPTIMAL_KHR or - vLog.log0("drawFrame: result:", result, "frameBufferResized:", frameBufferResized); + VkResult result = vkAcquireNextImageKHR(device, swapChain, blockFor, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR or frameBufferResized) { // result == VK_SUBOPTIMAL_KHR or + vLog.log0("drawFrame: result:", STR_VK_RESULT(result), "frameBufferResized:", frameBufferResized); frameBufferResized = false; recreateSwapChain(); return imageIndex; } - else if (result != vk::Result::eSuboptimalKHR and result != vk::Result::eSuccess) { + else if (result != VK_SUBOPTIMAL_KHR and result != VK_SUCCESS) { + /* vLog.error("Failed to acquire swap chain image. Result:", STR_VK_RESULT(result)); */ throw getVkException(result, "Failed to acquire swap chain image.", "beginFrameDraw"); } - result = device.resetFences(1, &inFlightFences[currentFrame]); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to reset fences", "VulkanInstance::beginFrameDraw"); - } + vkResetFences(device, 1, &inFlightFences[currentFrame]); // clear image - commandBuffersBegin[currentFrame].reset(NO_CMD_RESET_FLAGS); - vk::CommandBufferBeginInfo commandBufferBI; - result = commandBuffersBegin[currentFrame].begin(commandBufferBI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to begin clear command buffer", "VulkanInstance::beginFrameDraw"); + vkResetCommandBuffer(commandBuffersBegin[currentFrame], NO_FLAGS); + VkCommandBufferBeginInfo commandBufferBI{}; + commandBufferBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + result = vkBeginCommandBuffer(commandBuffersBegin[currentFrame], &commandBufferBI); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to begin clear command buffer", "beginFrameDraw"); } // transition to transfer dst layout - transitionImageLayout(scImages[imageIndex], scImageFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, &commandBuffersBegin[currentFrame]); - vk::ImageMemoryBarrier2 imageBarrier { - .srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe, - .dstStageMask = vk::PipelineStageFlagBits2::eTransfer, - .oldLayout = vk::ImageLayout::eUndefined, - .newLayout = vk::ImageLayout::eTransferDstOptimal, - .image = scImages[imageIndex], - .subresourceRange { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - } - }; - vk::DependencyInfo depI = getDepInfo(imageBarrier); - commandBuffersBegin[currentFrame].pipelineBarrier2(depI); + transitionImageLayout(scImages[imageIndex], scImageFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &commandBuffersBegin[currentFrame]); + VkImageMemoryBarrier2 imageBarrier{}; + imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + imageBarrier.image = scImages[imageIndex]; + imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + imageBarrier.srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT; + /* imageBarrier.srcAccessMask = VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV; */ + imageBarrier.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT; + imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + imageBarrier.subresourceRange.baseMipLevel = 0; + imageBarrier.subresourceRange.levelCount = 1; + imageBarrier.subresourceRange.baseArrayLayer = 0; + imageBarrier.subresourceRange.layerCount = 1; + VkDependencyInfo depI = getDepInfo(imageBarrier); + vkCmdPipelineBarrier2(commandBuffersBegin[currentFrame], &depI); - result = commandBuffersBegin[currentFrame].end(); - if (result != vk::Result::eSuccess) { - vLog.error("Failed to record clear command buffer", "VkResult:", result); - throw getVkException(result, "Failed to record 2D - command buffer", "VulkanInstance::beginFrameDraw"); + result = vkEndCommandBuffer(commandBuffersBegin[currentFrame]); + if (result != VK_SUCCESS) { + vLog.error("Failed to record clear command buffer", "VkResult:", STR_VK_RESULT(result)); + throw getVkException(result, "Failed to record 2D - command buffer", "beginFrameDraw"); } commandBuffersToSubmitThisFrame.push_back(commandBuffersBegin[currentFrame]); @@ -195,46 +318,57 @@ using std::uint32_t; void VulkanInstance::endFrameDraw(uint32_t imageIndex) { - commandBuffersEnd[currentFrame].reset(NO_CMD_RESET_FLAGS); - vk::CommandBufferBeginInfo commandBufferBI; - vk::Result result = commandBuffersEnd[currentFrame].begin(commandBufferBI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to begin command buffer", "VulkanInstance::endFrameDraw"); + vkResetCommandBuffer(commandBuffersEnd[currentFrame], NO_FLAGS); + VkCommandBufferBeginInfo commandBufferBI{}; + commandBufferBI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + VkResult result = vkBeginCommandBuffer(commandBuffersEnd[currentFrame], &commandBufferBI); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to begin command buffer", "beginFrameDraw"); } // transition to present layout - transitionImageLayout(scImages[imageIndex], scImageFormat, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::ePresentSrcKHR, &commandBuffersEnd[currentFrame]); - result = commandBuffersEnd[currentFrame].end(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to record command buffer", "VulkanInstance::endFrameDraw"); + transitionImageLayout(scImages[imageIndex], scImageFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, &commandBuffersEnd[currentFrame]); + result = vkEndCommandBuffer(commandBuffersEnd[currentFrame]); + if (result != VK_SUCCESS) { + vLog.error("Failed to record clear command buffer", "VkResult:", STR_VK_RESULT(result)); + throw getVkException(result, "Failed to record command buffer", "beginFrameDraw"); } commandBuffersToSubmitThisFrame.push_back(commandBuffersEnd[currentFrame]); // submit all command buffers - vk::SubmitInfo submitI; - submitI.setWaitSemaphores(imageAvailableSemaphores[currentFrame]); - vk::PipelineStageFlags dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput; - submitI.setWaitDstStageMask(dstStageMask); - submitI.setSignalSemaphores(renderFinishedSemaphores[currentFrame]); - submitI.setCommandBuffers(commandBuffersToSubmitThisFrame); + VkSubmitInfo submitI{}; + submitI.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - result = graphicsQ.submit(submitI, inFlightFences[currentFrame]); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to submit command buffers", "VulkanInstance::endFrameDraw"); + VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submitI.waitSemaphoreCount = 1; + submitI.pWaitSemaphores = waitSemaphores; + submitI.pWaitDstStageMask = waitStages; + submitI.commandBufferCount = static_cast(commandBuffersToSubmitThisFrame.size()); + submitI.pCommandBuffers = commandBuffersToSubmitThisFrame.data(); + VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; + submitI.signalSemaphoreCount = 1; + submitI.pSignalSemaphores = signalSemaphores; + + uint32_t submitCount = 1; + result = vkQueueSubmit(graphicsQ, submitCount, &submitI, inFlightFences[currentFrame]); + if (result != VK_SUCCESS) { + vLog.error("Failed to submit draw command buffer", "VkResult:", STR_VK_RESULT(result)); + throw std::runtime_error("Failed to submit draw command buffer"); } commandBuffersToSubmitThisFrame.clear(); // present the image - vk::PresentInfoKHR presentI { - .pImageIndices = &imageIndex, - .pResults = nullptr, - }; - presentI.setWaitSemaphores(renderFinishedSemaphores[currentFrame]); - presentI.setSwapchains(swapChain); + VkPresentInfoKHR presentI{}; + presentI.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentI.waitSemaphoreCount = 1; + presentI.pWaitSemaphores = signalSemaphores; - result = presentQ.presentKHR(presentI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed present image", "VulkanInstance::endFrameDraw"); - } + VkSwapchainKHR swapChains[] = {swapChain}; + presentI.swapchainCount = 1; + presentI.pSwapchains = swapChains; + presentI.pImageIndices = &imageIndex; + presentI.pResults = nullptr; + vkQueuePresentKHR(presentQ, &presentI); currentFrame = ++currentFrame % getMaxFramesInFlight(); } @@ -259,60 +393,54 @@ using std::uint32_t; // PUBLIC INTERFACE: VARIOUS UTILITY - void VulkanInstance::submitThisFrame(vk::CommandBuffer& cmdBuffer) { + void VulkanInstance::submitThisFrame(VkCommandBuffer& cmdBuffer) { commandBuffersToSubmitThisFrame.push_back(cmdBuffer); } - void VulkanInstance::copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize size) { - vk::CommandBuffer cmdBuffer = beginSingleTimeCommands(POOL_TRANSFER); - vk::BufferCopy copyRegion { - .srcOffset = 0, - .dstOffset = 0, - .size = size, - }; - cmdBuffer.copyBuffer(srcBuffer, dstBuffer, copyRegion); + void VulkanInstance::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { + VkCommandBuffer cmdBuffer = beginSingleTimeCommands(POOL_TRANSFER); + VkBufferCopy copyRegion{}; + copyRegion.srcOffset = 0; + copyRegion.dstOffset = 0; + copyRegion.size = size; + uint32_t copyRegionCount = 1; + vkCmdCopyBuffer(cmdBuffer, srcBuffer, dstBuffer, copyRegionCount, ©Region); endSingleTimeCommands(cmdBuffer, POOL_TRANSFER); } - vk::CommandBuffer VulkanInstance::beginSingleTimeCommands(InstanceCommandPool commandPool) { - vk::CommandBufferAllocateInfo allocI { - .level = vk::CommandBufferLevel::ePrimary, - .commandBufferCount = 1, - }; + VkCommandBuffer VulkanInstance::beginSingleTimeCommands(InstanceCommandPool commandPool) { + VkCommandBufferAllocateInfo allocI{}; + allocI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocI.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; if (commandPool == POOL_TRANSFER) { - allocI.setCommandPool(commandPoolTransfer); + allocI.commandPool = commandPoolTransfer; } else { - allocI.setCommandPool(commandPoolGraphics); + allocI.commandPool = commandPoolGraphics; } + allocI.commandBufferCount = 1; - vk::CommandBuffer cmdBuffer; - vk::Result result = device.allocateCommandBuffers(&allocI, &cmdBuffer); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to allocate command buffer", "beginSingleTimeCommands"); - } + VkCommandBuffer cmdBuffer; + vkAllocateCommandBuffers(device, &allocI, &cmdBuffer); - vk::CommandBufferBeginInfo beginI { - .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit, - }; - result = cmdBuffer.begin(beginI); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to begin command buffer", "beginSingleTimeCommands"); - } + VkCommandBufferBeginInfo beginI{}; + beginI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginI.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkBeginCommandBuffer(cmdBuffer, &beginI); return cmdBuffer; } - void VulkanInstance::endSingleTimeCommands(vk::CommandBuffer cmdBuffer, InstanceCommandPool commandPool) { - vk::Result result = cmdBuffer.end(); - if (result != vk::Result::eSuccess) { + void VulkanInstance::endSingleTimeCommands(VkCommandBuffer cmdBuffer, InstanceCommandPool commandPool) { + VkResult result = vkEndCommandBuffer(cmdBuffer); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to end commandBuffer", "endSingleTimeCommands"); } - vk::CommandPool cmdPool; - vk::Queue q; + VkCommandPool cmdPool; + VkQueue q; if (commandPool == POOL_TRANSFER) { cmdPool = commandPoolTransfer; q = transferQ; @@ -322,28 +450,30 @@ using std::uint32_t; q = graphicsQ; } - vk::SubmitInfo submitI; - submitI.setCommandBuffers(cmdBuffer); - - result = q.submit(submitI); - if (result != vk::Result::eSuccess) { + VkSubmitInfo submitI{}; + submitI.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitI.commandBufferCount = 1; + submitI.pCommandBuffers = &cmdBuffer; + uint32_t submitCount = 1; + result = vkQueueSubmit(q, submitCount, &submitI, VK_NULL_HANDLE); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to submit commandBuffer", "endSingleTimeCommands"); } - - result = q.waitIdle(); - if (result != vk::Result::eSuccess) { + result = vkQueueWaitIdle(q); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to wait for queue idle", "endSingleTimeCommands"); } - device.freeCommandBuffers(cmdPool, cmdBuffer); + const uint32_t commandBufferCount = 1; + vkFreeCommandBuffers(device, cmdPool, commandBufferCount, &cmdBuffer); } - void VulkanInstance::loadModel(const std::string& path, VerticesAndIndices& model) { + void VulkanInstance::loadModel(VerticesAndIndices& model) { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warnings, errors; - if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warnings, &errors, path.c_str())) { + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warnings, &errors, MODEL_PATH.c_str())) { vLog.warning("Warning from tinyobj::LoadObj: ", warnings); throw gz::Exception("Error loading obj: " + errors, "loadModel"); } @@ -375,37 +505,46 @@ using std::uint32_t; } } +// TODO + // DEPTH + /* VkFormat VulkanInstance::findDepthFormat() { */ + /* return findSupportedFormat({ VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT }, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); */ + /* } */ + // PUBLIC INTERFACE: CREATION AND DESTRUCTION // COMMAND BUFFER - void VulkanInstance::createCommandBuffers(std::vector& commandBuffers) { + void VulkanInstance::createCommandBuffers(std::vector& commandBuffers) { commandBuffers.resize(getMaxFramesInFlight()); - vk::CommandBufferAllocateInfo commandBufferAI { - .commandPool = commandPoolGraphics, - .level = vk::CommandBufferLevel::ePrimary, - .commandBufferCount = static_cast(commandBuffers.size()), - }; - vk::Result result = device.allocateCommandBuffers(&commandBufferAI, commandBuffers.data()); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create allocate buffers", "VulkanInstance::createCommandBuffers"); + VkCommandBufferAllocateInfo commandBufferAI{}; + commandBufferAI.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + commandBufferAI.commandPool = commandPoolGraphics; + commandBufferAI.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + commandBufferAI.commandBufferCount = static_cast(commandBuffers.size()); + VkResult result = vkAllocateCommandBuffers(device, &commandBufferAI, commandBuffers.data()); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create command buffer", "createCommandBuffer"); } } - void VulkanInstance::destroyCommandBuffers(std::vector& commandBuffers) { - device.freeCommandBuffers(commandPoolGraphics, commandBuffers); + void VulkanInstance::destroyCommandBuffers(std::vector& commandBuffers) { + vkFreeCommandBuffers(device, commandPoolGraphics, static_cast(commandBuffers.size()), commandBuffers.data()); commandBuffers.resize(0); } // DESCRIPTORS SET LAYOUTS - void VulkanInstance::createDescriptorSetLayout(std::vector bindings, vk::DescriptorSetLayout& layout) { - vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutCI; - descriptorSetLayoutCI.setBindings(bindings); + void VulkanInstance::createDescriptorSetLayout(std::vector bindings, VkDescriptorSetLayout& layout) { + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCI{}; + descriptorSetLayoutCI.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorSetLayoutCI.bindingCount = static_cast(bindings.size()); + descriptorSetLayoutCI.pBindings = bindings.data(); - vk::Result result = device.createDescriptorSetLayout(&descriptorSetLayoutCI, NO_ALLOC, &layout); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Could not create descriptorSetLayout", "VulkanInstance::createDescriptorSetLayout"); + + VkResult result = vkCreateDescriptorSetLayout(device, &descriptorSetLayoutCI, nullptr, &layout); + if (result != VK_SUCCESS) { + throw getVkException(result, "Could not create descriptorSetLayout", "createDescriptorSetLayout"); } /* vLog.log0("createDescriptorSetLayout: Created descriptor set layout."); */ } @@ -413,224 +552,238 @@ using std::uint32_t; // GRAPHICS PIPELINE template - void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, vk::RenderPass& renderPass, Pipeline& pipeline, vk::SpecializationInfo* fragSI, vk::SpecializationInfo* vertSI) { + void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, VkRenderPass& renderPass, Pipeline& pipeline) { auto vertShaderCode = readFile(vertexShader); auto fragShaderCode = readFile(fragmentShader); - vk::ShaderModule vertShaderModule = createShaderModule(vertShaderCode); - vk::ShaderModule fragShaderModule = createShaderModule(fragShaderCode); + VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); + VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); - vk::PipelineShaderStageCreateInfo vertexShaderStageCI { - .stage = vk::ShaderStageFlagBits::eVertex, - .module = vertShaderModule, - .pName = "main", - .pSpecializationInfo = vertSI, - }; + VkPipelineShaderStageCreateInfo vertexShaderStageCI{}; + vertexShaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertexShaderStageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertexShaderStageCI.module = vertShaderModule; + vertexShaderStageCI.pName = "main"; + /* vssCreateInfo.pSpecializationInfo = nullptr; */ - vk::PipelineShaderStageCreateInfo fragmentShaderStageCI { - .stage = vk::ShaderStageFlagBits::eFragment, - .module = fragShaderModule, - .pName = "main", - .pSpecializationInfo = fragSI, - }; + VkPipelineShaderStageCreateInfo fragmentShaderStageCI{}; + fragmentShaderStageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragmentShaderStageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragmentShaderStageCI.module = fragShaderModule; + fragmentShaderStageCI.pName = "main"; + /* vssCreateInfo.pSpecializationInfo = nullptr; */ - vk::PipelineShaderStageCreateInfo shaderStagesCI[] = { vertexShaderStageCI, fragmentShaderStageCI }; + VkPipelineShaderStageCreateInfo shaderStagesCI[] = { vertexShaderStageCI, fragmentShaderStageCI }; - vk::VertexInputBindingDescription bindingD = VertexT::getBindingDescription(); - // array + VkVertexInputBindingDescription bindingD = VertexT::getBindingDescription(); + // array auto attributeD = VertexT::getAttributeDescriptions(); - vk::PipelineVertexInputStateCreateInfo vertexInputStateCI; - vertexInputStateCI.setVertexAttributeDescriptions(attributeD); - vertexInputStateCI.setVertexBindingDescriptions(bindingD); + VkPipelineVertexInputStateCreateInfo vertexInputStateCI{}; + vertexInputStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputStateCI.vertexBindingDescriptionCount = 1; + vertexInputStateCI.pVertexBindingDescriptions = &bindingD; + vertexInputStateCI.vertexAttributeDescriptionCount = static_cast(attributeD.size());; + vertexInputStateCI.pVertexAttributeDescriptions = attributeD.data(); - vk::PipelineInputAssemblyStateCreateInfo inputAssemblyStateCI { - .topology = vk::PrimitiveTopology::eTriangleList, - .primitiveRestartEnable = VK_FALSE, - }; + VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI{}; + inputAssemblyStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssemblyStateCI.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssemblyStateCI.primitiveRestartEnable = VK_FALSE; - vk::Viewport viewport { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(scExtent.width), - .height = static_cast(scExtent.height), - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = static_cast(scExtent.width); + viewport.height = static_cast(scExtent.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; - vk::Rect2D scissor { - .offset = {0, 0}, - .extent = scExtent, - }; + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = scExtent; - vk::PipelineViewportStateCreateInfo viewportStateCI { - .viewportCount = 1, - .pViewports = &viewport, - .scissorCount = 1, - .pScissors = &scissor, - }; + VkPipelineViewportStateCreateInfo viewportStateCI{}; + viewportStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportStateCI.viewportCount = 1; + viewportStateCI.pViewports = &viewport; + viewportStateCI.scissorCount = 1; + viewportStateCI.pScissors = &scissor; - vk::PipelineRasterizationStateCreateInfo rasterizerCI { - .depthClampEnable = VK_FALSE, - .rasterizerDiscardEnable = VK_FALSE, - .polygonMode = vk::PolygonMode::eFill, - .cullMode = vk::CullModeFlagBits::eBack, - // not clockwise because of inverted y axis from glm - .frontFace = vk::FrontFace::eCounterClockwise, - .depthBiasEnable = VK_FALSE, - .lineWidth = 1.0f, - /* .depthBiasConstantFactor = 0.0f, */ - /* .depthBiasClamp = 0.0f, */ - /* .depthBiasSlopeFactor = 0.0f, */ - }; + VkPipelineRasterizationStateCreateInfo rasterizerCI{}; + rasterizerCI.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizerCI.depthClampEnable = VK_FALSE; + rasterizerCI.rasterizerDiscardEnable = VK_FALSE; + rasterizerCI.polygonMode = VK_POLYGON_MODE_FILL; + rasterizerCI.lineWidth = 1.0f; + rasterizerCI.cullMode = VK_CULL_MODE_BACK_BIT; + // not clockwise because of inverted y axis from glm + rasterizerCI.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rasterizerCI.depthBiasEnable = VK_FALSE; + /* rasterizerCI.depthBiasConstantFactor = 0.0f; */ + /* rasterizerCI.depthBiasClamp = 0.0f; */ + /* rasterizerCI.depthBiasSlopeFactor = 0.0f; */ - vk::PipelineMultisampleStateCreateInfo multisampleStateCI { - .rasterizationSamples = vk::SampleCountFlagBits::e1, - .sampleShadingEnable = VK_FALSE, - /* .minSampleShading = 1.0f, */ - /* .pSampleMask = nullptr, */ - /* .alphaToCoverageEnable = VK_FALSE, */ - /* .alphaToOneEnable = VK_FALSE, */ - }; + VkPipelineMultisampleStateCreateInfo multisampleStateCI{}; + multisampleStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampleStateCI.sampleShadingEnable = VK_FALSE; + multisampleStateCI.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + /* multisampleStateCI.minSampleShading = 1.0f; */ + /* multisampleStateCI.pSampleMask = nullptr; */ + /* multisampleStateCI.alphaToCoverageEnable = VK_FALSE; */ + /* multisampleStateCI.alphaToOneEnable = VK_FALSE; */ - vk::PipelineColorBlendAttachmentState colorBlendAttachment { - .blendEnable = VK_FALSE, - /* .srcColorBlendFactor = vk::BlendFactor::eOne, */ - /* .dstColorBlendFactor = vk::BlendFactor::eZero, */ - /* .colorBlendOp = vk::BlendOp::eAdd, */ - /* .srcAlphaBlendFactor = vk::BlendFactor::eOne, */ - /* .dstAlphaBlendFactor = vk::BlendFactor::eZero, */ - /* .alphaBlendOp = vk::BlendOp::eAdd, */ - .colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA, - }; + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + /* colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; */ + /* colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; */ + /* colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; */ + /* colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; */ + /* colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; */ + /* colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; */ - vk::PipelineColorBlendStateCreateInfo colorBlendCI { - .logicOpEnable = VK_FALSE, - }; - colorBlendCI.setAttachments(colorBlendAttachment); + VkPipelineColorBlendStateCreateInfo colorBlendCI{}; + colorBlendCI.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlendCI.logicOpEnable = VK_FALSE; + /* colorBlendCI.logicOp = VK_LOGIC_OP_COPY; */ + colorBlendCI.attachmentCount = 1; + colorBlendCI.pAttachments = &colorBlendAttachment; colorBlendCI.blendConstants[0] = 0.0f; colorBlendCI.blendConstants[1] = 0.0f; colorBlendCI.blendConstants[2] = 0.0f; colorBlendCI.blendConstants[3] = 0.0f; - /* std::vector dynamicStates = { */ - /* vk::DynamicState::eViewport, */ - /* vk::DynamicState::eLineWidth */ + /* std::vector dynamicStates = { */ + /* VK_DYNAMIC_STATE_VIEWPORT, */ + /* VK_DYNAMIC_STATE_LINE_WIDTH */ /* }; */ - /* vk::PipelineDynamicStateCreateInfo dynamicState { */ + /* VkPipelineDynamicStateCreateInfo dynamicState{}; */ + /* dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; */ /* dynamicState.dynamicStateCount = static_cast(dynamicStates.size()); */ /* dynamicState.pDynamicStates = dynamicStates.data(); */ - vk::PipelineDepthStencilStateCreateInfo depthStencilCI { - .depthTestEnable = VK_TRUE, - .depthWriteEnable = VK_TRUE, - .depthCompareOp = vk::CompareOp::eLess, - .depthBoundsTestEnable = VK_FALSE, - /* .minDepthBounds = 0.0f, */ - /* .maxDepthBounds = 1.0f, */ - .stencilTestEnable = VK_FALSE, - /* .front = {}, */ - /* .back = {}, */ - }; + VkPipelineDepthStencilStateCreateInfo depthStencilCI{}; + depthStencilCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencilCI.depthTestEnable = VK_TRUE; + depthStencilCI.depthWriteEnable = VK_TRUE; + depthStencilCI.depthCompareOp = VK_COMPARE_OP_LESS; + depthStencilCI.depthBoundsTestEnable = VK_FALSE; + /* depthStencilCI.minDepthBounds = 0.0f; */ + /* depthStencilCI.maxDepthBounds = 1.0f; */ + depthStencilCI.stencilTestEnable = VK_FALSE; + /* depthStencilCI.front = {}; */ + /* depthStencilCI.back = {}; */ - vk::PipelineLayoutCreateInfo pipelineLayoutCI; - /* pipelineLayoutCI.setPushConstantRanges() */ - pipelineLayoutCI.setSetLayouts(descriptorSetLayouts); - vk::Result result = device.createPipelineLayout(&pipelineLayoutCI, nullptr, &pipeline.layout); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create pipeline layout", "VulkanInstance::createGraphicsPipeline"); + VkPipelineLayoutCreateInfo pipelineLayoutCI{}; + pipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + /* pipelineLayoutCI.pushConstantRangeCount = 0; */ + /* pipelineLayoutCI.pPushConstantRanges = nullptr; */ + pipelineLayoutCI.setLayoutCount = static_cast(descriptorSetLayouts.size()); + pipelineLayoutCI.pSetLayouts = descriptorSetLayouts.data(); + VkResult result = vkCreatePipelineLayout(device, &pipelineLayoutCI, nullptr, &pipeline.layout); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create pipeline layout", "createGraphicsPipeline"); } - vk::GraphicsPipelineCreateInfo pipelineCI { - .pVertexInputState = &vertexInputStateCI, - .pInputAssemblyState = &inputAssemblyStateCI, - .pViewportState = &viewportStateCI, - .pRasterizationState = &rasterizerCI, - .pMultisampleState = &multisampleStateCI, - .pDepthStencilState = useDepthStencil ? &depthStencilCI : nullptr, - .pColorBlendState = &colorBlendCI, - /* .pDynamicState = nullptr, */ - .layout = pipeline.layout, - .renderPass = renderPass, - .subpass = 0, - /* .basePipelineHandle = VK_NULL_HANDLE, */ - /* .basePipelineIndex = -1, */ - }; - pipelineCI.setStages(shaderStagesCI); + VkGraphicsPipelineCreateInfo pipelineCI{}; + pipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineCI.stageCount = 2; + pipelineCI.pStages = shaderStagesCI; + pipelineCI.pVertexInputState = &vertexInputStateCI; + pipelineCI.pInputAssemblyState = &inputAssemblyStateCI; + pipelineCI.pViewportState = &viewportStateCI; + pipelineCI.pRasterizationState = &rasterizerCI; + pipelineCI.pMultisampleState = &multisampleStateCI; + if (useDepthStencil) { + pipelineCI.pDepthStencilState = &depthStencilCI; + } + else { + pipelineCI.pDepthStencilState = nullptr; + } + pipelineCI.pColorBlendState = &colorBlendCI; + /* pipelineCI.pDynamicState = nullptr; */ + pipelineCI.layout = pipeline.layout; + pipelineCI.renderPass = renderPass; + pipelineCI.subpass = 0; + /* pipelineCI.basePipelineHandle = VK_NULL_HANDLE; */ + /* pipelineCI.basePipelineIndex = -1; */ - // result, vector - auto [result2, pipelines] = device.createGraphicsPipelines(VK_NULL_HANDLE, pipelineCI, NO_ALLOC); - pipeline.pipeline = pipelines.front(); - if (result2 != vk::Result::eSuccess) { + result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineCI, nullptr, &pipeline.pipeline); + if (result != VK_SUCCESS) { throw getVkException(result, "Could not create graphics pipeline", "createGraphicsPipeline"); } - device.destroyShaderModule(vertShaderModule, nullptr); - device.destroyShaderModule(fragShaderModule, nullptr); + vkDestroyShaderModule(device, vertShaderModule, nullptr); + vkDestroyShaderModule(device, fragShaderModule, nullptr); vLog.log0("createGraphicsPipeline: Created graphics pipeline."); } - template void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, vk::RenderPass& renderPass, Pipeline& pipeline, vk::SpecializationInfo* fragSI, vk::SpecializationInfo* vertSI); - template void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, vk::RenderPass& renderPass, Pipeline& pipeline, vk::SpecializationInfo* fragSI, vk::SpecializationInfo* vertSI); + template void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, VkRenderPass& renderPass, Pipeline& pipeline); + template void VulkanInstance::createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, VkRenderPass& renderPass, Pipeline& pipeline); // SHADER MODULE - vk::ShaderModule VulkanInstance::createShaderModule(const std::vector& code) { - vk::ShaderModuleCreateInfo shaderModuleCI { - .codeSize = code.size(), - .pCode = reinterpret_cast(code.data()), - }; + VkShaderModule VulkanInstance::createShaderModule(const std::vector& code) { + VkShaderModuleCreateInfo smCreateInfo{}; + smCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + smCreateInfo.codeSize = code.size(); + smCreateInfo.pCode = reinterpret_cast(code.data()); - auto [result, shaderModule] = device.createShaderModule(shaderModuleCI, NO_ALLOC); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create shader module. Code size: " + std::to_string(code.size()), "VulkanInstance::createShaderModule"); + VkShaderModule shaderModule{}; + + VkResult result = vkCreateShaderModule(device, &smCreateInfo, nullptr, &shaderModule); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create shader module. Code size: " + std::to_string(code.size()), "createShaderModule"); } return shaderModule; } // BUFFER - void VulkanInstance::createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, MemoryInfo& bufferMI, vk::SharingMode sharingMode, std::vector* qFamiliesWithAccess) { - vk::BufferCreateInfo bufferCI { - .size = size, - .usage = usage, - .sharingMode = sharingMode, - }; - /* std::vector queueFamiliesWithAccess; */ - if (sharingMode == vk::SharingMode::eConcurrent) { + void VulkanInstance::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, MemoryInfo& bufferMI, VkSharingMode sharingMode, std::vector* qFamiliesWithAccess) { + VkBufferCreateInfo bufferCI{}; + bufferCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferCI.size = size; + bufferCI.usage = usage; + bufferCI.sharingMode = sharingMode; + std::vector queueFamiliesWithAccess; + if (sharingMode == VK_SHARING_MODE_CONCURRENT) { if (qFamiliesWithAccess == nullptr) { - throw VkUserError("Sharing mode is vk::SharingMode::eConcurrent but qFamiliesWithAccess is nullptr", "VulkanInstance::createBuffer"); + throw VkUserError("Sharing mode is VK_SHARING_MODE_CONCURRENT but qFamiliesWithAccess is nullptr", "createBuffer"); } - bufferCI.setQueueFamilyIndices(*qFamiliesWithAccess); + bufferCI.queueFamilyIndexCount = static_cast(qFamiliesWithAccess->size()); + bufferCI.pQueueFamilyIndices = qFamiliesWithAccess->data(); } - vk::Result result = device.createBuffer(&bufferCI, nullptr, &buffer); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create buffer", "VulkanInstance::createBuffer"); + VkResult result = vkCreateBuffer(device, &bufferCI, nullptr, &buffer); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create buffer", "createBuffer"); } - vk::BufferMemoryRequirementsInfo2 bufMemReq { .buffer = buffer, }; - vk::MemoryRequirements2 memReq = device.getBufferMemoryRequirements2(bufMemReq); + VkMemoryRequirements2 memReq; + VkBufferMemoryRequirementsInfo2 bufMemReq; + getBufferMemoryRequirements(device, buffer, bufMemReq, memReq); - vk::MemoryPropertyFlags wantedProperties = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent; - vk::MemoryAllocateInfo memoryAI { - .allocationSize = memReq.memoryRequirements.size, - .memoryTypeIndex = findMemoryType(memReq.memoryRequirements.memoryTypeBits, wantedProperties), - }; + VkMemoryAllocateInfo memoryAI{}; + memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memoryAI.allocationSize = memReq.memoryRequirements.size; + VkMemoryPropertyFlags wantedProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + memoryAI.memoryTypeIndex = findMemoryType(memReq.memoryRequirements.memoryTypeBits, wantedProperties); allocator.allocate(memoryAI, memReq, bufferMI); - result = device.bindBufferMemory(buffer, bufferMI.memory, bufferMI.offset); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to bind buffer to its memory", "VulkanInstance::createBuffer"); + result = vkBindBufferMemory(device, buffer, bufferMI.memory, bufferMI.offset); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to bind buffer to its memory", "createBuffer"); } vLog.log0("createBuffer: created and bound buffer of size", memoryAI.allocationSize); } - void VulkanInstance::destroyBuffer(vk::Buffer& buffer, MemoryInfo& bufferMemory) { - device.destroyBuffer(buffer, NO_ALLOC); + void VulkanInstance::destroyBuffer(VkBuffer& buffer, MemoryInfo& bufferMemory) { + vkDestroyBuffer(device, buffer, NO_ALLOC); allocator.free(bufferMemory); buffer = VK_NULL_HANDLE; } @@ -638,325 +791,316 @@ using std::uint32_t; // VERTEX BUFFER template - void VulkanInstance::createVertexBuffer(size_t vertexCount, vk::Buffer& vertexBuffer, MemoryInfo& vertexBufferMemory, vk::DeviceSize& vertexBufferSize) { + void VulkanInstance::createVertexBuffer(size_t vertexCount, VkBuffer& vertexBuffer, MemoryInfo& vertexBufferMemory, VkDeviceSize& vertexBufferSize) { vertexBufferSize = vertexCount * sizeof(VertexT); // create vertex buffer - vk::SharingMode sharingMode = vk::SharingMode::eExclusive; + VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE; std::vector qFamiliesWithAccess; if (qFamilyIndices.transferFamily.has_value()) { // prefer dedicated transfer family qFamiliesWithAccess = { qFamilyIndices.graphicsFamily.value(), qFamilyIndices.transferFamily.value() }; } - createBuffer(vertexBufferSize, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, vertexBuffer, vertexBufferMemory , sharingMode, &qFamiliesWithAccess); + createBuffer(vertexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory , sharingMode, &qFamiliesWithAccess); vLog.log0("createVertexBuffer: Created vertex buffer with size", vertexBufferSize); } - template void VulkanInstance::createVertexBuffer(size_t vertexCount, vk::Buffer& vertexBuffer, MemoryInfo& vertexBufferMemory, vk::DeviceSize& vertexBufferSize); - template void VulkanInstance::createVertexBuffer(size_t vertexCount, vk::Buffer& vertexBuffer, MemoryInfo& vertexBufferMemory, vk::DeviceSize& vertexBufferSize); + template void VulkanInstance::createVertexBuffer(size_t vertexCount, VkBuffer& vertexBuffer, MemoryInfo& vertexBufferMemory, VkDeviceSize& vertexBufferSize); + template void VulkanInstance::createVertexBuffer(size_t vertexCount, VkBuffer& vertexBuffer, MemoryInfo& vertexBufferMemory, VkDeviceSize& vertexBufferSize); // INDEX BUFFER template - void VulkanInstance::createIndexBuffer(size_t indexCount, vk::Buffer& indexBuffer, MemoryInfo& indexBufferMemory, vk::DeviceSize& indexBufferSize) { + void VulkanInstance::createIndexBuffer(size_t indexCount, VkBuffer& indexBuffer, MemoryInfo& indexBufferMemory, VkDeviceSize& indexBufferSize) { indexBufferSize = indexCount * sizeof(T); // create index buffer - vk::SharingMode sharingMode = vk::SharingMode::eExclusive; + VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE; std::vector qFamiliesWithAccess; if (qFamilyIndices.transferFamily.has_value()) { // prefer dedicated transfer family qFamiliesWithAccess = { qFamilyIndices.graphicsFamily.value(), qFamilyIndices.transferFamily.value() }; } - createBuffer(indexBufferSize, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eIndexBuffer, vk::MemoryPropertyFlagBits::eDeviceLocal, indexBuffer, indexBufferMemory, sharingMode, &qFamiliesWithAccess); + createBuffer(indexBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory, sharingMode, &qFamiliesWithAccess); vLog.log0("createIndexBuffer: Created index buffer with size:", indexBufferSize); } - template void VulkanInstance::createIndexBuffer(size_t indexCount, vk::Buffer& indexBuffer, MemoryInfo& indexBufferMemory, vk::DeviceSize& indexBufferSize); - template void VulkanInstance::createIndexBuffer(size_t indexCount, vk::Buffer& indexBuffer, MemoryInfo& indexBufferMemory, vk::DeviceSize& indexBufferSize); + template void VulkanInstance::createIndexBuffer(size_t indexCount, VkBuffer& indexBuffer, MemoryInfo& indexBufferMemory, VkDeviceSize& indexBufferSize); + template void VulkanInstance::createIndexBuffer(size_t indexCount, VkBuffer& indexBuffer, MemoryInfo& indexBufferMemory, VkDeviceSize& indexBufferSize); // FRAMEBUFFERS - void VulkanInstance::createFramebuffers(std::vector& framebuffers, std::vector& imageViews, vk::RenderPass& renderPass, vk::ImageView depthImageView) { + void VulkanInstance::createFramebuffers(std::vector& framebuffers, std::vector& imageViews, VkRenderPass& renderPass) { framebuffers.resize(scImageViews.size()); - vk::FramebufferCreateInfo framebufferCI { - .renderPass = renderPass, - .width = scExtent.width, - .height = scExtent.height, - .layers = 1, - }; - std::vector attachments; - for (size_t i = 0; i < framebuffers.size(); i++) { - if (static_cast(depthImageView) != VK_NULL_HANDLE) { - attachments = { imageViews[i] , depthImageView }; - } - else { - attachments = { imageViews[i] }; - } - framebufferCI.setAttachments(attachments); + VkFramebufferCreateInfo framebufferCI{}; + framebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebufferCI.renderPass = renderPass; + framebufferCI.width = scExtent.width; + framebufferCI.height = scExtent.height; + framebufferCI.layers = 1; - vk::Result result = device.createFramebuffer(&framebufferCI, NO_ALLOC, &framebuffers[i]); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Could not create framebuffer", "VulkanInstance::createFramebuffers"); + for (size_t i = 0; i < framebuffers.size(); i++) { + // TODO include depth image view for 3D + std::vector attachments = { imageViews[i] }; //, depthImageView }; + framebufferCI.pAttachments = attachments.data(); + framebufferCI.attachmentCount = static_cast(attachments.size()); + + VkResult result = vkCreateFramebuffer(device, &framebufferCI, nullptr, &framebuffers[i]); + if (result != VK_SUCCESS) { + throw getVkException(result, "Could not create framebuffer", "createFramebuffers_"); } } vLog.log0("createFramebuffers: Created", framebuffers.size(), "framebuffers."); } - void VulkanInstance::destroyFramebuffers(std::vector& framebuffers) { + void VulkanInstance::destroyFramebuffers(std::vector& framebuffers) { for (auto& framebuffer : framebuffers) { - device.destroyFramebuffer(framebuffer); + vkDestroyFramebuffer(device, framebuffer, nullptr); } } // TEXTURE SAMPLER - void VulkanInstance::createTextureSampler(vk::Sampler& sampler) { - vk::SamplerCreateInfo samplerCI { - // TODO: LINEAR or NEAREST - .magFilter = vk::Filter::eLinear, - .minFilter = vk::Filter::eLinear, - // TODO - .mipmapMode = vk::SamplerMipmapMode::eLinear, - .addressModeU = vk::SamplerAddressMode::eRepeat, - .addressModeV = vk::SamplerAddressMode::eRepeat, - .addressModeW = vk::SamplerAddressMode::eRepeat, - .mipLodBias = 0.0f, - .anisotropyEnable = bool2VkBool(settings.get("anisotropy_enable")), - .maxAnisotropy = settings.get("max_anisotropy"), - .compareEnable = VK_FALSE, - .compareOp = vk::CompareOp::eAlways, - .minLod = 0.0f, - .maxLod = 0.0f, - .borderColor = vk::BorderColor::eIntOpaqueBlack, - .unnormalizedCoordinates = VK_FALSE, - }; + void VulkanInstance::createTextureSampler(VkSampler& sampler) { + VkSamplerCreateInfo samplerCI{}; + samplerCI.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + // TODO: LINEAR or NEAREST + samplerCI.magFilter = VK_FILTER_LINEAR; + samplerCI.minFilter = VK_FILTER_LINEAR; + samplerCI.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerCI.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerCI.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + samplerCI.anisotropyEnable = bool2VkBool(settings.get("anisotropy_enable")); + samplerCI.maxAnisotropy = settings.get("max_anisotropy"); + samplerCI.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + // TODO + samplerCI.unnormalizedCoordinates = VK_FALSE; + samplerCI.compareEnable = VK_FALSE; + samplerCI.compareOp = VK_COMPARE_OP_ALWAYS; + samplerCI.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCI.mipLodBias = 0.0f; + samplerCI.minLod = 0.0f; + samplerCI.maxLod = 0.0f; - vk::Result result = device.createSampler(&samplerCI, nullptr, &sampler); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create texture sampler.", "VulkanInstance::createTextureSampler"); + VkResult result = vkCreateSampler(device, &samplerCI, nullptr, &sampler); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create texture sampler.", "createTextureSampler"); } } - void VulkanInstance::destroyTextureSampler(vk::Sampler& sampler) { - device.destroySampler(sampler, NO_ALLOC); + void VulkanInstance::destroyTextureSampler(VkSampler& sampler) { + vkDestroySampler(device, sampler, NO_ALLOC); sampler = VK_NULL_HANDLE; } // PUBLIC INTERFACE: IMAGE UTILITY - void VulkanInstance::createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags memoryProperties, vk::Image& image, MemoryInfo& imageMI) { - vk::ImageCreateInfo imageCI { - .imageType = vk::ImageType::e2D, - .format = format, - .extent { - .width = width, - .height = height, - .depth = 1, - }, - .mipLevels = 1, - .arrayLayers = 1, - .samples = vk::SampleCountFlagBits::e1, - // use linear when direct texel access is needed - .tiling = tiling, - .usage = usage, - .sharingMode = vk::SharingMode::eExclusive, - .initialLayout = vk::ImageLayout::eUndefined, - /* .flags = 0, */ - }; - vk::Result result = device.createImage(&imageCI, NO_ALLOC, &image); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create image", "VulkanInstance::createImage"); + void VulkanInstance::createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags memoryProperties, VkImage& image, MemoryInfo& imageMI) { + VkImageCreateInfo imageCI{}; + imageCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCI.imageType = VK_IMAGE_TYPE_2D; + imageCI.extent.width = static_cast(width); + imageCI.extent.height = static_cast(height); + imageCI.extent.depth = 1; + imageCI.mipLevels = 1; + imageCI.arrayLayers = 1; + imageCI.format = format; + // use linear when direct texel access is needed + imageCI.tiling = tiling; + imageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCI.usage = usage; + imageCI.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageCI.samples = VK_SAMPLE_COUNT_1_BIT; + /* imageCI.flags = 0; */ + VkResult result = vkCreateImage(device, &imageCI, NO_ALLOC, &image); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create image", "createImage"); } - vk::ImageMemoryRequirementsInfo2 imMemReq { .image = image }; - vk::MemoryRequirements2 memReq = device.getImageMemoryRequirements2(imMemReq); + VkMemoryRequirements2 memReq; + VkImageMemoryRequirementsInfo2 imMemReq; + getImageMemoryRequirements(device, image, imMemReq, memReq); - vk::MemoryAllocateInfo memoryAI { - .allocationSize = memReq.memoryRequirements.size, - .memoryTypeIndex = findMemoryType(memReq.memoryRequirements.memoryTypeBits, memoryProperties), - }; + VkMemoryAllocateInfo memoryAI{}; + memoryAI.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memoryAI.allocationSize = memReq.memoryRequirements.size; + memoryAI.memoryTypeIndex = findMemoryType(memReq.memoryRequirements.memoryTypeBits, memoryProperties); allocator.allocate(memoryAI, memReq, imageMI); - result = device.bindImageMemory(image, imageMI.memory, imageMI.offset); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to bind image to its memory", "VulkanInstance::createImage"); + result = vkBindImageMemory(device, image, imageMI.memory, imageMI.offset); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to bind image to its memory", "createImage"); } vLog.log0("createImage: created and bound image of size", memoryAI.allocationSize); } - void VulkanInstance::destroyImage(vk::Image& image, MemoryInfo& imageMemory) { - device.destroyImage(image, NO_ALLOC); + void VulkanInstance::destroyImage(VkImage& image, MemoryInfo& imageMemory) { + vkDestroyImage(device, image, NO_ALLOC); allocator.free(imageMemory); image = VK_NULL_HANDLE; } // IMAGE VIEW - void VulkanInstance::createImageView(vk::Format format, vk::Image& image, vk::ImageView& imageView, vk::ImageAspectFlags aspectFlags) { - vk::ImageViewCreateInfo imageViewCI { - .image = image, - .viewType = vk::ImageViewType::e2D, - .format = format, - .components { - .r = vk::ComponentSwizzle::eIdentity, - .g = vk::ComponentSwizzle::eIdentity, - .b = vk::ComponentSwizzle::eIdentity, - .a = vk::ComponentSwizzle::eIdentity, - }, - .subresourceRange { - .aspectMask = aspectFlags, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - vk::Result result = device.createImageView(&imageViewCI, NO_ALLOC, &imageView); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Could not create image view", "VulkanInstance::createImageViews"); + void VulkanInstance::createImageView(VkFormat format, VkImage& image, VkImageView& imageView, VkImageAspectFlags aspectFlags) { + VkImageViewCreateInfo imageViewCI{}; + imageViewCI.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + imageViewCI.viewType = VK_IMAGE_VIEW_TYPE_2D; + imageViewCI.format = format; + imageViewCI.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCI.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCI.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCI.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + imageViewCI.subresourceRange.aspectMask = aspectFlags; + imageViewCI.subresourceRange.baseMipLevel = 0; + imageViewCI.subresourceRange.levelCount = 1; + imageViewCI.subresourceRange.baseArrayLayer = 0; + imageViewCI.subresourceRange.layerCount = 1; + imageViewCI.image = image; + VkResult result = vkCreateImageView(device, &imageViewCI, nullptr, &imageView); + if (result != VK_SUCCESS) { + throw getVkException(result, "Could not create image view", "createImageViews"); } } - void VulkanInstance::destroyImageView(vk::ImageView& imageView) { - device.destroyImageView(imageView, NO_ALLOC); + void VulkanInstance::destroyImageView(VkImageView& imageView) { + vkDestroyImageView(device, imageView, NO_ALLOC); imageView = VK_NULL_HANDLE; } - void VulkanInstance::copyBufferToImage(vk::Buffer buffer, vk::Image image, int32_t offsetX, int32_t offsetY, uint32_t width, uint32_t height) { - vk::CommandBuffer cmdBuffer = beginSingleTimeCommands(POOL_TRANSFER); - vk::BufferImageCopy region { - .bufferOffset = NO_OFFSET, - .bufferRowLength = 0, - .bufferImageHeight = 0, - .imageSubresource { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .imageOffset = { offsetX, offsetY, 0 }, - .imageExtent = { width, height, 1 }, - }; - cmdBuffer.copyBufferToImage(buffer, image, vk::ImageLayout::eTransferDstOptimal, region); + void VulkanInstance::copyBufferToImage(VkBuffer buffer, VkImage image, int32_t offsetX, int32_t offsetY, uint32_t width, uint32_t height) { + VkCommandBuffer cmdBuffer = beginSingleTimeCommands(POOL_TRANSFER); + VkBufferImageCopy region{}; + region.bufferOffset = NO_OFFSET; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + + region.imageOffset = { offsetX, offsetY, 0 }; + region.imageExtent = { width, height, 1 }; + const uint32_t regionCount = 1; + vkCmdCopyBufferToImage(cmdBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regionCount, ®ion); endSingleTimeCommands(cmdBuffer, POOL_TRANSFER); } - void VulkanInstance::copyImageToImage(vk::CommandBuffer& cmdBuffer, vk::Image srcImage, vk::Image dstImage, vk::Extent2D extent) { - vk::ImageCopy region { - .srcSubresource { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .srcOffset = { 0, 0, 0 }, - .dstSubresource { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .mipLevel = 0, - .baseArrayLayer = 0, - .layerCount = 1, - }, - .dstOffset = { 0, 0, 0 }, - .extent = { extent.width, extent.height, 1 }, - }; - cmdBuffer.copyImage(srcImage, vk::ImageLayout::eTransferSrcOptimal, dstImage, vk::ImageLayout::eTransferDstOptimal, region); + void VulkanInstance::copyImageToImage(VkCommandBuffer& cmdBuffer, VkImage srcImage, VkImage dstImage, VkExtent2D extent) { + VkImageCopy region{}; + region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.srcSubresource.mipLevel = 0; + region.srcSubresource.baseArrayLayer = 0; + region.srcSubresource.layerCount = 1; + + region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.dstSubresource.mipLevel = 0; + region.dstSubresource.baseArrayLayer = 0; + region.dstSubresource.layerCount = 1; + + /* std::array offsets; */ + /* offsets[0] = { 0, 0, 0 }; */ + /* offsets[1] = { 0, 0, 0 }; */ + region.srcOffset = { 0, 0, 0 }; + region.dstOffset = { 0, 0, 0 }; + region.extent = { extent.width, extent.height, 1 }; + const uint32_t regionCount = 1; + vkCmdCopyImage(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regionCount, ®ion); } - bool hasStencilComponent(vk::Format format) { - return format == vk::Format::eD32SfloatS8Uint or format == vk::Format::eD24UnormS8Uint; + bool hasStencilComponent(VkFormat format) { + return format == VK_FORMAT_D32_SFLOAT_S8_UINT or format == VK_FORMAT_D24_UNORM_S8_UINT; } - void VulkanInstance::transitionImageLayout(vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::CommandBuffer* cmdBuffer) { - vk::ImageMemoryBarrier2 barrier { - .srcAccessMask = NO_ACC_2_FLAGS, - .dstAccessMask = NO_ACC_2_FLAGS, - .oldLayout = oldLayout, - .newLayout = newLayout, - // not using barrier for queue famlily ownership transfer - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange { - .aspectMask = vk::ImageAspectFlagBits::eColor, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; + void VulkanInstance::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkCommandBuffer* cmdBuffer) { + VkImageMemoryBarrier2 barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2; + barrier.oldLayout = oldLayout; + barrier.newLayout = newLayout; + // not using barrier for queue famlily ownership transfer + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = 0; + barrier.dstAccessMask = 0; InstanceCommandPool commandPool; - if (oldLayout == vk::ImageLayout::eUndefined and - newLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal) { - barrier.srcAccessMask = NO_ACC_2_FLAGS; - barrier.dstAccessMask = vk::AccessFlagBits2::eDepthStencilAttachmentRead | vk::AccessFlagBits2::eDepthStencilAttachmentWrite; - barrier.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eDepth; + if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED and + newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; if (hasStencilComponent(format)) { - barrier.subresourceRange.aspectMask |= vk::ImageAspectFlagBits::eStencil; + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; } - barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe; - barrier.dstStageMask = vk::PipelineStageFlagBits2::eEarlyFragmentTests; + barrier.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; commandPool = POOL_GRAPHICS; } - else if (oldLayout == vk::ImageLayout::eUndefined and - newLayout == vk::ImageLayout::eTransferDstOptimal) { - barrier.srcAccessMask = NO_ACC_2_FLAGS; - barrier.dstAccessMask = vk::AccessFlagBits2::eTransferWrite; + else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED and + newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.srcStageMask = vk::PipelineStageFlagBits2::eTopOfPipe; - barrier.dstStageMask = vk::PipelineStageFlagBits2::eTransfer; + barrier.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; commandPool = POOL_TRANSFER; } - else if (oldLayout == vk::ImageLayout::eTransferDstOptimal and - newLayout == vk::ImageLayout::eShaderReadOnlyOptimal) { - barrier.srcAccessMask = vk::AccessFlagBits2::eTransferWrite; - barrier.dstAccessMask = vk::AccessFlagBits2::eShaderRead; + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and + newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - barrier.srcStageMask = vk::PipelineStageFlagBits2::eTransfer; - barrier.dstStageMask = vk::PipelineStageFlagBits2::eFragmentShader; + barrier.srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; commandPool = POOL_GRAPHICS; } - else if (oldLayout == vk::ImageLayout::eShaderReadOnlyOptimal and - newLayout == vk::ImageLayout::eTransferDstOptimal) { - barrier.srcAccessMask = vk::AccessFlagBits2::eShaderRead; - barrier.dstAccessMask = vk::AccessFlagBits2::eTransferWrite; + else if (oldLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL and + newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.srcStageMask = vk::PipelineStageFlagBits2::eFragmentShader; - barrier.dstStageMask = vk::PipelineStageFlagBits2::eTransfer; + barrier.srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; commandPool = POOL_GRAPHICS; } - else if (oldLayout == vk::ImageLayout::eTransferDstOptimal and - newLayout == vk::ImageLayout::ePresentSrcKHR) { - barrier.srcAccessMask = vk::AccessFlagBits2::eTransferWrite; - barrier.dstAccessMask = vk::AccessFlagBits2::eMemoryRead; + else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL and + newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - barrier.srcStageMask = vk::PipelineStageFlagBits2::eTransfer; - barrier.dstStageMask = vk::PipelineStageFlagBits2::eColorAttachmentOutput; + barrier.srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; + barrier.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; commandPool = POOL_GRAPHICS; } else { - throw VkUserError(std::string("Unsupported layout transition") + ::toString(oldLayout) + "->" + ::toString(newLayout), "VulkanInstance::transitionImageLayout"); + throw VkUserError(std::string("transitionImageLayout: Unsupported layout transition") + STR_VK_IMAGE_LAYOUT(oldLayout) + "->" + STR_VK_IMAGE_LAYOUT(newLayout), "transitionImageLayout");; } // if not provided, get a single time command buffer - vk::CommandBuffer cmdBuffer_; + VkCommandBuffer cmdBuffer_; if (cmdBuffer == nullptr) { cmdBuffer_ = beginSingleTimeCommands(commandPool); } else { cmdBuffer_ = *cmdBuffer; } - vk::DependencyInfo depI = getDepInfo(barrier); - cmdBuffer_.pipelineBarrier2(depI); + VkDependencyInfo depI = getDepInfo(barrier); + vkCmdPipelineBarrier2(cmdBuffer_, &depI); if (cmdBuffer == nullptr) { endSingleTimeCommands(cmdBuffer_, commandPool); @@ -966,7 +1110,7 @@ using std::uint32_t; // // STATIC: DEBUG LOG // - gz::Log VulkanInstance::vLog("vulkan.log", true, true, "Vulkan", settings::VULKAN_MESSAGE_PREFIX_COLOR, true, settings::VULKAN_MESSAGE_TIME_COLOR); + gz::Log VulkanInstance::vLog("vulkan.log", true, true, "Vulkan", VULKAN_MESSAGE_PREFIX_COLOR, true, VULKAN_MESSAGE_TIME_COLOR); VKAPI_ATTR VkBool32 VKAPI_CALL VulkanInstance::debugLog( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverety, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -993,18 +1137,19 @@ using std::uint32_t; type = "None:"; colors.push_back(gz::Color::WHITE); } + // color for second keyword / whole message if not validation message switch(messageSeverety) { case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: colors.push_back(gz::Color::RESET); break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: colors.push_back(gz::Color::WHITE); break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: colors.push_back(gz::Color::BG_YELLOW); break; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: colors.push_back(gz::Color::BG_RED); break; default: @@ -1016,7 +1161,7 @@ using std::uint32_t; std::string_view messageIdName(pCallbackData->pMessageIdName); // extra differenciation between different validation messages // is validation or performance message: get type from brackets, print owner of any pointers - if (messageType & (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) { + if (messageType & (VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)) { // if cant be found npos + 1 = 0 size_t startAt = message.find(']') + 1; if (messageIdName.starts_with("UNASSIGNED-DEBUG-PRINTF")) { @@ -1055,7 +1200,7 @@ using std::uint32_t; vLog.clog(colors, std::move(type), message); } lastColorWhite = !lastColorWhite; - if (settings::throwExceptionOnValidationError and messageSeverety == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { + if (throwExceptionOnValidationError and messageSeverety == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { throw VkException("Validation error:" + std::string(message), "VulkanInstance::debugLog"); } return VK_FALSE; @@ -1069,123 +1214,94 @@ using std::uint32_t; // INSTANCE void VulkanInstance::createInstance() { - vk::ApplicationInfo appInfo { - .pApplicationName = "Glowzwiebels Vulkan Project", - .applicationVersion = VK_MAKE_VERSION(1, 0, 0), - .pEngineName = "Glowzwiebel Engine", - .apiVersion = VK_API_VERSION_1_3, - }; + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pEngineName = "Glowzwiebel Engine"; + appInfo.pApplicationName = "Hallo Dreieck"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_3; - VkDebugUtilsMessengerCreateInfoEXT debugCI = static_cast(debugUtilsMessengerCI); - vk::InstanceCreateInfo instanceCI { - .pNext = &debugCI, - .pApplicationInfo = &appInfo, - }; + VkInstanceCreateInfo instanceCI{}; + instanceCI.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceCI.pApplicationInfo = &appInfo; + instanceCI.pNext = &debugUtilsMessengerCI; + instanceCI.flags = 0; + instanceCI.ppEnabledExtensionNames = instanceExtensions.data(); + instanceCI.enabledExtensionCount = instanceExtensions.size(); if (enableValidationLayers) { if (!validationLayersSupported()) { - throw VkException("Validation layers enabled but not available.", "VulkanInstance::createInstance"); + throw std::runtime_error("Validation layers enabled but not available."); } - instanceCI.setPEnabledLayerNames(settings::validationLayers); + instanceCI.enabledLayerCount = static_cast(validationLayers.size()); + instanceCI.ppEnabledLayerNames = validationLayers.data(); + } + else { + instanceCI.enabledLayerCount = 0; + instanceCI.ppEnabledLayerNames = nullptr; } - std::vector requiredInstanceExtensions = getRequiredInstanceExtensions(); - instanceCI.setPEnabledExtensionNames(requiredInstanceExtensions); + std::vector requiredExtensions = getRequiredExtensions(); + instanceCI.enabledExtensionCount = static_cast(requiredExtensions.size()); + instanceCI.ppEnabledExtensionNames = requiredExtensions.data();; // log requiredExtensions std::string message; message.reserve(80); message += "Required extensions ("; message += std::to_string(instanceCI.enabledExtensionCount) + ')'; - for (uint32_t i = 0; i < requiredInstanceExtensions.size(); i++) { + for (uint32_t i = 0; i < requiredExtensions.size(); i++) { message += "\n\t"; - message += std::to_string(i + 1) + ": " + requiredInstanceExtensions[i]; + message += std::to_string(i + 1) + ": " + requiredExtensions[i]; } - vLog.log2(message); + vLog.log3(message); - vk::Result result = vk::createInstance(&instanceCI, NO_ALLOC, &instance); - if (result != vk::Result::eSuccess) { - vLog.error("Failed to create instance.", "VkResult:", result); - throw getVkException(result, "Failed to create instance", "VulkanInstance::createInstance"); + VkResult result = vkCreateInstance(&instanceCI, nullptr, &instance); + if (result != VK_SUCCESS) { + vLog.log3("Failed to create instance.", "VkResult:", STR_VK_RESULT(result)); + throw std::runtime_error("Failed to create instance."); } - auto [result2, extensions] = vk::enumerateInstanceExtensionProperties(); - if (result2 != vk::Result::eSuccess) { - throw getVkException(result, "Failed to enumerate instance extension properties", "VulkanInstance::createInstance"); - } + uint32_t extensionCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); // get count + std::vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); // log available extensions message = "Available extensions ("; - message += gz::toString(extensions.size()) + "):"; + message += std::to_string(extensionCount) + "):"; for (uint32_t i = 0; i < extensions.size(); i++) { message += "\n\t"; - message += gz::toString(i + 1) + ": " + gz::toString(extensions[i].extensionName); + message += std::to_string(i + 1) + ": " + extensions[i].extensionName; } - vLog.log2(message); + vLog.log3(message); - if (!areExtensionsAvailable(requiredInstanceExtensions, extensions)) { - throw VkException("Not all required extensions are available.", "VulkanInstance::createInstance"); + if (!checkRequiredExtensionsAvailable(requiredExtensions, extensions)) { + throw std::runtime_error("Not all required extensions are available."); } } - std::vector VulkanInstance::getRequiredInstanceExtensions() const { - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - std::vector requiredExtensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - - if (enableValidationLayers) { - requiredExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - requiredExtensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME); - } - return requiredExtensions; - } - // check if validation layers are supported/installed - bool VulkanInstance::validationLayersSupported() { - std::vector availableLayers; - vk::Result result; - std::tie(result, availableLayers) = vk::enumerateInstanceLayerProperties(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to enumerate available validation layers", "VulkanInstance::validationLayersSupported"); - } - - bool layerAvailable; - for (const char* requiredLayer : settings::validationLayers) { - layerAvailable = false; - for (const auto& layerProperties : availableLayers) { - if (strcmp(requiredLayer, layerProperties.layerName) == 0) { - layerAvailable = true; - break; - } - } - if (!layerAvailable) { return false; } - } - return true; - } - - - - -// PHYSICAL DEVICE: SELECTION PROCESS - // FEATURES - PhysicalDeviceFeatures VulkanInstance::getRequiredDeviceFeatures() const { +// PHYSICAL DEVICE + PhysicalDeviceFeatures VulkanInstance::getRequiredFeatures() const { PhysicalDeviceFeatures requiredFeatures; requiredFeatures.f13.synchronization2 = VK_TRUE; return requiredFeatures; } - void VulkanInstance::selectPhysicalDevice() { - auto [result, devices] = instance.enumeratePhysicalDevices(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to enumerate physical devices", "VulkanInstance::selectPhysicalDevice"); - } - if (devices.size() == 0) { + void VulkanInstance::selectPhysicalDevice() { + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + + if (deviceCount == 0) { vLog.error("Could not find any GPU."); - throw VkException("Could not find any GPU.", "VulkanInstance::selectPhysicalDevice"); + throw std::runtime_error("Could not find any GPU."); } + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); // find best gpu std::vector deviceScores; @@ -1199,15 +1315,10 @@ using std::uint32_t; } physicalDevice = devices[bestGPUIndex]; - // initialize members - phDevProperties = physicalDevice.getProperties2(); + vkGetPhysicalDeviceProperties(physicalDevice, &phDevProperties); vkGetPhysicalDeviceFeatures2(physicalDevice, &phDevFeatures.f); - /* phDevFeatures.f = physicalDevice.getFeatures2(&phDevFeatures.f); */ - phDevMemProperties = physicalDevice.getMemoryProperties2(); qFamilyIndices = findQueueFamilies(physicalDevice); - depthFormat = findSupportedFormat({ vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint }, vk::ImageTiling::eOptimal, vk::FormatFeatureFlagBits::eDepthStencilAttachment); - - vLog.log3("selectPhysicalDevice: Selected GPU:", phDevProperties.properties.deviceName); + vLog("Selected GPU:", phDevProperties.deviceName, "with the following queue family indices:", qFamilyIndices); } @@ -1217,26 +1328,27 @@ using std::uint32_t; const unsigned int SCORE_HAS_ALL_QUEUE_FAMILIES = 100; const unsigned int SCORE_HAS_FEATURE = 100; - unsigned int VulkanInstance::rateDevice(vk::PhysicalDevice phDevice) { + unsigned int VulkanInstance::rateDevice(VkPhysicalDevice device) { unsigned int score; // rate type - vk::PhysicalDeviceProperties2 properties = phDevice.getProperties2(); - switch(properties.properties.deviceType) { - case vk::PhysicalDeviceType::eDiscreteGpu: + VkPhysicalDeviceProperties properties{}; + vkGetPhysicalDeviceProperties(device, &properties); + switch(properties.deviceType) { + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: score = SCORE_DISCRETE_GPU; break; - case vk::PhysicalDeviceType::eIntegratedGpu: + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: score = SCORE_INTEGRATED_GPU; break; - case vk::PhysicalDeviceType::eVirtualGpu: + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: score = SCORE_VIRTUAL_GPU; break; default: return 0; } - qFamilyIndices = findQueueFamilies(phDevice); + qFamilyIndices = findQueueFamilies(device); // has needed queue families if (qFamilyIndices.hasAllValues()) { score += SCORE_HAS_ALL_QUEUE_FAMILIES; @@ -1245,22 +1357,16 @@ using std::uint32_t; return 0; } - // supports all extensions (global var) - vk::Result result; - std::vector availableExtensions; - std::tie(result, availableExtensions) = phDevice.enumerateDeviceExtensionProperties(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to enumerate device extension properties", "VulkanInstance::rateDevice"); - } - if (!areExtensionsAvailable(settings::deviceExtensions, availableExtensions)) { + // supports all extensions + if (!deviceExtensionsSupported(device)) { return 0; } // supports all features - PhysicalDeviceFeatures requiredFeatures = getRequiredDeviceFeatures(); + PhysicalDeviceFeatures requiredFeatures = getRequiredFeatures(); PhysicalDeviceFeatures features; - /* features.f = phDevice.getFeatures2(features.f); */ - vkGetPhysicalDeviceFeatures2(phDevice, &features.f); + vLog("features sType", STR_VK_STRUCTURE_TYPE(features.f.sType)); + vkGetPhysicalDeviceFeatures2(device, &features.f); if (!features.requiredFeaturesAvailable(requiredFeatures)) { return 0; } @@ -1268,35 +1374,38 @@ using std::uint32_t; if (features.f.features.samplerAnisotropy == VK_TRUE) { score += SCORE_HAS_FEATURE; } // swap chain support - SwapChainSupport scDetails = querySwapChainSupport(phDevice); + SwapChainSupport scDetails = querySwapChainSupport(device); if (scDetails.formats.empty() or scDetails.presentModes.empty()) { return 0; } // rate memory - vk::PhysicalDeviceMemoryProperties2 memProperties = phDevice.getMemoryProperties2(); - for (uint32_t i = 0; i < memProperties.memoryProperties.memoryHeapCount; i++) { - score += memProperties.memoryProperties.memoryHeaps[i].size / 1e6; + VkPhysicalDeviceMemoryProperties memProperties{}; + vkGetPhysicalDeviceMemoryProperties(device, &memProperties); + for (uint32_t i = 0; i < memProperties.memoryHeapCount; i++) { + score += memProperties.memoryHeaps[i].size / 1e6; } - vLog("rateDevice: GPU: ", properties.properties.deviceName, " - Score: ", score); + + vLog("rateDevice: GPU: ", properties.deviceName, " - Score: ", score); return score; } - vk::Format VulkanInstance::findSupportedFormat(const std::vector& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features) { - for (const vk::Format& format : candidates) { - vk::FormatProperties2 formatProperties = physicalDevice.getFormatProperties2(format); - if (tiling == vk::ImageTiling::eLinear and - (formatProperties.formatProperties.linearTilingFeatures & features) == features) { + VkFormat VulkanInstance::findSupportedFormat(const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { + for (const VkFormat& format : candidates) { + VkFormatProperties formatProperties; + vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); + if (tiling == VK_IMAGE_TILING_LINEAR and + (formatProperties.linearTilingFeatures & features) == features) { return format; } - else if (tiling == vk::ImageTiling::eOptimal and - (formatProperties.formatProperties.optimalTilingFeatures & features) == features) { + else if (tiling == VK_IMAGE_TILING_OPTIMAL and + (formatProperties.optimalTilingFeatures & features) == features) { return format; } } - throw VkException(std::string("Could not find a suitable format. tiling: ") + ::toString(tiling) + ".", "VulkanInstance::findSupportedFormat"); + throw VkException(std::string("Could not find a suitable format. tiling: ") + STR_VK_IMAGE_TILING(tiling) + ".", "findSupportedFormat"); } @@ -1305,38 +1414,40 @@ using std::uint32_t; // IMPORTANT: EDIT DOCUMENTATION WHEN ADDING/CHANGING VALUES // anisotropic filtering settings.setAllowedValues("anisotropy_enable", { false, vkBool2Bool(phDevFeatures.f.features.samplerAnisotropy) }, gz::SM_LIST); - settings.setAllowedValues("max_anisotropy", { 1.0f, phDevProperties.properties.limits.maxSamplerAnisotropy }, gz::SM_RANGE); + settings.setAllowedValues("max_anisotropy", { 1.0f, phDevProperties.limits.maxSamplerAnisotropy }, gz::SM_RANGE); settings.setAllowedValues("max_frames_in_flight", { 1, 4 }, SM_RANGE); } // QUEUE - QueueFamilyIndices VulkanInstance::findQueueFamilies(vk::PhysicalDevice phDevice) { + QueueFamilyIndices VulkanInstance::findQueueFamilies(VkPhysicalDevice device) { QueueFamilyIndices indices; - std::vector qFamilies = phDevice.getQueueFamilyProperties2(); - vLog.log1("findQueueFamilies: found", qFamilies.size(), "queue families:"); + uint32_t qFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &qFamilyCount, nullptr); + std::vector qFamilies(qFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &qFamilyCount, qFamilies.data()); + vLog("findQueueFamilies: found", qFamilyCount, "queue families:"); - vk::Bool32 presentSupport = false; - vk::Result result; - for (unsigned int i = 0; i < qFamilies.size(); i++) { + VkBool32 presentSupport = false; + for (unsigned int i = 0; i < qFamilyCount; i++) { // check for queue with graphic capabilities - if (qFamilies[i].queueFamilyProperties.queueFlags & vk::QueueFlagBits::eGraphics) { + if (qFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { indices.graphicsFamily = i; } - else if (qFamilies[i].queueFamilyProperties.queueFlags & vk::QueueFlagBits::eTransfer) { // only transfer, not graphics + else if (qFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) { // only transfer, not graphics indices.transferFamily = i; } // check for surface support - std::tie(result, presentSupport) = phDevice.getSurfaceSupportKHR(i, surface); + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); if (presentSupport == VK_TRUE) { indices.presentFamily = i; } - vLog.log1("findQueueFamilies:", i, "-", qFamilies[i].queueFamilyProperties.queueFlags); + vLog("findQueueFamilies:", i, "-", qFamilies[i].queueFlags); if (indices.hasAllValues()) { - vLog.log1("findQueueFamilies: Found all wanted families."); + vLog("findQueueFamilies: Found all wanted families."); break; } } @@ -1354,37 +1465,41 @@ using std::uint32_t; qFamiliyIndicesSet.insert(qFamilyIndices.transferFamily.value()); } - std::vector deviceQueueCI; + std::vector deviceQueueCI; for (uint32_t index : qFamiliyIndicesSet) { - deviceQueueCI.push_back(vk::DeviceQueueCreateInfo()); + deviceQueueCI.push_back(VkDeviceQueueCreateInfo()); + deviceQueueCI.back().sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; deviceQueueCI.back().queueFamilyIndex = index; deviceQueueCI.back().queueCount = 1; float qPriority = 1.0f; deviceQueueCI.back().pQueuePriorities = &qPriority; } - PhysicalDeviceFeatures enabledFeatures = getRequiredDeviceFeatures(); + PhysicalDeviceFeatures enabledFeatures = getRequiredFeatures(); // optional features enabledFeatures.f.features.samplerAnisotropy = bool2VkBool(settings.getOr("anisotropy_enable", false)); - vk::DeviceCreateInfo deviceCI { - .pNext = &enabledFeatures.f, - /* .pEnabledFeatures = &deviceFeatures.f, */ - }; - deviceCI.setQueueCreateInfos(deviceQueueCI); - deviceCI.setPEnabledExtensionNames(settings::deviceExtensions); + VkDeviceCreateInfo deviceCI{}; + deviceCI.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + deviceCI.pQueueCreateInfos = deviceQueueCI.data(); + deviceCI.queueCreateInfoCount = static_cast(deviceQueueCI.size()); + deviceCI.pNext = &enabledFeatures.f; + /* deviceCI.pEnabledFeatures = &deviceFeatures.f; */ + deviceCI.enabledExtensionCount = static_cast(extensions.size()); + deviceCI.ppEnabledExtensionNames = extensions.data(); - vk::Result result = physicalDevice.createDevice(&deviceCI, nullptr, &device); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create logical device.", "VulkanInstance::createLogicalDevice"); + VkResult result = vkCreateDevice(physicalDevice, &deviceCI, nullptr, &device); + if (result != VK_SUCCESS) { + vLog.error("createLogicalDevice: Failed to create logical device.", "VkResult:", STR_VK_RESULT(result)); + throw std::runtime_error("createLogicalDevice: Failed to create logical device."); } // get handles uint32_t index = 0; - graphicsQ = device.getQueue(qFamilyIndices.graphicsFamily.value(), index); - presentQ = device.getQueue(qFamilyIndices.presentFamily.value(), index); + vkGetDeviceQueue(device, qFamilyIndices.graphicsFamily.value(), index, &graphicsQ); + vkGetDeviceQueue(device, qFamilyIndices.presentFamily.value(), index, &presentQ); if (qFamilyIndices.transferFamily.has_value()) { - transferQ = device.getQueue(qFamilyIndices.transferFamily.value(), index); + vkGetDeviceQueue(device, qFamilyIndices.transferFamily.value(), index, &transferQ); } else { transferQ = graphicsQ; @@ -1395,48 +1510,38 @@ using std::uint32_t; // SURFACE void VulkanInstance::createSurface() { - VkSurfaceKHR surface2 = surface; - VkResult result = glfwCreateWindowSurface(static_cast(instance), window, nullptr, &surface2); - surface = surface2; + VkResult result = glfwCreateWindowSurface(instance, window, nullptr, &surface); if (result != VK_SUCCESS) { - throw getVkException(vk::Result(result), "Failed to create window surface.", "VulkanInstance::createSurface"); + vLog.error("createSurface: Failed to create window surface.", "VkResult:", STR_VK_RESULT(result)); + throw std::runtime_error("createSurface: Failed to create window surface."); } } // SWAP CHAIN - SwapChainSupport VulkanInstance::querySwapChainSupport(vk::PhysicalDevice physicalDevice) { + SwapChainSupport VulkanInstance::querySwapChainSupport(VkPhysicalDevice physicalDevice) { SwapChainSupport scDetails{}; - vk::Result result; - vk::PhysicalDeviceSurfaceInfo2KHR surfaceI { .surface = surface }; - std::tie(result, scDetails.formats) = physicalDevice.getSurfaceFormats2KHR(surfaceI); - if (result != vk::Result::eSuccess) { - throw getVkException(vk::Result(result), "Failed get surface formats.", "VulkanInstance::querySwapChainSupport"); - } + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr); + scDetails.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, scDetails.formats.data()); - std::tie(result, scDetails.presentModes) = physicalDevice.getSurfacePresentModesKHR(surface); - if (result != vk::Result::eSuccess) { - throw getVkException(vk::Result(result), "Failed get surface present modes.", "VulkanInstance::querySwapChainSupport"); - } + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr); + scDetails.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, scDetails.presentModes.data()); + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &scDetails.capabilities); - std::tie(result, scDetails.capabilities) = physicalDevice.getSurfaceCapabilities2KHR(surfaceI); - if (result != vk::Result::eSuccess) { - throw getVkException(vk::Result(result), "Failed get surface capabilities.", "VulkanInstance::querySwapChainSupport"); - } return scDetails; } - vk::SurfaceFormat2KHR VulkanInstance::selectSwapChainSurfaceFormat(const std::vector& availableFormats) { + VkSurfaceFormatKHR VulkanInstance::selectSwapChainSurfaceFormat(const std::vector& availableFormats) { vLog.log0("selectSwapChainSurfaceFormat:", availableFormats.size(), "formats available."); - // TODO REMOVE for (const auto& format : availableFormats) { - vLog.log0("selectSwapChainSurfaceFormat: format:", format.surfaceFormat.format, "with color space:", format.surfaceFormat.colorSpace); - } - - for (const auto& format : availableFormats) { - if (format.surfaceFormat.format == vk::Format::eB8G8R8A8Srgb and format.surfaceFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) { + if (format.format == VK_FORMAT_B8G8R8A8_SRGB and format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { return format; } } @@ -1444,86 +1549,85 @@ using std::uint32_t; } - vk::PresentModeKHR VulkanInstance::selectSwapChainPresentMode(const std::vector& availableModes) { + VkPresentModeKHR VulkanInstance::selectSwapChainPresentMode(const std::vector& availableModes) { for (const auto& mode : availableModes) { - if (mode == vk::PresentModeKHR::eMailbox) { + if (mode == VK_PRESENT_MODE_MAILBOX_KHR) { return mode; } } - return vk::PresentModeKHR::eFifo; + return VK_PRESENT_MODE_FIFO_KHR; } - vk::Extent2D VulkanInstance::selectSwapExtent(const vk::SurfaceCapabilities2KHR& capabilities) { + VkExtent2D VulkanInstance::selectSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) { // if width = max(uint32_t) then surface size will be determined by a swapchain targeting it - if (capabilities.surfaceCapabilities.currentExtent.width == std::numeric_limits::max()) { + if (capabilities.currentExtent.width == std::numeric_limits::max()) { int width, height; glfwGetFramebufferSize(window, &width, &height); - vk::Extent2D actualExtent { - .width = std::clamp(static_cast(width), capabilities.surfaceCapabilities.minImageExtent.width, capabilities.surfaceCapabilities.maxImageExtent.width), - .height = std::clamp(static_cast(height), capabilities.surfaceCapabilities.minImageExtent.height, capabilities.surfaceCapabilities.maxImageExtent.height), - }; + VkExtent2D actualExtent {}; + actualExtent.width = std::clamp(static_cast(width), capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + actualExtent.height = std::clamp(static_cast(height), capabilities.minImageExtent.height, capabilities.maxImageExtent.height); return actualExtent; } else { - return capabilities.surfaceCapabilities.currentExtent; + return capabilities.currentExtent; } } void VulkanInstance::createSwapChain() { SwapChainSupport scDetails = querySwapChainSupport(physicalDevice); - vk::SurfaceFormat2KHR surfaceFormat = selectSwapChainSurfaceFormat(scDetails.formats); + VkSurfaceFormatKHR surfaceFormat = selectSwapChainSurfaceFormat(scDetails.formats); - uint32_t imageCount = scDetails.capabilities.surfaceCapabilities.minImageCount + 1; + uint32_t imageCount = scDetails.capabilities.minImageCount + 1; // maxImageCount = 0 -> no max - if (scDetails.capabilities.surfaceCapabilities.maxImageCount > 0 and imageCount < scDetails.capabilities.surfaceCapabilities.maxImageCount) { - imageCount = scDetails.capabilities.surfaceCapabilities.maxImageCount; + if (scDetails.capabilities.maxImageCount > 0 and imageCount < scDetails.capabilities.maxImageCount) { + imageCount = scDetails.capabilities.maxImageCount; } - scImageFormat = surfaceFormat.surfaceFormat.format; + scImageFormat = surfaceFormat.format; scExtent = selectSwapExtent(scDetails.capabilities); - vk::SwapchainCreateInfoKHR swapChainCI { - .surface = surface, - .minImageCount = imageCount, - .imageFormat = scImageFormat, - .imageColorSpace = surfaceFormat.surfaceFormat.colorSpace, - .imageExtent = scExtent, - .imageArrayLayers = 1, - // if postProcessing: vk::ImageUsageFlagBits::eTransferDst - .imageUsage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst, - .preTransform = scDetails.capabilities.surfaceCapabilities.currentTransform, - .compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque, - .presentMode = selectSwapChainPresentMode(scDetails.presentModes), - .clipped = VK_TRUE, - .oldSwapchain = VK_NULL_HANDLE, - }; + VkSwapchainCreateInfoKHR swapChainCI{}; + swapChainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapChainCI.surface = surface; + swapChainCI.minImageCount = imageCount; + swapChainCI.imageFormat = scImageFormat; + swapChainCI.imageColorSpace = surfaceFormat.colorSpace; + swapChainCI.imageExtent = scExtent; + swapChainCI.imageArrayLayers = 1; + // if postProcessing: VK_IMAGE_USAGE_TRANSFER_DST_BIT + swapChainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; /* QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); */ // must live until vkCreateSwapchainKHR std::vector qIndices; if (qFamilyIndices.graphicsFamily.value() != qFamilyIndices.presentFamily.value()) { - swapChainCI.imageSharingMode = vk::SharingMode::eConcurrent, - qIndices = { qFamilyIndices.graphicsFamily.value(), qFamilyIndices.presentFamily.value() }; - swapChainCI.setQueueFamilyIndices(qIndices); + swapChainCI.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + qIndices = { qFamilyIndices.graphicsFamily.value(), qFamilyIndices.presentFamily.value() }; + swapChainCI.queueFamilyIndexCount = static_cast(qIndices.size()); + swapChainCI.pQueueFamilyIndices = qIndices.data(); } else { - swapChainCI.imageSharingMode = vk::SharingMode::eExclusive; + swapChainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; } + swapChainCI.preTransform = scDetails.capabilities.currentTransform; + swapChainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapChainCI.presentMode = selectSwapChainPresentMode(scDetails.presentModes); + swapChainCI.clipped = VK_TRUE; + swapChainCI.oldSwapchain = VK_NULL_HANDLE; - vk::Result result = device.createSwapchainKHR(&swapChainCI, nullptr, &swapChain); - if (result != vk::Result::eSuccess) { - vLog.error("createSwapChain: Couldn not create swap chain", "VkResult:", result); - throw getVkException(result, "Couldn not create swap chain", "VulkanInstance::createSwapChain"); + VkResult result = vkCreateSwapchainKHR(device, &swapChainCI, nullptr, &swapChain); + if (result != VK_SUCCESS) { + vLog.error("createSwapChain: Couldn not create swap chain", "VkResult:", STR_VK_RESULT(result)); + throw std::runtime_error("createSwapChain: Couldn not create swap chain"); } // get image handles - std::tie(result, scImages) = device.getSwapchainImagesKHR(swapChain); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Couldn not get swap chain images", "VulkanInstance::createSwapChain"); - } + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); + scImages.resize(imageCount); + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, scImages.data()); vLog.log0("createSwapChain: Created swap chain."); } @@ -1536,10 +1640,7 @@ using std::uint32_t; glfwWaitEvents(); } vLog.log0("recreateSwapChain: new framebuffer size:", width, height); - vk::Result result = device.waitIdle(); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to wait for device idle", "VulkanInstance::recreateSwapChain"); - } + vkDeviceWaitIdle(device); cleanupSwapChain(); createSwapChain(); @@ -1548,7 +1649,6 @@ using std::uint32_t; createCommandBuffers(commandBuffersBegin); createCommandBuffers(commandBuffersEnd); - // TODO: order? for (auto& f : scRecreateCallbacks) { f(); } @@ -1561,29 +1661,31 @@ using std::uint32_t; void VulkanInstance::cleanupSwapChain() { for (auto& imageView : scImageViews) { - device.destroyImageView(imageView, nullptr); + vkDestroyImageView(device, imageView, nullptr); } - device.destroySwapchainKHR(swapChain, nullptr); + vkDestroySwapchainKHR(device, swapChain, nullptr); } void VulkanInstance::createSwapChainImageViews() { scImageViews.resize(scImages.size()); for (unsigned int i = 0; i < scImageViews.size(); i++) { - createImageView(scImageFormat, scImages[i], scImageViews[i], vk::ImageAspectFlagBits::eColor); + createImageView(scImageFormat, scImages[i], scImageViews[i], VK_IMAGE_ASPECT_COLOR_BIT); } vLog.log0("createImageViews: Created", scImageViews.size(), "image views."); } - uint32_t VulkanInstance::findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties) { - for (uint32_t i = 0; i < phDevMemProperties.memoryProperties.memoryTypeCount; i++) { + uint32_t VulkanInstance::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) { + VkPhysicalDeviceMemoryProperties memoryProperties{}; + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties); + for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) { // if ith bit of typefilter is set - if ((typeFilter & (1 << i)) and (phDevMemProperties.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { + if ((typeFilter & (1 << i)) and (memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) { return i; } } - throw VkException("Could not find suitable memory type", "VulkanInstance::findMemoryType"); + throw VkException("Could not find suitable memory type", "findMemoryType"); } @@ -1595,29 +1697,29 @@ using std::uint32_t; // COMMAND POOLS void VulkanInstance::createCommandPools() { - /* QueueFamilyIndicjes queueFamilyIndices = findQueueFamilies(physicalDevice); */ - vk::CommandPoolCreateInfo commandPoolGraphicsCI { - .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, - .queueFamilyIndex = qFamilyIndices.graphicsFamily.value(), - }; - vk::Result result = device.createCommandPool(&commandPoolGraphicsCI, nullptr, &commandPoolGraphics); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create graphics command pool", "createCommandPool"); - } + /* QueueFamilyIndicjes queueFamilyIndices = findQueueFamilies(physicalDevice); */ + VkCommandPoolCreateInfo commandPoolGraphicsCI{}; + commandPoolGraphicsCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolGraphicsCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + commandPoolGraphicsCI.queueFamilyIndex = qFamilyIndices.graphicsFamily.value(); + VkResult result = vkCreateCommandPool(device, &commandPoolGraphicsCI, nullptr, &commandPoolGraphics); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create graphics command pool", "createCommandPool"); + } - if (qFamilyIndices.transferFamily.has_value()) { - vk::CommandPoolCreateInfo commandPoolTransferCI { - .flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer, - .queueFamilyIndex = qFamilyIndices.transferFamily.value(), - }; - result = device.createCommandPool(&commandPoolTransferCI, nullptr, &commandPoolTransfer); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to create transfer command pool", "createCommandPool"); - } - } - else { - commandPoolTransfer = commandPoolGraphics; - } + if (qFamilyIndices.transferFamily.has_value()) { + VkCommandPoolCreateInfo commandPoolTransferCI{}; + commandPoolTransferCI.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + commandPoolTransferCI.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + commandPoolTransferCI.queueFamilyIndex = qFamilyIndices.transferFamily.value(); + result = vkCreateCommandPool(device, &commandPoolTransferCI, nullptr, &commandPoolTransfer); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to create transfer command pool", "createCommandPool"); + } + } + else { + commandPoolTransfer = commandPoolGraphics; + } } @@ -1627,29 +1729,45 @@ using std::uint32_t; renderFinishedSemaphores.resize(getMaxFramesInFlight()); inFlightFences.resize(getMaxFramesInFlight()); - vk::SemaphoreCreateInfo semaphoreCI; + VkSemaphoreCreateInfo semaphoreCI{}; + semaphoreCI.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - vk::FenceCreateInfo fenceCI { - .flags = vk::FenceCreateFlagBits::eSignaled, - }; + VkFenceCreateInfo fenceCI{}; + fenceCI.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceCI.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < getMaxFramesInFlight(); i++) { - vk::Result result = device.createSemaphore(&semaphoreCI, nullptr, &imageAvailableSemaphores[i]); - if (result != vk::Result::eSuccess) { + VkResult result = vkCreateSemaphore(device, &semaphoreCI, nullptr, &imageAvailableSemaphores[i]); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to create imageAvailableSemaphores", "createSyncObjects"); } - result = device.createSemaphore(&semaphoreCI, nullptr, &renderFinishedSemaphores[i]); - if (result != vk::Result::eSuccess) { + result = vkCreateSemaphore(device, &semaphoreCI, nullptr, &renderFinishedSemaphores[i]); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to create renderFinishedSemaphores", "createSyncObjects"); } - result = device.createFence(&fenceCI, nullptr, &inFlightFences[i]); - if (result != vk::Result::eSuccess) { + result = vkCreateFence(device, &fenceCI, nullptr, &inFlightFences[i]); + if (result != VK_SUCCESS) { throw getVkException(result, "Failed to create inFlightFences", "createSyncObjects"); } } } + /* void VulkanInstance::createDepthImageAndView() { */ + /* VkMemoryPropertyFlags memoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; */ + /* VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; */ + /* VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; */ + /* VkFormat depthFormat = findDepthFormat(); */ + + /* createImage(scExtent.width, scExtent.height, depthFormat, tiling, imageUsage, memoryProperties, depthImage, depthImageMemory); */ + /* createImageView(depthFormat, depthImage, depthImageView, VK_IMAGE_ASPECT_DEPTH_BIT); */ + + /* transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); */ + + + /* } */ + + // SHADERS std::vector VulkanInstance::readFile(const std::string& filename) { std::ifstream file(filename, std::ios::ate | std::ios::binary); @@ -1674,12 +1792,11 @@ using std::uint32_t; // DEBUG void VulkanInstance::setupDebugMessenger() { // get the address of the vkCreateDebugUtilsMessengerEXT function - VkDebugUtilsMessengerCreateInfoEXT debugCI = static_cast(debugUtilsMessengerCI); - vk::Result result = runVkResultFunction("vkCreateDebugUtilsMessengerEXT", instance, &debugCI, nullptr, &debugMessenger); - if (result != vk::Result::eSuccess) { - throw getVkException(result, "Failed to initialise debug messenger", "VulkanInstance::setupDebugMessenger"); + VkResult result = runVkResultFunction("vkCreateDebugUtilsMessengerEXT", instance, &debugUtilsMessengerCI, nullptr, &debugMessenger); + if (result != VK_SUCCESS) { + throw getVkException(result, "Failed to initialise debug messenger", "setupDebugMessenger"); } - /* auto f = reinterpret_cast(vk::getInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")); */ + /* auto f = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT")); */ /* if (f == nullptr) { throw std::runtime_error("Failed to initialise debug messenger."); } */ /* else { */ /* f(instance, &debugUtilsMessengerCreateInfo, nullptr, &debugMessenger); */ @@ -1748,5 +1865,5 @@ using std::uint32_t; -} // namespace gz::vlk +} // namespace gz::vk diff --git a/src/vulkan_instance.hpp b/src/vulkan_instance.hpp index 9a2fade..4533fcf 100644 --- a/src/vulkan_instance.hpp +++ b/src/vulkan_instance.hpp @@ -1,45 +1,57 @@ #pragma once #define GLM_FORCE_DEPTH_ZERO_TO_ONE -/* #include */ +#include #define GLFW_INCLUDE_VULKAN #include -#define VULKAN_HPP_NO_EXCEPTIONS -#define VULKAN_HPP_NO_CONSTRUCTORS -#include - #include "vk_convert.hpp" #include "vertex.hpp" +#include "shape.hpp" #include "vulkan_util.hpp" #include "vulkan_allocator.hpp" -#include "vulkan_settings.hpp" #include #include #include +#include + #include #include -namespace gz::vlk { - constexpr vk::MemoryMapFlags NO_MEM_FLAGS; - constexpr vk::AccessFlags NO_ACC_FLAGS; - constexpr vk::AccessFlags2 NO_ACC_2_FLAGS; - constexpr vk::CommandBufferResetFlags NO_CMD_RESET_FLAGS; - const uint32_t NO_OFFSET = 0; - constexpr vk::AllocationCallbacks* NO_ALLOC = nullptr; - /* const vk::ImageSubresourceRange DEFAULT_SUBRESOURCE_RANGE { */ - /* .aspectMask = vk::ImageAspectFlagBits::eColor, */ - /* .baseMipLevel = 0, */ - /* .levelCount = 1, */ - /* .baseArrayLayer = 0, */ - /* .layerCount = 1, */ - /* }; */ +namespace gz::vk { + constexpr bool throwExceptionOnValidationError = true; + constexpr gz::Color VULKAN_MESSAGE_PREFIX_COLOR = gz::Color::BO_BLUE; + constexpr gz::Color VULKAN_MESSAGE_TIME_COLOR = gz::Color::BLUE; + const std::string CONFIG_FILE = "vulkan.conf"; +#define SettingsTypes uint32_t, bool, float + /* const std::string MODEL_PATH = "models/gazebo-3d-model/gazebo.obj"; */ + /* const std::string TEXTURE_PATH = "models/gazebo-3d-model/gazebo_diffuse.png"; */ + + const std::string MODEL_PATH = "models/armoire-3d-model/Armoire.obj"; + const std::string TEXTURE_PATH = "models/armoire-3d-model/Armoire_diffuse.png"; + + const gz::util::unordered_string_map INITIAL_SETTINGS = { + { "framerate", "60" }, + { "anisotropy_enable", "false" }, + { "max_anisotropy", "1" }, + { "max_frames_in_flight", "3" }, + /* { "", "" } */ + }; + + + constexpr VkClearColorValue missingTextureColor = { { 0.4f, 0.0f, 0.4f, 1.0f } }; + const int BINDING = 0; + const uint32_t NO_FLAGS = 0; + const uint32_t NO_OFFSET = 0; + constexpr VkAllocationCallbacks* NO_ALLOC = nullptr; + const size_t VERTEX_BUFFER_SIZE = 512; + const size_t INDEX_BUFFER_SIZE = 512; enum InstanceCommandPool { POOL_GRAPHICS, POOL_TRANSFER }; @@ -55,7 +67,7 @@ namespace gz::vlk { * These functions will probably called from your `main` function and loop. */ /// @{ - VulkanInstance(gz::SettingsManagerCreateInfosmCI) : settings(smCI), allocator(*this) {}; + VulkanInstance(gz::SettingsManagerCreateInfosmCI) : settings(smCI), allocator(*this) {}; /** * @brief Initializes the vulkan instance * @details @@ -146,13 +158,12 @@ namespace gz::vlk { */ public: /// @{ - const vk::Device& getDevice() const { return device; } - const vk::Extent2D& getScExtent() const { return scExtent; } - const std::vector& getScImages() const { return scImages; } - const vk::Format& getScImageFormat() const { return scImageFormat; } - const vk::Format& getDepthFormat() const { return depthFormat; } + const VkDevice& getDevice() const { return device; } + const VkExtent2D& getScExtent() const { return scExtent; } + const std::vector& getScImages() const { return scImages; } + const VkFormat& getScImageFormat() const { return scImageFormat; } - SettingsManager& getSettings() { return settings; } + SettingsManager& getSettings() { return settings; } /** * @brief Get the maximum number of frames in flight @@ -165,30 +176,28 @@ namespace gz::vlk { */ uint32_t getCurrentFrame() const { return currentFrame; } - void submitThisFrame(vk::CommandBuffer& cmdBuffer); + void submitThisFrame(VkCommandBuffer& cmdBuffer); /** * @brief Copy from srcBuffer to dstBuffer * @details * Uses @ref beginSingleTimeCommands() "a single time command buffer" from commandPoolTransfer. */ - void copyBuffer(vk::Buffer srcBuffer, vk::Buffer dstBuffer, vk::DeviceSize size); + void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); /** * @brief Begin a command buffer that is going to be used once * @param commandPool: The command pool from which the buffer should be allocated */ - vk::CommandBuffer beginSingleTimeCommands(InstanceCommandPool commandPool); + VkCommandBuffer beginSingleTimeCommands(InstanceCommandPool commandPool); /** * @brief Submit cmdBuffer on the queue and free it afterwards * @param cmdBuffer: Command buffer returned by beginSingleTimeCommands() * @param commandPool: The same pool as passed to beginSingleTimeCommands() - * @details - * After command buffer is submitted on the specified queue, the function waits for the queue to idle */ - void endSingleTimeCommands(vk::CommandBuffer cmdBuffer, InstanceCommandPool commandPool); + void endSingleTimeCommands(VkCommandBuffer cmdBuffer, InstanceCommandPool commandPool); - void loadModel(const std::string& path, VerticesAndIndices& model); + void loadModel(VerticesAndIndices& model); /// @} /** @@ -203,16 +212,16 @@ namespace gz::vlk { /** * @brief Create MAX_FRAMES_IN_FLIGHT command buffers from the commandPoolGraphics */ - void createCommandBuffers(std::vector& commandBuffers); + void createCommandBuffers(std::vector& commandBuffers); /** * @brief Destroy all command buffers (must be from commandPoolGraphics) */ - void destroyCommandBuffers(std::vector& commandBuffers); + void destroyCommandBuffers(std::vector& commandBuffers); /** * @brief Create a descriptor layout with bindings */ - void createDescriptorSetLayout(std::vector bindings, vk::DescriptorSetLayout& layout); + void createDescriptorSetLayout(std::vector bindings, VkDescriptorSetLayout& layout); /** * @brief Create a new graphics pipeline @@ -227,19 +236,17 @@ namespace gz::vlk { * @details * Create a pipeline with: * - 2 shader stages: vertex and fragment shader - * - vk::PrimitiveTopology::eTriangleList, vertices are triangles + * - VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vertices are triangles * - viewport viewing the whole image as described by scExtent * - scissor with offset (0, 0) * - rasterizer: * - triangles are filled with the colors from the vertex (VK_POLYGON_FILL) - * - counter clockwise front face (vk::FrontFace::eCounterClockwise) - * - * @todo Move shader module creation and maybe pipelineshaderstagecreateinfo outside + * - counter clockwise front face (VK_FRONT_FACE_COUNTER_CLOCKWISE) */ template - void createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, vk::RenderPass& renderPass, Pipeline& pipeline, vk::SpecializationInfo* fragSI=nullptr, vk::SpecializationInfo* vertSI=nullptr); + void createGraphicsPipeline(const std::string& vertexShader, const std::string& fragmentShader, std::vector& descriptorSetLayouts, bool useDepthStencil, VkRenderPass& renderPass, Pipeline& pipeline); - vk::ShaderModule createShaderModule(const std::vector& code); + VkShaderModule createShaderModule(const std::vector& code); /** * @brief Allocate memory, create a buffer and bind buffer to memory @@ -247,16 +254,15 @@ namespace gz::vlk { * @param buffer The (null) handle to the buffer * @param bufferMemory Reference to an (uninitialized) MemoryInfo struct. It will be valid when the function returns * @param properties Properties that the buffers memory needs to satisfy - * @param qFamiliesWithAccess [Optional] vector of queue families that have access to the buffer. Only needed with SHARING_MODE_CONCURRENT * @details * The memory the buffer will be bound to is HOST_VISIBLE and HOST_COHERENT * */ - void createBuffer(vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags properties, vk::Buffer& buffer, MemoryInfo& bufferMemory, vk::SharingMode sharingMode=vk::SharingMode::eExclusive, std::vector* qFamiliesWithAccess=nullptr); + void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, MemoryInfo& bufferMemory, VkSharingMode sharingMode=VK_SHARING_MODE_EXCLUSIVE, std::vector* qFamiliesWithAccess=nullptr); /** * @brief Destroy buffer and free memory */ - void destroyBuffer(vk::Buffer& buffer, MemoryInfo& bufferMemory); + void destroyBuffer(VkBuffer& buffer, MemoryInfo& bufferMemory); /** * @brief Create a vertex buffer @@ -267,7 +273,7 @@ namespace gz::vlk { * The function is instantiated for Vertex2D and Vertex3D */ template - void createVertexBuffer(size_t vertexCount, vk::Buffer& vertexBuffer, MemoryInfo& vertexBufferMemory, vk::DeviceSize& vertexBufferSize); + void createVertexBuffer(size_t vertexCount, VkBuffer& vertexBuffer, MemoryInfo& vertexBufferMemory, VkDeviceSize& vertexBufferSize); /** * @brief Create an index buffer @@ -278,30 +284,30 @@ namespace gz::vlk { * The function is instantiated for uint16_t and uint32_t */ template - void createIndexBuffer(size_t indexCount, vk::Buffer& indexBuffer, MemoryInfo& indexBufferMemory, vk::DeviceSize& indexBufferSize); + void createIndexBuffer(size_t indexCount, VkBuffer& indexBuffer, MemoryInfo& indexBufferMemory, VkDeviceSize& indexBufferSize); /** * @brief Create MAX_FRAMES_IN_FLIGHT uniform buffers */ template - void createUniformBuffers(std::vector& uniformBuffers, std::vector& uniformBuffersMemory); + void createUniformBuffers(std::vector& uniformBuffers, std::vector& uniformBuffersMemory); /** * @brief Create as many framebuffers as the swap chain has images, with the extent of the swap chain */ - void createFramebuffers(std::vector& framebuffers, std::vector& imageViews, vk::RenderPass& renderPass, vk::ImageView depthImageView=VK_NULL_HANDLE); + void createFramebuffers(std::vector& framebuffers, std::vector& imageViews, VkRenderPass& renderPass); /** * @brief Destroy the framebuffers */ - void destroyFramebuffers(std::vector& framebuffers); + void destroyFramebuffers(std::vector& framebuffers); /** * @brief Create a texture sampler * @todo add options and documentation */ - void createTextureSampler(vk::Sampler& sampler); + void createTextureSampler(VkSampler& sampler); - void destroyTextureSampler(vk::Sampler& sampler); + void destroyTextureSampler(VkSampler& sampler); /** * @name Public Interface: Image utility @@ -313,15 +319,15 @@ namespace gz::vlk { /** * @brief Create a 2D image, allocate the imageMemory and bind the image to it */ - void createImage(uint32_t width, uint32_t height, vk::Format format, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::MemoryPropertyFlags memoryProperties, vk::Image& image, MemoryInfo& imageMI); - void destroyImage(vk::Image& image, MemoryInfo& imageMemory); + void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags memoryProperties, VkImage& image, MemoryInfo& imageMI); + void destroyImage(VkImage& image, MemoryInfo& imageMemory); /** * @brief Create a 2D imageView with format for image. */ - void createImageView(vk::Format format, vk::Image& image, vk::ImageView& imageView, vk::ImageAspectFlags aspectFlags); - void destroyImageView(vk::ImageView& imageView); + void createImageView(VkFormat format, VkImage& image, VkImageView& imageView, VkImageAspectFlags aspectFlags); + void destroyImageView(VkImageView& imageView); - void copyBufferToImage(vk::Buffer buffer, vk::Image image, int32_t offsetX, int32_t offsetY, uint32_t width, uint32_t height); + void copyBufferToImage(VkBuffer buffer, VkImage image, int32_t offsetX, int32_t offsetY, uint32_t width, uint32_t height); /** * @todo make a version using vkCmdResolveImage for multisampled images * @brief Copy srcImage to dstImage @@ -336,7 +342,7 @@ namespace gz::vlk { * @param srcImage Image with layout TRANSFER_SRC_OPTIMAL * @param dstImage Image with layout TRANSFER_DST_OPTIMAL */ - void copyImageToImage(vk::CommandBuffer& cmdBuffer, vk::Image srcImage, vk::Image dstImage, vk::Extent2D extent); //, vk::CommandPool& commandPool=commandPoolTransfer); + void copyImageToImage(VkCommandBuffer& cmdBuffer, VkImage srcImage, VkImage dstImage, VkExtent2D extent); //, VkCommandPool& commandPool=commandPoolTransfer); /** * @brief Transition the layout of image from oldLayout to newLayout * @details @@ -350,12 +356,12 @@ namespace gz::vlk { * If you do not provide a command buffer, a command buffer from the indicated queue will be created and submitted. * If you do provide a command buffer, the command is recorded but NOT submitted. * - * The transition is done by submitting a vk::ImageMemoryBarrier2 + * The transition is done by submitting a VkImageMemoryBarrier2 * * @param cmdBuffer [Optional] The command buffer where the command will be recorded to - * @throws vk::UserError if the transition is not supported. + * @throws VkUserError if the transition is not supported. */ - void transitionImageLayout(vk::Image image, vk::Format format, vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::CommandBuffer* cmdBuffer=nullptr); + void transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, VkCommandBuffer* cmdBuffer=nullptr); /// @} @@ -387,7 +393,7 @@ namespace gz::vlk { * @name Settings */ /// @{ - gz::SettingsManager settings; + gz::SettingsManager settings; /** * @brief Set valid values for the SettingsManager according to phDevFeatures and phDevProperties * @details @@ -451,48 +457,37 @@ namespace gz::vlk { * @name Instance */ /// @{ - vk::Instance instance; + VkInstance instance; /** * @brief Create the vulkan instance * @details * -# check if validationLayers are available (if enabled) * -# create instance with info * -# check if all extensions required by glfw are available - * @throws VkException if: - * - validation layers are enabled but not supported - * - instance creation fails - * - not all required instance extensions are available */ void createInstance(); - /** - * @brief Get all the required instance extensions - * @details - * The required extensions are: - * - all extensions required by glfw (glfwGetRequiredInstanceExtensions()) - * - if validation layers are enabled: "VK_EXT_debug_utils" - */ - std::vector getRequiredInstanceExtensions() const; - /** - * @brief Check if @ref settings::validationLayers "all requrested validation layers" are supported - */ - bool validationLayersSupported(); /// @} /** - * @name Physical device (selection process) - * @brief Member variables and functions that are used to select a physical device + * @name Physical device */ /// @{ + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + /// all the properties of the selected physcial device + VkPhysicalDeviceProperties phDevProperties; + /// all the features that the selected physical device supports + PhysicalDeviceFeatures phDevFeatures; + /** + * @brief Get the required physical device features + * @details + * The required features are: + * - synchronization2 + */ + PhysicalDeviceFeatures getRequiredFeatures() const; /** * @brief Assign the physicalDevice handle to the @ref rateDevice "best rated" GPU * @details - * After this method, the following members will be initalized: - * - physicalDevice - * - phDevProperties - * - phDevFeatures - * - phDevMemProperties - * - qFamilyIndices - * - depthFormat + * After this method, physicalDevice, phDevProperties and phDevFeatures will be initialized */ void selectPhysicalDevice(); /** @@ -504,44 +499,20 @@ namespace gz::vlk { * - support all necessary extensions * - have swap chain support */ - unsigned int rateDevice(vk::PhysicalDevice device); - /** - * @brief Get the required physical device features - * @details - * The required features are: - * - synchronization2 - */ - PhysicalDeviceFeatures getRequiredDeviceFeatures() const; - - /** - * @name Physical device (selected) - * @brief Member variables and functions that are usable/initalized after selectPhysicalDevice - */ - /// @{ - vk::PhysicalDevice physicalDevice = VK_NULL_HANDLE; - /// all the properties of the selected physcial device - vk::PhysicalDeviceProperties2 phDevProperties; - /// memory properties of the selected physical device - vk::PhysicalDeviceMemoryProperties2 phDevMemProperties; - /// all the features that the selected physical device supports - PhysicalDeviceFeatures phDevFeatures; - /// preferred depth format - vk::Format depthFormat; - + unsigned int rateDevice(VkPhysicalDevice device); /** * @brief Find the best of the supported formats * @param candidates Candidate format, from best to worst * @returns The first format from candidates that is supported - * @throws VkException if no suitable format is found */ - vk::Format findSupportedFormat(const std::vector& candidates, vk::ImageTiling tiling, vk::FormatFeatureFlags features); + VkFormat findSupportedFormat(const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features); /// @} /** * @name Memory management */ /// @{ - uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties); + uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); VulkanAllocator allocator; /// @} @@ -549,19 +520,19 @@ namespace gz::vlk { * @name Queue */ /// @{ - QueueFamilyIndices findQueueFamilies(vk::PhysicalDevice device); + QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); QueueFamilyIndices qFamilyIndices; - vk::Queue graphicsQ; - vk::Queue presentQ; + VkQueue graphicsQ; + VkQueue presentQ; // if possible, use dedicated transferQ. if not available, transferQ = graphicsQ - vk::Queue transferQ; + VkQueue transferQ; /// @} /** * @name Logical device */ /// @{ - vk::Device device; + VkDevice device; /** * @details * request anisotropic sampling feature @@ -573,7 +544,7 @@ namespace gz::vlk { * @name Surface */ /// @{ - vk::SurfaceKHR surface; + VkSurfaceKHR surface; void createSurface(); /// @} @@ -581,23 +552,22 @@ namespace gz::vlk { * @name Swap chain */ /// @{ - vk::SwapchainKHR swapChain; - std::vector scImages; - std::vector scImageViews; - vk::Format scImageFormat; - vk::Extent2D scExtent; + VkSwapchainKHR swapChain; + std::vector scImages; + std::vector scImageViews; + VkFormat scImageFormat; + VkExtent2D scExtent; - SwapChainSupport querySwapChainSupport(vk::PhysicalDevice device); + SwapChainSupport querySwapChainSupport(VkPhysicalDevice device); /** * @todo Rate formats if preferred is not available - * @todo Move back to SurfaceFormatKHR? 2 is an (for now) unnecessary extension */ - vk::SurfaceFormat2KHR selectSwapChainSurfaceFormat(const std::vector& availableFormats); + VkSurfaceFormatKHR selectSwapChainSurfaceFormat(const std::vector& availableFormats); /** * @todo Check settings for preferred mode */ - vk::PresentModeKHR selectSwapChainPresentMode(const std::vector& availableModes); - vk::Extent2D selectSwapExtent(const vk::SurfaceCapabilities2KHR& capabilities); + VkPresentModeKHR selectSwapChainPresentMode(const std::vector& availableModes); + VkExtent2D selectSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapChain(); void createSwapChainImageViews(); void cleanupSwapChain(); @@ -619,31 +589,31 @@ namespace gz::vlk { * @name Command pools */ /// @{ - vk::CommandPool commandPoolGraphics; - vk::CommandPool commandPoolTransfer; + VkCommandPool commandPoolGraphics; + VkCommandPool commandPoolTransfer; void createCommandPools(); /// @} /** * @name Command buffers */ /// @{ - std::vector commandBuffersBegin; - std::vector commandBuffersEnd; + std::vector commandBuffersBegin; + std::vector commandBuffersEnd; /** * @brief All command buffers to submit on graphics queue for the current frame * @details * Use submitThisFrame() to submit a command buffer */ - std::vector commandBuffersToSubmitThisFrame; + std::vector commandBuffersToSubmitThisFrame; /// @} /** * @name Synchronization */ /// @{ - std::vector imageAvailableSemaphores; - std::vector renderFinishedSemaphores; - std::vector inFlightFences; + std::vector imageAvailableSemaphores; + std::vector renderFinishedSemaphores; + std::vector inFlightFences; void createSyncObjects(); /// @} @@ -664,7 +634,7 @@ namespace gz::vlk { */ /// @{ template - vk::Result runVkResultFunction(const char* name, Args&&... args); + VkResult runVkResultFunction(const char* name, Args&&... args); template void runVkVoidFunction(const char* name, Args&&... args); @@ -706,14 +676,14 @@ namespace gz::vlk { // UNIFORM BUFFERS // template - void VulkanInstance::createUniformBuffers(std::vector& uniformBuffers, std::vector& uniformBuffersMemory) { - vk::DeviceSize bufferSize = sizeof(T); + void VulkanInstance::createUniformBuffers(std::vector& uniformBuffers, std::vector& uniformBuffersMemory) { + VkDeviceSize bufferSize = sizeof(T); uniformBuffers.resize(MAX_FRAMES_IN_FLIGHT); uniformBuffersMemory.resize(MAX_FRAMES_IN_FLIGHT); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - createBuffer(bufferSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent, uniformBuffers[i], uniformBuffersMemory[i]); + createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformBuffers[i], uniformBuffersMemory[i]); } } @@ -721,14 +691,14 @@ namespace gz::vlk { // UTILITY // template - vk::Result VulkanInstance::runVkResultFunction(const char* name, Args&&... args) { + VkResult VulkanInstance::runVkResultFunction(const char* name, Args&&... args) { auto f = reinterpret_cast(vkGetInstanceProcAddr(instance, name)); if (f == nullptr) { vLog.error("getVkFunction: Could not get function:", name); throw std::runtime_error("getVkFunction: Could not get function."); } else { - return vk::Result(f(std::forward(args)...)); + return f(std::forward(args)...); } }; diff --git a/src/vulkan_settings.hpp b/src/vulkan_settings.hpp deleted file mode 100644 index 3deea63..0000000 --- a/src/vulkan_settings.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include - -#define VULKAN_HPP_NO_EXCEPTIONS -#define VULKAN_HPP_NO_CONSTRUCTORS -#include - -namespace gz::vlk::settings { - constexpr bool throwExceptionOnValidationError = true; - constexpr gz::Color VULKAN_MESSAGE_PREFIX_COLOR = gz::Color::BO_BLUE; - constexpr gz::Color VULKAN_MESSAGE_TIME_COLOR = gz::Color::BLUE; - const std::string CONFIG_FILE = "vulkan.conf"; - - /* const std::string MODEL_PATH = "models/gazebo-3d-model/gazebo.obj"; */ - /* const std::string TEXTURE_PATH = "models/gazebo-3d-model/gazebo_diffuse.png"; */ - - const std::string MODEL_PATH = "models/armoire-3d-model/Armoire.obj"; - const std::string TEXTURE_PATH = "models/armoire-3d-model/Armoire_diffuse.png"; - -#define VULKAN_SETTINGS_MAN_TYPES uint32_t, bool, float - const gz::util::unordered_string_map INITIAL_SETTINGS = { - { "framerate", "60" }, - { "anisotropy_enable", "false" }, - { "max_anisotropy", "1" }, - { "max_frames_in_flight", "3" }, - /* { "", "" } */ - }; - constexpr vk::ClearColorValue missingTextureColor = { std::array{ 0.4f, 0.0f, 0.4f, 1.0f } }; - - constexpr size_t VERTEX_BUFFER_SIZE = 512; - constexpr size_t INDEX_BUFFER_SIZE = 512; - - - constexpr std::array deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - /* VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME */ - }; - - // DEBUG - /** - * @brief Which message severities to log in VulkanInstance::debugLog() - */ - constexpr vk::DebugUtilsMessageSeverityFlagsEXT debugMessageSevereties = - vk::DebugUtilsMessageSeverityFlagBitsEXT::eVerbose | - vk::DebugUtilsMessageSeverityFlagBitsEXT::eInfo | - vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning | - vk::DebugUtilsMessageSeverityFlagBitsEXT::eError; - - /** - * @brief Which message types to log in VulkanInstance::debugLog() - */ - constexpr vk::DebugUtilsMessageTypeFlagsEXT debugMessageTypes = - vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral | - vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation | - vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance; - - // VALIDATION LAYERS - constexpr std::array validationLayers { - "VK_LAYER_KHRONOS_validation", - }; - constexpr std::array validationFeaturesEnable { - vk::ValidationFeatureEnableEXT::eDebugPrintf, - vk::ValidationFeatureEnableEXT::eSynchronizationValidation, - vk::ValidationFeatureEnableEXT::eBestPractices - }; - constexpr vk::ValidationFeaturesEXT validationFeatures { - .enabledValidationFeatureCount = static_cast(validationFeaturesEnable.size()), - .pEnabledValidationFeatures = validationFeaturesEnable.data(), - }; -} // namespace gz::vlk::setting