Merge pull request #3566 from ReinUsesLisp/vk-wrapper-part1
renderer_vulkan/wrapper: Add a Vulkan wrapper (part 1 of 2)
This commit is contained in:
		@@ -210,6 +210,8 @@ if (ENABLE_VULKAN)
 | 
				
			|||||||
        renderer_vulkan/vk_texture_cache.h
 | 
					        renderer_vulkan/vk_texture_cache.h
 | 
				
			||||||
        renderer_vulkan/vk_update_descriptor.cpp
 | 
					        renderer_vulkan/vk_update_descriptor.cpp
 | 
				
			||||||
        renderer_vulkan/vk_update_descriptor.h
 | 
					        renderer_vulkan/vk_update_descriptor.h
 | 
				
			||||||
 | 
					        renderer_vulkan/wrapper.cpp
 | 
				
			||||||
 | 
					        renderer_vulkan/wrapper.h
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include)
 | 
					    target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										342
									
								
								src/video_core/renderer_vulkan/wrapper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								src/video_core/renderer_vulkan/wrapper.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,342 @@
 | 
				
			|||||||
 | 
					// Copyright 2020 yuzu Emulator Project
 | 
				
			||||||
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <exception>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "video_core/renderer_vulkan/wrapper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Vulkan::vk {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					bool Proc(T& result, const InstanceDispatch& dld, const char* proc_name,
 | 
				
			||||||
 | 
					          VkInstance instance = nullptr) noexcept {
 | 
				
			||||||
 | 
					    result = reinterpret_cast<T>(dld.vkGetInstanceProcAddr(instance, proc_name));
 | 
				
			||||||
 | 
					    return result != nullptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					void Proc(T& result, const DeviceDispatch& dld, const char* proc_name, VkDevice device) noexcept {
 | 
				
			||||||
 | 
					    result = reinterpret_cast<T>(dld.vkGetDeviceProcAddr(device, proc_name));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Load(VkDevice device, DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					#define X(name) Proc(dld.name, dld, #name, device)
 | 
				
			||||||
 | 
					    X(vkAcquireNextImageKHR);
 | 
				
			||||||
 | 
					    X(vkAllocateCommandBuffers);
 | 
				
			||||||
 | 
					    X(vkAllocateDescriptorSets);
 | 
				
			||||||
 | 
					    X(vkAllocateMemory);
 | 
				
			||||||
 | 
					    X(vkBeginCommandBuffer);
 | 
				
			||||||
 | 
					    X(vkBindBufferMemory);
 | 
				
			||||||
 | 
					    X(vkBindImageMemory);
 | 
				
			||||||
 | 
					    X(vkCmdBeginQuery);
 | 
				
			||||||
 | 
					    X(vkCmdBeginRenderPass);
 | 
				
			||||||
 | 
					    X(vkCmdBeginTransformFeedbackEXT);
 | 
				
			||||||
 | 
					    X(vkCmdBindDescriptorSets);
 | 
				
			||||||
 | 
					    X(vkCmdBindIndexBuffer);
 | 
				
			||||||
 | 
					    X(vkCmdBindPipeline);
 | 
				
			||||||
 | 
					    X(vkCmdBindTransformFeedbackBuffersEXT);
 | 
				
			||||||
 | 
					    X(vkCmdBindVertexBuffers);
 | 
				
			||||||
 | 
					    X(vkCmdBlitImage);
 | 
				
			||||||
 | 
					    X(vkCmdClearAttachments);
 | 
				
			||||||
 | 
					    X(vkCmdCopyBuffer);
 | 
				
			||||||
 | 
					    X(vkCmdCopyBufferToImage);
 | 
				
			||||||
 | 
					    X(vkCmdCopyImage);
 | 
				
			||||||
 | 
					    X(vkCmdCopyImageToBuffer);
 | 
				
			||||||
 | 
					    X(vkCmdDispatch);
 | 
				
			||||||
 | 
					    X(vkCmdDraw);
 | 
				
			||||||
 | 
					    X(vkCmdDrawIndexed);
 | 
				
			||||||
 | 
					    X(vkCmdEndQuery);
 | 
				
			||||||
 | 
					    X(vkCmdEndRenderPass);
 | 
				
			||||||
 | 
					    X(vkCmdEndTransformFeedbackEXT);
 | 
				
			||||||
 | 
					    X(vkCmdFillBuffer);
 | 
				
			||||||
 | 
					    X(vkCmdPipelineBarrier);
 | 
				
			||||||
 | 
					    X(vkCmdPushConstants);
 | 
				
			||||||
 | 
					    X(vkCmdSetBlendConstants);
 | 
				
			||||||
 | 
					    X(vkCmdSetCheckpointNV);
 | 
				
			||||||
 | 
					    X(vkCmdSetDepthBias);
 | 
				
			||||||
 | 
					    X(vkCmdSetDepthBounds);
 | 
				
			||||||
 | 
					    X(vkCmdSetScissor);
 | 
				
			||||||
 | 
					    X(vkCmdSetStencilCompareMask);
 | 
				
			||||||
 | 
					    X(vkCmdSetStencilReference);
 | 
				
			||||||
 | 
					    X(vkCmdSetStencilWriteMask);
 | 
				
			||||||
 | 
					    X(vkCmdSetViewport);
 | 
				
			||||||
 | 
					    X(vkCreateBuffer);
 | 
				
			||||||
 | 
					    X(vkCreateBufferView);
 | 
				
			||||||
 | 
					    X(vkCreateCommandPool);
 | 
				
			||||||
 | 
					    X(vkCreateComputePipelines);
 | 
				
			||||||
 | 
					    X(vkCreateDescriptorPool);
 | 
				
			||||||
 | 
					    X(vkCreateDescriptorSetLayout);
 | 
				
			||||||
 | 
					    X(vkCreateDescriptorUpdateTemplateKHR);
 | 
				
			||||||
 | 
					    X(vkCreateFence);
 | 
				
			||||||
 | 
					    X(vkCreateFramebuffer);
 | 
				
			||||||
 | 
					    X(vkCreateGraphicsPipelines);
 | 
				
			||||||
 | 
					    X(vkCreateImage);
 | 
				
			||||||
 | 
					    X(vkCreateImageView);
 | 
				
			||||||
 | 
					    X(vkCreatePipelineLayout);
 | 
				
			||||||
 | 
					    X(vkCreateQueryPool);
 | 
				
			||||||
 | 
					    X(vkCreateRenderPass);
 | 
				
			||||||
 | 
					    X(vkCreateSampler);
 | 
				
			||||||
 | 
					    X(vkCreateSemaphore);
 | 
				
			||||||
 | 
					    X(vkCreateShaderModule);
 | 
				
			||||||
 | 
					    X(vkCreateSwapchainKHR);
 | 
				
			||||||
 | 
					    X(vkDestroyBuffer);
 | 
				
			||||||
 | 
					    X(vkDestroyBufferView);
 | 
				
			||||||
 | 
					    X(vkDestroyCommandPool);
 | 
				
			||||||
 | 
					    X(vkDestroyDescriptorPool);
 | 
				
			||||||
 | 
					    X(vkDestroyDescriptorSetLayout);
 | 
				
			||||||
 | 
					    X(vkDestroyDescriptorUpdateTemplateKHR);
 | 
				
			||||||
 | 
					    X(vkDestroyFence);
 | 
				
			||||||
 | 
					    X(vkDestroyFramebuffer);
 | 
				
			||||||
 | 
					    X(vkDestroyImage);
 | 
				
			||||||
 | 
					    X(vkDestroyImageView);
 | 
				
			||||||
 | 
					    X(vkDestroyPipeline);
 | 
				
			||||||
 | 
					    X(vkDestroyPipelineLayout);
 | 
				
			||||||
 | 
					    X(vkDestroyQueryPool);
 | 
				
			||||||
 | 
					    X(vkDestroyRenderPass);
 | 
				
			||||||
 | 
					    X(vkDestroySampler);
 | 
				
			||||||
 | 
					    X(vkDestroySemaphore);
 | 
				
			||||||
 | 
					    X(vkDestroyShaderModule);
 | 
				
			||||||
 | 
					    X(vkDestroySwapchainKHR);
 | 
				
			||||||
 | 
					    X(vkDeviceWaitIdle);
 | 
				
			||||||
 | 
					    X(vkEndCommandBuffer);
 | 
				
			||||||
 | 
					    X(vkFreeCommandBuffers);
 | 
				
			||||||
 | 
					    X(vkFreeDescriptorSets);
 | 
				
			||||||
 | 
					    X(vkFreeMemory);
 | 
				
			||||||
 | 
					    X(vkGetBufferMemoryRequirements);
 | 
				
			||||||
 | 
					    X(vkGetDeviceQueue);
 | 
				
			||||||
 | 
					    X(vkGetFenceStatus);
 | 
				
			||||||
 | 
					    X(vkGetImageMemoryRequirements);
 | 
				
			||||||
 | 
					    X(vkGetQueryPoolResults);
 | 
				
			||||||
 | 
					    X(vkGetQueueCheckpointDataNV);
 | 
				
			||||||
 | 
					    X(vkMapMemory);
 | 
				
			||||||
 | 
					    X(vkQueueSubmit);
 | 
				
			||||||
 | 
					    X(vkResetFences);
 | 
				
			||||||
 | 
					    X(vkResetQueryPoolEXT);
 | 
				
			||||||
 | 
					    X(vkUnmapMemory);
 | 
				
			||||||
 | 
					    X(vkUpdateDescriptorSetWithTemplateKHR);
 | 
				
			||||||
 | 
					    X(vkUpdateDescriptorSets);
 | 
				
			||||||
 | 
					    X(vkWaitForFences);
 | 
				
			||||||
 | 
					#undef X
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // Anonymous namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Load(InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					#define X(name) Proc(dld.name, dld, #name)
 | 
				
			||||||
 | 
					    return X(vkCreateInstance) && X(vkEnumerateInstanceExtensionProperties);
 | 
				
			||||||
 | 
					#undef X
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					#define X(name) Proc(dld.name, dld, #name, instance)
 | 
				
			||||||
 | 
					    // These functions may fail to load depending on the enabled extensions.
 | 
				
			||||||
 | 
					    // Don't return a failure on these.
 | 
				
			||||||
 | 
					    X(vkCreateDebugUtilsMessengerEXT);
 | 
				
			||||||
 | 
					    X(vkDestroyDebugUtilsMessengerEXT);
 | 
				
			||||||
 | 
					    X(vkDestroySurfaceKHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceFeatures2KHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceProperties2KHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceSurfaceFormatsKHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceSurfacePresentModesKHR);
 | 
				
			||||||
 | 
					    X(vkGetPhysicalDeviceSurfaceSupportKHR);
 | 
				
			||||||
 | 
					    X(vkGetSwapchainImagesKHR);
 | 
				
			||||||
 | 
					    X(vkQueuePresentKHR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return X(vkCreateDevice) && X(vkDestroyDevice) && X(vkDestroyDevice) &&
 | 
				
			||||||
 | 
					           X(vkEnumerateDeviceExtensionProperties) && X(vkEnumeratePhysicalDevices) &&
 | 
				
			||||||
 | 
					           X(vkGetDeviceProcAddr) && X(vkGetPhysicalDeviceFormatProperties) &&
 | 
				
			||||||
 | 
					           X(vkGetPhysicalDeviceMemoryProperties) && X(vkGetPhysicalDeviceProperties) &&
 | 
				
			||||||
 | 
					           X(vkGetPhysicalDeviceQueueFamilyProperties);
 | 
				
			||||||
 | 
					#undef X
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char* Exception::what() const noexcept {
 | 
				
			||||||
 | 
					    return ToString(result);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char* ToString(VkResult result) noexcept {
 | 
				
			||||||
 | 
					    switch (result) {
 | 
				
			||||||
 | 
					    case VkResult::VK_SUCCESS:
 | 
				
			||||||
 | 
					        return "VK_SUCCESS";
 | 
				
			||||||
 | 
					    case VkResult::VK_NOT_READY:
 | 
				
			||||||
 | 
					        return "VK_NOT_READY";
 | 
				
			||||||
 | 
					    case VkResult::VK_TIMEOUT:
 | 
				
			||||||
 | 
					        return "VK_TIMEOUT";
 | 
				
			||||||
 | 
					    case VkResult::VK_EVENT_SET:
 | 
				
			||||||
 | 
					        return "VK_EVENT_SET";
 | 
				
			||||||
 | 
					    case VkResult::VK_EVENT_RESET:
 | 
				
			||||||
 | 
					        return "VK_EVENT_RESET";
 | 
				
			||||||
 | 
					    case VkResult::VK_INCOMPLETE:
 | 
				
			||||||
 | 
					        return "VK_INCOMPLETE";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_OUT_OF_HOST_MEMORY:
 | 
				
			||||||
 | 
					        return "VK_ERROR_OUT_OF_HOST_MEMORY";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_OUT_OF_DEVICE_MEMORY:
 | 
				
			||||||
 | 
					        return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INITIALIZATION_FAILED:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INITIALIZATION_FAILED";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_DEVICE_LOST:
 | 
				
			||||||
 | 
					        return "VK_ERROR_DEVICE_LOST";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_MEMORY_MAP_FAILED:
 | 
				
			||||||
 | 
					        return "VK_ERROR_MEMORY_MAP_FAILED";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_LAYER_NOT_PRESENT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_LAYER_NOT_PRESENT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_EXTENSION_NOT_PRESENT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_EXTENSION_NOT_PRESENT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_FEATURE_NOT_PRESENT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_FEATURE_NOT_PRESENT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INCOMPATIBLE_DRIVER:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INCOMPATIBLE_DRIVER";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_TOO_MANY_OBJECTS:
 | 
				
			||||||
 | 
					        return "VK_ERROR_TOO_MANY_OBJECTS";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_FORMAT_NOT_SUPPORTED:
 | 
				
			||||||
 | 
					        return "VK_ERROR_FORMAT_NOT_SUPPORTED";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_FRAGMENTED_POOL:
 | 
				
			||||||
 | 
					        return "VK_ERROR_FRAGMENTED_POOL";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_OUT_OF_POOL_MEMORY:
 | 
				
			||||||
 | 
					        return "VK_ERROR_OUT_OF_POOL_MEMORY";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INVALID_EXTERNAL_HANDLE:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_SURFACE_LOST_KHR:
 | 
				
			||||||
 | 
					        return "VK_ERROR_SURFACE_LOST_KHR";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
 | 
				
			||||||
 | 
					        return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
 | 
				
			||||||
 | 
					    case VkResult::VK_SUBOPTIMAL_KHR:
 | 
				
			||||||
 | 
					        return "VK_SUBOPTIMAL_KHR";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_OUT_OF_DATE_KHR:
 | 
				
			||||||
 | 
					        return "VK_ERROR_OUT_OF_DATE_KHR";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_VALIDATION_FAILED_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_VALIDATION_FAILED_EXT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INVALID_SHADER_NV:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INVALID_SHADER_NV";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_FRAGMENTATION_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_FRAGMENTATION_EXT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_NOT_PERMITTED_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_NOT_PERMITTED_EXT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_INVALID_DEVICE_ADDRESS_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
 | 
				
			||||||
 | 
					    case VkResult::VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:
 | 
				
			||||||
 | 
					        return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return "Unknown";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkInstance instance, const InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyInstance(instance, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, const InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyDevice(device, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkBuffer handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyBuffer(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkBufferView handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyBufferView(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkCommandPool handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyCommandPool(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkDescriptorPool handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyDescriptorPool(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkDescriptorSetLayout handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyDescriptorSetLayout(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkDescriptorUpdateTemplateKHR handle,
 | 
				
			||||||
 | 
					             const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyDescriptorUpdateTemplateKHR(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkFreeMemory(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkFence handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyFence(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkFramebuffer handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyFramebuffer(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkImage handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyImage(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkImageView handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyImageView(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkPipeline handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyPipeline(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkPipelineLayout handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyPipelineLayout(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkQueryPool handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyQueryPool(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkRenderPass handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyRenderPass(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkSampler handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroySampler(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkSwapchainKHR handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroySwapchainKHR(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkSemaphore handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroySemaphore(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice device, VkShaderModule handle, const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyShaderModule(device, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkInstance instance, VkDebugUtilsMessengerEXT handle,
 | 
				
			||||||
 | 
					             const InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroyDebugUtilsMessengerEXT(instance, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkDestroySurfaceKHR(instance, handle, nullptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkResult Free(VkDevice device, VkDescriptorPool handle, Span<VkDescriptorSet> sets,
 | 
				
			||||||
 | 
					              const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    return dld.vkFreeDescriptorSets(device, handle, sets.size(), sets.data());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffers,
 | 
				
			||||||
 | 
					              const DeviceDispatch& dld) noexcept {
 | 
				
			||||||
 | 
					    dld.vkFreeCommandBuffers(device, handle, buffers.size(), buffers.data());
 | 
				
			||||||
 | 
					    return VK_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Vulkan::vk
 | 
				
			||||||
							
								
								
									
										545
									
								
								src/video_core/renderer_vulkan/wrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										545
									
								
								src/video_core/renderer_vulkan/wrapper.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,545 @@
 | 
				
			|||||||
 | 
					// Copyright 2020 yuzu Emulator Project
 | 
				
			||||||
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <exception>
 | 
				
			||||||
 | 
					#include <iterator>
 | 
				
			||||||
 | 
					#include <limits>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
 | 
					#include <type_traits>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VK_NO_PROTOTYPES
 | 
				
			||||||
 | 
					#include <vulkan/vulkan.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "common/common_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Vulkan::vk {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Span for Vulkan arrays.
 | 
				
			||||||
 | 
					 * Based on std::span but optimized for array access instead of iterators.
 | 
				
			||||||
 | 
					 * Size returns uint32_t instead of size_t to ease interaction with Vulkan functions.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					template <typename T>
 | 
				
			||||||
 | 
					class Span {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    using value_type = T;
 | 
				
			||||||
 | 
					    using size_type = u32;
 | 
				
			||||||
 | 
					    using difference_type = std::ptrdiff_t;
 | 
				
			||||||
 | 
					    using reference = const T&;
 | 
				
			||||||
 | 
					    using const_reference = const T&;
 | 
				
			||||||
 | 
					    using pointer = const T*;
 | 
				
			||||||
 | 
					    using const_pointer = const T*;
 | 
				
			||||||
 | 
					    using iterator = const T*;
 | 
				
			||||||
 | 
					    using const_iterator = const T*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct an empty span.
 | 
				
			||||||
 | 
					    constexpr Span() noexcept = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a span from a single element.
 | 
				
			||||||
 | 
					    constexpr Span(const T& value) noexcept : ptr{&value}, num{1} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a span from a range.
 | 
				
			||||||
 | 
					    template <typename Range>
 | 
				
			||||||
 | 
					    // requires std::data(const Range&)
 | 
				
			||||||
 | 
					    // requires std::size(const Range&)
 | 
				
			||||||
 | 
					    constexpr Span(const Range& range) : ptr{std::data(range)}, num{std::size(range)} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a span from a pointer and a size.
 | 
				
			||||||
 | 
					    /// This is inteded for subranges.
 | 
				
			||||||
 | 
					    constexpr Span(const T* ptr, std::size_t num) noexcept : ptr{ptr}, num{num} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the data pointer by the span.
 | 
				
			||||||
 | 
					    constexpr const T* data() const noexcept {
 | 
				
			||||||
 | 
					        return ptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the number of elements in the span.
 | 
				
			||||||
 | 
					    /// @note Returns a 32 bits integer because most Vulkan functions expect this type.
 | 
				
			||||||
 | 
					    constexpr u32 size() const noexcept {
 | 
				
			||||||
 | 
					        return static_cast<u32>(num);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns true when the span is empty.
 | 
				
			||||||
 | 
					    constexpr bool empty() const noexcept {
 | 
				
			||||||
 | 
					        return num == 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a reference to the element in the passed index.
 | 
				
			||||||
 | 
					    /// @pre: index < size()
 | 
				
			||||||
 | 
					    constexpr const T& operator[](std::size_t index) const noexcept {
 | 
				
			||||||
 | 
					        return ptr[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an iterator to the beginning of the span.
 | 
				
			||||||
 | 
					    constexpr const T* begin() const noexcept {
 | 
				
			||||||
 | 
					        return ptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an iterator to the end of the span.
 | 
				
			||||||
 | 
					    constexpr const T* end() const noexcept {
 | 
				
			||||||
 | 
					        return ptr + num;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an iterator to the beginning of the span.
 | 
				
			||||||
 | 
					    constexpr const T* cbegin() const noexcept {
 | 
				
			||||||
 | 
					        return ptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns an iterator to the end of the span.
 | 
				
			||||||
 | 
					    constexpr const T* cend() const noexcept {
 | 
				
			||||||
 | 
					        return ptr + num;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    const T* ptr = nullptr;
 | 
				
			||||||
 | 
					    std::size_t num = 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Vulkan exception generated from a VkResult.
 | 
				
			||||||
 | 
					class Exception final : public std::exception {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /// Construct the exception with a result.
 | 
				
			||||||
 | 
					    /// @pre result != VK_SUCCESS
 | 
				
			||||||
 | 
					    explicit Exception(VkResult result_) : result{result_} {}
 | 
				
			||||||
 | 
					    virtual ~Exception() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const char* what() const noexcept override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    VkResult result;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Converts a VkResult enum into a rodata string
 | 
				
			||||||
 | 
					const char* ToString(VkResult) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Throws a Vulkan exception if result is not success.
 | 
				
			||||||
 | 
					inline void Check(VkResult result) {
 | 
				
			||||||
 | 
					    if (result != VK_SUCCESS) {
 | 
				
			||||||
 | 
					        throw Exception(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Throws a Vulkan exception if result is an error.
 | 
				
			||||||
 | 
					/// @return result
 | 
				
			||||||
 | 
					inline VkResult Filter(VkResult result) {
 | 
				
			||||||
 | 
					    if (result < 0) {
 | 
				
			||||||
 | 
					        throw Exception(result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Table holding Vulkan instance function pointers.
 | 
				
			||||||
 | 
					struct InstanceDispatch {
 | 
				
			||||||
 | 
					    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PFN_vkCreateInstance vkCreateInstance;
 | 
				
			||||||
 | 
					    PFN_vkDestroyInstance vkDestroyInstance;
 | 
				
			||||||
 | 
					    PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
 | 
				
			||||||
 | 
					    PFN_vkCreateDevice vkCreateDevice;
 | 
				
			||||||
 | 
					    PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
 | 
				
			||||||
 | 
					    PFN_vkDestroyDevice vkDestroyDevice;
 | 
				
			||||||
 | 
					    PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
 | 
				
			||||||
 | 
					    PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
 | 
				
			||||||
 | 
					    PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
 | 
				
			||||||
 | 
					    PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
 | 
				
			||||||
 | 
					    PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
 | 
				
			||||||
 | 
					    PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
 | 
				
			||||||
 | 
					    PFN_vkQueuePresentKHR vkQueuePresentKHR;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Table holding Vulkan device function pointers.
 | 
				
			||||||
 | 
					struct DeviceDispatch : public InstanceDispatch {
 | 
				
			||||||
 | 
					    PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
 | 
				
			||||||
 | 
					    PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
 | 
				
			||||||
 | 
					    PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets;
 | 
				
			||||||
 | 
					    PFN_vkAllocateMemory vkAllocateMemory;
 | 
				
			||||||
 | 
					    PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
 | 
				
			||||||
 | 
					    PFN_vkBindBufferMemory vkBindBufferMemory;
 | 
				
			||||||
 | 
					    PFN_vkBindImageMemory vkBindImageMemory;
 | 
				
			||||||
 | 
					    PFN_vkCmdBeginQuery vkCmdBeginQuery;
 | 
				
			||||||
 | 
					    PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
 | 
				
			||||||
 | 
					    PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
 | 
				
			||||||
 | 
					    PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets;
 | 
				
			||||||
 | 
					    PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
 | 
				
			||||||
 | 
					    PFN_vkCmdBindPipeline vkCmdBindPipeline;
 | 
				
			||||||
 | 
					    PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT;
 | 
				
			||||||
 | 
					    PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
 | 
				
			||||||
 | 
					    PFN_vkCmdBlitImage vkCmdBlitImage;
 | 
				
			||||||
 | 
					    PFN_vkCmdClearAttachments vkCmdClearAttachments;
 | 
				
			||||||
 | 
					    PFN_vkCmdCopyBuffer vkCmdCopyBuffer;
 | 
				
			||||||
 | 
					    PFN_vkCmdCopyBufferToImage vkCmdCopyBufferToImage;
 | 
				
			||||||
 | 
					    PFN_vkCmdCopyImage vkCmdCopyImage;
 | 
				
			||||||
 | 
					    PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer;
 | 
				
			||||||
 | 
					    PFN_vkCmdDispatch vkCmdDispatch;
 | 
				
			||||||
 | 
					    PFN_vkCmdDraw vkCmdDraw;
 | 
				
			||||||
 | 
					    PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
 | 
				
			||||||
 | 
					    PFN_vkCmdEndQuery vkCmdEndQuery;
 | 
				
			||||||
 | 
					    PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
 | 
				
			||||||
 | 
					    PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT;
 | 
				
			||||||
 | 
					    PFN_vkCmdFillBuffer vkCmdFillBuffer;
 | 
				
			||||||
 | 
					    PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier;
 | 
				
			||||||
 | 
					    PFN_vkCmdPushConstants vkCmdPushConstants;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetScissor vkCmdSetScissor;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
 | 
				
			||||||
 | 
					    PFN_vkCmdSetViewport vkCmdSetViewport;
 | 
				
			||||||
 | 
					    PFN_vkCreateBuffer vkCreateBuffer;
 | 
				
			||||||
 | 
					    PFN_vkCreateBufferView vkCreateBufferView;
 | 
				
			||||||
 | 
					    PFN_vkCreateCommandPool vkCreateCommandPool;
 | 
				
			||||||
 | 
					    PFN_vkCreateComputePipelines vkCreateComputePipelines;
 | 
				
			||||||
 | 
					    PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
 | 
				
			||||||
 | 
					    PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
 | 
				
			||||||
 | 
					    PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
 | 
				
			||||||
 | 
					    PFN_vkCreateFence vkCreateFence;
 | 
				
			||||||
 | 
					    PFN_vkCreateFramebuffer vkCreateFramebuffer;
 | 
				
			||||||
 | 
					    PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
 | 
				
			||||||
 | 
					    PFN_vkCreateImage vkCreateImage;
 | 
				
			||||||
 | 
					    PFN_vkCreateImageView vkCreateImageView;
 | 
				
			||||||
 | 
					    PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
 | 
				
			||||||
 | 
					    PFN_vkCreateQueryPool vkCreateQueryPool;
 | 
				
			||||||
 | 
					    PFN_vkCreateRenderPass vkCreateRenderPass;
 | 
				
			||||||
 | 
					    PFN_vkCreateSampler vkCreateSampler;
 | 
				
			||||||
 | 
					    PFN_vkCreateSemaphore vkCreateSemaphore;
 | 
				
			||||||
 | 
					    PFN_vkCreateShaderModule vkCreateShaderModule;
 | 
				
			||||||
 | 
					    PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
 | 
				
			||||||
 | 
					    PFN_vkDestroyBuffer vkDestroyBuffer;
 | 
				
			||||||
 | 
					    PFN_vkDestroyBufferView vkDestroyBufferView;
 | 
				
			||||||
 | 
					    PFN_vkDestroyCommandPool vkDestroyCommandPool;
 | 
				
			||||||
 | 
					    PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
 | 
				
			||||||
 | 
					    PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
 | 
				
			||||||
 | 
					    PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
 | 
				
			||||||
 | 
					    PFN_vkDestroyFence vkDestroyFence;
 | 
				
			||||||
 | 
					    PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
 | 
				
			||||||
 | 
					    PFN_vkDestroyImage vkDestroyImage;
 | 
				
			||||||
 | 
					    PFN_vkDestroyImageView vkDestroyImageView;
 | 
				
			||||||
 | 
					    PFN_vkDestroyPipeline vkDestroyPipeline;
 | 
				
			||||||
 | 
					    PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
 | 
				
			||||||
 | 
					    PFN_vkDestroyQueryPool vkDestroyQueryPool;
 | 
				
			||||||
 | 
					    PFN_vkDestroyRenderPass vkDestroyRenderPass;
 | 
				
			||||||
 | 
					    PFN_vkDestroySampler vkDestroySampler;
 | 
				
			||||||
 | 
					    PFN_vkDestroySemaphore vkDestroySemaphore;
 | 
				
			||||||
 | 
					    PFN_vkDestroyShaderModule vkDestroyShaderModule;
 | 
				
			||||||
 | 
					    PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
 | 
				
			||||||
 | 
					    PFN_vkDeviceWaitIdle vkDeviceWaitIdle;
 | 
				
			||||||
 | 
					    PFN_vkEndCommandBuffer vkEndCommandBuffer;
 | 
				
			||||||
 | 
					    PFN_vkFreeCommandBuffers vkFreeCommandBuffers;
 | 
				
			||||||
 | 
					    PFN_vkFreeDescriptorSets vkFreeDescriptorSets;
 | 
				
			||||||
 | 
					    PFN_vkFreeMemory vkFreeMemory;
 | 
				
			||||||
 | 
					    PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
 | 
				
			||||||
 | 
					    PFN_vkGetDeviceQueue vkGetDeviceQueue;
 | 
				
			||||||
 | 
					    PFN_vkGetFenceStatus vkGetFenceStatus;
 | 
				
			||||||
 | 
					    PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
 | 
				
			||||||
 | 
					    PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
 | 
				
			||||||
 | 
					    PFN_vkGetQueueCheckpointDataNV vkGetQueueCheckpointDataNV;
 | 
				
			||||||
 | 
					    PFN_vkMapMemory vkMapMemory;
 | 
				
			||||||
 | 
					    PFN_vkQueueSubmit vkQueueSubmit;
 | 
				
			||||||
 | 
					    PFN_vkResetFences vkResetFences;
 | 
				
			||||||
 | 
					    PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
 | 
				
			||||||
 | 
					    PFN_vkUnmapMemory vkUnmapMemory;
 | 
				
			||||||
 | 
					    PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR;
 | 
				
			||||||
 | 
					    PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets;
 | 
				
			||||||
 | 
					    PFN_vkWaitForFences vkWaitForFences;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Loads instance agnostic function pointers.
 | 
				
			||||||
 | 
					/// @return True on success, false on error.
 | 
				
			||||||
 | 
					bool Load(InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Loads instance function pointers.
 | 
				
			||||||
 | 
					/// @return True on success, false on error.
 | 
				
			||||||
 | 
					bool Load(VkInstance, InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkInstance, const InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, const InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkBuffer, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkBufferView, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkDescriptorUpdateTemplateKHR, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkImageView, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkPipeline, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkPipelineLayout, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkQueryPool, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkRenderPass, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkSampler, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkDevice, VkShaderModule, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkInstance, VkDebugUtilsMessengerEXT, const InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					VkResult Free(VkDevice, VkCommandPool, Span<VkCommandBuffer>, const DeviceDispatch&) noexcept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename Type, typename OwnerType, typename Dispatch>
 | 
				
			||||||
 | 
					class Handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Handle with an owning type.
 | 
				
			||||||
 | 
					/// Analogue to std::unique_ptr.
 | 
				
			||||||
 | 
					template <typename Type, typename OwnerType, typename Dispatch>
 | 
				
			||||||
 | 
					class Handle {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /// Construct a handle and hold it's ownership.
 | 
				
			||||||
 | 
					    explicit Handle(Type handle_, OwnerType owner_, const Dispatch& dld_) noexcept
 | 
				
			||||||
 | 
					        : handle{handle_}, owner{owner_}, dld{&dld_} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct an empty handle.
 | 
				
			||||||
 | 
					    Handle() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Copying Vulkan objects is not supported and will never be.
 | 
				
			||||||
 | 
					    Handle(const Handle&) = delete;
 | 
				
			||||||
 | 
					    Handle& operator=(const Handle&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a handle transfering the ownership from another handle.
 | 
				
			||||||
 | 
					    Handle(Handle&& rhs) noexcept
 | 
				
			||||||
 | 
					        : handle{std::exchange(rhs.handle, nullptr)}, owner{rhs.owner}, dld{rhs.dld} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Assign the current handle transfering the ownership from another handle.
 | 
				
			||||||
 | 
					    /// Destroys any previously held object.
 | 
				
			||||||
 | 
					    Handle& operator=(Handle&& rhs) noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        handle = std::exchange(rhs.handle, nullptr);
 | 
				
			||||||
 | 
					        owner = rhs.owner;
 | 
				
			||||||
 | 
					        dld = rhs.dld;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Destroys the current handle if it existed.
 | 
				
			||||||
 | 
					    ~Handle() noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Destroys any held object.
 | 
				
			||||||
 | 
					    void reset() noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        handle = nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the address of the held object.
 | 
				
			||||||
 | 
					    /// Intended for Vulkan structures that expect a pointer to an array.
 | 
				
			||||||
 | 
					    const Type* address() const noexcept {
 | 
				
			||||||
 | 
					        return std::addressof(handle);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the held Vulkan handle.
 | 
				
			||||||
 | 
					    Type operator*() const noexcept {
 | 
				
			||||||
 | 
					        return handle;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns true when there's a held object.
 | 
				
			||||||
 | 
					    explicit operator bool() const noexcept {
 | 
				
			||||||
 | 
					        return handle != nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    Type handle = nullptr;
 | 
				
			||||||
 | 
					    OwnerType owner = nullptr;
 | 
				
			||||||
 | 
					    const Dispatch* dld = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    /// Destroys the held object if it exists.
 | 
				
			||||||
 | 
					    void Release() noexcept {
 | 
				
			||||||
 | 
					        if (handle) {
 | 
				
			||||||
 | 
					            Destroy(owner, handle, *dld);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Dummy type used to specify a handle has no owner.
 | 
				
			||||||
 | 
					struct NoOwner {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Handle without an owning type.
 | 
				
			||||||
 | 
					/// Analogue to std::unique_ptr
 | 
				
			||||||
 | 
					template <typename Type, typename Dispatch>
 | 
				
			||||||
 | 
					class Handle<Type, NoOwner, Dispatch> {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /// Construct a handle and hold it's ownership.
 | 
				
			||||||
 | 
					    explicit Handle(Type handle_, const Dispatch& dld_) noexcept : handle{handle_}, dld{&dld_} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct an empty handle.
 | 
				
			||||||
 | 
					    Handle() noexcept = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Copying Vulkan objects is not supported and will never be.
 | 
				
			||||||
 | 
					    Handle(const Handle&) = delete;
 | 
				
			||||||
 | 
					    Handle& operator=(const Handle&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct a handle transfering ownership from another handle.
 | 
				
			||||||
 | 
					    Handle(Handle&& rhs) noexcept : handle{std::exchange(rhs.handle, nullptr)}, dld{rhs.dld} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Assign the current handle transfering the ownership from another handle.
 | 
				
			||||||
 | 
					    /// Destroys any previously held object.
 | 
				
			||||||
 | 
					    Handle& operator=(Handle&& rhs) noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        handle = std::exchange(rhs.handle, nullptr);
 | 
				
			||||||
 | 
					        dld = rhs.dld;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Destroys the current handle if it existed.
 | 
				
			||||||
 | 
					    ~Handle() noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Destroys any held object.
 | 
				
			||||||
 | 
					    void reset() noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        handle = nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the address of the held object.
 | 
				
			||||||
 | 
					    /// Intended for Vulkan structures that expect a pointer to an array.
 | 
				
			||||||
 | 
					    const Type* address() const noexcept {
 | 
				
			||||||
 | 
					        return std::addressof(handle);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the held Vulkan handle.
 | 
				
			||||||
 | 
					    Type operator*() const noexcept {
 | 
				
			||||||
 | 
					        return handle;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns true when there's a held object.
 | 
				
			||||||
 | 
					    operator bool() const noexcept {
 | 
				
			||||||
 | 
					        return handle != nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
					    Type handle = nullptr;
 | 
				
			||||||
 | 
					    const Dispatch* dld = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    /// Destroys the held object if it exists.
 | 
				
			||||||
 | 
					    void Release() noexcept {
 | 
				
			||||||
 | 
					        if (handle) {
 | 
				
			||||||
 | 
					            Destroy(handle, *dld);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Array of a pool allocation.
 | 
				
			||||||
 | 
					/// Analogue to std::vector
 | 
				
			||||||
 | 
					template <typename AllocationType, typename PoolType>
 | 
				
			||||||
 | 
					class PoolAllocations {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					    /// Construct an empty allocation.
 | 
				
			||||||
 | 
					    PoolAllocations() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct an allocation. Errors are reported through IsOutOfPoolMemory().
 | 
				
			||||||
 | 
					    explicit PoolAllocations(std::unique_ptr<AllocationType[]> allocations, std::size_t num,
 | 
				
			||||||
 | 
					                             VkDevice device, PoolType pool, const DeviceDispatch& dld) noexcept
 | 
				
			||||||
 | 
					        : allocations{std::move(allocations)}, num{num}, device{device}, pool{pool}, dld{&dld} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Copying Vulkan allocations is not supported and will never be.
 | 
				
			||||||
 | 
					    PoolAllocations(const PoolAllocations&) = delete;
 | 
				
			||||||
 | 
					    PoolAllocations& operator=(const PoolAllocations&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Construct an allocation transfering ownership from another allocation.
 | 
				
			||||||
 | 
					    PoolAllocations(PoolAllocations&& rhs) noexcept
 | 
				
			||||||
 | 
					        : allocations{std::move(rhs.allocations)}, num{rhs.num}, device{rhs.device}, pool{rhs.pool},
 | 
				
			||||||
 | 
					          dld{rhs.dld} {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Assign an allocation transfering ownership from another allocation.
 | 
				
			||||||
 | 
					    /// Releases any previously held allocation.
 | 
				
			||||||
 | 
					    PoolAllocations& operator=(PoolAllocations&& rhs) noexcept {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					        allocations = std::move(rhs.allocations);
 | 
				
			||||||
 | 
					        num = rhs.num;
 | 
				
			||||||
 | 
					        device = rhs.device;
 | 
				
			||||||
 | 
					        pool = rhs.pool;
 | 
				
			||||||
 | 
					        dld = rhs.dld;
 | 
				
			||||||
 | 
					        return *this;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Destroys any held allocation.
 | 
				
			||||||
 | 
					    ~PoolAllocations() {
 | 
				
			||||||
 | 
					        Release();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the number of allocations.
 | 
				
			||||||
 | 
					    std::size_t size() const noexcept {
 | 
				
			||||||
 | 
					        return num;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns a pointer to the array of allocations.
 | 
				
			||||||
 | 
					    AllocationType const* data() const noexcept {
 | 
				
			||||||
 | 
					        return allocations.get();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Returns the allocation in the specified index.
 | 
				
			||||||
 | 
					    /// @pre index < size()
 | 
				
			||||||
 | 
					    AllocationType operator[](std::size_t index) const noexcept {
 | 
				
			||||||
 | 
					        return allocations[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// True when a pool fails to construct.
 | 
				
			||||||
 | 
					    bool IsOutOfPoolMemory() const noexcept {
 | 
				
			||||||
 | 
					        return !device;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    /// Destroys the held allocations if they exist.
 | 
				
			||||||
 | 
					    void Release() noexcept {
 | 
				
			||||||
 | 
					        if (!allocations) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const Span<AllocationType> span(allocations.get(), num);
 | 
				
			||||||
 | 
					        const VkResult result = Free(device, pool, span, *dld);
 | 
				
			||||||
 | 
					        // There's no way to report errors from a destructor.
 | 
				
			||||||
 | 
					        if (result != VK_SUCCESS) {
 | 
				
			||||||
 | 
					            std::terminate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::unique_ptr<AllocationType[]> allocations;
 | 
				
			||||||
 | 
					    std::size_t num = 0;
 | 
				
			||||||
 | 
					    VkDevice device = nullptr;
 | 
				
			||||||
 | 
					    PoolType pool = nullptr;
 | 
				
			||||||
 | 
					    const DeviceDispatch* dld = nullptr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using BufferView = Handle<VkBufferView, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using DebugCallback = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
 | 
				
			||||||
 | 
					using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using Framebuffer = Handle<VkFramebuffer, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using ImageView = Handle<VkImageView, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using RenderPass = Handle<VkRenderPass, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using Sampler = Handle<VkSampler, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using Semaphore = Handle<VkSemaphore, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using ShaderModule = Handle<VkShaderModule, VkDevice, DeviceDispatch>;
 | 
				
			||||||
 | 
					using SurfaceKHR = Handle<VkSurfaceKHR, VkInstance, InstanceDispatch>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using DescriptorSets = PoolAllocations<VkDescriptorSet, VkDescriptorPool>;
 | 
				
			||||||
 | 
					using CommandBuffers = PoolAllocations<VkCommandBuffer, VkCommandPool>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					} // namespace Vulkan::vk
 | 
				
			||||||
		Reference in New Issue
	
	Block a user