diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
index bd898251e6..b40aff9ea0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt
@@ -23,6 +23,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_FORCE_MAX_CLOCK("force_max_clock"),
RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"),
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
+ RENDERER_ENABLE_RAII("renderer_enable_raii"),
SYNC_MEMORY_OPERATIONS("sync_memory_operations"),
BUFFER_REORDER_DISABLE("disable_buffer_reorder"),
RENDERER_DEBUG("debug"),
@@ -71,9 +72,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning"),
ENABLE_OVERLAY("enable_overlay");
-
-// external fun isFrameSkippingEnabled(): Boolean
- external fun isFrameInterpolationEnabled(): Boolean
+ external fun isRaiiEnabled(): Boolean
override fun getBoolean(needsGlobal: Boolean): Boolean =
NativeConfig.getBoolean(key, needsGlobal)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
index 50143a449e..9e3c32e0d6 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
@@ -630,6 +630,14 @@ abstract class SettingsItem(
valuesId = R.array.optimizeSpirvOutputValues
)
)
+ put(
+ SwitchSetting(
+ BooleanSetting.RENDERER_ENABLE_RAII,
+ titleId = R.string.renderer_enable_raii,
+ descriptionId = R.string.renderer_enable_raii_description
+ )
+ )
+
put(
SingleChoiceSetting(
IntSetting.DMA_ACCURACY,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
index dc58e7d23b..e0ebe3b46b 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
@@ -270,6 +270,7 @@ class SettingsFragmentPresenter(
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
+ add(BooleanSetting.RENDERER_ENABLE_RAII.key)
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key)
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 4bfa5afd01..11250fa7b0 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -469,6 +469,8 @@
Anti-aliasing method
Optimize SPIRV output
Optimizes compiled shaders to improve GPU efficiency, but may introduce longer loading times and initial slowdowns.
+ RAII
+ A method of automatic resource management in Vulkan that ensures proper release of resources when they are no longer needed, but may cause crashes in bundled games.
Advanced
diff --git a/src/common/settings.h b/src/common/settings.h
index 874ba7aee2..44f799bc00 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -451,6 +451,7 @@ struct Values {
"astc_recompression",
Category::RendererAdvanced};
+ SwitchableSetting renderer_enable_raii{linkage, false, "renderer_enable_raii", Category::Renderer};
SwitchableSetting sync_memory_operations{linkage,
false,
diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp
index a3a720db8e..4783d6659b 100644
--- a/src/qt_common/config/shared_translation.cpp
+++ b/src/qt_common/config/shared_translation.cpp
@@ -254,6 +254,13 @@ std::unique_ptr InitializeTranslations(QObject* parent)
// Renderer (Advanced Graphics)
INSERT(Settings, use_asynchronous_gpu_emulation, QString(), QString());
+ INSERT(Settings,
+ renderer_enable_raii,
+ tr("RAII"),
+ tr("A method of automatic resource management in Vulkan "
+ "that ensures proper release of resources "
+ "when they are no longer needed, but may cause crashes in bundled games."));
+
INSERT(Settings, sync_memory_operations, tr("Sync Memory Operations"),
tr("Ensures data consistency between compute and memory operations.\nThis option fixes issues in games, but may degrade performance.\nUnreal Engine 4 games often see the most significant changes thereof."));
INSERT(Settings,
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 3b47570a7e..eb185cf253 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -164,6 +164,15 @@ try
PresentFiltersForAppletCapture)
, rasterizer(render_window, gpu, device_memory, device, memory_allocator, state_tracker, scheduler) {
+ // Initialize RAII wrappers after creating the main objects
+ if (Settings::values.renderer_enable_raii.GetValue()) {
+ managed_instance = MakeManagedInstance(instance, dld);
+ if (Settings::values.renderer_debug) {
+ managed_debug_messenger = MakeManagedDebugUtilsMessenger(debug_messenger, instance, dld);
+ }
+ managed_surface = MakeManagedSurface(surface, instance, dld);
+ }
+
if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
turbo_mode.emplace(instance, dld);
scheduler.RegisterOnSubmit([this] { turbo_mode->QueueSubmitted(); });
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 4fb88b29de..ef1d90d609 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -23,6 +23,7 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
+#include "video_core/vulkan_common/vulkan_raii.h"
namespace Core::Memory {
class Memory;
@@ -80,10 +81,16 @@ private:
// Keep original handles for compatibility with existing code
vk::Instance instance;
+ // RAII wrapper for instance
+ ManagedInstance managed_instance;
vk::DebugUtilsMessenger debug_messenger;
+ // RAII wrapper for debug messenger
+ ManagedDebugUtilsMessenger managed_debug_messenger;
vk::SurfaceKHR surface;
+ // RAII wrapper for surface
+ ManagedSurface managed_surface;
Device device;
MemoryAllocator memory_allocator;
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 7418ad934e..6d6fa1908d 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -361,7 +361,6 @@ void Swapchain::CreateSemaphores() {
void Swapchain::Destroy() {
frame_index = 0;
present_semaphores.clear();
- render_semaphores.clear();
swapchain.reset();
}
diff --git a/src/video_core/vulkan_common/vulkan_raii.h b/src/video_core/vulkan_common/vulkan_raii.h
new file mode 100644
index 0000000000..188ea521c3
--- /dev/null
+++ b/src/video_core/vulkan_common/vulkan_raii.h
@@ -0,0 +1,234 @@
+// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+// SPDX-FileCopyrightText: Copyright 2025 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include "common/logging/log.h"
+
+#include "video_core/vulkan_common/vulkan_wrapper.h"
+
+namespace Vulkan {
+
+/**
+ * RAII wrapper for Vulkan resources.
+ * Automatically manages the lifetime of Vulkan objects using RAII principles.
+ */
+template
+class VulkanRaii {
+public:
+ using DeleterFunc = std::function;
+
+ // Default constructor - creates a null handle
+ VulkanRaii() : handle{}, deleter{}, dispatch{} {}
+
+ // Constructor with handle and deleter
+ VulkanRaii(T handle_, DeleterFunc deleter_, const Dispatch& dispatch_, const char* resource_name = "Vulkan resource")
+ : handle{handle_}, deleter{std::move(deleter_)}, dispatch{dispatch_} {
+ LOG_DEBUG(Render_Vulkan, "RAII wrapper created for {}", resource_name);
+ }
+
+ // Move constructor
+ VulkanRaii(VulkanRaii&& other) noexcept
+ : handle{std::exchange(other.handle, VK_NULL_HANDLE)},
+ deleter{std::move(other.deleter)},
+ dispatch{other.dispatch} {
+ }
+
+ // Move assignment
+ VulkanRaii& operator=(VulkanRaii&& other) noexcept {
+ if (this != &other) {
+ cleanup();
+ handle = std::exchange(other.handle, VK_NULL_HANDLE);
+ deleter = std::move(other.deleter);
+ dispatch = other.dispatch;
+ }
+ return *this;
+ }
+
+ // Destructor - automatically cleans up the resource
+ ~VulkanRaii() {
+ cleanup();
+ }
+
+ // Disallow copying
+ VulkanRaii(const VulkanRaii&) = delete;
+ VulkanRaii& operator=(const VulkanRaii&) = delete;
+
+ // Get the underlying handle
+ T get() const noexcept {
+ return handle;
+ }
+
+ // Check if the handle is valid
+ bool valid() const noexcept {
+ return handle != VK_NULL_HANDLE;
+ }
+
+ // Release ownership of the handle without destroying it
+ T release() noexcept {
+ return std::exchange(handle, VK_NULL_HANDLE);
+ }
+
+ // Reset the handle (destroying the current one if it exists)
+ void reset(T new_handle = VK_NULL_HANDLE, DeleterFunc new_deleter = {}) {
+ cleanup();
+ handle = new_handle;
+ deleter = std::move(new_deleter);
+ }
+
+ // Implicit conversion to handle type
+ operator T() const noexcept {
+ return handle;
+ }
+
+ // Dereference operator for pointer-like access
+ T operator->() const noexcept {
+ return handle;
+ }
+
+private:
+ // Optimized cleanup function
+ void cleanup() noexcept {
+ if (handle != VK_NULL_HANDLE && deleter) {
+ deleter(handle, dispatch);
+ handle = VK_NULL_HANDLE;
+ }
+ }
+
+ T handle;
+ DeleterFunc deleter;
+ Dispatch dispatch;
+};
+
+// Common type aliases for Vulkan RAII wrappers with clearer names
+using ManagedInstance = VulkanRaii;
+using ManagedDevice = VulkanRaii;
+using ManagedSurface = VulkanRaii;
+using ManagedSwapchain = VulkanRaii;
+using ManagedCommandPool = VulkanRaii;
+using ManagedBuffer = VulkanRaii;
+using ManagedImage = VulkanRaii;
+using ManagedImageView = VulkanRaii;
+using ManagedSampler = VulkanRaii;
+using ManagedShaderModule = VulkanRaii;
+using ManagedPipeline = VulkanRaii;
+using ManagedPipelineLayout = VulkanRaii;
+using ManagedDescriptorSetLayout = VulkanRaii;
+using ManagedDescriptorPool = VulkanRaii;
+using ManagedSemaphore = VulkanRaii;
+using ManagedFence = VulkanRaii;
+using ManagedDebugUtilsMessenger = VulkanRaii;
+
+// Helper functions to create RAII wrappers
+
+/**
+ * Creates an RAII wrapper for a Vulkan instance
+ */
+inline ManagedInstance MakeManagedInstance(const vk::Instance& instance, const vk::InstanceDispatch& dispatch) {
+ auto deleter = [](VkInstance handle, const vk::InstanceDispatch& dld) {
+ dld.vkDestroyInstance(handle, nullptr);
+ };
+ return ManagedInstance(*instance, deleter, dispatch, "VkInstance");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan device
+ */
+inline ManagedDevice MakeManagedDevice(const vk::Device& device, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [](VkDevice handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroyDevice(handle, nullptr);
+ };
+ return ManagedDevice(*device, deleter, dispatch, "VkDevice");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan surface
+ */
+inline ManagedSurface MakeManagedSurface(const vk::SurfaceKHR& surface, const vk::Instance& instance, const vk::InstanceDispatch& dispatch) {
+ auto deleter = [instance_ptr = *instance](VkSurfaceKHR handle, const vk::InstanceDispatch& dld) {
+ dld.vkDestroySurfaceKHR(instance_ptr, handle, nullptr);
+ };
+ return ManagedSurface(*surface, deleter, dispatch, "VkSurfaceKHR");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan debug messenger
+ */
+inline ManagedDebugUtilsMessenger MakeManagedDebugUtilsMessenger(const vk::DebugUtilsMessenger& messenger,
+ const vk::Instance& instance,
+ const vk::InstanceDispatch& dispatch) {
+ auto deleter = [instance_ptr = *instance](VkDebugUtilsMessengerEXT handle, const vk::InstanceDispatch& dld) {
+ dld.vkDestroyDebugUtilsMessengerEXT(instance_ptr, handle, nullptr);
+ };
+ return ManagedDebugUtilsMessenger(*messenger, deleter, dispatch, "VkDebugUtilsMessengerEXT");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan swapchain
+ */
+inline ManagedSwapchain MakeManagedSwapchain(VkSwapchainKHR swapchain_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkSwapchainKHR handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroySwapchainKHR(device_handle, handle, nullptr);
+ };
+ return ManagedSwapchain(swapchain_handle, deleter, dispatch, "VkSwapchainKHR");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan buffer
+ */
+inline ManagedBuffer MakeManagedBuffer(VkBuffer buffer_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkBuffer handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroyBuffer(device_handle, handle, nullptr);
+ };
+ return ManagedBuffer(buffer_handle, deleter, dispatch, "VkBuffer");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan image
+ */
+inline ManagedImage MakeManagedImage(VkImage image_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkImage handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroyImage(device_handle, handle, nullptr);
+ };
+ return ManagedImage(image_handle, deleter, dispatch, "VkImage");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan image view
+ */
+inline ManagedImageView MakeManagedImageView(VkImageView view_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkImageView handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroyImageView(device_handle, handle, nullptr);
+ };
+ return ManagedImageView(view_handle, deleter, dispatch, "VkImageView");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan semaphore
+ */
+inline ManagedSemaphore MakeManagedSemaphore(VkSemaphore semaphore_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkSemaphore handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroySemaphore(device_handle, handle, nullptr);
+ };
+ return ManagedSemaphore(semaphore_handle, deleter, dispatch, "VkSemaphore");
+}
+
+/**
+ * Creates an RAII wrapper for a Vulkan fence
+ */
+inline ManagedFence MakeManagedFence(VkFence fence_handle, VkDevice device_handle, const vk::DeviceDispatch& dispatch) {
+ auto deleter = [device_handle](VkFence handle, const vk::DeviceDispatch& dld) {
+ dld.vkDestroyFence(device_handle, handle, nullptr);
+ };
+ return ManagedFence(fence_handle, deleter, dispatch, "VkFence");
+}
+
+} // namespace Vulkan
\ No newline at end of file
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 534a11edd4..92324807c3 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -12,6 +12,7 @@
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "video_core/vulkan_common/vk_enum_string_helper.h"
#include "video_core/vulkan_common/vma.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -313,7 +314,10 @@ const char* Exception::what() const noexcept {
}
void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
- dld.vkDestroyInstance(instance, nullptr);
+ // FIXME: A double free occurs here if RAII is enabled.
+ if (!Settings::values.renderer_enable_raii.GetValue()) {
+ dld.vkDestroyInstance(instance, nullptr);
+ }
}
void Destroy(VkDevice device, const InstanceDispatch& dld) noexcept {
@@ -416,7 +420,10 @@ void Destroy(VkInstance instance, VkDebugReportCallbackEXT handle,
}
void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept {
- dld.vkDestroySurfaceKHR(instance, handle, nullptr);
+ // FIXME: A double free occurs here if RAII is enabled.
+ if (!Settings::values.renderer_enable_raii.GetValue()) {
+ dld.vkDestroySurfaceKHR(instance, handle, nullptr);
+ }
}
VkResult Free(VkDevice device, VkDescriptorPool handle, Span sets,
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 04b9420d98..a2e2efe61a 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -519,7 +519,7 @@ public:
}
/// Returns true when there's a held object.
- explicit operator bool() const noexcept {
+ operator bool() const noexcept {
return handle != nullptr;
}
@@ -630,7 +630,7 @@ class Instance : public Handle {
public:
/// Creates a Vulkan instance.
/// @throw Exception on initialization error.
- [[nodiscard]] static Instance Create(u32 version, Span layers, Span extensions,
+ static Instance Create(u32 version, Span layers, Span extensions,
InstanceDispatch& dispatch);
/// Enumerates physical devices.
@@ -640,12 +640,12 @@ public:
/// Creates a debug callback messenger.
/// @throw Exception on creation failure.
- [[nodiscard]] DebugUtilsMessenger CreateDebugUtilsMessenger(
+ DebugUtilsMessenger CreateDebugUtilsMessenger(
const VkDebugUtilsMessengerCreateInfoEXT& create_info) const;
/// Creates a debug report callback.
/// @throw Exception on creation failure.
- [[nodiscard]] DebugReportCallback CreateDebugReportCallback(
+ DebugReportCallback CreateDebugReportCallback(
const VkDebugReportCallbackCreateInfoEXT& create_info) const;
/// Returns dispatch table.
@@ -989,60 +989,58 @@ class Device : public Handle {
using Handle::Handle;
public:
- [[nodiscard]] static Device Create(VkPhysicalDevice physical_device,
- Span queues_ci,
- Span enabled_extensions, const void* next,
- DeviceDispatch& dispatch);
+ static Device Create(VkPhysicalDevice physical_device, Span queues_ci,
+ Span enabled_extensions, const void* next,
+ DeviceDispatch& dispatch);
- [[nodiscard]] Queue GetQueue(u32 family_index) const noexcept;
+ Queue GetQueue(u32 family_index) const noexcept;
- [[nodiscard]] BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
+ BufferView CreateBufferView(const VkBufferViewCreateInfo& ci) const;
- [[nodiscard]] ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
+ ImageView CreateImageView(const VkImageViewCreateInfo& ci) const;
- [[nodiscard]] Semaphore CreateSemaphore() const;
+ Semaphore CreateSemaphore() const;
- [[nodiscard]] Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const;
+ Semaphore CreateSemaphore(const VkSemaphoreCreateInfo& ci) const;
- [[nodiscard]] Fence CreateFence(const VkFenceCreateInfo& ci) const;
+ Fence CreateFence(const VkFenceCreateInfo& ci) const;
- [[nodiscard]] DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
+ DescriptorPool CreateDescriptorPool(const VkDescriptorPoolCreateInfo& ci) const;
- [[nodiscard]] RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
+ RenderPass CreateRenderPass(const VkRenderPassCreateInfo& ci) const;
- [[nodiscard]] DescriptorSetLayout CreateDescriptorSetLayout(
- const VkDescriptorSetLayoutCreateInfo& ci) const;
+ DescriptorSetLayout CreateDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo& ci) const;
- [[nodiscard]] PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const;
+ PipelineCache CreatePipelineCache(const VkPipelineCacheCreateInfo& ci) const;
- [[nodiscard]] PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
+ PipelineLayout CreatePipelineLayout(const VkPipelineLayoutCreateInfo& ci) const;
- [[nodiscard]] Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
- VkPipelineCache cache = nullptr) const;
+ Pipeline CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& ci,
+ VkPipelineCache cache = nullptr) const;
- [[nodiscard]] Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
- VkPipelineCache cache = nullptr) const;
+ Pipeline CreateComputePipeline(const VkComputePipelineCreateInfo& ci,
+ VkPipelineCache cache = nullptr) const;
- [[nodiscard]] Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
+ Sampler CreateSampler(const VkSamplerCreateInfo& ci) const;
- [[nodiscard]] Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
+ Framebuffer CreateFramebuffer(const VkFramebufferCreateInfo& ci) const;
- [[nodiscard]] CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
+ CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const;
- [[nodiscard]] DescriptorUpdateTemplate CreateDescriptorUpdateTemplate(
+ DescriptorUpdateTemplate CreateDescriptorUpdateTemplate(
const VkDescriptorUpdateTemplateCreateInfo& ci) const;
- [[nodiscard]] QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const;
+ QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const;
- [[nodiscard]] ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
+ ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
- [[nodiscard]] Event CreateEvent() const;
+ Event CreateEvent() const;
- [[nodiscard]] SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
+ SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
- [[nodiscard]] DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
+ DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
- [[nodiscard]] DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const;
+ DeviceMemory AllocateMemory(const VkMemoryAllocateInfo& ai) const;
VkMemoryRequirements GetBufferMemoryRequirements(VkBuffer buffer,
void* pnext = nullptr) const noexcept;