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
2 changes: 1 addition & 1 deletion src/contrib/vcpkg
Submodule vcpkg updated 4469 files
5 changes: 5 additions & 0 deletions src/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ SET(segfault_renderer_src
renderer/RHIVulkan.cpp
renderer/vulkanbuffer.cpp
renderer/vulkanbuffer.h
renderer/vulkandevice.cpp
renderer/vulkandevice.h
renderer/vulkanutils.cpp
renderer/vulkanutils.h
renderer/vulkantypes.h
)

SET(segfault_application_src
Expand Down
25 changes: 25 additions & 0 deletions src/runtime/core/genericfilemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,39 @@

namespace segfault::core {

/// @class GenericFileManager
/// @brief A generic file manager implementation.
class SEGFAULT_EXPORT GenericFileManager final : public IFileManager {
public:
/// @brief Constructs a new instance of GenericFileManager.
GenericFileManager() = default;

/// @brief Destroys the GenericFileManager instance.
~GenericFileManager() final = default;

/// @brief Creates a file reader for the specified file.
/// @param name The name of the file to read.
/// @return A pointer to the created file reader, or nullptr if creation failed.
FileArchive *createFileReader(const char *name) final;

/// @brief Creates a file writer for the specified file.
/// @param name The name of the file to write.
/// @return A pointer to the created file writer, or nullptr if creation failed.
FileArchive *createFileWriter(const char *name) final;

/// @brief Closes the specified file archive.
/// @param archive The file archive to close.
void close(FileArchive *archive) final;

/// @brief Checks if a file exists.
/// @param name The name of the file to check.
/// @return True if the file exists, false otherwise.
bool exist(const char* name) final;
/// @brief Gets statistics for the specified archive.

/// @param name The name of the archive.
/// @param stat The structure to store the statistics in.
/// @return True if statistics were successfully retrieved, false otherwise.
bool getArchiveStat(const char *name, FileStat &stat) final;
};

Expand Down
142 changes: 42 additions & 100 deletions src/runtime/renderer/RHIVulkan.cpp

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions src/runtime/renderer/vulkanbuffer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "vulkanbuffer.h"
#include <memory>
#include <cassert>
#include <string.h>

namespace segfault::renderer {

uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties) {
Expand Down Expand Up @@ -58,7 +60,7 @@ namespace segfault::renderer {
if (vkAllocateMemory(mDevice, &allocInfo, nullptr, &mMemory) != VK_SUCCESS) {
return false;
}

return true;
}

Expand Down Expand Up @@ -95,7 +97,7 @@ namespace segfault::renderer {
assert(mMapped != nullptr && "Buffer must be mapped before copying data to it.");
assert(size <= VK_WHOLE_SIZE && "Size must be less than or equal to VK_WHOLE_SIZE.");
assert(size <= 0 || data != nullptr && "Data pointer must not be null when size is greater than 0.");

if (mMapped != nullptr) {
memcpy(mMapped, data, static_cast<size_t>(size));
}
Expand Down
9 changes: 3 additions & 6 deletions src/runtime/renderer/vulkanbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@

#include "volk.h"

#include "vulkantypes.h"

namespace segfault::renderer {

enum class BufferUsage : uint32_t {
VertexBuffer = 0x1,
IndexBuffer = 0x2,
UniformBuffer = 0x4
};

class VulkanBuffer {
public:
VulkanBuffer(VkPhysicalDevice physicalDevice, VkDevice device);
Expand All @@ -26,13 +21,15 @@ namespace segfault::renderer {
void copyTo(void *data, VkDeviceSize size);
VkBuffer getBuffer() const { return mBuffer; }
VkDeviceMemory getMemory() const { return mMemory; }
size_t getSize() const { return mSize; }

private:
VkPhysicalDevice mPhysicalDevice{};
VkDevice mDevice{};
VkBuffer mBuffer{};
VkDeviceMemory mMemory{};
void *mMapped{nullptr};
size_t mSize{0};
};

} // namespace segfault::renderer
92 changes: 92 additions & 0 deletions src/runtime/renderer/vulkandevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "vulkandevice.h"

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

Missing MIT license header in new .cpp file.

Please add the required MIT header block at the top of this file.
As per coding guidelines, "Include MIT license header in all source files".

🤖 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/vulkandevice.cpp` at line 1, The vulkandevice.cpp file
is missing the required MIT license header block at the top. Add the standard
MIT license header block before the existing `#include` "vulkandevice.h" statement
to comply with the coding guidelines that require all source files to include
proper licensing information.

Source: Coding guidelines


namespace segfault::renderer {

bool QueueFamilyIndices::isGraphicsComplete() const {
return graphicsFamily.has_value() && presentFamily.has_value();
}
Comment on lines +5 to +7

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

QueueFamilyIndices::isComplete() is declared but not defined.

isComplete() is in vulkandevice.h (Line 18) but this TU only defines isGraphicsComplete(). Any call to isComplete() will fail at link time.

🤖 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/vulkandevice.cpp` around lines 5 - 7, The method
isComplete() is declared in vulkandevice.h but has no implementation in
vulkandevice.cpp. Add a definition for the isComplete() method in
vulkandevice.cpp alongside the existing isGraphicsComplete() method. The
isComplete() method should return a boolean indicating whether all required
queue family indices (graphicsFamily and presentFamily) have values, similar to
how isGraphicsComplete() works but potentially checking additional required
families if they exist in the QueueFamilyIndices struct.


VulkanDevice::VulkanDevice(VkPhysicalDevice physicalDevice) : mPhysicalDevice(physicalDevice) {
// empty
}

VulkanDevice::~VulkanDevice() {
shutdown();
}

bool VulkanDevice::init(VkSurfaceKHR surface, const DeviceRequirements& requirements) {
if (mDevice != VK_NULL_HANDLE) {
return true; // Already initialized
}

mSurface = surface;

return true;
}
Comment on lines +13 to +21

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

Lifecycle contract is incomplete: destructor is empty and init() reports success without initialization.

~VulkanDevice() does not release resources, and init() returns true after only storing mSurface. This exposes a “successful” object with mDevice still null and shifts cleanup burden to callers.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 13-13: Use "=default" instead of the default implementation of this special member functions.

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

🤖 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/vulkandevice.cpp` around lines 13 - 21, The VulkanDevice
lifecycle is incomplete: the destructor VulkanDevice::~VulkanDevice() is empty
and does not release resources, while the init() method returns true after only
storing the surface without actually initializing the mDevice member or other
critical resources. You need to implement proper initialization logic in init()
that creates and configures the Vulkan device based on the provided surface and
requirements, returning false if initialization fails, and then implement
corresponding cleanup logic in the destructor to release those allocated Vulkan
resources when the object is destroyed.


void VulkanDevice::shutdown() {
if (mDevice == VK_NULL_HANDLE) {
return;
}

vkDestroyDevice(mDevice, nullptr);
mDevice = VK_NULL_HANDLE;
mSurface = VK_NULL_HANDLE;
}

VulkanBuffer* VulkanDevice::createBuffer(size_t size, BufferUsage usageFlags, uint32_t memoryPropertyFlags) {
VulkanBuffer* buffer = new VulkanBuffer(mPhysicalDevice, mDevice);

Check failure on line 38 in src/runtime/renderer/vulkandevice.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the use of "new" with an operation that automatically manages the memory.

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

Check warning on line 38 in src/runtime/renderer/vulkandevice.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace the redundant type with "auto".

See more on https://sonarcloud.io/project/issues?id=kimkulling_Segfault&issues=AZ7R9IE5bH8oLnz3HCcZ&open=AZ7R9IE5bH8oLnz3HCcZ&pullRequest=12
if (!buffer->init(size, usageFlags, memoryPropertyFlags)) {
delete buffer;

Check failure on line 40 in src/runtime/renderer/vulkandevice.cpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Rewrite the code so that you no longer need this "delete".

See more on https://sonarcloud.io/project/issues?id=kimkulling_Segfault&issues=AZ7R9IE5bH8oLnz3HCcb&open=AZ7R9IE5bH8oLnz3HCcb&pullRequest=12
return nullptr;
}
return buffer;
}

bool VulkanDevice::copyBuffer(VulkanBuffer* source, VulkanBuffer* destination, VkDeviceSize size, VkQueue queue, VkCommandPool pool) {
if (!source || !destination) {
return false;
}

VkCommandBuffer copyCmd = createCommandBuffer(pool);
VkBufferCopy bufferCopy{};
if (size == 0)
{
bufferCopy.size = source->getSize();
}
else
{
bufferCopy.size = size;
}

vkCmdCopyBuffer(copyCmd, source->getBuffer(), destination->getBuffer(), 1, &bufferCopy);

flushCommandBuffer(copyCmd, queue, pool, true);
}

VkCommandBuffer VulkanDevice::createCommandBuffer(VkCommandPool commandPool, VkCommandBufferLevel level) {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = commandPool;
allocInfo.level = level;
allocInfo.commandBufferCount = 1;

VkCommandBuffer commandBuffer;

vkAllocateCommandBuffers(mDevice, &allocInfo, &commandBuffer);
return commandBuffer;
}


void VulkanDevice::flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free) {
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
if (free) {
vkFreeCommandBuffers(mDevice, pool, 1, &commandBuffer);
}
}

} // namespace segfault::renderer
95 changes: 95 additions & 0 deletions src/runtime/renderer/vulkandevice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#pragma once

#include "volk.h"
#include "core/segfault.h"
#include <vector>
#include <optional>
#include <string>
#include <cstdint>
#include "vulkantypes.h"
#include "vulkanbuffer.h"

namespace segfault::renderer {

struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
std::optional<uint32_t> computeFamily;
std::optional<uint32_t> transferFamily;

bool isComplete() const;
bool isGraphicsComplete() const;
};

struct DeviceRequirements {
std::vector<const char*> requiredExtensions;
std::vector<const char*> optionalExtensions;
VkPhysicalDeviceFeatures requiredFeatures{};
VkPhysicalDeviceFeatures optionalFeatures{};
bool requirePresentQueue{ false };
bool requireComputeQueue{ false };
bool requireTransferQueue{ false };
};

struct DeviceProperties {
VkPhysicalDeviceProperties properties{};
VkPhysicalDeviceFeatures features{};
VkPhysicalDeviceMemoryProperties memoryProperties{};
std::vector<VkExtensionProperties> availableExtensions;
std::vector<VkQueueFamilyProperties> queueFamilies;
};

//---------------------------------------------------------------------------------------------
/// @class VulkanDevice
/// @brief Encapsulates a Vulkan physical and logical device with queue management.
///
/// This class manages the selection, creation, and lifecycle of Vulkan devices.
/// It provides access to device properties, features, queues, and memory management.
//---------------------------------------------------------------------------------------------
class SEGFAULT_EXPORT VulkanDevice final {
public:
// Disallow copying
VulkanDevice(const VulkanDevice&) = delete;
VulkanDevice& operator=(const VulkanDevice&) = delete;

/// @brief Constructs a VulkanDevice.
/// @param instance The Vulkan instance.
VulkanDevice(VkPhysicalDevice physicalDevice);

Check failure on line 57 in src/runtime/renderer/vulkandevice.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add the "explicit" keyword to this constructor.

See more on https://sonarcloud.io/project/issues?id=kimkulling_Segfault&issues=AZ7R8BXJBbkRz2zW9NMg&open=AZ7R8BXJBbkRz2zW9NMg&pullRequest=12
Comment on lines +1 to +55

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

Header docs/compliance need cleanup (MIT header + incorrect Doxygen param).

MIT file header is missing, and Line 54 documents @param instance while the constructor parameter is physicalDevice.
As per coding guidelines, "Include MIT license header in all source files" and "**/*.h: Use Doxygen-style comments in headers with @brief, @param, and @return tags".

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 55-55: Add the "explicit" keyword to this constructor.

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

🤖 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/vulkandevice.h` around lines 1 - 55, Add the MIT license
header at the top of the file before the pragma once directive, and fix the
Doxygen documentation for the VulkanDevice constructor to use the correct
parameter name. Change the `@param` documentation from `@param` instance to `@param`
physicalDevice to match the actual constructor parameter in the VulkanDevice
class.

Source: Coding guidelines

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

Make the single-argument constructor explicit.

Implicit conversion from VkPhysicalDevice to VulkanDevice is currently allowed and can create accidental temporary objects.

🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[failure] 55-55: Add the "explicit" keyword to this constructor.

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

🤖 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/vulkandevice.h` at line 55, The VulkanDevice constructor
that takes a single VkPhysicalDevice parameter allows implicit conversions,
which can accidentally create temporary objects. Add the explicit keyword before
the VulkanDevice constructor declaration to prevent implicit conversions and
require explicit object construction calls.

Source: Linters/SAST tools


/// @brief The class destructor. Ensures that all Vulkan resources are properly released.
~VulkanDevice();

/// @brief Initializes the device with the given surface and requirements.
/// @param surface The presentation surface (can be VK_NULL_HANDLE for headless).
/// @param requirements Device feature and extension requirements.
/// @return True if device initialization succeeded.
bool init(VkSurfaceKHR surface, const DeviceRequirements& requirements = {});

/// @brief Shuts down the device and releases all resources.
void shutdown();

// Accessors
VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
VkDevice getDevice() const { return mDevice; }
VkQueue getGraphicsQueue() const { return mGraphicsQueue; }
VkQueue getPresentQueue() const { return mPresentQueue; }
const QueueFamilyIndices& getQueueFamilyIndices() const { return mQueueFamilyIndices; }
uint32_t getGraphicsQueueFamilyIndex() const;
uint32_t getPresentQueueFamilyIndex() const;
const DeviceProperties& getProperties() const { return mProperties; }
VulkanBuffer* createBuffer(size_t size, BufferUsage usageFlags, uint32_t memoryPropertyFlags);
bool copyBuffer(VulkanBuffer *source, VulkanBuffer *destination, VkDeviceSize size, VkQueue queue, VkCommandPool pool);
VkCommandBuffer createCommandBuffer(VkCommandPool commandPool, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY);
void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free);

private:
VkPhysicalDevice mPhysicalDevice{};
VkDevice mDevice{};
VkQueue mGraphicsQueue{};
VkQueue mPresentQueue{};
QueueFamilyIndices mQueueFamilyIndices{};
DeviceProperties mProperties{};
VkSurfaceKHR mSurface{};
};

} // namespace segfault::renderer
13 changes: 13 additions & 0 deletions src/runtime/renderer/vulkantypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#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

Missing required MIT license header in new source file.

Line 1 starts directly with #pragma once; this header needs the project MIT license header block per repo rules.

🤖 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/vulkantypes.h` at line 1, The file
src/runtime/renderer/vulkantypes.h is missing the required MIT license header at
the start. Add the project's MIT license header block before the `#pragma` once
directive at the beginning of the file to comply with repository licensing
requirements.

Source: Coding guidelines


#include <cstdint>

namespace segfault::renderer {

enum class BufferUsage : uint32_t {
VertexBuffer = 0x1,
IndexBuffer = 0x2,
UniformBuffer = 0x4
};
Comment on lines +7 to +11

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

BufferUsage is defined as bit flags, but current contract behaves like a single-choice enum.

BufferUsage uses bit values (0x1, 0x2, 0x4), but downstream conversion in src/runtime/renderer/vulkanbuffer.cpp:25-38 checks == instead of bitwise membership. Combined usage flags will silently map to 0, which breaks buffer creation behavior.

🤖 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/vulkantypes.h` around lines 7 - 11, The BufferUsage enum
in vulkantypes.h is properly defined with bit flag values, but the conversion
logic in vulkanbuffer.cpp at lines 25-38 incorrectly uses equality checks (==)
instead of bitwise membership checks. Update the conversion logic to use bitwise
AND operations (&) when checking if specific BufferUsage flags are set, so that
combined flag values are properly handled instead of silently mapping to zero.
For example, change conditions like `bufferUsage == BufferUsage::VertexBuffer`
to `(bufferUsage & BufferUsage::VertexBuffer) != 0` or equivalent bitwise checks
to correctly detect which flags are present in the combined usage value.


} // namespace segfault::renderer
65 changes: 65 additions & 0 deletions src/runtime/renderer/vulkanutils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include "vulkanutils.h"

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

Missing MIT license header in new .cpp file.

This source file should include the required MIT license header at the top.
As per coding guidelines, "Include MIT license header in all source files".

🤖 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/vulkanutils.cpp` at line 1, The file vulkanutils.cpp is
missing the required MIT license header at the top. Add the MIT license header
text before the first include statement (the include "vulkanutils.h" line). The
license header should be the very first content in the file, followed by a blank
line, and then the existing includes and code.

Source: Coding guidelines

#include "core/segfaultexception.h"
#include "volk.h"

#include <array>

namespace segfault::renderer {

using namespace segfault::core;

std::array<VkVertexInputAttributeDescription, 3> Vertex::getAttributeDescriptions() {
std::array<VkVertexInputAttributeDescription, 3> attributeDescriptions{};

attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);

attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);

attributeDescriptions[2].binding = 0;
attributeDescriptions[2].location = 2;
attributeDescriptions[2].format = VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[2].offset = offsetof(Vertex, texCoord);

return attributeDescriptions;
}

VkVertexInputBindingDescription Vertex::getBindingDescription() {
VkVertexInputBindingDescription bindingDescription{};

bindingDescription.binding = 0;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

return bindingDescription;
}

VkFormat VulkanUtils::findSupportedFormat(VkPhysicalDevice &physicalDevice, const std::vector<VkFormat>& candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
for (VkFormat format : candidates) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(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 SegfaultException("failed to find supported format!");
}

VkFormat VulkanUtils::findDepthFormat(VkPhysicalDevice &physicalDevice) {
return findSupportedFormat(
physicalDevice,
{ 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
);
}

}
Loading
Loading