From df80f2cf0b851b527f715ebfe385dc4930a61512 Mon Sep 17 00:00:00 2001 From: omnisci3nce <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 23 Mar 2024 12:19:52 +1100 Subject: required extensions and validation layers --- src/std/containers/darray.h | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'src/std/containers/darray.h') diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index 25bf846..8eb00cb 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -39,15 +39,17 @@ /* } else {\ */ /* }\ */ -#define KITC_DECL_TYPED_ARRAY(T) \ - typedef typed_array(T) T##_darray; \ - typedef typed_array_iterator(T) T##_darray_iter; \ +#define KITC_DECL_TYPED_ARRAY(T) DECL_TYPED_ARRAY(T, T) + +#define DECL_TYPED_ARRAY(T, Type) \ + typedef typed_array(T) Type##_darray; \ + typedef typed_array_iterator(Type) Type##_darray_iter; \ \ /* Create a new one growable array */ \ - PREFIX T##_darray *T##_darray_new(size_t starting_capacity) { \ - T##_darray *d; \ + PREFIX Type##_darray *Type##_darray_new(size_t starting_capacity) { \ + Type##_darray *d; \ T *data; \ - d = malloc(sizeof(T##_darray)); \ + d = malloc(sizeof(Type##_darray)); \ data = malloc(starting_capacity * sizeof(T)); \ \ d->len = 0; \ @@ -57,14 +59,14 @@ return d; \ } \ \ - PREFIX void T##_darray_free(T##_darray *d) { \ + PREFIX void Type##_darray_free(Type##_darray *d) { \ if (d != NULL) { \ free(d->data); \ free(d); \ } \ } \ \ - PREFIX T *T##_darray_resize(T##_darray *d, size_t capacity) { \ + PREFIX T *Type##_darray_resize(Type##_darray *d, size_t capacity) { \ /* resize the internal data block */ \ T *new_data = realloc(d->data, sizeof(T) * capacity); \ /* TODO: handle OOM error */ \ @@ -74,22 +76,22 @@ return new_data; \ } \ \ - PREFIX void T##_darray_push(T##_darray *d, T value) { \ + PREFIX void Type##_darray_push(Type##_darray *d, T value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ d->data[d->len] = value; \ d->len += 1; \ } \ \ - PREFIX void T##_darray_push_copy(T##_darray *d, const T *value) { \ + PREFIX void Type##_darray_push_copy(Type##_darray *d, const T *value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ T *place = d->data + d->len; \ @@ -97,18 +99,18 @@ memcpy(place, value, sizeof(T)); \ } \ \ - PREFIX void T##_darray_pop(T##_darray *d, T *dest) { \ + PREFIX void Type##_darray_pop(Type##_darray *d, T *dest) { \ T *item = d->data + (d->len - 1); \ d->len -= 1; \ memcpy(dest, item, sizeof(T)); \ } \ \ - PREFIX void T##_darray_ins(T##_darray *d, const T *value, size_t index) { \ + PREFIX void Type##_darray_ins(Type##_darray *d, const T *value, size_t index) { \ /* check if requires resize */ \ if (d->len + 1 > d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = T##_darray_resize(d, new_capacity); \ + T *resized = Type##_darray_resize(d, new_capacity); \ } \ \ /* shift existing data after index */ \ @@ -122,14 +124,14 @@ memcpy(insert_dest, value, sizeof(T)); \ } \ \ - PREFIX void T##_darray_clear(T##_darray *d) { \ + PREFIX void Type##_darray_clear(Type##_darray *d) { \ d->len = 0; \ memset(d->data, 0, d->capacity * sizeof(T)); \ } \ \ - PREFIX size_t T##_darray_len(T##_darray *d) { return d->len; } \ + PREFIX size_t Type##_darray_len(Type##_darray *d) { return d->len; } \ \ - PREFIX void T##_darray_print(T##_darray *d) { \ + PREFIX void Type##_darray_print(Type##_darray *d) { \ printf("len: %zu ", d->len); \ printf("capacity: %zu\n", d->capacity); \ for (int i = 0; i < d->len; i++) { \ @@ -137,14 +139,14 @@ } \ } \ \ - PREFIX T##_darray_iter T##_darray_iter_new(T##_darray *d) { \ - T##_darray_iter iterator; \ + PREFIX Type##_darray_iter Type##_darray_iter_new(Type##_darray *d) { \ + Type##_darray_iter iterator; \ iterator.array = d; \ iterator.current_idx = 0; \ return iterator; \ } \ \ - PREFIX void *T##_darray_iter_next(T##_darray_iter *iterator) { \ + PREFIX void *Type##_darray_iter_next(Type##_darray_iter *iterator) { \ if (iterator->current_idx < iterator->array->len) { \ return &iterator->array->data[iterator->current_idx++]; \ } else { \ -- cgit v1.2.3-70-g09d2 From 8b9094ff517126ed102b79425e5fe4c67c589e47 Mon Sep 17 00:00:00 2001 From: omnisci3nce <17525998+omnisci3nce@users.noreply.github.com> Date: Sun, 24 Mar 2024 15:50:47 +1100 Subject: swapchain creation and main renderpass --- src/maths/maths.h | 2 + src/renderer/backends/backend_vulkan.c | 294 ++++++++++++++++++++++++++++++++- src/std/containers/darray.h | 4 + 3 files changed, 298 insertions(+), 2 deletions(-) (limited to 'src/std/containers/darray.h') diff --git a/src/maths/maths.h b/src/maths/maths.h index d832739..6816415 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -52,6 +52,8 @@ static inline vec3 vec3_cross(vec3 a, vec3 b) { static inline vec2 vec2_create(f32 x, f32 y) { return (vec2){ x, y }; } // TODO: Dimension 4 +static inline vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; } +#define vec4(x, y, z, w) (vec4_create(x, y, z, w)) #define VEC4_ZERO ((vec4){ .x = 0.0, .y = 0.0, .z = 0.0, .w = 0.0 }) // --- Quaternion Implementations diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 1f1f6f7..ba12696 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -1,4 +1,5 @@ #include +#include #define CEL_PLATFORM_LINUX #include #include @@ -10,6 +11,7 @@ #include "defines.h" #include "file.h" #include "log.h" +#include "maths.h" #include "maths_types.h" #include "render_backend.h" #include "render_types.h" @@ -17,6 +19,9 @@ #include +#define SCR_WIDTH 1080 +#define SCR_HEIGHT 800 + #if CEL_REND_BACKEND_VULKAN #include @@ -38,8 +43,35 @@ typedef struct vulkan_device { VkPhysicalDeviceProperties properties; VkPhysicalDeviceFeatures features; VkPhysicalDeviceMemoryProperties memory; + VkFormat depth_format; } vulkan_device; +typedef struct vulkan_image { + VkImage handle; + VkDeviceMemory memory; + VkImageView view; + u32 width; + u32 height; +} vulkan_image; + +typedef enum vulkan_renderpass_state { + READY, + RECORDING, + IN_RENDER_PASS, + RECORDING_ENDING, + SUBMITTED, + NOT_ALLOCATED +} vulkan_renderpass_state; + +typedef struct vulkan_renderpass { + VkRenderPass handle; + vec4 render_area; + vec4 clear_colour; + f32 depth; + u32 stencil; + vulkan_renderpass_state state; +} vulkan_renderpass; + typedef struct vulkan_swapchain { VkSurfaceFormatKHR image_format; u8 max_frames_in_flight; @@ -47,14 +79,29 @@ typedef struct vulkan_swapchain { u32 image_count; VkImage* images; VkImageView* views; + vulkan_image depth_attachment; } vulkan_swapchain; +typedef enum vulkan_command_buffer_state { + COMMAND_BUFFER_STATE_READY, + COMMAND_BUFFER_STATE_IN_RENDER_PASS, + COMMAND_BUFFER_STATE_RECORDING, +} vulkan_command_buffer_state; + +typedef struct vulkan_command_buffer { + VkCommandBuffer handle; + vulkan_command_buffer_state state; +} vulkan_command_buffer; + typedef struct vulkan_context { VkInstance instance; VkAllocationCallbacks* allocator; VkSurfaceKHR surface; vulkan_device device; + u32 framebuffer_width; + u32 framebuffer_height; vulkan_swapchain swapchain; + vulkan_renderpass main_renderpass; u32 image_index; u32 current_frame; @@ -215,6 +262,109 @@ void vulkan_device_destroy(vulkan_context* context) { // TODO: reset other memory } +bool vulkan_device_detect_depth_format(vulkan_device* device) { + const size_t n_candidates = 3; + VkFormat candidates[3] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, + VK_FORMAT_D24_UNORM_S8_UINT }; + u32 flags = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT; + for (u64 i = 0; i < n_candidates; i++) { + VkFormatProperties properties; + vkGetPhysicalDeviceFormatProperties(device->physical_device, candidates[i], &properties); + + if ((properties.linearTilingFeatures & flags) == flags) { + device->depth_format = candidates[i]; + return true; + } + if ((properties.optimalTilingFeatures & flags) == flags) { + device->depth_format = candidates[i]; + return true; + } + } + return false; +} + +void vulkan_image_view_create(vulkan_context* context, VkFormat format, vulkan_image* image, + VkImageAspectFlags aspect_flags) { + VkImageViewCreateInfo view_create_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_create_info.image = image->handle; + view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_create_info.format = format; + view_create_info.subresourceRange.aspectMask = aspect_flags; + + view_create_info.subresourceRange.baseMipLevel = 0; + view_create_info.subresourceRange.levelCount = 1; + view_create_info.subresourceRange.baseArrayLayer = 0; + view_create_info.subresourceRange.layerCount = 1; + + vkCreateImageView(context->device.logical_device, &view_create_info, context->allocator, + &image->view); +} + +void vulkan_image_create(vulkan_context* context, VkImageType image_type, u32 width, u32 height, + VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, + VkMemoryPropertyFlags memory_flags, bool create_view, + VkImageAspectFlags aspect_flags, vulkan_image* out_image) { + // copy params + out_image->width = width; + out_image->height = height; + + // create info + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = image_type; + image_create_info.extent.width = width; + image_create_info.extent.height = height; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 4; + image_create_info.arrayLayers = 1; + image_create_info.format = format; + image_create_info.tiling = tiling; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_create_info.usage = usage; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + vkCreateImage(context->device.logical_device, &image_create_info, context->allocator, + &out_image->handle); + + VkMemoryRequirements memory_reqs; + vkGetImageMemoryRequirements(context->device.logical_device, out_image->handle, &memory_reqs); + + i32 memory_type = -1; + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties(context->device.physical_device, &memory_properties); + + for (u32 i = 0; i < memory_properties.memoryTypeCount; i++) { + // typefilter = memoryTypeBits , prop filter = memory_flags + if (memory_reqs.memoryTypeBits & (1 << i) && + (memory_properties.memoryTypes[i].propertyFlags & memory_flags)) { + memory_type = i; + break; + } + } + + if (memory_type < 0) { + ERROR_EXIT("couldnt find a suitable memory type for the image"); + } + + // allocate memory + VkMemoryAllocateInfo memory_allocate_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + memory_allocate_info.allocationSize = memory_reqs.size; + memory_allocate_info.memoryTypeIndex = memory_type; + vkAllocateMemory(context->device.logical_device, &memory_allocate_info, context->allocator, + &out_image->memory); + + // bind memory + // TODO: maybe bind context->device.logical_device to device at the top of the functions? + vkBindImageMemory(context->device.logical_device, out_image->handle, out_image->memory, 0); + + if (create_view) { + out_image->view = 0; + vulkan_image_view_create(context, format, out_image, aspect_flags); + } +} + +// TODO: vulkan_image_destroy + void vulkan_swapchain_create(vulkan_context* context, u32 width, u32 height, vulkan_swapchain* out_swapchain) { VkExtent2D swapchain_extent = { width, height }; @@ -261,8 +411,9 @@ void vulkan_swapchain_create(vulkan_context* context, u32 width, u32 height, swapchain_create_info.clipped = VK_TRUE; swapchain_create_info.oldSwapchain = 0; - vkCreateSwapchainKHR(context->device.logical_device, &swapchain_create_info, context->allocator, - &out_swapchain->handle); + TRACE("Create swapchain"); + VK_CHECK(vkCreateSwapchainKHR(context->device.logical_device, &swapchain_create_info, + context->allocator, &out_swapchain->handle)); context->current_frame = 0; @@ -285,6 +436,7 @@ void vulkan_swapchain_create(vulkan_context* context, u32 width, u32 height, VkImageViewCreateInfo view_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; view_info.image = out_swapchain->images[i]; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = out_swapchain->image_format.format; view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; view_info.subresourceRange.baseMipLevel = 0; view_info.subresourceRange.levelCount = 1; @@ -294,6 +446,19 @@ void vulkan_swapchain_create(vulkan_context* context, u32 width, u32 height, VK_CHECK(vkCreateImageView(context->device.logical_device, &view_info, context->allocator, &out_swapchain->views[i])); } + + // depth attachment + if (!vulkan_device_detect_depth_format(&context->device)) { + ERROR_EXIT("Failed to find a supported depth format"); + } + vulkan_image_create(context, VK_IMAGE_TYPE_2D, swapchain_extent.width, swapchain_extent.height, + context->device.depth_format, VK_IMAGE_TILING_OPTIMAL, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, true, VK_IMAGE_ASPECT_DEPTH_BIT, + &out_swapchain->depth_attachment); + INFO("Depth attachment created"); + + INFO("Swapchain created successfully"); } // TODO: swapchain destroy @@ -335,6 +500,123 @@ void vulkan_swapchain_present(vulkan_context* context, vulkan_swapchain* swapcha } } +void vulkan_renderpass_create(vulkan_context* context, vulkan_renderpass* out_renderpass, + vec4 render_area, vec4 clear_colour, f32 depth, u32 stencil) { + // main subpass + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + + // attachments + u32 attachment_desc_count = 2; + VkAttachmentDescription attachment_descriptions[2]; + + // Colour attachment + VkAttachmentDescription color_attachment; + color_attachment.format = context->swapchain.image_format.format; + color_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + color_attachment.flags = 0; + + attachment_descriptions[0] = color_attachment; + + VkAttachmentReference color_attachment_reference; + color_attachment_reference.attachment = 0; + color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_attachment_reference; + + // Depth attachment + VkAttachmentDescription depth_attachment; + depth_attachment.format = context->device.depth_format; + depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT; + depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + depth_attachment.flags = 0; + + attachment_descriptions[1] = depth_attachment; + + VkAttachmentReference depth_attachment_reference; + depth_attachment_reference.attachment = 1; + depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + subpass.pDepthStencilAttachment = &depth_attachment_reference; + + // TODO: other attachment styles + + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = 0; + subpass.pResolveAttachments = 0; + subpass.preserveAttachmentCount = 0; + subpass.preserveAttachmentCount = 0; + + // renderpass dependencies + VkSubpassDependency dependency; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependency.dependencyFlags = 0; + + VkRenderPassCreateInfo render_pass_create_info = { VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO }; + render_pass_create_info.attachmentCount = attachment_desc_count; + render_pass_create_info.pAttachments = attachment_descriptions; + render_pass_create_info.subpassCount = 1; + render_pass_create_info.pSubpasses = &subpass; + render_pass_create_info.dependencyCount = 1; + render_pass_create_info.pDependencies = &dependency; + render_pass_create_info.pNext = 0; + render_pass_create_info.flags = 0; + + VK_CHECK(vkCreateRenderPass(context->device.logical_device, &render_pass_create_info, + context->allocator, &out_renderpass->handle)); +} + +// TODO: renderpass destroy + +void vulkan_renderpass_begin(vulkan_command_buffer* command_buffer, vulkan_renderpass* renderpass, + VkFramebuffer framebuffer) { + VkRenderPassBeginInfo begin_info = { VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO }; + begin_info.renderPass = renderpass->handle; + begin_info.framebuffer = framebuffer; + begin_info.renderArea.offset.x = renderpass->render_area.x; + begin_info.renderArea.offset.y = renderpass->render_area.y; + begin_info.renderArea.extent.width = renderpass->render_area.z; + begin_info.renderArea.extent.height = renderpass->render_area.w; + + VkClearValue clear_values[2]; + memset(&clear_values, 0, sizeof(VkClearValue) * 2); + clear_values[0].color.float32[0] = renderpass->clear_colour.x; + clear_values[0].color.float32[1] = renderpass->clear_colour.y; + clear_values[0].color.float32[2] = renderpass->clear_colour.z; + clear_values[0].color.float32[3] = renderpass->clear_colour.w; + clear_values[1].depthStencil.depth = renderpass->depth; + clear_values[1].depthStencil.stencil = renderpass->stencil; + + begin_info.clearValueCount = 2; + begin_info.pClearValues = clear_values; + + vkCmdBeginRenderPass(command_buffer->handle, &begin_info, VK_SUBPASS_CONTENTS_INLINE); + command_buffer->state = COMMAND_BUFFER_STATE_IN_RENDER_PASS; +} + +void vulkan_renderpass_end(vulkan_command_buffer* command_buffer, vulkan_renderpass* renderpass) { + vkCmdEndRenderPass(command_buffer->handle); + command_buffer->state = COMMAND_BUFFER_STATE_RECORDING; +} + bool gfx_backend_init(renderer* ren) { INFO("loading Vulkan backend"); @@ -449,6 +731,14 @@ bool gfx_backend_init(renderer* ren) { return false; } + // Swapchain creation + vulkan_swapchain_create(&context, SCR_WIDTH, SCR_HEIGHT, &context.swapchain); + + // Renderpass creation + vulkan_renderpass_create(&context, &context.main_renderpass, + vec4(0, 0, context.framebuffer_width, context.framebuffer_height), + vec4(0.0, 0.0, 0.2, 1.0), 1.0, 0); + INFO("Vulkan renderer initialisation succeeded"); return true; } diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index 8eb00cb..45d92e2 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -5,6 +5,10 @@ */ // COPIED FROM KITC WITH SOME MINOR ADJUSTMENTS +/* TODO: + - a 'find' function that takes a predicate (maybe wrap with a macro so we dont have to define a new function?) +*/ + #ifndef KITC_TYPED_ARRAY_H #define KITC_TYPED_ARRAY_H -- cgit v1.2.3-70-g09d2 From fe83372519e3ae8dd88ecfb4c67d484a1a5f13af Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:07:16 +1100 Subject: brainsforming refined layout for renderer --- assets/shaders/triangle.frag | 4 +-- assets/shaders/triangle.vert | 4 +-- src/maths/maths.h | 6 ++++ src/platform/file.c | 50 +++++++++++++-------------- src/platform/file.h | 6 ++-- src/renderer/backends/backend_vulkan.c | 15 +++----- src/renderer/cleanroom/README.md | 1 + src/renderer/cleanroom/types.h | 63 ++++++++++++++++++++++++++++++++++ src/renderer/render_types.h | 3 +- src/std/containers/darray.h | 3 +- 10 files changed, 109 insertions(+), 46 deletions(-) create mode 100644 src/renderer/cleanroom/README.md create mode 100644 src/renderer/cleanroom/types.h (limited to 'src/std/containers/darray.h') diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag index d26e5c4..44c1eb3 100644 --- a/assets/shaders/triangle.frag +++ b/assets/shaders/triangle.frag @@ -3,6 +3,4 @@ layout(location = 0) out vec4 out_colour; -void main() { - out_colour = vec4(1.0); -} \ No newline at end of file +void main() { out_colour = vec4(1.0); } \ No newline at end of file diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert index 0518c62..f253d9b 100644 --- a/assets/shaders/triangle.vert +++ b/assets/shaders/triangle.vert @@ -3,6 +3,4 @@ layout(location = 0) in vec3 in_position; -void main() { - gl_Position = vec4(in_position, 1.0); -} \ No newline at end of file +void main() { gl_Position = vec4(in_position, 1.0); } \ No newline at end of file diff --git a/src/maths/maths.h b/src/maths/maths.h index 6816415..db63072 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -236,3 +236,9 @@ typedef struct u32x3 { }; } u32x3; #define u32x3(x, y, z) ((u32x3){ x, y, z }) + +typedef struct u32x2 { + u32 x; + u32 y; +} u32x2; +#define u32x2(x, y) ((u32x3){ x, y }) \ No newline at end of file diff --git a/src/platform/file.c b/src/platform/file.c index ac5014d..6030620 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -63,31 +63,31 @@ str8_opt str8_from_file(arena *a, str8 path) { } FileData load_spv_file(const char *path) { - FILE *f = fopen(path, "rb"); - if (f == NULL) { - perror("Error opening file"); - return (FileData){NULL, 0}; - } - - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - rewind(f); - - char *data = (char *)malloc(fsize); - if (data == NULL) { - perror("Memory allocation failed"); - fclose(f); - return (FileData){NULL, 0}; - } - - size_t bytesRead = fread(data, 1, fsize, f); - if (bytesRead < fsize) { - perror("Failed to read the entire file"); - free(data); - fclose(f); - return (FileData){NULL, 0}; - } + FILE *f = fopen(path, "rb"); + if (f == NULL) { + perror("Error opening file"); + return (FileData){ NULL, 0 }; + } + + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + rewind(f); + char *data = (char *)malloc(fsize); + if (data == NULL) { + perror("Memory allocation failed"); fclose(f); - return (FileData){data, bytesRead}; + return (FileData){ NULL, 0 }; + } + + size_t bytesRead = fread(data, 1, fsize, f); + if (bytesRead < fsize) { + perror("Failed to read the entire file"); + free(data); + fclose(f); + return (FileData){ NULL, 0 }; + } + + fclose(f); + return (FileData){ data, bytesRead }; } \ No newline at end of file diff --git a/src/platform/file.h b/src/platform/file.h index 83d1317..a8aa8ea 100644 --- a/src/platform/file.h +++ b/src/platform/file.h @@ -19,8 +19,8 @@ const char* string_from_file(const char* path); str8_opt str8_from_file(arena* a, str8 path); typedef struct { - char *data; - size_t size; + char* data; + size_t size; } FileData; -FileData load_spv_file(const char *path); \ No newline at end of file +FileData load_spv_file(const char* path); \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index c57da9d..d78d4d2 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -173,20 +173,15 @@ typedef struct vulkan_state { } vulkan_state; // pipeline stuff -bool vulkan_graphics_pipeline_create( - vulkan_context* context, - vulkan_renderpass* renderpass, - u32 attribute_count, - VkVertexInputAttributeDescription* attributes, - // ... https://youtu.be/OmPmftW7Kjg?si=qn_777v_ppHKzswK&t=568 -) { - -} +bool vulkan_graphics_pipeline_create(vulkan_context* context, vulkan_renderpass* renderpass, + u32 attribute_count, + VkVertexInputAttributeDescription* attributes, + // ... https://youtu.be/OmPmftW7Kjg?si=qn_777v_ppHKzswK&t=568 +) {} bool create_shader_module(vulkan_context* context, const char* filename, const char* type_str, VkShaderStageFlagBits flag, u32 stage_index, vulkan_shader_stage* shader_stages) { - memset(&shader_stages[stage_index].create_info, 0, sizeof(VkShaderModuleCreateInfo)); memset(&shader_stages[stage_index].stage_create_info, 0, sizeof(VkPipelineShaderStageCreateInfo)); diff --git a/src/renderer/cleanroom/README.md b/src/renderer/cleanroom/README.md new file mode 100644 index 0000000..d510f16 --- /dev/null +++ b/src/renderer/cleanroom/README.md @@ -0,0 +1 @@ +# Cleanroom / Re-jig of the renderer structure \ No newline at end of file diff --git a/src/renderer/cleanroom/types.h b/src/renderer/cleanroom/types.h new file mode 100644 index 0000000..cd51fca --- /dev/null +++ b/src/renderer/cleanroom/types.h @@ -0,0 +1,63 @@ +#pragma once +#include "defines.h" + +typedef int texture_handle; +typedef int buffer_handle; +typedef int model_handle; + +/** @brief Texture Description - used by texture creation functions */ +typedef struct texture_desc { + // gpu_texture_type tex_type; + // gpu_texture_format format; + // u32x2 extents; +} texture_desc; + +/* + - render_types.h + - ral_types.h + - ral.h + - render.h ? +*/ + +/* render_types */ +typedef struct mesh mesh; +typedef struct model model; +typedef struct model pbr_material; +typedef struct model bp_material; // blinn-phong + +// Three registers +// 1. low level graphics api calls "ral" +// 2. higher level render calls +// 3. simplified immediate mode API + +/* render.h */ +// frontend -- these can be called from say a loop in an example, or via FFI +texture_handle texture_create(const char* debug_name, texture_desc description); +void texture_data_upload(texture_handle texture); +buffer_handle buffer_create(const char* debug_name, u64 size); + +// models and meshes are implemented **in terms of the above** +mesh mesh_create(); +model_handle model_load(const char* filepath); + +/* ral.h */ +// backend -- these are not seen by the higher-level code +void gpu_texture_init(); +void gpu_texture_upload(); +void gpu_buffer_init(); +void gpu_buffer_upload(); + +// command buffer gubbins + +// 3. SIMA (simplified immediate mode api) +// - dont need to worry about uploading mesh data +void debug_draw_cuboid(); +void debug_draw_sphere(); +void debug_draw_camera_frustum(); +static void imm_draw_model(const char* model_filepath); // tracks internally whether the model is loaded + +static void imm_draw_model(const char* model_filepath) { + // check that model is loaded + // if not loaded, load model and upload to gpu - LRU cache for models + // else submit draw call +} \ No newline at end of file diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 7bb6e60..2cc321c 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -8,6 +8,7 @@ #pragma once #include "darray.h" +#include "maths.h" #include "maths_types.h" #include "str.h" @@ -178,4 +179,4 @@ typedef enum gpu_texture_format { TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, TEXTURE_FORMAT_DEPTH_DEFAULT, TEXTURE_FORMAT_COUNT -} gpu_texture_format; +} gpu_texture_format; \ No newline at end of file diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index 45d92e2..b15d269 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -6,7 +6,8 @@ // COPIED FROM KITC WITH SOME MINOR ADJUSTMENTS /* TODO: - - a 'find' function that takes a predicate (maybe wrap with a macro so we dont have to define a new function?) + - a 'find' function that takes a predicate (maybe wrap with a macro so we dont have to define a + new function?) */ #ifndef KITC_TYPED_ARRAY_H -- cgit v1.2.3-70-g09d2