summaryrefslogtreecommitdiff
path: root/src/renderer/backends
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/backends')
-rw-r--r--src/renderer/backends/backend_vulkan.c143
-rw-r--r--src/renderer/backends/backend_vulkan.h11
2 files changed, 138 insertions, 16 deletions
diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c
index b66aeca..2502dd2 100644
--- a/src/renderer/backends/backend_vulkan.c
+++ b/src/renderer/backends/backend_vulkan.c
@@ -1,39 +1,109 @@
+#include <glfw3.h>
+#include <stdlib.h>
#include <vulkan/vk_platform.h>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
#include "backend_vulkan.h"
+#include "mem.h"
+#include "vulkan_helpers.h"
#include "defines.h"
#include "log.h"
#include "ral.h"
#include "ral_types.h"
+// TEMP
+#define SCREEN_WIDTH 1000
+#define SCREEN_HEIGHT 1000
+
#define VULKAN_QUEUES_COUNT 2
const char* queue_names[VULKAN_QUEUES_COUNT] = { "GRAPHICS", "TRANSFER" };
typedef struct vulkan_context {
- gpu_device device;
+ VkInstance instance;
VkAllocationCallbacks* allocator;
+ VkSurfaceKHR surface;
- VkInstance instance;
+ arena temp_arena;
+ gpu_device* device;
+ gpu_swapchain* swapchain;
+ u32 screen_width;
+ u32 screen_height;
} vulkan_context;
static vulkan_context context;
-static bool select_physical_device(gpu_device* out_device) {}
+// --- Function forward declarations
+
+/** @brief Enumerates and selects the most appropriate graphics device */
+bool select_physical_device(gpu_device* out_device);
+/** @brief Helper function for creating array of all extensions we want */
+cstr_darray* get_all_extensions();
+
+bool gpu_backend_init(const char* window_name, GLFWwindow* window) {
+ context.allocator = 0; // TODO: use an allocator
+ context.screen_width = SCREEN_WIDTH;
+ context.screen_height = SCREEN_HEIGHT;
+
+ // Create an allocator
+ size_t temp_arena_size = 1024 * 1024;
+ arena_create(malloc(temp_arena_size), temp_arena_size);
+
+ // Setup Vulkan instance
+ VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
+ app_info.apiVersion = VK_API_VERSION_1_3;
+ app_info.pApplicationName = window_name;
+ app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
+ app_info.pEngineName = "Celeritas Engine";
+ app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
+
+ VkInstanceCreateInfo create_info = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
+ create_info.pApplicationInfo = &app_info;
+
+ // Extensions
+ // FIXME: Use my own extension choices
+ // cstr_darray* required_extensions = cstr_darray_new(2);
+ // cstr_darray_push(required_extensions, VK_KHR_SURFACE_EXTENSION_NAME);
+ // create_info.enabledExtensionCount = cstr_darray_len(required_extensions);
+ // create_info.ppEnabledExtensionNames = required_extensions->data;
+ uint32_t count;
+ const char** extensions = glfwGetRequiredInstanceExtensions(&count);
+ create_info.enabledExtensionCount = count;
+ create_info.ppEnabledExtensionNames = extensions;
+
+ // TODO: Validation layers
+ create_info.enabledLayerCount = 0;
+ create_info.ppEnabledLayerNames = NULL;
+
+ VkResult result = vkCreateInstance(&create_info, NULL, &context.instance);
+ if (result != VK_SUCCESS) {
+ ERROR("vkCreateInstance failed with result: %u", result);
+ return false;
+ }
+ TRACE("Vulkan Instance created");
+
+ // Surface creation
+ VkSurfaceKHR surface;
+ VK_CHECK(glfwCreateWindowSurface(context.instance, window, NULL, &surface));
+ context.surface = surface;
+ TRACE("Vulkan Surface created");
-gpu_device gpu_device_create() {
- gpu_device device = { 0 };
+ return true;
+}
+
+void gpu_backend_shutdown() { arena_free_storage(&context.temp_arena); }
+
+bool gpu_device_create(gpu_device* out_device) {
// Physical device
- // if (!select_physical_device()) {
- // return false;
- // }
- INFO("Physical device selected");
+ if (!select_physical_device(out_device)) {
+ return false;
+ }
+ TRACE("Physical device selected");
// Features
- VkPhysicalDeviceFeatures device_features = {};
+ VkPhysicalDeviceFeatures device_features = { 0 };
device_features.samplerAnisotropy = VK_TRUE; // request anistrophy
// Logical device
@@ -47,20 +117,59 @@ gpu_device gpu_device_create() {
const char* extension_names = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
device_create_info.ppEnabledExtensionNames = &extension_names;
- VkResult result = vkCreateDevice(device.physical_device, &device_create_info, context.allocator,
- &device.logical_device);
+ VkResult result = vkCreateDevice(out_device->physical_device, &device_create_info,
+ context.allocator, &out_device->logical_device);
if (result != VK_SUCCESS) {
FATAL("Error creating logical device with status %u\n", result);
exit(1);
}
- INFO("Logical device created");
+ TRACE("Logical device created");
// Queues
// Create the command pool
- context.device = device;
- return device;
+ return true;
+}
+
+bool gpu_swapchain_create(gpu_swapchain* out_swapchain) {
+ VkExtent2D swapchain_extent = { context.screen_width, context.screen_height };
+
+ // find a format
+
+ VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; // guaranteed to be implemented
+
+ VkSwapchainCreateInfoKHR swapchain_create_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
+
+ // swapchain_create_info.minImageCount =
+
+ VK_CHECK(vkCreateSwapchainKHR(context.device->logical_device, &swapchain_create_info,
+ context.allocator, &out_swapchain->handle));
+ TRACE("Vulkan Swapchain created");
+}
+
+gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) {
+ VkViewport viewport = { .x = 0,
+ .y = 0,
+ .width = (f32)context.screen_width,
+ .height = (f32)context.screen_height,
+ .minDepth = 0.0,
+ .maxDepth = 1.0 };
+ VkRect2D scissor = { .offset = { .x = 0, .y = 0 },
+ .extent = { .width = context.screen_width,
+ .height = context.screen_height } };
+
+ // TODO: Attributes
+
+ // TODO: layouts
+
+ VkPipelineViewportStateCreateInfo viewport_state = {
+ VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
+ };
+ viewport_state.viewportCount = 1;
+ viewport_state.pViewports = &viewport;
+ viewport_state.scissorCount = 1;
+ viewport_state.pScissors = &scissor;
}
gpu_renderpass* gpu_renderpass_create() {
@@ -81,4 +190,6 @@ void encode_set_pipeline(gpu_cmd_encoder* encoder, gpu_pipeline* pipeline) {
// --- Drawing
inline void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count) {
vkCmdDrawIndexed(encoder->cmd_buffer, index_count, 1, 0, 0, 0);
-} \ No newline at end of file
+}
+
+bool select_physical_device(gpu_device* out_device) {} \ No newline at end of file
diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h
index 05f043e..dfe6a0f 100644
--- a/src/renderer/backends/backend_vulkan.h
+++ b/src/renderer/backends/backend_vulkan.h
@@ -1,9 +1,20 @@
#pragma once
+#include <vulkan/vk_platform.h>
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_core.h>
+
#include "defines.h"
#define GPU_SWAPCHAIN_IMG_COUNT 2
+/*
+Conventions:
+ - Place the 'handle' as the first field of a struct
+ - Vulkan specific data goes at the top, followed by our internal data
+*/
+
typedef struct gpu_swapchain {
+ VkSwapchainKHR handle;
} gpu_swapchain;
typedef struct gpu_device {
// In Vulkan we store both physical and logical device here