summaryrefslogtreecommitdiff
path: root/src/ral
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-07-19 09:56:36 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-07-19 09:56:36 +1000
commit0942a484a90695749f05d49273951f2b8d452866 (patch)
tree319aff81e879168b152505875e608aee26fed5ff /src/ral
parent01d598220b403f4ac4da3b7aa1f0ce398be3198f (diff)
merge
Diffstat (limited to 'src/ral')
-rw-r--r--src/ral/backends/vulkan/backend_vulkan.c0
-rw-r--r--src/ral/backends/vulkan/backend_vulkan.h44
-rw-r--r--src/ral/backends/vulkan/vulkan_glossary.md18
-rw-r--r--src/ral/backends/vulkan/vulkan_helpers.h199
-rw-r--r--src/ral/ral_impl.h9
5 files changed, 269 insertions, 1 deletions
diff --git a/src/ral/backends/vulkan/backend_vulkan.c b/src/ral/backends/vulkan/backend_vulkan.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ral/backends/vulkan/backend_vulkan.c
diff --git a/src/ral/backends/vulkan/backend_vulkan.h b/src/ral/backends/vulkan/backend_vulkan.h
index e69de29..790344b 100644
--- a/src/ral/backends/vulkan/backend_vulkan.h
+++ b/src/ral/backends/vulkan/backend_vulkan.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#ifdef CEL_REND_BACKEND_VULKAN
+#include "ral_impl.h"
+#include "defines.h"
+#include "maths_types.h"
+#include "ral.h"
+#include "ral_types.h"
+
+#include <vulkan/vk_platform.h>
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_core.h>
+
+// Provide definitions for RAL structs
+
+struct GPU_Swapchain {
+ VkSwapchainKHR handle;
+};
+
+struct GPU_Device {
+ VkPhysicalDevice physical_device;
+ VkDevice logical_device;
+};
+
+struct GPU_PipelineLayout {};
+ struct GPU_Pipeline {};
+ struct GPU_Renderpass {};
+ struct GPU_CmdEncoder {};
+ struct GPU_CmdBuffer {};
+ struct GPU_Buffer {
+ VkBuffer handle;
+ VkDeviceMemory memory;
+ u64 size;
+ };
+ struct GPU_Texture {
+ VkImage handle;
+ VkDeviceMemory memory;
+ u64 size;
+ VkImageView view;
+ VkSampler sampler;
+ char* debug_label;
+ };
+
+#endif
diff --git a/src/ral/backends/vulkan/vulkan_glossary.md b/src/ral/backends/vulkan/vulkan_glossary.md
new file mode 100644
index 0000000..4214f9d
--- /dev/null
+++ b/src/ral/backends/vulkan/vulkan_glossary.md
@@ -0,0 +1,18 @@
+# Vulkan Glossary
+
+*from https://vkguide.dev/docs/introduction/vulkan_execution/*
+
+- **VkInstance**: The Vulkan context, used to access drivers.
+- **VkPhysicalDevice**: A GPU. Used to query physical GPU details, like features, capabilities, memory size, etc.
+- **VkDevice**: The “logical” GPU context that you actually execute things on.
+- **VkBuffer**: A chunk of GPU visible memory.
+- **VkImage**: A texture you can write to and read from.
+- **VkPipeline**: Holds the state of the gpu needed to draw. For example: shaders, rasterization options, depth settings.
+- **VkRenderPass**: Holds information about the images you are rendering into. All drawing commands have to be done inside a renderpass. Only used in legacy vkguide.
+- **VkFrameBuffer**: Holds the target images for a renderpass. Only used in legacy vkguide.
+- **VkCommandBuffer**: Encodes GPU commands. All execution that is performed on the GPU itself (not in the driver) has to be encoded in a VkCommandBuffer.
+- **VkQueue**: Execution “port” for commands. GPUs will have a set of queues with different properties. Some allow only graphics commands, others only allow memory commands, etc. Command buffers are executed by submitting them into a queue, which will copy the rendering commands onto the GPU for execution.
+- **VkDescriptorSet**: Holds the binding information that connects shader inputs to data such as VkBuffer resources and VkImage textures. Think of it as a set of gpu-side pointers that you bind once.
+- **VkSwapchainKHR**: Holds the images for the screen. It allows you to render things into a visible window. The KHR suffix shows that it comes from an extension, which in this case is VK_KHR_swapchain.
+- **VkSemaphore**: Synchronizes GPU to GPU execution of commands. Used for syncing multiple command buffer submissions one after another.
+- **VkFence**: Synchronizes GPU to CPU execution of commands. Used to know if a command buffer has finished being executed on the GPU.
diff --git a/src/ral/backends/vulkan/vulkan_helpers.h b/src/ral/backends/vulkan/vulkan_helpers.h
new file mode 100644
index 0000000..23666c6
--- /dev/null
+++ b/src/ral/backends/vulkan/vulkan_helpers.h
@@ -0,0 +1,199 @@
+#pragma once
+
+#include <assert.h>
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_core.h>
+
+#include "darray.h"
+#include "defines.h"
+#include "log.h"
+#include "str.h"
+
+#define VULKAN_PHYS_DEVICE_MAX_EXTENSION_NAMES 36
+
+DECL_TYPED_ARRAY(const char*, cstr)
+
+static void plat_get_required_extension_names(cstr_darray* extensions) {
+#ifdef CEL_PLATFORM_LINUX
+ cstr_darray_push(extensions, "VK_KHR_xcb_surface");
+#endif
+}
+
+// TODO(omni): port to using internal assert functions
+#define VK_CHECK(vulkan_expr) \
+ do { \
+ VkResult res = vulkan_expr; \
+ if (res != VK_SUCCESS) { \
+ ERROR_EXIT("Vulkan error: %u (%s:%d)", res, __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+// TODO: typedef struct vk_debugger {} vk_debugger;
+
+typedef struct vulkan_physical_device_requirements {
+ bool graphics;
+ bool present;
+ bool compute;
+ bool transfer;
+ str8 device_ext_names[VULKAN_PHYS_DEVICE_MAX_EXTENSION_NAMES];
+ size_t device_ext_name_count;
+ bool sampler_anistropy;
+ bool discrete_gpu;
+} vulkan_physical_device_requirements;
+
+#define VULKAN_MAX_DEFAULT 32
+
+typedef struct vulkan_swapchain_support_info {
+ VkSurfaceCapabilitiesKHR capabilities;
+ VkSurfaceFormatKHR formats[VULKAN_MAX_DEFAULT];
+ u32 format_count;
+ VkPresentModeKHR present_modes[VULKAN_MAX_DEFAULT];
+ u32 mode_count;
+} vulkan_swapchain_support_info;
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags,
+ const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data);
+
+static void vulkan_device_query_swapchain_support(VkPhysicalDevice device, VkSurfaceKHR surface,
+ vulkan_swapchain_support_info* out_support_info) {
+ // TODO: add VK_CHECK to these calls!
+
+ // Surface capabilities
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &out_support_info->capabilities);
+
+ // Surface formats
+ vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &out_support_info->format_count,
+ 0); // Get number of formats
+ if (out_support_info->format_count > 0) {
+ vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &out_support_info->format_count,
+ out_support_info->formats);
+ }
+
+ // Present Modes
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &out_support_info->mode_count,
+ 0); // Get number of formats
+ if (out_support_info->mode_count > 0) {
+ vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &out_support_info->mode_count,
+ out_support_info->present_modes);
+ }
+}
+
+static VkSurfaceFormatKHR choose_swapchain_format(
+ vulkan_swapchain_support_info* swapchain_support) {
+ assert(swapchain_support->format_count > 0);
+ // find a format
+ for (u32 i = 0; i < swapchain_support->format_count; i++) {
+ VkSurfaceFormatKHR format = swapchain_support->formats[i];
+ if (format.format == VK_FORMAT_B8G8R8A8_SRGB &&
+ format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
+ return format;
+ }
+ }
+ return swapchain_support->formats[0];
+}
+
+// static bool physical_device_meets_requirements(
+// VkPhysicalDevice device, VkSurfaceKHR surface, const VkPhysicalDeviceProperties* properties,
+// const VkPhysicalDeviceFeatures* features,
+// const vulkan_physical_device_requirements* requirements,
+// vulkan_physical_device_queue_family_info* out_queue_info,
+// vulkan_swapchain_support_info* out_swapchain_support) {
+// // TODO: pass in an arena
+
+// out_queue_info->graphics_family_index = -1;
+// out_queue_info->present_family_index = -1;
+// out_queue_info->compute_family_index = -1;
+// out_queue_info->transfer_family_index = -1;
+
+// if (requirements->discrete_gpu) {
+// if (properties->deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
+// TRACE("Device is not a physical GPU. Skipping.");
+// return false;
+// }
+// }
+
+// u32 queue_family_count = 0;
+// vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, 0);
+// VkQueueFamilyProperties queue_families[queue_family_count];
+// vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families);
+
+// INFO("Graphics | Present | Compute | Transfer | Name");
+// u8 min_transfer_score = 255;
+// for (u32 i = 0; i < queue_family_count; i++) {
+// u8 current_transfer_score = 0;
+
+// // Graphics queue
+// if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+// out_queue_info->graphics_family_index = i;
+// current_transfer_score++;
+// }
+
+// // Compute queue
+// if (queue_families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+// out_queue_info->compute_family_index = i;
+// current_transfer_score++;
+// }
+
+// // Transfer queue
+// if (queue_families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
+// // always take the lowest score transfer index
+// if (current_transfer_score <= min_transfer_score) {
+// min_transfer_score = current_transfer_score;
+// out_queue_info->transfer_family_index = i;
+// }
+// }
+
+// // Present Queue
+// VkBool32 supports_present = VK_FALSE;
+// vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &supports_present);
+// if (supports_present) {
+// out_queue_info->present_family_index = i;
+// }
+// }
+
+// INFO(" %d | %d | %d | %d | %s",
+// out_queue_info->graphics_family_index != -1, out_queue_info->present_family_index != -1,
+// out_queue_info->compute_family_index != -1, out_queue_info->transfer_family_index != -1,
+// properties->deviceName);
+// TRACE("Graphics Family queue index: %d", out_queue_info->graphics_family_index);
+// TRACE("Present Family queue index: %d", out_queue_info->present_family_index);
+// TRACE("Compute Family queue index: %d", out_queue_info->compute_family_index);
+// TRACE("Transfer Family queue index: %d", out_queue_info->transfer_family_index);
+
+// if ((!requirements->graphics ||
+// (requirements->graphics && out_queue_info->graphics_family_index != -1))) {
+// INFO("Physical device meets our requirements! Proceed.");
+
+// vulkan_device_query_swapchain_support(
+// device, surface, out_swapchain_support
+
+// // TODO: error handling i.e. format count = 0 or present mode = 0
+
+// );
+// return true;
+// }
+
+// return false;
+// }
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vk_debug_callback(
+ VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags,
+ const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) {
+ switch (severity) {
+ default:
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ ERROR("%s", callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ WARN("%s", callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ INFO("%s", callback_data->pMessage);
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ TRACE("%s", callback_data->pMessage);
+ break;
+ }
+ return VK_FALSE;
+} \ No newline at end of file
diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h
index 9343962..7b40f28 100644
--- a/src/ral/ral_impl.h
+++ b/src/ral/ral_impl.h
@@ -77,4 +77,11 @@ PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, u64 index_count);
// --- Frame cycle
PUB bool GPU_Backend_BeginFrame();
-PUB void GPU_Backend_EndFrame(); \ No newline at end of file
+PUB void GPU_Backend_EndFrame();
+
+// Concrete implementation
+#if defined(CEL_REND_BACKEND_OPENGL)
+#include "backend_opengl.h"
+#elif defined(CEL_REND_BACKEND_VULKAN)
+#include "backend_vulkan.h"
+#endif