Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SET(segfault_core_src
core/argumentparser.h
core/argumentparser.cpp
core/segfault.h
core/segfaultexception.h
core/filearchive.h
core/ifilemanager.h
core/genericfilemanager.h
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/core/genericfilemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@ namespace segfault::core {
#ifdef _WIN32
// Get the windows specific file-size
struct __stat64 fileStat;
int err = _stat64(name, &fileStat);
const int err = _stat64(name, &fileStat);
if (0 != err) {
return false;
}
stat.filesize = fileStat.st_size;
#else
// For unix
struct stat s{};
int err = ::stat(name, &s);
const int err = ::stat(name, &s);
if (0 != err) {
return false;
}
Expand Down
27 changes: 27 additions & 0 deletions src/runtime/core/segfaultexception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add the required MIT license header.

Line 1 starts a new .h file without the project-mandated MIT license banner.

As per coding guidelines, "Include MIT license header in all source files" for **/*.{h,cpp}.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/core/segfaultexception.h` at line 1, Add the project-mandated MIT
license header to the top of the new header file
src/runtime/core/segfaultexception.h by inserting the standard multi-line MIT
banner used across the repo before the existing `#pragma` once; ensure the header
text matches the exact format used in other .h/.cpp files (including year and
copyright holder) so the file complies with "Include MIT license header in all
source files" policy.

Source: Coding guidelines


#include <exception>
#include <string>

namespace segfault::core {

/// @class SegfaultException
/// @brief This class implements a segfault-specific expeption.
class SegfaultException : public std::exception {
public:
/// @brief Constructs a new segfault exception with the specified message.
/// @param message The error message for the exception.
explicit SegfaultException(std::string message) : std::exception(), mMessage(message){

Check warning on line 14 in src/runtime/core/segfaultexception.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Pass expensive to copy object "message" by reference to const.

See more on https://sonarcloud.io/project/issues?id=kimkulling_Segfault&issues=AZ6tqgttkG19EokxPRKL&open=AZ6tqgttkG19EokxPRKL&pullRequest=11
// empty
}

/// @brief Retrieves the error message associated with the exception.
/// @return The error message as a C-style string.
const char* what() const noexcept override {
return mMessage.c_str();
}

private:
std::string mMessage;
};
} // namespace segfault::core
77 changes: 45 additions & 32 deletions src/runtime/renderer/RHIVulkan.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "RHI.h"
#include "rendercore.h"

#include "core/segfaultexception.h"
#include "volk.h"
#include "SDL_vulkan.h"
#define GLM_FORCE_RADIANS
Expand All @@ -21,6 +21,7 @@
#include <chrono>

namespace segfault::renderer {
using namespace segfault::core;

struct Vertex {
glm::vec3 pos{};
Expand Down Expand Up @@ -88,7 +89,7 @@
std::optional<uint32_t> graphicsFamily{};
std::optional<uint32_t> presentFamily{};

bool isComplete() {
bool isComplete() const {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
Expand Down Expand Up @@ -143,7 +144,7 @@
VkDeviceMemory indexBufferMemory{};
VkImage textureImage{};
VkImageView textureImageView{};
VkSampler textureSampler;
VkSampler textureSampler{};
VkDeviceMemory textureImageMemory{};
VkImage depthImage{};
VkDeviceMemory depthImageMemory{};
Expand All @@ -163,7 +164,7 @@
const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger);
QueueFamilyIndices findQueueFamilies(QueueFamilyIndices& indices);
bool createLogicalDevice(bool enableValidationLayers, VkPhysicalDevice physicalDevice, VkDevice& device, QueueFamilyIndices& indices);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) const;
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes);
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
VkShaderModule createShaderModule(const std::vector<char>& code);
Expand Down Expand Up @@ -214,7 +215,7 @@
}
}

throw std::runtime_error("failed to find supported format!");
throw SegfaultException("failed to find supported format!");
}

VkFormat findDepthFormat(RHIImpl* rhi) {
Expand All @@ -234,7 +235,7 @@
errorMsg += filename;
errorMsg += ".";
core::logMessage(core::LogType::Error, errorMsg.c_str());
throw std::runtime_error("failed to open file!");
throw SegfaultException("failed to open file!");
}

size_t fileSize = (size_t)file.tellg();
Expand Down Expand Up @@ -314,8 +315,20 @@
&& supportedFeatures.samplerAnisotropy;
}

bool RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice device) {
return true;
bool RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice device_) {
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, nullptr);

std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, availableExtensions.data());
Comment on lines +318 to +323

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all extension-enumeration call sites and whether return values are checked.
rg -nP 'vkEnumerateDeviceExtensionProperties\s*\(' src/runtime/renderer/RHIVulkan.cpp -C3

Repository: kimkulling/Segfault

Length of output: 1122


Initialize and validate Vulkan extension-enumeration results in RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice)

At src/runtime/renderer/RHIVulkan.cpp lines 318-323, extensionCount is left uninitialized and both vkEnumerateDeviceExtensionProperties calls ignore the returned VkResult; if enumeration fails, this can produce an invalid extensionCount and unsafe vector sizing.

🛠️ Proposed fix
 bool RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice device_) {
-    uint32_t extensionCount;
-    vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, nullptr);
+    uint32_t extensionCount{};
+    VkResult result = vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, nullptr);
+    if (result != VK_SUCCESS) {
+        return false;
+    }
 
     std::vector<VkExtensionProperties> availableExtensions(extensionCount);
-    vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, availableExtensions.data());
+    result = vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, availableExtensions.data());
+    if (result != VK_SUCCESS) {
+        return false;
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice device_) {
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, availableExtensions.data());
bool RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice device_) {
uint32_t extensionCount{};
VkResult result = vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, nullptr);
if (result != VK_SUCCESS) {
return false;
}
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
result = vkEnumerateDeviceExtensionProperties(device_, nullptr, &extensionCount, availableExtensions.data());
if (result != VK_SUCCESS) {
return false;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/renderer/RHIVulkan.cpp` around lines 318 - 323, The Vulkan
extension enumeration in RHIImpl::checkDeviceExtensionSupport(VkPhysicalDevice)
leaves extensionCount uninitialized and ignores
vkEnumerateDeviceExtensionProperties return values; change to initialize
uint32_t extensionCount = 0, call vkEnumerateDeviceExtensionProperties and check
its VkResult for success before using extensionCount, bail out (return false or
handle error) if the call fails, then allocate/resize the
std::vector<VkExtensionProperties> to extensionCount and call
vkEnumerateDeviceExtensionProperties again while checking its result; ensure you
validate extensionCount (e.g., zero means no extensions) before using
availableExtensions.


std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());

Check warning on line 325 in src/runtime/renderer/RHIVulkan.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the transparent comparator "std::less<>" with this associative string container.

See more on https://sonarcloud.io/project/issues?id=kimkulling_Segfault&issues=AZ6tqgxekG19EokxPRKM&open=AZ6tqgxekG19EokxPRKM&pullRequest=11

for (const auto& extension : availableExtensions) {
requiredExtensions.erase(extension.extensionName);
}

return requiredExtensions.empty();
}

bool RHIImpl::checkValidationLayerSupport() {
Expand Down Expand Up @@ -469,7 +482,7 @@
return true;
}

VkSurfaceFormatKHR RHIImpl::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
VkSurfaceFormatKHR RHIImpl::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) const {
for (const auto& availableFormat : availableFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return availableFormat;
Expand Down Expand Up @@ -671,7 +684,7 @@
layoutInfo.pBindings = bindings.data();

if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor set layout!");
throw SegfaultException("failed to create descriptor set layout!");
}
}

Expand Down Expand Up @@ -774,7 +787,7 @@
pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;

if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
throw std::runtime_error("failed to create pipeline layout!");
throw SegfaultException("failed to create pipeline layout!");
}

VkGraphicsPipelineCreateInfo pipelineInfo{};
Expand All @@ -795,7 +808,7 @@
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;

if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
throw std::runtime_error("failed to create graphics pipeline!");
throw SegfaultException("failed to create graphics pipeline!");
}

vkDestroyShaderModule(device, fragShaderModule, nullptr);
Expand All @@ -810,7 +823,7 @@
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
throw std::runtime_error("failed to create buffer!");
throw SegfaultException("failed to create buffer!");
}

VkMemoryRequirements memRequirements;
Expand All @@ -822,7 +835,7 @@
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);

if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate buffer memory!");
throw SegfaultException("failed to allocate buffer memory!");
}

vkBindBufferMemory(device, buffer, bufferMemory, 0);
Expand Down Expand Up @@ -858,7 +871,7 @@

if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to create freamebuffer!");
throw std::runtime_error("failed to create framebuffer!");
throw SegfaultException("failed to create framebuffer!");
}
}
}
Expand All @@ -873,7 +886,7 @@

if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to create command pool mocule!");
throw std::runtime_error("failed to create command pool!");
throw SegfaultException("failed to create command pool!");
}
}

Expand All @@ -898,7 +911,7 @@

if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to allocate command buffers!");
throw std::runtime_error("failed to allocate command buffers!");
throw SegfaultException("failed to allocate command buffers!");
}
}

Expand All @@ -910,7 +923,7 @@

if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to begin recording command buffer!");
throw std::runtime_error("failed to begin recording command buffer!");
throw SegfaultException("failed to begin recording command buffer!");
}

VkRenderPassBeginInfo renderPassInfo{};
Expand Down Expand Up @@ -958,7 +971,7 @@

if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to recording command buffer!");
throw std::runtime_error("failed to record command buffer!");
throw SegfaultException("failed to record command buffer!");
}
}

Expand All @@ -980,7 +993,7 @@
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS ||
vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to create synchronization objects for a frame!");
throw std::runtime_error("failed to create synchronization objects for a frame!");
throw SegfaultException("failed to create synchronization objects for a frame!");
}
}
}
Expand Down Expand Up @@ -1009,7 +1022,7 @@
return;
} else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
core::logMessage(core::LogType::Error, "failed to acquire swap chain image!");
throw std::runtime_error("failed to acquire swap chain image!");
throw SegfaultException("failed to acquire swap chain image!");
}
Comment on lines +1025 to 1026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify throw/catch balance around public API boundaries.
rg -nP '^\s*(bool|void)\s+RHI::(init|drawFrame)\s*\(' src/runtime/renderer/RHIVulkan.cpp -A120
rg -nP '\bthrow\s+SegfaultException\s*\(' src/runtime/renderer/RHIVulkan.cpp
rg -nP '\bcatch\s*\(' src/runtime/renderer/RHIVulkan.cpp

Repository: kimkulling/Segfault

Length of output: 8447


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/runtime/renderer/RHIVulkan.cpp"

# Show context around the specific throw sites mentioned in the review
sed -n '1000,1100p' "$file" | cat -n

# Find the RHIImpl drawFrame implementation and show around it
rg -n "drawFrame\\s*\\(" "$file" | head -n 20
# also dump a larger window around the likely drawFrame impl region
sed -n '1600,1750p' "$file" | cat -n

# Confirm whether any catch exists anywhere in this file
rg -n "\\bcatch\\b" "$file" || true

Repository: kimkulling/Segfault

Length of output: 8214


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any catches for SegfaultException anywhere in the repo
rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' 'catch\s*\(\s*[^)]*SegfaultException' . || true
rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' 'SegfaultException' . | head -n 50

# 2) Find call sites of RHI::drawFrame()
rg -n '\.drawFrame\s*\(\s*\)\s*;' src || true
rg -n 'RHI::drawFrame\s*\(' . || true

# 3) Inspect the loop where drawFrame is called most likely (grab a few hits)
# (Use only a small amount of context to avoid huge output)
rg -n '\.drawFrame\s*\(\s*\)\s*;' src -n -C 3 || true

Repository: kimkulling/Segfault

Length of output: 3789


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any catch blocks that might intercept exceptions generically
rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' '\bcatch\s*\(' src | head -n 200

# 2) Inspect SegfaultException definition
if [ -f src/runtime/core/segfaultexception.h ]; then
  nl -ba src/runtime/core/segfaultexception.h | sed -n '1,120p'
fi

# 3) Inspect hello_world drawFrame callsite and surrounding code
nl -ba src/examples/hello_world/hello_world.cpp | sed -n '1,120p'

# 4) Trace where myApp.drawFrame() is implemented (look for "drawFrame()" method in app classes)
rg -n 'drawFrame\s*\(\s*\)' src/runtime src/examples | head -n 200

Repository: kimkulling/Segfault

Length of output: 45


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any catch blocks that might intercept exceptions
rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' '\bcatch\s*\(' src || true | head -n 200

# 2) Inspect SegfaultException definition
if [ -f src/runtime/core/segfaultexception.h ]; then
  nl -ba src/runtime/core/segfaultexception.h | sed -n '1,160p'
fi

# 3) Inspect hello_world drawFrame callsite and surrounding code
nl -ba src/examples/hello_world/hello_world.cpp | sed -n '1,200p'

# 4) Locate implementations of drawFrame() methods (likely app delegates)
rg -n '(\b|::)drawFrame\s*\(\s*\)' src/runtime src/examples || true

# 5) Locate main loop / drawFrame routing (look for "mainloop" and "RHI")
rg -n 'mainloop\s*\(\s*\)|RHI::drawFrame|myApp\.drawFrame|drawFrame\s*\(\s*\)\s*;' src/examples src/runtime || true

Repository: kimkulling/Segfault

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any catch blocks that might intercept exceptions
rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' '\bcatch\s*\(' src || true | head -n 200

# 2) Inspect SegfaultException definition
if [ -f src/runtime/core/segfaultexception.h ]; then
  cat -n src/runtime/core/segfaultexception.h | sed -n '1,200p'
fi

# 3) Inspect hello_world drawFrame callsite and surrounding code
if [ -f src/examples/hello_world/hello_world.cpp ]; then
  cat -n src/examples/hello_world/hello_world.cpp | sed -n '1,220p'
fi

# 4) Locate implementations of drawFrame() methods (avoid matching RHI::drawFrame signature only by including "void ...::drawFrame")
rg -n 'void\s+([A-Za-z_]\w*::)?drawFrame\s*\(' src/runtime src/examples || true | head -n 200

# 5) Locate main loop / routing
rg -n 'mainloop\s*\(\s*\)|myApp\.drawFrame\s*\(\s*\)|RHI::drawFrame\s*\(' src/examples src/runtime || true | head -n 200

Repository: kimkulling/Segfault

Length of output: 2325


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file_app="src/runtime/application/app.cpp"
file_apph="src/runtime/application/app.h"
file_rhi="src/runtime/renderer/RHI.h"
file_rhi_impl="src/runtime/renderer/RHIVulkan.cpp"

# Show drawFrame/mainloop implementations with surrounding context
cat -n "$file_app" | sed -n '1,220p'
echo "----"
cat -n "$file_app" | sed -n '220,420p' || true

echo "---- RHI.h ----"
cat -n "$file_rhi" | sed -n '1,140p'

echo "---- RHI::drawFrame call in App::drawFrame ----"
rg -n "drawFrame\\s*\\(\\s*\\)" "$file_app" "$file_apph" || true
rg -n "RHI::drawFrame|mRHI->drawFrame|drawFrame\\s*\\(" "$file_app" -n -C 3 || true

echo "---- try/catch in App:: paths ----"
rg -n "\\btry\\b|\\bcatch\\b" "$file_app" "$file_apph" "$file_rhi_impl" || true

Repository: kimkulling/Segfault

Length of output: 8246


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="src/runtime/renderer/RHIVulkan.cpp"

# Helper: print a window with nearby function header lines
for start in 180 200 600 660 760 780 800 820 860 880 900 960 980 1000 1010 1030 1060 1080 1100 1120 1140 1160 1200 1230 1300 1450; do
  echo "==== lines $start-$((start+80)) ===="
  sed -n "${start},$((start+80))p" "$file" | head -n 120
done

Repository: kimkulling/Segfault

Length of output: 50375


🏁 Script executed:

rg -n --hidden --no-ignore-vcs --glob='!**/node_modules/**' '\bcatch\s*\(' src | head -n 50 || true

Repository: kimkulling/Segfault

Length of output: 45


🏁 Script executed:

#!/bin/bash
set -euo pipefail
file="src/runtime/renderer/RHIVulkan.cpp"

# Print the beginning of the file to see namespaces/includes/usings for SegfaultException
sed -n '1,120p' "$file" | cat -n

# Also show the exact RHI::init signature/namespace context (first few lines of the function)
sed -n '1500,1565p' "$file" | cat -n

Repository: kimkulling/Segfault

Length of output: 7765


Translate renderer exceptions at the RHI API boundary.

RHIImpl::drawFrame() throws SegfaultException on swapchain acquire/submit/present failures, but neither RHI::drawFrame() (void) nor RHI::init() (bool) catches, and App::drawFrame()/main have no exception handling either—so these exceptions can escape the RHI boundary and terminate the process instead of controlled failure.

Add boundary handling around RHI::init() and RHI::drawFrame() to catch segfault::core::SegfaultException and map to false (and/or a log) / safely return without propagating.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/renderer/RHIVulkan.cpp` around lines 1025 - 1026, Wrap calls into
the RHI boundary so SegfaultException cannot escape: in the public RHI API entry
points (RHI::init() and RHI::drawFrame()) catch
segfault::core::SegfaultException and convert it to a safe failure (return false
from RHI::init() and return from RHI::drawFrame() without throwing), logging the
error; likewise add try/catch in higher-level callers (App::drawFrame() and
main) where they call RHIImpl::drawFrame()/RHI::drawFrame() to ensure any
remaining segfault::core::SegfaultException is caught, logged, and translated to
a controlled shutdown path rather than allowing the exception to propagate.

Source: Coding guidelines


updateUniformBuffer(currentFrame);
Expand All @@ -1036,7 +1049,7 @@

if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to submit draw command buffer!");
throw std::runtime_error("failed to submit draw command buffer!");
throw SegfaultException("failed to submit draw command buffer!");
}

VkPresentInfoKHR presentInfo{};
Expand All @@ -1058,7 +1071,7 @@
recreateSwapChain();
} else if (result != VK_SUCCESS) {
core::logMessage(core::LogType::Error, "failed to present swap chain image!");
throw std::runtime_error("failed to present swap chain image!");
throw SegfaultException("failed to present swap chain image!");
}

currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
Expand Down Expand Up @@ -1099,7 +1112,7 @@
}
}

throw std::runtime_error("failed to find suitable memory type!");
throw SegfaultException("failed to find suitable memory type!");
}

void RHIImpl::createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling,
Expand All @@ -1121,7 +1134,7 @@
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;

if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
throw std::runtime_error("failed to create image!");
throw SegfaultException("failed to create image!");
}

VkMemoryRequirements memRequirements;
Expand All @@ -1133,7 +1146,7 @@
allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);

if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate image memory!");
throw SegfaultException("failed to allocate image memory!");
}

vkBindImageMemory(device, image, imageMemory, 0);
Expand All @@ -1145,7 +1158,7 @@
VkDeviceSize imageSize = texWidth * texHeight * 4;

if (pixels == nullptr) {
throw std::runtime_error("failed to load texture image!");
throw SegfaultException("failed to load texture image!");
}

VkBuffer stagingBuffer;
Expand Down Expand Up @@ -1187,7 +1200,7 @@

VkImageView imageView;
if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) {
throw std::runtime_error("failed to create image view!");
throw SegfaultException("failed to create image view!");
}

return imageView;
Expand Down Expand Up @@ -1224,7 +1237,7 @@
samplerInfo.maxLod = 0.0f;

if (vkCreateSampler(device, &samplerInfo, nullptr, &textureSampler) != VK_SUCCESS) {
throw std::runtime_error("failed to create texture sampler!");
throw SegfaultException("failed to create texture sampler!");
}
}

Expand Down Expand Up @@ -1298,7 +1311,7 @@
poolInfo.maxSets = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT);

if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
throw std::runtime_error("failed to create descriptor pool!");
throw SegfaultException("failed to create descriptor pool!");
}
}

Expand All @@ -1312,7 +1325,7 @@

descriptorSets.resize(MAX_FRAMES_IN_FLIGHT);
if (vkAllocateDescriptorSets(device, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
throw std::runtime_error("failed to allocate descriptor sets!");
throw SegfaultException("failed to allocate descriptor sets!");
}

for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
Expand Down Expand Up @@ -1449,7 +1462,7 @@
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
} else {
throw std::invalid_argument("unsupported layout transition!");
throw SegfaultException("unsupported layout transition!");
}

vkCmdPipelineBarrier(
Expand Down
Loading