From 6252052a42fdf4edb61534802af90465d79a6d06 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 14 May 2026 14:01:52 +0200 Subject: [PATCH 1/5] IMplement depth resource creation --- assets/shaders/default.vert | 4 +- src/contrib/vcpkg | 2 +- src/runtime/application/app.cpp | 7 ++- src/runtime/renderer/RHIVulkan.cpp | 83 ++++++++++++++++++++++++++---- 4 files changed, 80 insertions(+), 16 deletions(-) diff --git a/assets/shaders/default.vert b/assets/shaders/default.vert index 5510aa3..840711c 100644 --- a/assets/shaders/default.vert +++ b/assets/shaders/default.vert @@ -6,7 +6,7 @@ layout(binding = 0) uniform UniformBufferObject { mat4 proj; } ubo; -layout(location = 0) in vec2 inPosition; +layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec2 inTexCoord; @@ -14,7 +14,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoord; void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); fragColor = inColor; fragTexCoord = inTexCoord; } diff --git a/src/contrib/vcpkg b/src/contrib/vcpkg index e7d7451..f75c836 160000 --- a/src/contrib/vcpkg +++ b/src/contrib/vcpkg @@ -1 +1 @@ -Subproject commit e7d7451462697d77ef319ddf2da8ff7320a82662 +Subproject commit f75c836a67777a86a2c1116a28b179827f028b66 diff --git a/src/runtime/application/app.cpp b/src/runtime/application/app.cpp index 740eafe..8b44f66 100644 --- a/src/runtime/application/app.cpp +++ b/src/runtime/application/app.cpp @@ -105,9 +105,12 @@ namespace segfault::application { } mRHI = new RHI; - mRHI->init(appName, mSdlWindow); + const bool ret = mRHI->init(appName, mSdlWindow); + if (!ret) { + logMessage(LogType::Error, "Failed to init RHI."); + } - return true; + return ret; } bool App::mainloop() { diff --git a/src/runtime/renderer/RHIVulkan.cpp b/src/runtime/renderer/RHIVulkan.cpp index 3df63f6..251f044 100644 --- a/src/runtime/renderer/RHIVulkan.cpp +++ b/src/runtime/renderer/RHIVulkan.cpp @@ -23,7 +23,7 @@ namespace segfault::renderer { struct Vertex { - glm::vec2 pos{}; + glm::vec3 pos{}; glm::vec3 color{}; glm::vec2 texCoord{}; @@ -60,14 +60,20 @@ namespace segfault::renderer { }; const std::vector vertices = { - {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, - {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, - {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, - {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}} + {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 0.0f}}, + {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}}, + {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}}, + {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, + + {{-0.5f, -0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, + {{0.5f, -0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, + {{0.5f, 0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, + {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}} }; const std::vector indices = { - 0, 1, 2, 2, 3, 0 + 0, 1, 2, 2, 3, 0, + 4, 5, 6, 6, 7, 4 }; const std::vector validationLayers = { @@ -139,6 +145,9 @@ namespace segfault::renderer { VkImageView textureImageView{}; VkSampler textureSampler; VkDeviceMemory textureImageMemory{}; + VkImage depthImage{}; + VkDeviceMemory depthImageMemory{}; + VkImageView depthImageView{}; RHIImpl() = default; ~RHIImpl() = default; @@ -167,6 +176,7 @@ namespace segfault::renderer { void createGraphicsPipeline(); void createFramebuffers(); void createCommandPool(QueueFamilyIndices& indices); + void createDepthResources(); void createCommandBuffer(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); @@ -177,7 +187,7 @@ namespace segfault::renderer { uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); void createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory); void createTextureImage(); - VkImageView createImageView(VkImage image, VkFormat format); + VkImageView createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags); void createTextureImageView(); void createTextureSampler(); void createVertexBuffer(); @@ -535,7 +545,7 @@ namespace segfault::renderer { void RHIImpl::createImageViews() { swapChainImageViews.resize(swapChainImages.size()); for (size_t i = 0; i < swapChainImages.size(); i++) { - swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat); + swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT); } } @@ -805,6 +815,40 @@ namespace segfault::renderer { } } + VkFormat findSupportedFormat(RHIImpl *rhi, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { + for (VkFormat format : candidates) { + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(rhi->physicalDevice, format, &props); + if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { + return format; + } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { + return format; + } + } + + throw std::runtime_error("failed to find supported format!"); + } + + VkFormat findDepthFormat(RHIImpl* rhi) { + return findSupportedFormat( + rhi, + { 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 + ); + } + + bool hasStencilComponent(VkFormat format) { + return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; + } + + void RHIImpl::createDepthResources() { + VkFormat depthFormat = findDepthFormat(this); + createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory); + depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT); + transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + } + void RHIImpl::createCommandBuffer() { commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); VkCommandBufferAllocateInfo allocInfo{}; @@ -1083,13 +1127,13 @@ namespace segfault::renderer { vkFreeMemory(device, stagingBufferMemory, nullptr); } - VkImageView RHIImpl::createImageView(VkImage image, VkFormat format) { + VkImageView RHIImpl::createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) { VkImageViewCreateInfo viewInfo{}; viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; viewInfo.image = image; viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.format = format; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewInfo.subresourceRange.aspectMask = aspectFlags; viewInfo.subresourceRange.baseMipLevel = 0; viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = 0; @@ -1104,7 +1148,7 @@ namespace segfault::renderer { } void RHIImpl::createTextureImageView() { - textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB); + textureImageView = createImageView(textureImage, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_ASPECT_COLOR_BIT); } void RHIImpl::createTextureSampler() { @@ -1344,6 +1388,16 @@ namespace segfault::renderer { VkPipelineStageFlags sourceStage; VkPipelineStageFlags destinationStage; + if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + + if (hasStencilComponent(format)) { + barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + } else { + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { barrier.srcAccessMask = 0; barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; @@ -1356,6 +1410,12 @@ namespace segfault::renderer { sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT; destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && 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; + + sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; } else { throw std::invalid_argument("unsupported layout transition!"); } @@ -1511,6 +1571,7 @@ namespace segfault::renderer { mImpl->createUniformBuffers(); mImpl->createDescriptorPool(); mImpl->createDescriptorSets(); + mImpl->createDepthResources(); mImpl->createCommandBuffer(); mImpl->createSyncObjects(); return true; From c501dc04df871a5c33a44b936b7b4a5ba0408161 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Mon, 18 May 2026 16:10:43 +0200 Subject: [PATCH 2/5] Finalize depth image --- src/contrib/vcpkg | 2 +- src/runtime/renderer/RHIVulkan.cpp | 129 ++++++++++++++++++----------- 2 files changed, 82 insertions(+), 49 deletions(-) diff --git a/src/contrib/vcpkg b/src/contrib/vcpkg index f75c836..e7d7451 160000 --- a/src/contrib/vcpkg +++ b/src/contrib/vcpkg @@ -1 +1 @@ -Subproject commit f75c836a67777a86a2c1116a28b179827f028b66 +Subproject commit e7d7451462697d77ef319ddf2da8ff7320a82662 diff --git a/src/runtime/renderer/RHIVulkan.cpp b/src/runtime/renderer/RHIVulkan.cpp index 251f044..dbf690b 100644 --- a/src/runtime/renderer/RHIVulkan.cpp +++ b/src/runtime/renderer/RHIVulkan.cpp @@ -203,6 +203,29 @@ namespace segfault::renderer { void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height); }; + VkFormat findSupportedFormat(RHIImpl *rhi, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { + for (VkFormat format : candidates) { + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(rhi->physicalDevice, format, &props); + if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { + return format; + } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { + return format; + } + } + + throw std::runtime_error("failed to find supported format!"); + } + + VkFormat findDepthFormat(RHIImpl* rhi) { + return findSupportedFormat( + rhi, + { 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 + ); + } + static std::vector readFile(const std::string& filename) { std::ifstream file(filename, std::ios::ate | std::ios::binary); @@ -578,22 +601,53 @@ namespace segfault::renderer { colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + VkAttachmentDescription depthAttachment{}; + depthAttachment.format = findDepthFormat(this); + 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; + + VkAttachmentReference depthAttachmentRef{}; + depthAttachmentRef.attachment = 1; + depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + VkAttachmentReference colorAttachmentRef{}; colorAttachmentRef.attachment = 0; colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; VkSubpassDescription subpass{}; subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &colorAttachmentRef; + subpass.pDepthStencilAttachment = &depthAttachmentRef; - VkRenderPassCreateInfo renderPassInfo{}; + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dependency.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + 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; + + /*VkRenderPassCreateInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; renderPassInfo.attachmentCount = 1; renderPassInfo.pAttachments = &colorAttachment; renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass;*/ + std::array attachments = {colorAttachment, depthAttachment}; + VkRenderPassCreateInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = static_cast(attachments.size()); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.subpassCount = 1; renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { return; @@ -688,6 +742,18 @@ namespace segfault::renderer { 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; + VkPipelineDepthStencilStateCreateInfo depthStencil{}; + depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depthStencil.depthTestEnable = VK_TRUE; + depthStencil.depthWriteEnable = VK_TRUE; + depthStencil.depthCompareOp = VK_COMPARE_OP_LESS; + depthStencil.depthBoundsTestEnable = VK_FALSE; + depthStencil.minDepthBounds = 0.0f; // Optional + depthStencil.maxDepthBounds = 1.0f; // Optional + depthStencil.stencilTestEnable = VK_FALSE; + depthStencil.front = {}; // Optional + depthStencil.back = {}; // Optional + VkPipelineColorBlendStateCreateInfo colorBlending{}; colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; colorBlending.logicOpEnable = VK_FALSE; @@ -729,6 +795,7 @@ namespace segfault::renderer { pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pDynamicState = &dynamicState; pipelineInfo.layout = pipelineLayout; + pipelineInfo.pDepthStencilState = &depthStencil; pipelineInfo.renderPass = renderPass; pipelineInfo.subpass = 0; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; @@ -781,15 +848,16 @@ namespace segfault::renderer { swapChainFramebuffers.resize(swapChainImageViews.size()); for (size_t i = 0; i < swapChainImageViews.size(); i++) { - VkImageView attachments[] = { - swapChainImageViews[i] + std::array attachments = { + swapChainImageViews[i], + depthImageView }; VkFramebufferCreateInfo framebufferInfo{}; framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; framebufferInfo.renderPass = renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; + framebufferInfo.attachmentCount = static_cast(attachments.size()); + framebufferInfo.pAttachments = attachments.data(); framebufferInfo.width = swapChainExtent.width; framebufferInfo.height = swapChainExtent.height; framebufferInfo.layers = 1; @@ -815,29 +883,6 @@ namespace segfault::renderer { } } - VkFormat findSupportedFormat(RHIImpl *rhi, const std::vector& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { - for (VkFormat format : candidates) { - VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(rhi->physicalDevice, format, &props); - if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { - return format; - } else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { - return format; - } - } - - throw std::runtime_error("failed to find supported format!"); - } - - VkFormat findDepthFormat(RHIImpl* rhi) { - return findSupportedFormat( - rhi, - { 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 - ); - } - bool hasStencilComponent(VkFormat format) { return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT; } @@ -874,11 +919,16 @@ namespace segfault::renderer { throw std::runtime_error("failed to begin recording command buffer!"); } + std::array clearValues{}; + clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}}; + clearValues[1].depthStencil = {1.0f, 0}; + VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = renderPass; renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; - + renderPassInfo.clearValueCount = static_cast(clearValues.size()); + renderPassInfo.pClearValues = clearValues.data(); renderPassInfo.renderArea.offset = { 0, 0 }; renderPassInfo.renderArea.extent = swapChainExtent; @@ -1539,28 +1589,12 @@ namespace segfault::renderer { mImpl->createLogicalDevice(mImpl->enableValidationLayers, mImpl->physicalDevice, mImpl->device, mImpl->queueFamilyIndices); - /*mImpl->createSwapChain(); - mImpl->createImageViews(); - mImpl->createRenderPass(); - mImpl->createDescriptorSetLayout(); - mImpl->createUniformBuffers(); - mImpl->createDescriptorPool(); - mImpl->createDescriptorSets(); - mImpl->createGraphicsPipeline(); - mImpl->createFramebuffers(); - mImpl->createCommandPool(mImpl->queueFamilyIndices); - mImpl->createCommandBuffer(); - mImpl->createSyncObjects(); - mImpl->createTextureImage(); - mImpl->createTextureImageView(); - mImpl->createVertexBuffer(); - mImpl->createIndexBuffer();*/ - mImpl->createSwapChain(); mImpl->createImageViews(); mImpl->createRenderPass(); mImpl->createDescriptorSetLayout(); mImpl->createGraphicsPipeline(); + mImpl->createDepthResources(); mImpl->createFramebuffers(); mImpl->createCommandPool(mImpl->queueFamilyIndices); mImpl->createTextureImage(); @@ -1571,7 +1605,6 @@ namespace segfault::renderer { mImpl->createUniformBuffers(); mImpl->createDescriptorPool(); mImpl->createDescriptorSets(); - mImpl->createDepthResources(); mImpl->createCommandBuffer(); mImpl->createSyncObjects(); return true; From 66712b633d89386f92aa95334e2fd8511a59f49b Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 19 May 2026 00:25:03 +0200 Subject: [PATCH 3/5] Bufixes --- src/contrib/vcpkg | 2 +- src/runtime/renderer/RHIVulkan.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/contrib/vcpkg b/src/contrib/vcpkg index e7d7451..f75c836 160000 --- a/src/contrib/vcpkg +++ b/src/contrib/vcpkg @@ -1 +1 @@ -Subproject commit e7d7451462697d77ef319ddf2da8ff7320a82662 +Subproject commit f75c836a67777a86a2c1116a28b179827f028b66 diff --git a/src/runtime/renderer/RHIVulkan.cpp b/src/runtime/renderer/RHIVulkan.cpp index dbf690b..f3ecf1b 100644 --- a/src/runtime/renderer/RHIVulkan.cpp +++ b/src/runtime/renderer/RHIVulkan.cpp @@ -32,7 +32,7 @@ namespace segfault::renderer { attributeDescriptions[0].binding = 0; attributeDescriptions[0].location = 0; - attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; + attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; attributeDescriptions[0].offset = offsetof(Vertex, pos); attributeDescriptions[1].binding = 0; @@ -1074,6 +1074,10 @@ namespace segfault::renderer { } void RHIImpl::cleanupSwapChain() { + vkDestroyImageView(device, depthImageView, nullptr); + vkDestroyImage(device, depthImage, nullptr); + vkFreeMemory(device, depthImageMemory, nullptr); + for (auto framebuffer : swapChainFramebuffers) { vkDestroyFramebuffer(device, framebuffer, nullptr); } @@ -1090,6 +1094,7 @@ namespace segfault::renderer { cleanupSwapChain(); createSwapChain(); createImageViews(); + createDepthResources(); createFramebuffers(); } @@ -1594,9 +1599,9 @@ namespace segfault::renderer { mImpl->createRenderPass(); mImpl->createDescriptorSetLayout(); mImpl->createGraphicsPipeline(); + mImpl->createCommandPool(mImpl->queueFamilyIndices); mImpl->createDepthResources(); mImpl->createFramebuffers(); - mImpl->createCommandPool(mImpl->queueFamilyIndices); mImpl->createTextureImage(); mImpl->createTextureImageView(); mImpl->createTextureSampler(); From 2d36797fd9862241d5e4c737cdc637b273ec0762 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 21 May 2026 16:44:28 +0200 Subject: [PATCH 4/5] Fix depth crash --- src/contrib/vcpkg | 2 +- src/runtime/renderer/RHIVulkan.cpp | 41 +++++++----------------------- src/runtime/renderer/rendercore.h | 18 +------------ 3 files changed, 11 insertions(+), 50 deletions(-) diff --git a/src/contrib/vcpkg b/src/contrib/vcpkg index f75c836..e7d7451 160000 --- a/src/contrib/vcpkg +++ b/src/contrib/vcpkg @@ -1 +1 @@ -Subproject commit f75c836a67777a86a2c1116a28b179827f028b66 +Subproject commit e7d7451462697d77ef319ddf2da8ff7320a82662 diff --git a/src/runtime/renderer/RHIVulkan.cpp b/src/runtime/renderer/RHIVulkan.cpp index f3ecf1b..11094fc 100644 --- a/src/runtime/renderer/RHIVulkan.cpp +++ b/src/runtime/renderer/RHIVulkan.cpp @@ -177,7 +177,7 @@ namespace segfault::renderer { void createFramebuffers(); void createCommandPool(QueueFamilyIndices& indices); void createDepthResources(); - void createCommandBuffer(); + void createCommandBuffers(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); void updateUniformBuffer(uint32_t currentImage); @@ -633,12 +633,6 @@ namespace segfault::renderer { 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; - /*VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass;*/ std::array attachments = {colorAttachment, depthAttachment}; VkRenderPassCreateInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; @@ -894,7 +888,7 @@ namespace segfault::renderer { transitionImageLayout(depthImage, depthFormat, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } - void RHIImpl::createCommandBuffer() { + void RHIImpl::createCommandBuffers() { commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -919,22 +913,19 @@ namespace segfault::renderer { throw std::runtime_error("failed to begin recording command buffer!"); } - std::array clearValues{}; - clearValues[0].color = {{0.0f, 0.0f, 0.0f, 1.0f}}; - clearValues[1].depthStencil = {1.0f, 0}; - VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = renderPass; renderPassInfo.framebuffer = swapChainFramebuffers[imageIndex]; - renderPassInfo.clearValueCount = static_cast(clearValues.size()); - renderPassInfo.pClearValues = clearValues.data(); renderPassInfo.renderArea.offset = { 0, 0 }; renderPassInfo.renderArea.extent = swapChainExtent; - VkClearValue clearColor = { {{0.5f, 0.5f, 0.5f, 1.0f}} }; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; + std::array clearValues{}; + clearValues[0].color = {{0.8f, 0.8f, 0.8f, 1.0f}}; + clearValues[1].depthStencil = {1.0f, 0}; + + renderPassInfo.clearValueCount = static_cast(clearValues.size()); + renderPassInfo.pClearValues = clearValues.data(); vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -1354,20 +1345,6 @@ namespace segfault::renderer { descriptorWrites[1].pImageInfo = &imageInfo; vkUpdateDescriptorSets(device, static_cast(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr); - /*VkWriteDescriptorSet descriptorWrite{}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSets[i]; - descriptorWrite.dstBinding = 0; - descriptorWrite.dstArrayElement = 0; - - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrite.descriptorCount = 1; - - descriptorWrite.pBufferInfo = &bufferInfo; - descriptorWrite.pImageInfo = nullptr; // Optional - descriptorWrite.pTexelBufferView = nullptr; // Optional - - vkUpdateDescriptorSets(device, 1, &descriptorWrite, 0, nullptr);*/ } } @@ -1610,7 +1587,7 @@ namespace segfault::renderer { mImpl->createUniformBuffers(); mImpl->createDescriptorPool(); mImpl->createDescriptorSets(); - mImpl->createCommandBuffer(); + mImpl->createCommandBuffers(); mImpl->createSyncObjects(); return true; } diff --git a/src/runtime/renderer/rendercore.h b/src/runtime/renderer/rendercore.h index dc01af1..9879b8c 100644 --- a/src/runtime/renderer/rendercore.h +++ b/src/runtime/renderer/rendercore.h @@ -21,27 +21,11 @@ namespace segfault::renderer { glm::mat4 proj; }; - struct RenderPipelineState{ - }; - - struct DrawCommand { - //RenderPipelineState rpState; - - uint32_t numVertices{0}; - uint32_t numInstances{0}; - uint32_t vertexOffset{0}; - uint32_t instanceOffset{0}; - uint32_t indexCount{0}; - }; - class RenderGraph { public: RenderGraph() = default; - ~RenderGraph() = default; - void addCommand(const DrawCommand& command) { - // Implementation for adding a draw command to the render graph - } + ~RenderGraph() = default; void execute(RHI &rhi) { // Implementation for executing the render graph From 860efcfc9fdd552d4a7ccd602612297315d03037 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 21 May 2026 18:32:52 +0200 Subject: [PATCH 5/5] Add base docs. --- src/runtime/application/app.h | 27 ++++++++++++++++++++++++++- src/runtime/renderer/RHI.h | 25 ++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/runtime/application/app.h b/src/runtime/application/app.h index 8d75dbd..ee3f0bf 100644 --- a/src/runtime/application/app.h +++ b/src/runtime/application/app.h @@ -8,6 +8,14 @@ struct SDL_Window; namespace segfault::application { + //--------------------------------------------------------------------------------------------- + /// @class App + /// @brief The App class serves as the main entry point for the application. + /// + /// Managing the lifecycle of the application, including initialization, main loop, and + /// shutdown. It encapsulates the core functionality of the application, such as window + /// management, rendering, and event handling. + //--------------------------------------------------------------------------------------------- class SEGFAULT_EXPORT App final { public: using Rect = core::Rect; @@ -16,11 +24,28 @@ namespace segfault::application { App(const App &rhs) = delete; App& operator = (const App& rhs) = delete; + /// @brief The class constructor. App(); + + /// @brief The class destructor. ~App(); - bool init(const char* appName, const Rect &rect, const char* title, bool fullscreen); + + /// @brief Initializes the application with the specified parameters. + /// @param[ in ] appName The name of the application. + /// @param[ in ] rect The dimensions of the application window. + /// @param[ in ] title The title of the application window. + /// @param[ in ] fullscreen Whether to start the application in fullscreen mode. + /// @return True if initialization was successful, false otherwise. + bool init(const char* appName, const Rect &rect, const char* title,bool fullscreen); + + /// @brief The main loop of the application, which processes events and renders frames. + /// @return True if the main loop should continue running, false if it should exit. bool mainloop(); + + /// @brief Shuts down the application and releases all resources. void shutdown(); + + /// @brief Draws a single frame of the application. void drawFrame(); private: diff --git a/src/runtime/renderer/RHI.h b/src/runtime/renderer/RHI.h index 09c53ae..6449f1a 100644 --- a/src/runtime/renderer/RHI.h +++ b/src/runtime/renderer/RHI.h @@ -8,17 +8,40 @@ namespace segfault::renderer { struct RHIImpl; + //--------------------------------------------------------------------------------------------- + /// @class RHI + /// @brief RHI (Rendering Hardware Interface) class provides an abstraction layer for rendering operations. + /// + /// Allowing for flexibility in choosing different graphics APIs (e.g., Vulkan, DirectX, OpenGL) + /// without changing the higher-level rendering code. It manages the initialization, rendering, + /// and cleanup of graphics resources. + //--------------------------------------------------------------------------------------------- class RHI { public: + /// @brief Constructs a new RHI instance. RHI(); + + /// @brief Destroys the RHI instance. ~RHI(); + + /// @brief Initializes the RHI with the specified application name and window. + /// @param[ in ] appName The name of the application. + /// @param[ in ] window The SDL window to use for rendering. + /// @return True if initialization was successful, false otherwise. bool init(const char* appName, SDL_Window* window); + + /// @brief Shuts down the RHI. + /// @return True if shutdown was successful, false otherwise. bool shutdown(); + + /// @brief Draws a single frame. void drawFrame(); + + /// @brief Resizes the rendering surface. void resize(); private: - RHIImpl *mImpl; + RHIImpl* mImpl{ nullptr }; }; } // namespace segfault::renderer