From 08d7e23fd5ed95953822a72ba11d4b6cd96b2846 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 11 May 2024 17:30:58 +1000 Subject: prototyping shader data --- examples/cube/ex_cube.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 examples/cube/ex_cube.c (limited to 'examples/cube/ex_cube.c') diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c new file mode 100644 index 0000000..71b7917 --- /dev/null +++ b/examples/cube/ex_cube.c @@ -0,0 +1,145 @@ +#include + +#include "buf.h" +#include "camera.h" +#include "core.h" +#include "file.h" +#include "log.h" +#include "maths.h" +#include "mem.h" +#include "ral.h" +#include "ral_types.h" +#include "render.h" + +extern core g_core; + +// Define the shader data +typedef struct mvp_uniforms { + mat4 model; + mat4 view; + mat4 projection; +} mvp_uniforms; + +shader_data_layout mvp_uniforms_layout(void* data) { + mvp_uniforms* d = (mvp_uniforms*)data; + bool has_data = data != NULL; + + shader_binding b1 = { + .label = "model", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + shader_binding b2 = { + .label = "view", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + shader_binding b3 = { + .label = "projection", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes = { .size = sizeof(mat4) }} + }; + if (has_data) { + b1.data.bytes.data = &d->model; + b2.data.bytes.data = &d->view; + b3.data.bytes.data = &d->projection; + } + return (shader_data_layout ){.name = "mvp_uniforms", .bindings = { + b1, b2, b3 + }}; +} + +int main() { + core_bringup(); + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); + + shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); + + mvp_uniforms mvp_data = { + .model = mat4_ident(), + .view = mat4_ident(), + .projection = mat4_ident() + }; + + shader_data mvp_uniforms_data = { + .data = &mvp_data, + .shader_data_get_layout = &mvp_uniforms_layout + }; + + gpu_renderpass_desc pass_description = {}; + gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); + + str8 vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); + str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); + str8_opt vertex_shader = str8_from_file(&scratch, vert_path); + str8_opt fragment_shader = str8_from_file(&scratch, frag_path); + if (!vertex_shader.has_value || !fragment_shader.has_value) { + ERROR_EXIT("Failed to load shaders from disk") + } + + struct graphics_pipeline_desc pipeline_description = { + .debug_name = "Basic Pipeline", + .vs = { .debug_name = "Triangle Vertex Shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = true }, + .fs = { .debug_name = "Triangle Fragment Shader", + .filepath = frag_path, + .code = fragment_shader.contents, + .is_spirv = true }, + .renderpass = renderpass, + .wireframe = false, + .depth_test = false + }; + gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); + + buffer_handle triangle_vert_buf = + gpu_buffer_create(sizeof(vertices), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); + + buffer_handle triangle_index_buf = + gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); + + // Main loop + while (!should_exit(&g_core)) { + glfwPollEvents(); + input_update(&g_core.input); + + // render_frame_begin(&g_core.renderer); + + if (!gpu_backend_begin_frame()) { + continue; + } + gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); + // begin recording + gpu_cmd_encoder_begin(*enc); + gpu_cmd_encoder_begin_render(enc, renderpass); + encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); + encode_set_default_settings(enc); + + // Record draw calls + encode_set_vertex_buffer(enc, triangle_vert_buf); + encode_set_index_buffer(enc, triangle_index_buf); + encode_bind_shader_data(enc, 0, &mvp_uniforms_data); + gpu_temp_draw(6); + + // End recording + gpu_cmd_encoder_end_render(enc); + + gpu_cmd_buffer buf = gpu_cmd_encoder_finish(enc); + gpu_queue_submit(&buf); + // Submit + gpu_backend_end_frame(); + + // render_frame_end(&g_core.renderer); + // glfwSwapBuffers(core->renderer.window); + } + + renderer_shutdown(&g_core.renderer); + + return 0; +} -- cgit v1.2.3-70-g09d2 From 677ab09b0dc3b6d9c872b732f8e31543fa2d11bb Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sat, 11 May 2024 22:06:55 +1000 Subject: WIP: shader data --- examples/cube/ex_cube.c | 62 +++++++----------- examples/triangle/ex_triangle.c | 2 + src/renderer/backends/backend_vulkan.c | 116 ++++++++++++++++++++++++++++++++- src/renderer/backends/backend_vulkan.h | 21 ++++++ src/renderer/ral.h | 13 ++++ src/renderer/ral_types.h | 15 +++++ src/renderer/render.h | 2 +- xmake.lua | 7 ++ 8 files changed, 199 insertions(+), 39 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 71b7917..699cf55 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -13,6 +13,14 @@ extern core g_core; +const custom_vertex vertices[] = { + (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, + (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, + (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, + (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, +}; +const u16 indices[] = { 0, 1, 2, 2, 3, 0 }; + // Define the shader data typedef struct mvp_uniforms { mat4 model; @@ -23,33 +31,15 @@ typedef struct mvp_uniforms { shader_data_layout mvp_uniforms_layout(void* data) { mvp_uniforms* d = (mvp_uniforms*)data; bool has_data = data != NULL; - - shader_binding b1 = { - .label = "model", - .type = SHADER_BINDING_BYTES, - .stores_data = has_data, - .data = {.bytes = { .size = sizeof(mat4) }} - }; - shader_binding b2 = { - .label = "view", - .type = SHADER_BINDING_BYTES, - .stores_data = has_data, - .data = {.bytes = { .size = sizeof(mat4) }} - }; - shader_binding b3 = { - .label = "projection", - .type = SHADER_BINDING_BYTES, - .stores_data = has_data, - .data = {.bytes = { .size = sizeof(mat4) }} - }; + + shader_binding b1 = { .label = "mvp_uniforms", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = { .bytes = { .size = sizeof(mvp_uniforms) } } }; if (has_data) { - b1.data.bytes.data = &d->model; - b2.data.bytes.data = &d->view; - b3.data.bytes.data = &d->projection; + b1.data.bytes.data = d; } - return (shader_data_layout ){.name = "mvp_uniforms", .bindings = { - b1, b2, b3 - }}; + return (shader_data_layout){ .name = "global_ubo", .bindings = { b1 } }; } int main() { @@ -58,18 +48,7 @@ int main() { DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); - shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); - - mvp_uniforms mvp_data = { - .model = mat4_ident(), - .view = mat4_ident(), - .projection = mat4_ident() - }; - - shader_data mvp_uniforms_data = { - .data = &mvp_data, - .shader_data_get_layout = &mvp_uniforms_layout - }; + shader_data mvp_uniforms_data = { .data = NULL, .shader_data_get_layout = &mvp_uniforms_layout }; gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); @@ -84,6 +63,8 @@ int main() { struct graphics_pipeline_desc pipeline_description = { .debug_name = "Basic Pipeline", + .data_layouts = { mvp_uniforms_data }, + .data_layouts_count = 1, .vs = { .debug_name = "Triangle Vertex Shader", .filepath = vert_path, .code = vertex_shader.contents, @@ -121,6 +102,13 @@ int main() { encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); encode_set_default_settings(enc); + /* shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); */ + + mvp_uniforms mvp_data = { .model = mat4_ident(), + .view = mat4_ident(), + .projection = mat4_ident() }; + mvp_uniforms_data.data = &mvp_data; + // Record draw calls encode_set_vertex_buffer(enc, triangle_vert_buf); encode_set_index_buffer(enc, triangle_index_buf); diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index c6f0e54..5d8f0cf 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -11,6 +11,7 @@ #include "ral.h" #include "ral_types.h" #include "render.h" +#include "render_types.h" extern core g_core; @@ -53,6 +54,7 @@ int main() { }; gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); + // Load triangle vertex and index data buffer_handle triangle_vert_buf = gpu_buffer_create(sizeof(vertices), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index dbae96e..c145c1a 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -25,8 +25,9 @@ // TEMP #define SCREEN_WIDTH 1000 #define SCREEN_HEIGHT 1000 -#define MAX_FRAMES_IN_FLIGHT 2 #define VULKAN_QUEUES_COUNT 2 +#define MAX_DESCRIPTOR_SETS 100 + const char* queue_names[VULKAN_QUEUES_COUNT] = { "GRAPHICS", "TRANSFER" }; typedef struct vulkan_context { @@ -78,6 +79,7 @@ queue_family_indices find_queue_families(VkPhysicalDevice device); bool create_logical_device(gpu_device* out_device); void create_swapchain_framebuffers(); void create_sync_objects(); +void create_descriptor_pools(); VkShaderModule create_shader_module(str8 spirv); @@ -494,6 +496,83 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip dynamic_state.dynamicStateCount = DYNAMIC_STATE_COUNT; dynamic_state.pDynamicStates = dynamic_states; + // Descriptor Set layouts + + VkDescriptorSetLayout* desc_set_layouts = + malloc(description.data_layouts_count * sizeof(VkDescriptorSetLayout)); + pipeline->desc_set_layouts = desc_set_layouts; + pipeline->desc_set_layouts_count = description.data_layouts_count; + pipeline->uniform_pointers = + malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); + + for (u32 i = 0; i < description.data_layouts_count; i++) { + shader_data_layout sdl = description.data_layouts[i].shader_data_get_layout(NULL); + + // NOTE: is using VLA generally ok? + VkDescriptorSetLayoutBinding desc_set_bindings[description.data_layouts_count]; + + // Bindings + for (u32 j = 0; j < sdl.bindings_count; j++) { + desc_set_bindings[j].binding = j; + desc_set_bindings[j].descriptorCount = 1; + switch (sdl.bindings[j].type) { + case SHADER_BINDING_BUFFER: + case SHADER_BINDING_BYTES: + desc_set_bindings[j].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + + u64 buffer_size = sdl.bindings[j].data.bytes.size; + VkDeviceSize uniform_buf_size = buffer_size; + // TODO: Create backing buffer + + VkBuffer buffers[MAX_FRAMES_IN_FLIGHT]; + VkDeviceMemory uniform_buf_memorys[MAX_FRAMES_IN_FLIGHT]; + void* uniform_buf_mem_mappings[MAX_FRAMES_IN_FLIGHT]; + // void* s? + for (size_t frame_i = 0; frame_i < MAX_FRAMES_IN_FLIGHT; frame_i++) { + buffer_handle uniform_buf_handle = + gpu_buffer_create(buffer_size, CEL_BUFFER_UNIFORM, CEL_BUFFER_FLAG_CPU, NULL); + buffers[frame_i] = context.buffers[uniform_buf_handle.raw].handle; + vkMapMemory(context.device->logical_device, uniform_buf_memorys[frame_i], 0, + uniform_buf_size, 0, &uniform_buf_mem_mappings[frame_i]); + } + + desc_set_uniform_buffer uniform_data; + memcpy(&uniform_data.buffers, &buffers, sizeof(buffers)); + memcpy(&uniform_data.uniform_buf_memorys, &uniform_buf_memorys, + sizeof(uniform_buf_memorys)); + memcpy(&uniform_data.uniform_buf_mem_mappings, &uniform_buf_mem_mappings, + sizeof(uniform_buf_mem_mappings)); + uniform_data.size = buffer_size; + + pipeline->uniform_pointers[j] = uniform_data; + + break; + default: + ERROR_EXIT("Unimplemented binding type!! in backend_vulkan"); + } + switch (sdl.bindings[j].vis) { + case VISIBILITY_VERTEX: + desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + break; + case VISIBILITY_FRAGMENT: + desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + break; + case VISIBILITY_COMPUTE: + WARN("Compute is not implemented yet"); + break; + } + } + + VkDescriptorSetLayoutCreateInfo desc_set_layout_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO + }; + desc_set_layout_info.bindingCount = sdl.bindings_count; + desc_set_layout_info.pBindings = desc_set_bindings; + + VK_CHECK(vkCreateDescriptorSetLayout(context.device->logical_device, &desc_set_layout_info, + context.allocator, &desc_set_layouts[i])); + } + // Layout VkPipelineLayoutCreateInfo pipeline_layout_create_info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO @@ -652,6 +731,18 @@ gpu_cmd_encoder gpu_cmd_encoder_create() { VK_CHECK(vkAllocateCommandBuffers(context.device->logical_device, &allocate_info, &encoder.cmd_buffer);); + VkDescriptorPoolSize uniform_pool_size; + uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uniform_pool_size.descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; + + VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + pool_info.poolSizeCount = 1; + pool_info.pPoolSizes = &uniform_pool_size; + pool_info.maxSets = 10000; + + VK_CHECK(vkCreateDescriptorPool(context.device->logical_device, &pool_info, context.allocator, + &encoder.descriptor_pool)); + return encoder; } void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) { @@ -698,7 +789,27 @@ gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) { // --- Binding void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline) { vkCmdBindPipeline(encoder->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); + encoder->pipeline = pipeline; +} + +void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) { + assert(data->data != NULL); + + // Update the local buffer + desc_set_uniform_buffer ubo = encoder->pipeline->uniform_pointers[group]; + memcpy(ubo.uniform_buf_mem_mappings[context.current_frame], data->data, ubo.size); + + VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; + alloc_info.descriptorPool =encoder->descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; + + VkDescriptorSet sets[1]; + VK_CHECK(vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, + sets)); + } + void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { gpu_buffer buffer = context.buffers[buf.raw]; VkBuffer vbs[] = { buffer.handle }; @@ -970,6 +1081,9 @@ VkShaderModule create_shader_module(str8 spirv) { return shader_module; } + +void create_descriptor_pools() {} + void create_swapchain_framebuffers() { WARN("Recreating framebuffers..."); u32 image_count = context.swapchain->image_count; diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 0b0a492..7bdf821 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -7,6 +7,7 @@ #include "ral.h" // #include "vulkan_helpers.h" +#define MAX_FRAMES_IN_FLIGHT 2 #define GPU_SWAPCHAIN_IMG_COUNT 2 /* @@ -59,9 +60,26 @@ typedef struct gpu_pipeline_layout { VkPipelineLayout handle; } gpu_pipeline_layout; +typedef struct desc_set_uniform_buffer { + VkBuffer buffers[MAX_FRAMES_IN_FLIGHT]; + VkDeviceMemory uniform_buf_memorys[MAX_FRAMES_IN_FLIGHT]; + void* uniform_buf_mem_mappings[MAX_FRAMES_IN_FLIGHT]; + size_t size; +} desc_set_uniform_buffer; + typedef struct gpu_pipeline { VkPipeline handle; VkPipelineLayout layout_handle; + + // Descriptor gubbins + shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; + u32 data_layouts_count; + + VkDescriptorSetLayout* desc_set_layouts; + // Based on group, we know which data to load + desc_set_uniform_buffer* uniform_pointers; + u32 desc_set_layouts_count; + } gpu_pipeline; typedef struct gpu_renderpass { @@ -71,6 +89,8 @@ typedef struct gpu_renderpass { typedef struct gpu_cmd_encoder { VkCommandBuffer cmd_buffer; + VkDescriptorPool descriptor_pool; + gpu_pipeline* pipeline; } gpu_cmd_encoder; typedef struct gpu_cmd_buffer { @@ -82,3 +102,4 @@ typedef struct gpu_buffer { VkDeviceMemory memory; u64 size; } gpu_buffer; + diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 38a653d..0df23ea 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -30,6 +30,8 @@ typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer gpu_buffer; +#define MAX_SHADER_DATA_LAYOUTS 5 + /** @brief A*/ // typedef struct gpu_bind_group @@ -54,6 +56,17 @@ struct graphics_pipeline_desc { const char* debug_name; shader_desc vs; /** @brief Vertex shader stage */ shader_desc fs; /** @brief Fragment shader stage */ + + /* shader_data_layout data_layouts[MAX_SHADER_DATA_LAYOUTS]; */ + /* u32 data_layouts_count; */ + + // Roughly equivalent to a descriptor set layout each. each layout can have multiple bindings + // examples: + // - uniform buffer reprensenting view projection matrix + // - texture for shadow map ? + shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; + u32 data_layouts_count; + // gpu_pipeline_layout* layout; gpu_renderpass* renderpass; diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 230afc3..e7863a9 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -59,6 +59,7 @@ typedef enum gpu_buffer_type { CEL_BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? CEL_BUFFER_VERTEX, CEL_BUFFER_INDEX, + CEL_BUFFER_UNIFORM, CEL_BUFFER_COUNT } gpu_buffer_type; @@ -75,6 +76,7 @@ typedef enum vertex_format { VERTEX_SPRITE, VERTEX_SKINNED, VERTEX_COLOURED_STATIC_3D, + VERTEX_RAW_POS_COLOUR, VERTEX_COUNT } vertex_format; @@ -106,6 +108,11 @@ typedef union vertex { vec3 normal; vec4 colour; } coloured_static_3d; /** @brief vertex format used for debugging */ + + struct { + vec2 position; + vec3 colour; + } raw_pos_colour; } vertex; #ifndef TYPED_VERTEX_ARRAY @@ -136,6 +143,12 @@ typedef enum vertex_attrib_type { ATTR_I32x4, } vertex_attrib_type; +typedef enum shader_visibility { + VISIBILITY_VERTEX = 1 << 0, + VISIBILITY_FRAGMENT = 1 << 1 , + VISIBILITY_COMPUTE = 1 << 2, +} shader_visibility; + typedef enum shader_binding_type { SHADER_BINDING_BUFFER, SHADER_BINDING_TEXTURE, @@ -146,6 +159,7 @@ typedef enum shader_binding_type { typedef struct shader_binding { const char* label; shader_binding_type type; + shader_visibility vis; bool stores_data; /** @brief if this is true then the shader binding has references to live data, if false then its just being used to describe a layout and .data should be zeroed */ @@ -168,6 +182,7 @@ typedef struct shader_binding { typedef struct shader_data_layout { char* name; shader_binding bindings[MAX_LAYOUT_BINDINGS]; + u32 bindings_count; } shader_data_layout; typedef struct shader_data { diff --git a/src/renderer/render.h b/src/renderer/render.h index e6dd8b8..c690e80 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -43,4 +43,4 @@ mesh mesh_create(geometry_data* geometry); model_handle model_load(const char* debug_name, const char* filepath); -void geo_set_vertex_colours(geometry_data* geo, vec4 colour); \ No newline at end of file +void geo_set_vertex_colours(geometry_data* geo, vec4 colour); diff --git a/xmake.lua b/xmake.lua index 882535d..7ebd63d 100644 --- a/xmake.lua +++ b/xmake.lua @@ -157,6 +157,13 @@ target("tri") add_files("examples/triangle/ex_triangle.c") set_rundir("$(projectdir)") +target("cube") + set_kind("binary") + set_group("examples") + add_deps("core_static") + add_files("examples/cube/ex_cube.c") + set_rundir("$(projectdir)") + -- target("std") -- set_kind("binary") -- set_group("examples") -- cgit v1.2.3-70-g09d2 From d52d39d7843ed2203b001a822efe6d4b692c2642 Mon Sep 17 00:00:00 2001 From: Omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sun, 12 May 2024 12:31:24 +1000 Subject: uniforms working with hardcoded stuff --- assets/shaders/cube.frag | 0 assets/shaders/cube.vert | 18 ++++++++ examples/cube/ex_cube.c | 16 ++++--- src/renderer/backends/backend_vulkan.c | 76 ++++++++++++++++++++++++++++------ src/renderer/backends/vulkan_helpers.h | 2 +- xmake.lua | 1 + 6 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 assets/shaders/cube.frag create mode 100644 assets/shaders/cube.vert (limited to 'examples/cube/ex_cube.c') diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag new file mode 100644 index 0000000..e69de29 diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert new file mode 100644 index 0000000..80ad854 --- /dev/null +++ b/assets/shaders/cube.vert @@ -0,0 +1,18 @@ +#version 450 + +layout(binding = 0) uniform UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +} +ubo; + +layout(location = 0) in vec2 inPosition; +layout(location = 1) in vec3 inColor; + +layout(location = 0) out vec3 fragColor; + +void main() { + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); + fragColor = inColor; +} diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 699cf55..712485c 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -6,6 +6,7 @@ #include "file.h" #include "log.h" #include "maths.h" +#include "maths_types.h" #include "mem.h" #include "ral.h" #include "ral_types.h" @@ -39,7 +40,10 @@ shader_data_layout mvp_uniforms_layout(void* data) { if (has_data) { b1.data.bytes.data = d; } - return (shader_data_layout){ .name = "global_ubo", .bindings = { b1 } }; + /* char* name; */ + /* shader_binding bindings[MAX_LAYOUT_BINDINGS]; */ + /* u32 bindings_count; */ + return (shader_data_layout){ .name = "global_ubo", .bindings = { b1 }, .bindings_count = 1 }; } int main() { @@ -53,7 +57,7 @@ int main() { gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); - str8 vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); + str8 vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv"); str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); str8_opt vertex_shader = str8_from_file(&scratch, vert_path); str8_opt fragment_shader = str8_from_file(&scratch, frag_path); @@ -104,9 +108,11 @@ int main() { /* shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); */ - mvp_uniforms mvp_data = { .model = mat4_ident(), - .view = mat4_ident(), - .projection = mat4_ident() }; + static f32 x = 0.0; + x += 0.01; + quat rotation = quat_from_axis_angle(VEC3_Z, x, true); + mat4 model = mat4_rotation(rotation); + mvp_uniforms mvp_data = { .model = model, .view = mat4_ident(), .projection = mat4_ident() }; mvp_uniforms_data.data = &mvp_data; // Record draw calls diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index c145c1a..a845ebf 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -10,6 +10,7 @@ #include "backend_vulkan.h" #include "buf.h" +#include "darray.h" #include "maths_types.h" #include "mem.h" #include "ral_types.h" @@ -26,10 +27,12 @@ #define SCREEN_WIDTH 1000 #define SCREEN_HEIGHT 1000 #define VULKAN_QUEUES_COUNT 2 -#define MAX_DESCRIPTOR_SETS 100 +#define MAX_DESCRIPTOR_SETS 10 const char* queue_names[VULKAN_QUEUES_COUNT] = { "GRAPHICS", "TRANSFER" }; +KITC_DECL_TYPED_ARRAY(VkDescriptorSet) + typedef struct vulkan_context { VkInstance instance; VkAllocationCallbacks* allocator; @@ -61,6 +64,7 @@ typedef struct vulkan_context { // Storage gpu_buffer buffers[1024]; size_t buffer_count; + VkDescriptorSet_darray* free_set_queue; VkDebugUtilsMessengerEXT vk_debugger; } vulkan_context; @@ -94,6 +98,7 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { context.window = window; context.current_img_index = 0; context.current_frame = 0; + context.free_set_queue = VkDescriptorSet_darray_new(100); // Create an allocator size_t temp_arena_size = 1024 * 1024; @@ -505,6 +510,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip pipeline->uniform_pointers = malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); + assert(description.data_layouts_count == 1); for (u32 i = 0; i < description.data_layouts_count; i++) { shader_data_layout sdl = description.data_layouts[i].shader_data_get_layout(NULL); @@ -512,6 +518,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip VkDescriptorSetLayoutBinding desc_set_bindings[description.data_layouts_count]; // Bindings + assert(sdl.bindings_count == 1); for (u32 j = 0; j < sdl.bindings_count; j++) { desc_set_bindings[j].binding = j; desc_set_bindings[j].descriptorCount = 1; @@ -519,6 +526,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip case SHADER_BINDING_BUFFER: case SHADER_BINDING_BYTES: desc_set_bindings[j].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // FIXME: dont hardcode u64 buffer_size = sdl.bindings[j].data.bytes.size; VkDeviceSize uniform_buf_size = buffer_size; @@ -531,9 +539,12 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip for (size_t frame_i = 0; frame_i < MAX_FRAMES_IN_FLIGHT; frame_i++) { buffer_handle uniform_buf_handle = gpu_buffer_create(buffer_size, CEL_BUFFER_UNIFORM, CEL_BUFFER_FLAG_CPU, NULL); - buffers[frame_i] = context.buffers[uniform_buf_handle.raw].handle; + gpu_buffer created_gpu_buffer = context.buffers[uniform_buf_handle.raw]; + buffers[frame_i] = created_gpu_buffer.handle; + uniform_buf_memorys[frame_i] = created_gpu_buffer.memory; vkMapMemory(context.device->logical_device, uniform_buf_memorys[frame_i], 0, uniform_buf_size, 0, &uniform_buf_mem_mappings[frame_i]); + // now we have a pointer in unifrom_buf_mem_mappings we can write to } desc_set_uniform_buffer uniform_data; @@ -577,8 +588,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip VkPipelineLayoutCreateInfo pipeline_layout_create_info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - pipeline_layout_create_info.setLayoutCount = 0; - pipeline_layout_create_info.pSetLayouts = NULL; + pipeline_layout_create_info.setLayoutCount = description.data_layouts_count; + pipeline_layout_create_info.pSetLayouts = desc_set_layouts; pipeline_layout_create_info.pushConstantRangeCount = 0; pipeline_layout_create_info.pPushConstantRanges = NULL; VK_CHECK(vkCreatePipelineLayout(context.device->logical_device, &pipeline_layout_create_info, @@ -733,12 +744,12 @@ gpu_cmd_encoder gpu_cmd_encoder_create() { VkDescriptorPoolSize uniform_pool_size; uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniform_pool_size.descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; + uniform_pool_size.descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; pool_info.poolSizeCount = 1; pool_info.pPoolSizes = &uniform_pool_size; - pool_info.maxSets = 10000; + pool_info.maxSets = 100; VK_CHECK(vkCreateDescriptorPool(context.device->logical_device, &pool_info, context.allocator, &encoder.descriptor_pool)); @@ -751,6 +762,8 @@ void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder) { } void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder) { + VK_CHECK(vkResetDescriptorPool(context.device->logical_device, encoder.descriptor_pool, 0)); + VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; VK_CHECK(vkBeginCommandBuffer(encoder.cmd_buffer, &begin_info)); } @@ -782,6 +795,7 @@ void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder) { gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder) { vkEndCommandBuffer(encoder->cmd_buffer); + // TEMP: submit return (gpu_cmd_buffer){ .cmd_buffer = encoder->cmd_buffer }; } @@ -800,14 +814,50 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d memcpy(ubo.uniform_buf_mem_mappings[context.current_frame], data->data, ubo.size); VkDescriptorSetAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO }; - alloc_info.descriptorPool =encoder->descriptor_pool; + alloc_info.descriptorPool = encoder->descriptor_pool; alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; + alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; + + VkDescriptorSet sets[1]; + /* VK_CHECK( */ + vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets); + /* ); */ + VkDescriptorSet_darray_push(context.free_set_queue, sets[0]); + + shader_data_layout sdl = data->shader_data_get_layout(NULL); + assert(sdl.bindings_count == 1); + + VkWriteDescriptorSet write_sets[1]; + memset(&write_sets, 0, sizeof(write_sets)); + + assert(sdl.bindings_count == 1); + for (u32 i = 0; i < sdl.bindings_count; i++) { + shader_binding binding = sdl.bindings[i]; + + if (binding.type == SHADER_BINDING_BUFFER || binding.type == SHADER_BINDING_BYTES) { + VkDescriptorBufferInfo buffer_info; + buffer_info.buffer = ubo.buffers[context.current_frame]; + buffer_info.offset = 0; + buffer_info.range = binding.data.bytes.size; + + write_sets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_sets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_sets[0].descriptorCount = 1; + write_sets[0].dstSet = sets[0]; + write_sets[0].dstBinding = 0; + write_sets[0].dstArrayElement = 0; + write_sets[0].pBufferInfo = &buffer_info; + } else { + WARN("Unknown binding"); + } + } - VkDescriptorSet sets[1]; - VK_CHECK(vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, - sets)); + // Update + vkUpdateDescriptorSets(context.device->logical_device, 1, write_sets, 0, NULL); + // Bind + vkCmdBindDescriptorSets(encoder->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + encoder->pipeline->layout_handle, 0, 1, sets, 0, NULL); } void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { @@ -1081,7 +1131,6 @@ VkShaderModule create_shader_module(str8 spirv) { return shader_module; } - void create_descriptor_pools() {} void create_swapchain_framebuffers() { @@ -1155,6 +1204,9 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f case CEL_BUFFER_INDEX: buffer_info.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; break; + case CEL_BUFFER_UNIFORM: + buffer_info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; + break; case CEL_BUFFER_COUNT: WARN("Incorrect gpu_buffer_type provided. using default"); break; diff --git a/src/renderer/backends/vulkan_helpers.h b/src/renderer/backends/vulkan_helpers.h index aa43c62..db9b5a4 100644 --- a/src/renderer/backends/vulkan_helpers.h +++ b/src/renderer/backends/vulkan_helpers.h @@ -24,7 +24,7 @@ static void plat_get_required_extension_names(cstr_darray* extensions) { do { \ VkResult res = vulkan_expr; \ if (res != VK_SUCCESS) { \ - ERROR_EXIT("Vulkan error: %u", res); \ + ERROR_EXIT("Vulkan error: %u (%s:%d)", res, __FILE__, __LINE__); \ } \ } while (0) diff --git a/xmake.lua b/xmake.lua index 7ebd63d..f1b648b 100644 --- a/xmake.lua +++ b/xmake.lua @@ -114,6 +114,7 @@ target("core_config") add_rules("compile_glsl_frag_shaders") add_files("assets/shaders/triangle.vert") add_files("assets/shaders/triangle.frag") + add_files("assets/shaders/cube.vert") -- add_files("assets/shaders/*.frag") if is_plat("windows") then add_includedirs("$(env VULKAN_SDK)/Include", {public = true}) -- cgit v1.2.3-70-g09d2 From 634f22e2b6d538fc5a45da2b1b23af631f6f8703 Mon Sep 17 00:00:00 2001 From: omniscient <17525998+omnisci3nce@users.noreply.github.com> Date: Sun, 12 May 2024 15:07:57 +1000 Subject: more restructuring --- examples/cube/ex_cube.c | 5 + src/maths/primitives.c | 265 +++++++++++++++++---------------- src/physics/broadphase.h | 10 ++ src/physics/collision.h | 30 ++++ src/physics/narrowphase.h | 10 ++ src/physics/physics.c | 1 + src/physics/physics.h | 23 +++ src/renderer/backends/backend_vulkan.c | 7 +- src/renderer/backends/metal/README.md | 1 + src/renderer/backends/opengl/README.md | 1 + src/renderer/backends/vulkan/README.md | 1 + src/renderer/ral.h | 4 + src/renderer/ral_types.h | 32 +++- src/renderer/render.h | 2 + src/renderer/standard_vertex_types.c | 11 ++ src/systems/physics.c | 1 - src/systems/physics.h | 41 ----- xmake.lua | 2 + 18 files changed, 274 insertions(+), 173 deletions(-) create mode 100644 src/physics/broadphase.h create mode 100644 src/physics/collision.h create mode 100644 src/physics/narrowphase.h create mode 100644 src/physics/physics.c create mode 100644 src/physics/physics.h create mode 100644 src/renderer/backends/metal/README.md create mode 100644 src/renderer/backends/opengl/README.md create mode 100644 src/renderer/backends/vulkan/README.md create mode 100644 src/renderer/standard_vertex_types.c delete mode 100644 src/systems/physics.c delete mode 100644 src/systems/physics.h (limited to 'examples/cube/ex_cube.c') diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 712485c..a115fe3 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -52,6 +52,10 @@ int main() { DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); + vertex_description vertex_input = {0}; + vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x2); + vertex_desc_add(&vertex_input, "inColor", ATTR_F32x3); + shader_data mvp_uniforms_data = { .data = NULL, .shader_data_get_layout = &mvp_uniforms_layout }; gpu_renderpass_desc pass_description = {}; @@ -67,6 +71,7 @@ int main() { struct graphics_pipeline_desc pipeline_description = { .debug_name = "Basic Pipeline", + .vertex_desc = vertex_input, .data_layouts = { mvp_uniforms_data }, .data_layouts_count = 1, .vs = { .debug_name = "Triangle Vertex Shader", diff --git a/src/maths/primitives.c b/src/maths/primitives.c index 310fc98..459a535 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -1,5 +1,6 @@ #include "primitives.h" #include "maths.h" +#include "ral_types.h" // vertices f32 plane_vertex_positions[] = { @@ -30,136 +31,148 @@ static const vec3 FRONT_BOT_RIGHT = (vec3){ 1, 0, 1 }; static const vec3 FRONT_TOP_LEFT = (vec3){ 0, 1, 1 }; static const vec3 FRONT_TOP_RIGHT = (vec3){ 1, 1, 1 }; +#define VERT_3D(arr, pos, norm, uv) \ + { \ + vertex v = { + .static_3d = { \ + .position = pos, \ + .normal = norm, \ + .tex_coords = uv \ + }}; \ + vertex_darray_push(arr, v); \ + } + static mesh prim_cube_mesh_create() { mesh cube = { 0 }; cube.vertices = vertex_darray_new(36); - // // back faces - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); - - // // front faces - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); - - // // top faces - // vertex_darray_push(cube.vertices, - // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 - // } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push(cube.vertices, - // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 - // } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 0 } }); - - // // bottom faces - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - - // // right faces - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 1 } }); - - // // left faces - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - - // cube.indices_len = cube.vertices->len; - // cube.indices = malloc(sizeof(u32) * cube.indices_len); - - // for (u32 i = 0; i < cube.indices_len; i++) { - // cube.indices[i] = i; - // } + // back faces + VERT_3D(cube.vertices, BACK_BOT_LEFT, VEC3_NEG_Z, (vec2){ 0, 1 })) + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 0 } }); + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 1 } }); + // vertex_darray_push( + // cube.vertices, + // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); + + // front faces + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); + + // top faces + vertex_darray_push(cube.vertices, + (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 + } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); + vertex_darray_push(cube.vertices, + (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 + } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 0 } }); + + // bottom faces + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); + + // right faces + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 1 } }); + + // left faces + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + vertex_darray_push( + cube.vertices, + (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); + + cube.indices_len = cube.vertices->len; + cube.indices = malloc(sizeof(u32) * cube.indices_len); + + for (u32 i = 0; i < cube.indices_len; i++) { + cube.indices[i] = i; + } cube.has_indices = true; diff --git a/src/physics/broadphase.h b/src/physics/broadphase.h new file mode 100644 index 0000000..43b57f6 --- /dev/null +++ b/src/physics/broadphase.h @@ -0,0 +1,10 @@ +/** + * @file broadphase.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-05-12 + * + * @copyright Copyright (c) 2024 + * + */ \ No newline at end of file diff --git a/src/physics/collision.h b/src/physics/collision.h new file mode 100644 index 0000000..3b65b1b --- /dev/null +++ b/src/physics/collision.h @@ -0,0 +1,30 @@ +/** + * @file collision.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-05-12 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once +#include "geometry.h" + + enum collider_type { + cuboid_collider, + sphere_collider, +}; + +/** @brief generic collider structure */ +typedef struct physics_collider { + u64 id; // ? Replace with handle? + enum collider_type shape; + union collider_data { + cuboid cuboid; + sphere sphere; + } geometry; + transform transform; + u8 layer; + bool on_ground; +} physics_collider; \ No newline at end of file diff --git a/src/physics/narrowphase.h b/src/physics/narrowphase.h new file mode 100644 index 0000000..501c690 --- /dev/null +++ b/src/physics/narrowphase.h @@ -0,0 +1,10 @@ +/** + * @file narrowphase.h + * @author your name (you@domain.com) + * @brief + * @version 0.1 + * @date 2024-05-12 + * + * @copyright Copyright (c) 2024 + * + */ \ No newline at end of file diff --git a/src/physics/physics.c b/src/physics/physics.c new file mode 100644 index 0000000..299c0c1 --- /dev/null +++ b/src/physics/physics.c @@ -0,0 +1 @@ +#include "physics.h" \ No newline at end of file diff --git a/src/physics/physics.h b/src/physics/physics.h new file mode 100644 index 0000000..e0e3b89 --- /dev/null +++ b/src/physics/physics.h @@ -0,0 +1,23 @@ +#pragma once + +#include "geometry.h" +#include "maths_types.h" + +// 'system' means that it gets called per frame + +typedef struct physics_settings { + f32 gravity_strength; +} physics_settings; + +// What else do I need? +// intersection methods + +typedef struct physics_world { + physics_settings settings; +} physics_world; + +physics_world physics_init(physics_settings settings); +void physics_shutdown(physics_world* phys_world); + +/** @brief perform one or more simulation steps */ +void physics_system_update(physics_world* phys_world, f64 deltatime); \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index a845ebf..f83ef84 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -393,6 +393,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip attribute_descs[1].offset = offsetof(custom_vertex, color); // Vertex input + // TODO: Generate this from descroiption now VkVertexInputBindingDescription binding_desc; binding_desc.binding = 0; binding_desc.stride = sizeof(custom_vertex); @@ -819,9 +820,9 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; VkDescriptorSet sets[1]; - /* VK_CHECK( */ - vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets); - /* ); */ + VK_CHECK( + vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets) + ); VkDescriptorSet_darray_push(context.free_set_queue, sets[0]); shader_data_layout sdl = data->shader_data_get_layout(NULL); diff --git a/src/renderer/backends/metal/README.md b/src/renderer/backends/metal/README.md new file mode 100644 index 0000000..f87f5c1 --- /dev/null +++ b/src/renderer/backends/metal/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/src/renderer/backends/opengl/README.md b/src/renderer/backends/opengl/README.md new file mode 100644 index 0000000..f87f5c1 --- /dev/null +++ b/src/renderer/backends/opengl/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/src/renderer/backends/vulkan/README.md b/src/renderer/backends/vulkan/README.md new file mode 100644 index 0000000..220ed64 --- /dev/null +++ b/src/renderer/backends/vulkan/README.md @@ -0,0 +1 @@ +# Vulkan Backend Overview \ No newline at end of file diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 0df23ea..30d5413 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -54,6 +54,7 @@ typedef struct shader_desc { struct graphics_pipeline_desc { const char* debug_name; + vertex_description vertex_desc; shader_desc vs; /** @brief Vertex shader stage */ shader_desc fs; /** @brief Fragment shader stage */ @@ -150,8 +151,11 @@ void gpu_sampler_create(); // --- Vertex formats bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* vertices); +void vertex_desc_add(vertex_description* builder, const char* name, vertex_attrib_type type); + // TODO: Bindgroup texture samplers / shader resources // TEMP void gpu_temp_draw(size_t n_verts); + diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index e7863a9..48695ea 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -1,7 +1,7 @@ /** * @file ral_types.h * @author your name (you@domain.com) - * @brief + * @brief Struct and enum definitions for RAL * @version 0.1 * @date 2024-04-27 * @@ -14,6 +14,8 @@ #include "defines.h" #include "maths_types.h" +#define MAX_VERTEX_ATTRIBUTES 16 + #ifndef RENDERER_TYPED_HANDLES CORE_DEFINE_HANDLE(buffer_handle); CORE_DEFINE_HANDLE(texture_handle); @@ -143,19 +145,45 @@ typedef enum vertex_attrib_type { ATTR_I32x4, } vertex_attrib_type; +typedef struct vertex_description { + char* debug_label; + const char* attr_names[MAX_VERTEX_ATTRIBUTES]; + vertex_attrib_type attributes[MAX_VERTEX_ATTRIBUTES]; + size_t stride; +} vertex_description; + +// --- Shaders & Bindings + typedef enum shader_visibility { VISIBILITY_VERTEX = 1 << 0, VISIBILITY_FRAGMENT = 1 << 1 , VISIBILITY_COMPUTE = 1 << 2, } shader_visibility; +/** @brief Describes the kind of binding a `shader_binding` is for. This changes how we create backing data for it. */ typedef enum shader_binding_type { + /** + * @brief Binds a buffer to a shader + * @note Vulkan: Becomes a Storage Buffer + */ SHADER_BINDING_BUFFER, + SHADER_BINDING_BUFFER_ARRAY, SHADER_BINDING_TEXTURE, + SHADER_BINDING_TEXTURE_ARRAY, + SHADER_BINDING_SAMPLER, + /** + * @brief Binds raw data to a shader + * @note Vulkan: Becomes a Uniform Buffer + */ SHADER_BINDING_BYTES, + // TODO: Acceleration Structure SHADER_BINDING_COUNT } shader_binding_type; +// pub trait ShaderBindable: Clone + Copy { +// fn bind_to(&self, context: &mut PipelineContext, index: u32); +// } + typedef struct shader_binding { const char* label; shader_binding_type type; @@ -171,7 +199,7 @@ typedef struct shader_binding { void* data; size_t size; } bytes; - } data; + } data; /** @brief */ } shader_binding; #define MAX_LAYOUT_BINDINGS 8 diff --git a/src/renderer/render.h b/src/renderer/render.h index c690e80..4477121 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -44,3 +44,5 @@ mesh mesh_create(geometry_data* geometry); model_handle model_load(const char* debug_name, const char* filepath); void geo_set_vertex_colours(geometry_data* geo, vec4 colour); + +vertex_description static_3d_vertex_description(); \ No newline at end of file diff --git a/src/renderer/standard_vertex_types.c b/src/renderer/standard_vertex_types.c new file mode 100644 index 0000000..4973bf0 --- /dev/null +++ b/src/renderer/standard_vertex_types.c @@ -0,0 +1,11 @@ +#include "ral.h" +#include "ral_types.h" +#include "render.h" + +vertex_description static_3d_vertex_description() { + vertex_description builder = { .debug_label = "vertex" }; + vertex_desc_add(&builder, "position", ATTR_F32x3); + vertex_desc_add(&builder, "normal", ATTR_F32x3); + vertex_desc_add(&builder, "texCoords", ATTR_F32x2); + return builder; +} \ No newline at end of file diff --git a/src/systems/physics.c b/src/systems/physics.c deleted file mode 100644 index 299c0c1..0000000 --- a/src/systems/physics.c +++ /dev/null @@ -1 +0,0 @@ -#include "physics.h" \ No newline at end of file diff --git a/src/systems/physics.h b/src/systems/physics.h deleted file mode 100644 index 7239ab5..0000000 --- a/src/systems/physics.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "geometry.h" -#include "maths_types.h" - -// 'system' means that it gets called per frame - -typedef struct physics_settings { - f32 gravity_strength; -} physics_settings; - -enum collider_type { - cuboid_collider, - sphere_collider, -}; - -/** @brief generic collider structure */ -typedef struct physics_collider { - u64 id; // ? Replace with handle? - enum collider_type shape; - union collider_data { - cuboid cuboid; - sphere sphere; - } geometry; - transform transform; - u8 layer; - bool on_ground; -} physics_collider; - -// What else do I need? -// intersection methods - -typedef struct physics_world { - physics_settings settings; -} physics_world; - -physics_world physics_init(physics_settings settings); -void physics_shutdown(physics_world* phys_world); - -/** @brief perform one or more simulation steps */ -void physics_system_update(physics_world* phys_world, f64 deltatime); \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index f1b648b..1d576c7 100644 --- a/xmake.lua +++ b/xmake.lua @@ -59,6 +59,7 @@ local core_sources = { -- "src/logos/*.c", "src/maths/*.c", "src/platform/*.c", + "src/physics/*.c", "src/renderer/*.c", "src/renderer/backends/*.c", "src/resources/*.c", @@ -103,6 +104,7 @@ target("core_config") -- add_includedirs("src/logos/", {public = true}) add_includedirs("src/maths/", {public = true}) add_includedirs("src/platform/", {public = true}) + add_includedirs("src/physics/", {public = true}) add_includedirs("src/renderer/", {public = true}) add_includedirs("src/renderer/backends/", {public = true}) add_includedirs("src/resources/", {public = true}) -- cgit v1.2.3-70-g09d2 From e61a2e43947cebaafe4c3725414d33e092bb6fad Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 17 May 2024 08:39:51 +1000 Subject: cube working --- assets/shaders/cube.vert | 9 +- assets/shaders/triangle.frag | 4 +- examples/README.md | 11 ++ examples/cube/ex_cube.c | 58 ++++---- src/maths/primitives.c | 253 +++++++++++++-------------------- src/renderer/backends/backend_vulkan.c | 103 ++++++++++++-- src/renderer/ral_types.h | 3 +- src/renderer/render.c | 43 ++++++ src/renderer/render.h | 21 ++- src/renderer/render_types.h | 3 + 10 files changed, 302 insertions(+), 206 deletions(-) create mode 100644 examples/README.md (limited to 'examples/cube/ex_cube.c') diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index 80ad854..1818c3c 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -7,12 +7,13 @@ layout(binding = 0) uniform UniformBufferObject { } ubo; -layout(location = 0) in vec2 inPosition; -layout(location = 1) in vec3 inColor; +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec3 inTexCoords; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); - fragColor = inColor; + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + fragColor = abs(inNormal); } diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag index 2151162..a8c6e69 100644 --- a/assets/shaders/triangle.frag +++ b/assets/shaders/triangle.frag @@ -3,4 +3,6 @@ layout(location = 0) in vec3 fragColor; layout(location = 0) out vec4 outColor; -void main() { outColor = vec4(fragColor, 1.0); } \ No newline at end of file +void main() { + outColor = vec4(fragColor, 0.0); +} diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..f289e80 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,11 @@ + +### RAL examples + +These examples show off how the lowest register of rendering, the Rendering Abstraction Layer (RAL), is used to draw things to the screen. + +- triangle +- cube + +### Renderer + +The 'renderer' is the default renderer provided by Celeritas. diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index a115fe3..7c7831d 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -8,20 +8,14 @@ #include "maths.h" #include "maths_types.h" #include "mem.h" +#include "primitives.h" #include "ral.h" #include "ral_types.h" #include "render.h" +#include "render_types.h" extern core g_core; -const custom_vertex vertices[] = { - (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, - (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, - (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, - (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, -}; -const u16 indices[] = { 0, 1, 2, 2, 3, 0 }; - // Define the shader data typedef struct mvp_uniforms { mat4 model; @@ -29,6 +23,7 @@ typedef struct mvp_uniforms { mat4 projection; } mvp_uniforms; +// We also must create a function that knows how to return a `shader_data_layout` shader_data_layout mvp_uniforms_layout(void* data) { mvp_uniforms* d = (mvp_uniforms*)data; bool has_data = data != NULL; @@ -40,9 +35,6 @@ shader_data_layout mvp_uniforms_layout(void* data) { if (has_data) { b1.data.bytes.data = d; } - /* char* name; */ - /* shader_binding bindings[MAX_LAYOUT_BINDINGS]; */ - /* u32 bindings_count; */ return (shader_data_layout){ .name = "global_ubo", .bindings = { b1 }, .bindings_count = 1 }; } @@ -52,9 +44,15 @@ int main() { DEBUG("render capacity %d", g_core.default_scene.renderables->capacity); - vertex_description vertex_input = {0}; - vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x2); - vertex_desc_add(&vertex_input, "inColor", ATTR_F32x3); + vec3 camera_pos = vec3(2., 2., 2.); + vec3 camera_front = vec3_normalise(vec3_negate(camera_pos)); + camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0)); + + vertex_description vertex_input; + vertex_input.debug_label = "Standard Static 3D Vertex Format"; + vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x3); + vertex_desc_add(&vertex_input, "inNormal", ATTR_F32x3); + vertex_desc_add(&vertex_input, "inTexCoords", ATTR_F32x2); shader_data mvp_uniforms_data = { .data = NULL, .shader_data_get_layout = &mvp_uniforms_layout }; @@ -88,19 +86,13 @@ int main() { }; gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); - buffer_handle triangle_vert_buf = - gpu_buffer_create(sizeof(vertices), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); - - buffer_handle triangle_index_buf = - gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); + geometry_data cube_data = geo_create_cuboid(f32x3(1, 1, 1)); + mesh cube = mesh_create(&cube_data, false); // Main loop while (!should_exit(&g_core)) { - glfwPollEvents(); input_update(&g_core.input); - // render_frame_begin(&g_core.renderer); - if (!gpu_backend_begin_frame()) { continue; } @@ -111,20 +103,26 @@ int main() { encode_bind_pipeline(enc, PIPELINE_GRAPHICS, gfx_pipeline); encode_set_default_settings(enc); - /* shader_data_layout mvp_layout = mvp_uniforms_layout(NULL); */ - static f32 x = 0.0; x += 0.01; - quat rotation = quat_from_axis_angle(VEC3_Z, x, true); + quat rotation = quat_from_axis_angle(VEC3_Y, x, true); + mat4 translation = mat4_translation(vec3(-0.5, -0.5, -0.5)); mat4 model = mat4_rotation(rotation); - mvp_uniforms mvp_data = { .model = model, .view = mat4_ident(), .projection = mat4_ident() }; + model = mat4_mult(translation, model); + mat4 view, proj; + camera_view_projection(&cam, g_core.renderer.swapchain.extent.width, + g_core.renderer.swapchain.extent.height, &view, &proj); + mvp_uniforms mvp_data = { .model = model, .view = view, .projection = proj }; mvp_uniforms_data.data = &mvp_data; + encode_bind_shader_data(enc, 0, &mvp_uniforms_data); // Record draw calls - encode_set_vertex_buffer(enc, triangle_vert_buf); - encode_set_index_buffer(enc, triangle_index_buf); - encode_bind_shader_data(enc, 0, &mvp_uniforms_data); - gpu_temp_draw(6); + // -- NEW + draw_mesh(&cube, &model); + // -- OLD + /* encode_set_vertex_buffer(enc, triangle_vert_buf); */ + /* encode_set_index_buffer(enc, triangle_index_buf); */ + /* gpu_temp_draw(6); */ // End recording gpu_cmd_encoder_end_render(enc); diff --git a/src/maths/primitives.c b/src/maths/primitives.c index 459a535..b9ec868 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -1,6 +1,18 @@ #include "primitives.h" +#include "colours.h" #include "maths.h" #include "ral_types.h" +#include "render_types.h" + +// TODO: move to another file +void geo_free_data(geometry_data* geo) { + vertex_darray_free(geo->vertices); + geo->vertices = NULL; + // TODO: do indices as well + /* if (geo->has_indices) { */ + /* u32_darray_free(&geo->indices); */ + /* } */ +} // vertices f32 plane_vertex_positions[] = { @@ -31,169 +43,96 @@ static const vec3 FRONT_BOT_RIGHT = (vec3){ 1, 0, 1 }; static const vec3 FRONT_TOP_LEFT = (vec3){ 0, 1, 1 }; static const vec3 FRONT_TOP_RIGHT = (vec3){ 1, 1, 1 }; -#define VERT_3D(arr, pos, norm, uv) \ - { \ - vertex v = { - .static_3d = { \ - .position = pos, \ - .normal = norm, \ - .tex_coords = uv \ - }}; \ - vertex_darray_push(arr, v); \ - } - -static mesh prim_cube_mesh_create() { - mesh cube = { 0 }; - cube.vertices = vertex_darray_new(36); - - // back faces - VERT_3D(cube.vertices, BACK_BOT_LEFT, VEC3_NEG_Z, (vec2){ 0, 1 })) - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 1 } }); - // vertex_darray_push( - // cube.vertices, - // (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } }); - - // front faces - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } }); - - // top faces - vertex_darray_push(cube.vertices, - (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 - } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); - vertex_darray_push(cube.vertices, - (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 - } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 0 } }); - - // bottom faces - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } }); - - // right faces - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 1 } }); - - // left faces - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - vertex_darray_push( - cube.vertices, - (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_NEG_X, .uv = (vec2){ 0 } }); - - cube.indices_len = cube.vertices->len; - cube.indices = malloc(sizeof(u32) * cube.indices_len); - - for (u32 i = 0; i < cube.indices_len; i++) { - cube.indices[i] = i; - } - - cube.has_indices = true; - - return cube; +#define VERT_3D(arr, pos, norm, uv) \ + { \ + vertex v = { .static_3d = { .position = pos, .normal = norm, .tex_coords = uv } }; \ + vertex_darray_push(arr, v); \ + } + +geometry_data geo_create_cuboid(f32x3 extents) { + /* static mesh prim_cube_mesh_create() { */ + vertex_darray* vertices = vertex_darray_new(36); + + // back faces + VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(1, 0)); + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Z, vec2(0, 1)); + VERT_3D(vertices, BACK_TOP_LEFT, VEC3_NEG_Z, vec2(0, 0)); + VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_NEG_Z, vec2(1, 0)); + VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_NEG_Z, vec2(1, 1)); + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Z, vec2(0, 1)); + + // front faces + VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_Z, vec2(0, 1)); + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Z, vec2(1, 0)); + VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_Z, vec2(0, 0)); + VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_Z, vec2(0, 1)); + VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_Z, vec2(1, 1)); + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Z, vec2(1, 0)); + + // top faces + VERT_3D(vertices, BACK_TOP_LEFT, VEC3_Y, vec2(0, 0)); + VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_Y, vec2(0, 1)); + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Y, vec2(1, 1)); + VERT_3D(vertices, BACK_TOP_LEFT, VEC3_Y, vec2(0, 0)); + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_Y, vec2(1, 1)); + VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_Y, vec2(1, 0)); + + // bottom faces + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); + VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_NEG_Y, vec2(1, 1)); + VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_Y, vec2(0, 1)); + VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_NEG_Y, vec2(1, 1)); + VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_NEG_Y, vec2(0, 1)); + + // right faces + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_X, vec2(0, 0)); + VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_X, vec2(1, 1)); + VERT_3D(vertices, BACK_TOP_RIGHT, VEC3_X, vec2(1, 0)); + VERT_3D(vertices, BACK_BOT_RIGHT, VEC3_X, vec2(1, 1)); + VERT_3D(vertices, FRONT_TOP_RIGHT, VEC3_X, vec2(0, 0)); + VERT_3D(vertices, FRONT_BOT_RIGHT, VEC3_X, vec2(0, 1)); + + // left faces + VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); + VERT_3D(vertices, BACK_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); + VERT_3D(vertices, BACK_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); + VERT_3D(vertices, FRONT_BOT_LEFT, VEC3_NEG_X, vec2(0, 0)); + VERT_3D(vertices, FRONT_TOP_LEFT, VEC3_NEG_X, vec2(0, 0)); + + u32_darray* indices = u32_darray_new(vertices->len); + + for (u32 i = 0; i < vertices->len; i++) { + u32_darray_push(indices, i); + } + + geometry_data geo = { + .format = VERTEX_STATIC_3D, + .vertices = vertices, + .has_indices = true, + .indices = *indices, // FIXME: make darray methods that return stack allocated struct + .colour = vec3(0, 0, 0), + }; + + return geo; } -/** @brief create a new model with the shape of a cube */ -static model_handle prim_cube_new(core* core) { - model model = { 0 }; - mesh cube = prim_cube_mesh_create(); +/* /\** @brief create a new model with the shape of a cube *\/ */ +/* static model_handle prim_cube_new(core* core) { */ +/* model model = { 0 }; */ +/* mesh cube = prim_cube_mesh_create(); */ - mesh_darray_push(model.meshes, cube); - assert(mesh_darray_len(model.meshes) == 1); +/* mesh_darray_push(model.meshes, cube); */ +/* assert(mesh_darray_len(model.meshes) == 1); */ - u32 index = (u32)model_darray_len(core->models); - model_darray_push_copy(core->models, &model); - return (model_handle){ .raw = index }; -} +/* u32 index = (u32)model_darray_len(core->models); */ +/* model_darray_push_copy(core->models, &model); */ +/* return (model_handle){ .raw = index }; */ +/* } */ // --- Spheres geometry_data geo_create_uvsphere(f32 radius, f32 north_south_lines, f32 east_west_lines) { // TODO -} \ No newline at end of file +} diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index f83ef84..3a9c4e1 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -84,6 +84,7 @@ bool create_logical_device(gpu_device* out_device); void create_swapchain_framebuffers(); void create_sync_objects(); void create_descriptor_pools(); +size_t vertex_attrib_size(vertex_attrib_type attr); VkShaderModule create_shader_module(str8 spirv); @@ -106,7 +107,7 @@ bool gpu_backend_init(const char* window_name, GLFWwindow* window) { // Setup Vulkan instance VkApplicationInfo app_info = { VK_STRUCTURE_TYPE_APPLICATION_INFO }; - app_info.apiVersion = VK_API_VERSION_1_3; + app_info.apiVersion = VK_API_VERSION_1_2; app_info.pApplicationName = window_name; app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); app_info.pEngineName = "Celeritas Engine"; @@ -351,6 +352,35 @@ static void recreate_swapchain(gpu_swapchain* swapchain) { create_swapchain_framebuffers(); } +VkFormat format_from_vertex_attr(vertex_attrib_type attr) { + switch (attr) { + case ATTR_F32: + return VK_FORMAT_R32_SFLOAT; + case ATTR_U32: + return VK_FORMAT_R32_UINT; + case ATTR_I32: + return VK_FORMAT_R32_SINT; + case ATTR_F32x2: + return VK_FORMAT_R32G32_SFLOAT; + case ATTR_U32x2: + return VK_FORMAT_R32G32_UINT; + case ATTR_I32x2: + return VK_FORMAT_R32G32_UINT; + case ATTR_F32x3: + return VK_FORMAT_R32G32B32_SFLOAT; + case ATTR_U32x3: + return VK_FORMAT_R32G32B32_UINT; + case ATTR_I32x3: + return VK_FORMAT_R32G32B32_SINT; + case ATTR_F32x4: + return VK_FORMAT_R32G32B32A32_SFLOAT; + case ATTR_U32x4: + return VK_FORMAT_R32G32B32A32_UINT; + case ATTR_I32x4: + return VK_FORMAT_R32G32B32A32_SINT; + } +} + gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) { // Allocate gpu_pipeline_layout* layout = malloc(sizeof(gpu_pipeline_layout)); @@ -381,22 +411,35 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip frag_shader_stage_info }; // TODO: Attributes - VkVertexInputAttributeDescription attribute_descs[2]; + VkVertexInputAttributeDescription attribute_descs[2] = {0}; + /* u32 offset = 0; */ + /* for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { */ + /* attribute_descs[i].binding = 0; */ + /* attribute_descs[i].location = i; */ + /* attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); */ + /* attribute_descs[i].offset = offset; */ + /* size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); */ + /* printf("offset total %d this attr %ld\n", offset, this_offset); */ + /* printf("sizeof vertex %ld\n", sizeof(vertex)); */ + /* printf("%d \n", offsetof(vertex, static_3d)); */ + /* offset += this_offset; */ + /* } */ + printf("Vertex attributes\n"); attribute_descs[0].binding = 0; attribute_descs[0].location = 0; - attribute_descs[0].format = VK_FORMAT_R32G32_SFLOAT; - attribute_descs[0].offset = offsetof(custom_vertex, pos); + attribute_descs[0].format = VK_FORMAT_R32G32B32_SFLOAT; + attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); attribute_descs[1].binding = 0; attribute_descs[1].location = 1; attribute_descs[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_descs[1].offset = offsetof(custom_vertex, color); + attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); // Vertex input // TODO: Generate this from descroiption now VkVertexInputBindingDescription binding_desc; binding_desc.binding = 0; - binding_desc.stride = sizeof(custom_vertex); + binding_desc.stride = sizeof(vertex); // description.vertex_desc.stride; binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; VkPipelineVertexInputStateCreateInfo vertex_input_info = { @@ -404,7 +447,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip }; vertex_input_info.vertexBindingDescriptionCount = 1; vertex_input_info.pVertexBindingDescriptions = &binding_desc; - vertex_input_info.vertexAttributeDescriptionCount = 2; + vertex_input_info.vertexAttributeDescriptionCount = 2; // description.vertex_desc.attributes_count; vertex_input_info.pVertexAttributeDescriptions = attribute_descs; // Input Assembly @@ -441,6 +484,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip rasterizer_create_info.lineWidth = 1.0f; rasterizer_create_info.cullMode = VK_CULL_MODE_BACK_BIT; rasterizer_create_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + /* rasterizer_create_info.frontFace = VK_FRONT_FACE_CLOCKWISE; */ rasterizer_create_info.depthBiasEnable = VK_FALSE; rasterizer_create_info.depthBiasConstantFactor = 0.0; rasterizer_create_info.depthBiasClamp = 0.0; @@ -584,6 +628,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip VK_CHECK(vkCreateDescriptorSetLayout(context.device->logical_device, &desc_set_layout_info, context.allocator, &desc_set_layouts[i])); } + printf("Descriptor set layouts\n"); // Layout VkPipelineLayoutCreateInfo pipeline_layout_create_info = { @@ -621,13 +666,18 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_create_info.basePipelineIndex = -1; + printf("Here\n"); + VkResult result = vkCreateGraphicsPipelines(context.device->logical_device, VK_NULL_HANDLE, 1, &pipeline_create_info, context.allocator, &pipeline->handle); if (result != VK_SUCCESS) { + printf("BAD\n"); FATAL("graphics pipeline creation failed. its fked mate"); ERROR_EXIT("Doomed"); } + printf("Here2\n"); + TRACE("Vulkan Graphics pipeline created"); // once the pipeline has been created we can destroy these vkDestroyShaderModule(context.device->logical_device, vertex_shader, context.allocator); @@ -820,9 +870,7 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; VkDescriptorSet sets[1]; - VK_CHECK( - vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets) - ); + VK_CHECK(vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets)); VkDescriptorSet_darray_push(context.free_set_queue, sets[0]); shader_data_layout sdl = data->shader_data_get_layout(NULL); @@ -870,7 +918,7 @@ void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { gpu_buffer buffer = context.buffers[buf.raw]; - vkCmdBindIndexBuffer(encoder->cmd_buffer, buffer.handle, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindIndexBuffer(encoder->cmd_buffer, buffer.handle, 0, VK_INDEX_TYPE_UINT32); } // TEMP @@ -1310,3 +1358,36 @@ void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_off vkCmdCopyBuffer(encoder->cmd_buffer, context.buffers[src.raw].handle, context.buffers[dst.raw].handle, 1, ©_region); } + +size_t vertex_attrib_size(vertex_attrib_type attr) { + switch (attr) { + case ATTR_F32: + case ATTR_U32: + case ATTR_I32: + return 4; + case ATTR_F32x2: + case ATTR_U32x2: + case ATTR_I32x2: + return 8; + case ATTR_F32x3: + case ATTR_U32x3: + case ATTR_I32x3: + return 12; + case ATTR_F32x4: + case ATTR_U32x4: + case ATTR_I32x4: + return 16; + break; + } +} + +void vertex_desc_add(vertex_description* builder, const char* name, vertex_attrib_type type) { + u32 i = builder->attributes_count; + + size_t size = vertex_attrib_size(type); + builder->attributes[i] = type; + builder->stride += size; + builder->attr_names[i] = name; + + builder->attributes_count++; +} diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 48695ea..c802a9b 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -85,8 +85,8 @@ typedef enum vertex_format { typedef union vertex { struct { vec3 position; - vec2 tex_coords; vec3 normal; + vec2 tex_coords; } static_3d; /** @brief standard vertex format for static geometry in 3D */ struct { @@ -149,6 +149,7 @@ typedef struct vertex_description { char* debug_label; const char* attr_names[MAX_VERTEX_ATTRIBUTES]; vertex_attrib_type attributes[MAX_VERTEX_ATTRIBUTES]; + u32 attributes_count; size_t stride; } vertex_description; diff --git a/src/renderer/render.c b/src/renderer/render.c index 9f5b21a..efef6a6 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -4,6 +4,7 @@ #include "file.h" #include "log.h" #include "ral.h" +#include "ral_types.h" /** @brief Creates the pipelines built into Celeritas such as rendering static opaque geometry, debug visualisations, immediate mode UI, etc */ @@ -126,6 +127,48 @@ void render_frame_end(renderer* ren) { } void render_frame_draw(renderer* ren) {} +void draw_mesh(mesh* mesh, mat4* model) { // , mat4* view, mat4* proj) { + gpu_cmd_encoder* enc = gpu_get_default_cmd_encoder(); + encode_set_vertex_buffer(enc, mesh->vertex_buffer); + if (mesh->has_indices) { + encode_set_index_buffer(enc, mesh->index_buffer); + } + // Assume this has already been done + /* encode_bind_shader_data(enc, 0, &mvp_uniforms_data); */ + encode_draw_indexed(enc, mesh->index_count); +} + void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex) {} void geo_set_vertex_colours(geometry_data* geo, vec4 colour) {} + +// --- NEW + +mesh mesh_create(geometry_data* geometry, bool free_on_upload) { + mesh m = { 0 }; + + // Create and upload vertex buffer + size_t vert_bytes = geometry->vertices->len * sizeof(vertex); + INFO("Creating vertex buffer with size %d (%d x %d)", vert_bytes, geometry->vertices->len, + sizeof(vertex)); + m.vertex_buffer = gpu_buffer_create(vert_bytes, CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, + geometry->vertices->data); + + // Create and upload index buffer + size_t index_bytes = geometry->indices.len * sizeof(u32); + INFO("Creating index buffer with size %d (len: %d)", index_bytes, geometry->indices.len); + m.index_buffer = + gpu_buffer_create(index_bytes, CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, geometry->indices.data); + + m.is_uploaded = true; + m.has_indices = geometry->has_indices; + m.index_count = geometry->indices.len; + m.vertices = geometry; + if (free_on_upload) { + geo_free_data(geometry); + } + + // TODO: materials? + + return m; +} diff --git a/src/renderer/render.h b/src/renderer/render.h index 4477121..c87e5f7 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -25,6 +25,11 @@ void render_frame_draw(renderer* ren); typedef struct camera camera; void gfx_backend_draw_frame(renderer* ren, camera* camera, mat4 model, texture* tex); +typedef struct render_ctx { + mat4 view; + mat4 projection; +} render_ctx; + // 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, const u8* data); @@ -39,10 +44,22 @@ sampler_handle sampler_create(); void shader_hot_reload(const char* filepath); // models and meshes are implemented **in terms of the above** -mesh mesh_create(geometry_data* geometry); + +/** + * @brief Creates buffers and returns a struct that holds handles to our resources + * + * @param geometry + * @param free_on_upload frees the CPU-side vertex/index data stored in geometry_data when we successfully upload + that data to the GPU-side buffer + * @return mesh + */ +mesh mesh_create(geometry_data* geometry, bool free_on_upload); + +void draw_mesh(mesh* mesh, mat4* model);//, mat4* view, mat4* proj); // TODO: material model_handle model_load(const char* debug_name, const char* filepath); +void geo_free_data(geometry_data* geo); void geo_set_vertex_colours(geometry_data* geo, vec4 colour); -vertex_description static_3d_vertex_description(); \ No newline at end of file +vertex_description static_3d_vertex_description(); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 06a8415..ac98627 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -45,12 +45,15 @@ typedef struct geometry_data { vec3 colour; /** Optional: set vertex colours */ } geometry_data; +// 'Upload' a geometry_data (to GPU) -> get back a mesh typedef struct mesh { buffer_handle vertex_buffer; buffer_handle index_buffer; u32 index_count; bool has_indices; geometry_data* vertices; // NULL means it has been freed + bool is_uploaded; + bool is_latent; } mesh; /* Hot reloading: -- cgit v1.2.3-70-g09d2 From d79a8aa200bd64b14b85d2ec0c207601ba5c7922 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sat, 18 May 2024 23:53:11 +1000 Subject: working on image creation --- assets/shaders/triangle.vert | 2 - examples/cube/ex_cube.c | 5 + examples/triangle/ex_triangle.c | 18 ++- src/renderer/backends/backend_vulkan.c | 224 ++++++++++++++++++++++++++++----- src/renderer/backends/backend_vulkan.h | 8 ++ src/renderer/ral.c | 21 ---- src/renderer/ral.h | 7 ++ src/renderer/ral_types.h | 3 - src/renderer/render.c | 44 ++++++- src/renderer/render.h | 16 ++- src/renderer/render_types.h | 15 +-- 11 files changed, 289 insertions(+), 74 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert index b8c8f63..8030561 100644 --- a/assets/shaders/triangle.vert +++ b/assets/shaders/triangle.vert @@ -2,8 +2,6 @@ layout(location = 0) in vec2 inPos; layout(location = 1) in vec3 inColor; -// layout(location = 1) in vec3 inNormal; -// layout(location = 2) in vec2 inTexCoords; layout(location = 0) out vec3 fragColor; diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 7c7831d..264bf71 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -86,9 +86,14 @@ int main() { }; gpu_pipeline* gfx_pipeline = gpu_graphics_pipeline_create(pipeline_description); + // Geometry geometry_data cube_data = geo_create_cuboid(f32x3(1, 1, 1)); mesh cube = mesh_create(&cube_data, false); + // Texture + texture_data tex_data = texture_data_load("assets/textures/texture.jpg", false); + texture_handle texture = texture_data_upload(tex_data, true); + // Main loop while (!should_exit(&g_core)) { input_update(&g_core.input); diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index 5d8f0cf..886637a 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -16,17 +16,22 @@ extern core g_core; const custom_vertex vertices[] = { + (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, + (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, - (custom_vertex){ .pos = vec2(0.5, -0.5), .color = vec3(1.0, 0.0, 0.0) }, - (custom_vertex){ .pos = vec2(-0.5, -0.5), .color = vec3(1.0, 1.0, 1.0) }, }; -const u16 indices[] = { 0, 1, 2, 2, 3, 0 }; +const u32 indices[] = { 2, 1, 0, 1, 2, 3}; int main() { core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + vertex_description vertex_input = {0}; + vertex_input.debug_label = "Hello"; + vertex_desc_add(&vertex_input, "inPos", ATTR_F32x2); + vertex_desc_add(&vertex_input, "inColor", ATTR_F32x3); + gpu_renderpass_desc pass_description = {}; gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); @@ -40,6 +45,9 @@ int main() { struct graphics_pipeline_desc pipeline_description = { .debug_name = "Basic Pipeline", + .vertex_desc = vertex_input, + // .data_layouts = {0}, + // .data_layouts_count = 0, .vs = { .debug_name = "Triangle Vertex Shader", .filepath = vert_path, .code = vertex_shader.contents, @@ -56,13 +64,13 @@ int main() { // Load triangle vertex and index data buffer_handle triangle_vert_buf = - gpu_buffer_create(sizeof(vertices), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); + gpu_buffer_create(4 * sizeof(vertex) , CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); buffer_handle triangle_index_buf = gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); // Main loop - while (!should_exit(&g_core)) { + while (!should_exit()) { input_update(&g_core.input); if (!gpu_backend_begin_frame()) { diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 2dc11b5..208aef0 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -414,37 +414,39 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip VkPipelineShaderStageCreateInfo shader_stages[2] = { vert_shader_stage_info, frag_shader_stage_info }; - // TODO: Attributes - VkVertexInputAttributeDescription attribute_descs[2] = { 0 }; - /* u32 offset = 0; */ - /* for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { */ - /* attribute_descs[i].binding = 0; */ - /* attribute_descs[i].location = i; */ - /* attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); - */ - /* attribute_descs[i].offset = offset; */ - /* size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); */ - /* printf("offset total %d this attr %ld\n", offset, this_offset); */ - /* printf("sizeof vertex %ld\n", sizeof(vertex)); */ - /* printf("%d \n", offsetof(vertex, static_3d)); */ - /* offset += this_offset; */ - /* } */ - printf("Vertex attributes\n"); - attribute_descs[0].binding = 0; - attribute_descs[0].location = 0; - attribute_descs[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); - - attribute_descs[1].binding = 0; - attribute_descs[1].location = 1; - attribute_descs[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); + // Attributes + u32 attr_count = description.vertex_desc.attributes_count; + printf("N attributes %d\n", attr_count); + VkVertexInputAttributeDescription attribute_descs[attr_count]; + memset(attribute_descs, 0, attr_count * sizeof(VkVertexInputAttributeDescription)); + u32 offset = 0; + for (u32 i = 0; i < description.vertex_desc.attributes_count; i++) { + attribute_descs[i].binding = 0; + attribute_descs[i].location = i; + attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); + attribute_descs[i].offset = offset; + size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); + printf("offset total %d this attr %ld\n", offset, this_offset); + printf("sizeof vertex %ld\n", sizeof(vertex)); + /* printf("%d \n", offsetof(vertex, static_3d)); */ + offset += this_offset; + } + /* printf("Vertex attributes\n"); */ + /* attribute_descs[0].binding = 0; */ + /* attribute_descs[0].location = 0; */ + /* attribute_descs[0].format = VK_FORMAT_R32G32B32_SFLOAT; */ + /* attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); */ + + /* attribute_descs[1].binding = 0; */ + /* attribute_descs[1].location = 1; */ + /* attribute_descs[1].format = VK_FORMAT_R32G32B32_SFLOAT; */ + /* attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); */ // Vertex input // TODO: Generate this from descroiption now VkVertexInputBindingDescription binding_desc; binding_desc.binding = 0; - binding_desc.stride = sizeof(vertex); // description.vertex_desc.stride; + binding_desc.stride = description.vertex_desc.stride; binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; VkPipelineVertexInputStateCreateInfo vertex_input_info = { @@ -453,7 +455,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip vertex_input_info.vertexBindingDescriptionCount = 1; vertex_input_info.pVertexBindingDescriptions = &binding_desc; vertex_input_info.vertexAttributeDescriptionCount = - 2; // description.vertex_desc.attributes_count; + attr_count; // description.vertex_desc.attributes_count; vertex_input_info.pVertexAttributeDescriptions = attribute_descs; // Input Assembly @@ -558,10 +560,15 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip malloc(description.data_layouts_count * sizeof(VkDescriptorSetLayout)); pipeline->desc_set_layouts = desc_set_layouts; pipeline->desc_set_layouts_count = description.data_layouts_count; + if (description.data_layouts_count > 0) { pipeline->uniform_pointers = malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); + } else { + pipeline->uniform_pointers = NULL; + } // assert(description.data_layouts_count == 1); + printf("data layouts %d\n", description.data_layouts_count); for (u32 i = 0; i < description.data_layouts_count; i++) { shader_data_layout sdl = description.data_layouts[i].shader_data_get_layout(NULL); @@ -1343,15 +1350,15 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f void gpu_buffer_destroy(buffer_handle buffer) { gpu_buffer* b = - buffer_pool_get(&context.resource_pools->buffers, buffer); // context.buffers[buffer.raw]; + buffer_pool_get(&context.resource_pools->buffers, buffer); vkDestroyBuffer(context.device->logical_device, b->handle, context.allocator); vkFreeMemory(context.device->logical_device, b->memory, context.allocator); + buffer_pool_dealloc(&context.resource_pools->buffers, buffer); } // Upload data to a void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size) { gpu_buffer* buffer = buffer_pool_get(&context.resource_pools->buffers, gpu_buf); - /* gpu_buffer buffer = context.buffers[gpu_buf.raw]; */ void* data_ptr; vkMapMemory(context.device->logical_device, buffer->memory, 0, size, 0, &data_ptr); DEBUG("Uploading %d bytes to buffer", size); @@ -1371,6 +1378,80 @@ void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_off vkCmdCopyBuffer(encoder->cmd_buffer, src_buf->handle, dst_buf->handle, 1, ©_region); } +// one-shot command buffers +VkCommandBuffer vulkan_command_buffer_create_oneshot() { + VkCommandBufferAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; + alloc_info.commandPool = context.device->pool; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandBufferCount = 1; + alloc_info.pNext = 0; + + VkCommandBuffer cmd_buffer; + vkAllocateCommandBuffers(context.device->logical_device, &alloc_info, &cmd_buffer); + + VkCommandBufferBeginInfo begin_info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(cmd_buffer, &begin_info); + + return cmd_buffer; +} + +void vulkan_command_buffer_finish_oneshot(VkCommandBuffer cmd_buffer) { + VK_CHECK(vkEndCommandBuffer(cmd_buffer)); + + // submit to queue + VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO }; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &cmd_buffer; + VK_CHECK(vkQueueSubmit(context.device->graphics_queue, 1, &submit_info, 0)); + VK_CHECK(vkQueueWaitIdle(context.device->graphics_queue)); + + vkFreeCommandBuffers(context.device->logical_device, context.device->pool, 1, &cmd_buffer); +} + +void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, + u64 dst_offset, u64 copy_size) { + VkBufferCopy copy_region; + copy_region.srcOffset = src_offset; + copy_region.dstOffset = dst_offset; + copy_region.size = copy_size; + + gpu_buffer* src_buf = buffer_pool_get(&context.resource_pools->buffers, src); + gpu_buffer* dst_buf = buffer_pool_get(&context.resource_pools->buffers, dst); + VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); + vkCmdCopyBuffer(temp_cmd_buffer, src_buf->handle, dst_buf->handle, 1, ©_region); + vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); +} + +void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst) { + gpu_buffer* src_buf = buffer_pool_get(&context.resource_pools->buffers, src); + gpu_texture* dst_tex = texture_pool_get(&context.resource_pools->textures, dst); + + VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); + + VkBufferImageCopy region; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + printf("Image details width: %d height %d\n", dst_tex->desc.extents.x, dst_tex->desc.extents.y); + region.imageOffset.x = 0; + region.imageOffset.y = 0; + region.imageOffset.z = 0; + region.imageExtent.width = dst_tex->desc.extents.x; + region.imageExtent.height = dst_tex->desc.extents.y; + region.imageExtent.depth = 1; + + vkCmdCopyBufferToImage(temp_cmd_buffer, src_buf->handle, dst_tex->handle, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); +} + texture_handle gpu_texture_create(texture_desc desc, const void* data) { VkDeviceSize image_size = desc.extents.x * desc.extents.y * 4; @@ -1380,6 +1461,91 @@ texture_handle gpu_texture_create(texture_desc desc, const void* data) { gpu_buffer_create(image_size, CEL_BUFFER_DEFAULT, CEL_BUFFER_FLAG_CPU, NULL); // Copy data into it buffer_upload_bytes(staging, (bytebuffer){ .buf = (u8*)data, .size = image_size }, 0, image_size); + + VkImage image; + VkDeviceMemory image_memory; + + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.extent.width = desc.extents.x; + image_create_info.extent.height = desc.extents.y; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.format = VK_FORMAT_R8G8B8A8_SRGB; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + + VK_CHECK( + vkCreateImage(context.device->logical_device, &image_create_info, context.allocator, &image)); + + VkMemoryRequirements memory_reqs; + vkGetImageMemoryRequirements(context.device->logical_device, image, &memory_reqs); + + VkMemoryAllocateInfo alloc_info = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + alloc_info.allocationSize = memory_reqs.size; + alloc_info.memoryTypeIndex = + find_memory_index(memory_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + vkAllocateMemory(context.device->logical_device, &alloc_info, context.allocator, &image_memory); + + vkBindImageMemory(context.device->logical_device, image, image_memory, 0); + +gpu_buffer_destroy(staging); + + texture_handle handle; + gpu_texture* texture = texture_pool_alloc(&context.resource_pools->textures, &handle); + texture->handle = image; + texture->memory = image_memory; + texture->size = image_size; + return handle; +} + +void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkImageLayout old_layout, + VkImageLayout new_layout) { + VkCommandBuffer temp_cmd_buffer = vulkan_command_buffer_create_oneshot(); + + VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER }; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = context.device->queue_family_indicies.graphics_family_index; + barrier.dstQueueFamilyIndex = context.device->queue_family_indicies.graphics_family_index; + barrier.image = texture->handle; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.srcAccessMask = 0; // TODO + barrier.dstAccessMask = 0; // TODO + + VkPipelineStageFlags source_stage; + VkPipelineStageFlags dest_stage; + + if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && + new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + dest_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + + } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && + new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dest_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else { + FATAL("Unsupported image layout transition"); + return; + } + + vkCmdPipelineBarrier(temp_cmd_buffer, source_stage, dest_stage, 0, 0, 0, 0, 0, 1, &barrier); + + vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); } size_t vertex_attrib_size(vertex_attrib_type attr) { diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 77b9f94..1e36ca3 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -6,6 +6,7 @@ #include "defines.h" #include "mem.h" #include "ral.h" +#include "ral_types.h" #define MAX_FRAMES_IN_FLIGHT 2 #define GPU_SWAPCHAIN_IMG_COUNT 2 @@ -102,3 +103,10 @@ typedef struct gpu_buffer { VkDeviceMemory memory; u64 size; } gpu_buffer; + +typedef struct gpu_texture { + VkImage handle; + VkDeviceMemory memory; + u64 size; + texture_desc desc; +} gpu_texture; diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 6a417dd..304017d 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -1,22 +1 @@ #include "ral.h" - -/* typedef struct foo { */ -/* u32 a; */ -/* f32 b; */ -/* char c; */ -/* } foo; */ - -/* TYPED_POOL(gpu_buffer, buffer); */ - -/* typedef struct buffer_handle { */ -/* u32 raw; */ -/* } buffer_handle; */ - -/* typedef struct gpu_buffer gpu_buffer; */ -/* TYPED_POOL(gpu_buffer, buffer); */ -/* TYPED_POOL(gpu_texture, texture); */ - -/* struct resource_pools { */ -/* buffer_pool buffers; */ -/* texture_pool textures; */ -/* }; */ diff --git a/src/renderer/ral.h b/src/renderer/ral.h index da9eb93..48be83a 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -30,6 +30,7 @@ typedef struct gpu_renderpass gpu_renderpass; typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer gpu_buffer; +typedef struct gpu_texture gpu_texture; #define MAX_SHADER_DATA_LAYOUTS 5 #define MAX_BUFFERS 256 @@ -174,3 +175,9 @@ struct resource_pools { // Must be implemented by backends void resource_pools_init(arena* a, struct resource_pools* res_pools); + +void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, u64 dst_offset, + u64 copy_size); +void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst); + +// --- Helpers diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 5d4e88a..fc8bb8b 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -66,9 +66,6 @@ typedef struct texture_desc { u32x2 extents; } texture_desc; -typedef struct gpu_texture { -} gpu_texture; - typedef enum gpu_buffer_type { CEL_BUFFER_DEFAULT, // on Vulkan this would be a storage buffer? CEL_BUFFER_VERTEX, diff --git a/src/renderer/render.c b/src/renderer/render.c index b06620b..fc45093 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -1,11 +1,15 @@ -#include "render.h" #include +#include "maths_types.h" +#define STB_IMAGE_IMPLEMENTATION +#include + #include "camera.h" #include "file.h" #include "log.h" #include "mem.h" #include "ral.h" #include "ral_types.h" +#include "render.h" /** @brief Creates the pipelines built into Celeritas such as rendering static opaque geometry, debug visualisations, immediate mode UI, etc */ @@ -194,3 +198,41 @@ mesh mesh_create(geometry_data* geometry, bool free_on_upload) { return m; } + +// --- Textures + +texture_data texture_data_load(const char* path, bool invert_y) { + TRACE("Load texture %s", path); + + // load the file data + int width, height, num_channels; + stbi_set_flip_vertically_on_load(invert_y); + +#pragma GCC diagnostic ignored "-Wpointer-sign" + char* data = stbi_load(path, &width, &height, &num_channels, 0); // STBI_rgb_alpha); + if (data) { + DEBUG("loaded texture: %s", path); + } else { + WARN("failed to load texture"); + } + + unsigned int channel_type; + if (num_channels == 4) { + channel_type = GL_RGBA; + } else { + channel_type = GL_RGB; + } + texture_desc desc = { .extents = { width, height }, + .format = CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, + .tex_type = CEL_TEXTURE_TYPE_2D }; + + return (texture_data){ .description = desc, .image_data = data }; +} + +texture_handle texture_data_upload(texture_data data, bool free_on_upload) { + texture_handle handle = gpu_texture_create(data.description, data.image_data); + if (free_on_upload) { + stbi_image_free(data.image_data); + } + return handle; +} diff --git a/src/renderer/render.h b/src/renderer/render.h index 5657fc1..9a7ff2f 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -34,9 +34,17 @@ typedef struct render_ctx { texture_handle texture_create(const char* debug_name, texture_desc description, const u8* data); // Frontend Resources -// TODO: void texture_data_upload(texture_handle texture); -void texture_data_upload(texture* tex); -texture texture_data_load(const char* path, bool invert_y); +texture_data texture_data_load(const char* path, bool invert_y); + +/** + * @brief + * + * @param data + * @param free_on_upload frees the CPU-side pixel data stored in `data` + * @return texture_handle + */ +texture_handle texture_data_upload(texture_data data, bool free_on_upload); + buffer_handle buffer_create(const char* debug_name, u64 size); bool buffer_destroy(buffer_handle buffer); sampler_handle sampler_create(); @@ -49,7 +57,7 @@ void shader_hot_reload(const char* filepath); * @brief Creates buffers and returns a struct that holds handles to our resources * * @param geometry - * @param free_on_upload frees the CPU-side vertex/index data stored in geometry_data when we + * @param free_on_upload frees the CPU-side vertex/index data stored in `geometry` when we successfully upload that data to the GPU-side buffer * @return mesh */ diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index bd9ef3c..c6aec8e 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -69,16 +69,13 @@ typedef struct model { u32 mesh_count; } model; -typedef struct texture { - u32 texture_id; - char name[256]; +typedef struct texture {} texture; + +typedef struct texture_data { + texture_desc description; void* image_data; - void* backend_data; - u32 width; - u32 height; - u8 channel_count; - u32 channel_type; -} texture; +} texture_data; + typedef struct blinn_phong_material { char name[256]; -- cgit v1.2.3-70-g09d2 From b1b2d988e8f2fa3b0f63ff3aeb02849497433647 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 19 May 2024 00:01:50 +1000 Subject: cube compiles again --- examples/cube/ex_cube.c | 2 +- examples/triangle/ex_triangle.c | 2 +- src/renderer/backends/backend_vulkan.c | 2 +- src/renderer/ral_types.h | 1 + src/renderer/render.c | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 264bf71..346dd10 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -48,7 +48,7 @@ int main() { vec3 camera_front = vec3_normalise(vec3_negate(camera_pos)); camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0)); - vertex_description vertex_input; + vertex_description vertex_input = {.use_full_vertex_size = true}; vertex_input.debug_label = "Standard Static 3D Vertex Format"; vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x3); vertex_desc_add(&vertex_input, "inNormal", ATTR_F32x3); diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index 886637a..69c29ac 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -27,7 +27,7 @@ int main() { core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - vertex_description vertex_input = {0}; + vertex_description vertex_input = {.use_full_vertex_size=false}; vertex_input.debug_label = "Hello"; vertex_desc_add(&vertex_input, "inPos", ATTR_F32x2); vertex_desc_add(&vertex_input, "inColor", ATTR_F32x3); diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 208aef0..ae49cc3 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -446,7 +446,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip // TODO: Generate this from descroiption now VkVertexInputBindingDescription binding_desc; binding_desc.binding = 0; - binding_desc.stride = description.vertex_desc.stride; + binding_desc.stride = description.vertex_desc.use_full_vertex_size ? sizeof(vertex) : description.vertex_desc.stride; binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; VkPipelineVertexInputStateCreateInfo vertex_input_info = { diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index fc8bb8b..8339625 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -160,6 +160,7 @@ typedef struct vertex_description { vertex_attrib_type attributes[MAX_VERTEX_ATTRIBUTES]; u32 attributes_count; size_t stride; + bool use_full_vertex_size; } vertex_description; // --- Shaders & Bindings diff --git a/src/renderer/render.c b/src/renderer/render.c index fc45093..9f9a97c 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -209,7 +209,7 @@ texture_data texture_data_load(const char* path, bool invert_y) { stbi_set_flip_vertically_on_load(invert_y); #pragma GCC diagnostic ignored "-Wpointer-sign" - char* data = stbi_load(path, &width, &height, &num_channels, 0); // STBI_rgb_alpha); + char* data = stbi_load(path, &width, &height, &num_channels, STBI_rgb_alpha); if (data) { DEBUG("loaded texture: %s", path); } else { -- cgit v1.2.3-70-g09d2 From ebee348781e68e61f97c31411512dc0aabab7acb Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 19 May 2024 00:04:31 +1000 Subject: chore: fmt --- examples/cube/ex_cube.c | 2 +- examples/triangle/ex_triangle.c | 6 +++--- src/renderer/backends/backend_vulkan.c | 15 ++++++++------- src/renderer/ral.h | 4 ++-- src/renderer/render.h | 10 +++++----- src/renderer/render_types.h | 4 ++-- src/scene.h | 8 ++++---- 7 files changed, 25 insertions(+), 24 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 346dd10..80a4e26 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -48,7 +48,7 @@ int main() { vec3 camera_front = vec3_normalise(vec3_negate(camera_pos)); camera cam = camera_create(camera_pos, camera_front, VEC3_Y, deg_to_rad(45.0)); - vertex_description vertex_input = {.use_full_vertex_size = true}; + vertex_description vertex_input = { .use_full_vertex_size = true }; vertex_input.debug_label = "Standard Static 3D Vertex Format"; vertex_desc_add(&vertex_input, "inPosition", ATTR_F32x3); vertex_desc_add(&vertex_input, "inNormal", ATTR_F32x3); diff --git a/examples/triangle/ex_triangle.c b/examples/triangle/ex_triangle.c index 69c29ac..d57e224 100644 --- a/examples/triangle/ex_triangle.c +++ b/examples/triangle/ex_triangle.c @@ -21,13 +21,13 @@ const custom_vertex vertices[] = { (custom_vertex){ .pos = vec2(-0.5, 0.5), .color = vec3(0.0, 0.0, 1.0) }, (custom_vertex){ .pos = vec2(0.5, 0.5), .color = vec3(0.0, 1.0, 0.0) }, }; -const u32 indices[] = { 2, 1, 0, 1, 2, 3}; +const u32 indices[] = { 2, 1, 0, 1, 2, 3 }; int main() { core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - vertex_description vertex_input = {.use_full_vertex_size=false}; + vertex_description vertex_input = { .use_full_vertex_size = false }; vertex_input.debug_label = "Hello"; vertex_desc_add(&vertex_input, "inPos", ATTR_F32x2); vertex_desc_add(&vertex_input, "inColor", ATTR_F32x3); @@ -64,7 +64,7 @@ int main() { // Load triangle vertex and index data buffer_handle triangle_vert_buf = - gpu_buffer_create(4 * sizeof(vertex) , CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); + gpu_buffer_create(4 * sizeof(vertex), CEL_BUFFER_VERTEX, CEL_BUFFER_FLAG_GPU, vertices); buffer_handle triangle_index_buf = gpu_buffer_create(sizeof(indices), CEL_BUFFER_INDEX, CEL_BUFFER_FLAG_GPU, indices); diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index ae49cc3..33e0860 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -425,7 +425,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip attribute_descs[i].location = i; attribute_descs[i].format = format_from_vertex_attr(description.vertex_desc.attributes[i]); attribute_descs[i].offset = offset; - size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); + size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); printf("offset total %d this attr %ld\n", offset, this_offset); printf("sizeof vertex %ld\n", sizeof(vertex)); /* printf("%d \n", offsetof(vertex, static_3d)); */ @@ -446,7 +446,9 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip // TODO: Generate this from descroiption now VkVertexInputBindingDescription binding_desc; binding_desc.binding = 0; - binding_desc.stride = description.vertex_desc.use_full_vertex_size ? sizeof(vertex) : description.vertex_desc.stride; + binding_desc.stride = description.vertex_desc.use_full_vertex_size + ? sizeof(vertex) + : description.vertex_desc.stride; binding_desc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; VkPipelineVertexInputStateCreateInfo vertex_input_info = { @@ -561,8 +563,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip pipeline->desc_set_layouts = desc_set_layouts; pipeline->desc_set_layouts_count = description.data_layouts_count; if (description.data_layouts_count > 0) { - pipeline->uniform_pointers = - malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); + pipeline->uniform_pointers = + malloc(description.data_layouts_count * sizeof(desc_set_uniform_buffer)); } else { pipeline->uniform_pointers = NULL; } @@ -1349,8 +1351,7 @@ buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_f } void gpu_buffer_destroy(buffer_handle buffer) { - gpu_buffer* b = - buffer_pool_get(&context.resource_pools->buffers, buffer); + gpu_buffer* b = buffer_pool_get(&context.resource_pools->buffers, buffer); vkDestroyBuffer(context.device->logical_device, b->handle, context.allocator); vkFreeMemory(context.device->logical_device, b->memory, context.allocator); buffer_pool_dealloc(&context.resource_pools->buffers, buffer); @@ -1493,7 +1494,7 @@ texture_handle gpu_texture_create(texture_desc desc, const void* data) { vkBindImageMemory(context.device->logical_device, image, image_memory, 0); -gpu_buffer_destroy(staging); + gpu_buffer_destroy(staging); texture_handle handle; gpu_texture* texture = texture_pool_alloc(&context.resource_pools->textures, &handle); diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 48be83a..a82a2ba 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -176,8 +176,8 @@ struct resource_pools { // Must be implemented by backends void resource_pools_init(arena* a, struct resource_pools* res_pools); -void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, u64 dst_offset, - u64 copy_size); +void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, + u64 dst_offset, u64 copy_size); void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst); // --- Helpers diff --git a/src/renderer/render.h b/src/renderer/render.h index 9a7ff2f..c193ff9 100644 --- a/src/renderer/render.h +++ b/src/renderer/render.h @@ -37,11 +37,11 @@ texture_handle texture_create(const char* debug_name, texture_desc description, texture_data texture_data_load(const char* path, bool invert_y); /** - * @brief - * - * @param data - * @param free_on_upload frees the CPU-side pixel data stored in `data` - * @return texture_handle + * @brief + * + * @param data + * @param free_on_upload frees the CPU-side pixel data stored in `data` + * @return texture_handle */ texture_handle texture_data_upload(texture_data data, bool free_on_upload); diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index c6aec8e..cc5fd93 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -69,14 +69,14 @@ typedef struct model { u32 mesh_count; } model; -typedef struct texture {} texture; +typedef struct texture { +} texture; typedef struct texture_data { texture_desc description; void* image_data; } texture_data; - typedef struct blinn_phong_material { char name[256]; texture diffuse_texture; diff --git a/src/scene.h b/src/scene.h index 5a85e2e..5ac7542 100644 --- a/src/scene.h +++ b/src/scene.h @@ -32,10 +32,10 @@ void scene_free(scene* s); // Simplified API - no scene pointer; gets and sets global scene // Add/Remove objects from the scene - /* vec3 direction; */ - /* vec3 ambient; */ - /* vec3 diffuse; */ - /* vec3 specular; */ +/* vec3 direction; */ +/* vec3 ambient; */ +/* vec3 diffuse; */ +/* vec3 specular; */ void scene_set_dir_light(directional_light light); void _scene_set_dir_light(vec3 ambient, vec3 diffuse, vec3 specular, vec3 direction); -- cgit v1.2.3-70-g09d2 From b6a4ac7b2d9d94a25ecdff007f87587512f5711d Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 19 May 2024 22:25:31 +1000 Subject: cube texture mapping working --- assets/shaders/cube.frag | 12 ++ assets/shaders/cube.vert | 7 +- examples/cube/ex_cube.c | 25 ++++- src/renderer/backends/backend_vulkan.c | 200 +++++++++++++++++++++++---------- src/renderer/backends/backend_vulkan.h | 3 + src/renderer/ral.h | 2 +- src/renderer/ral_types.h | 6 +- src/renderer/render.c | 3 +- xmake.lua | 1 + 9 files changed, 191 insertions(+), 68 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag index e69de29..11f1efa 100644 --- a/assets/shaders/cube.frag +++ b/assets/shaders/cube.frag @@ -0,0 +1,12 @@ +#version 450 + +layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragTexCoord; + +layout(binding = 1) uniform sampler2D texSampler; + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); +} diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index 1818c3c..fa9f85b 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -4,16 +4,17 @@ layout(binding = 0) uniform UniformBufferObject { mat4 model; mat4 view; mat4 proj; -} -ubo; +} ubo; layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; -layout(location = 2) in vec3 inTexCoords; +layout(location = 2) in vec2 inTexCoords; layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragTexCoord; void main() { gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); fragColor = abs(inNormal); + fragTexCoord = inTexCoords; } diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 80a4e26..5d6cbbe 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -22,20 +22,30 @@ typedef struct mvp_uniforms { mat4 view; mat4 projection; } mvp_uniforms; +typedef struct my_shader_bind_group { + mvp_uniforms mvp; + texture_handle tex; +} my_shader_bind_group; // We also must create a function that knows how to return a `shader_data_layout` shader_data_layout mvp_uniforms_layout(void* data) { - mvp_uniforms* d = (mvp_uniforms*)data; + my_shader_bind_group* d = (my_shader_bind_group*)data; bool has_data = data != NULL; shader_binding b1 = { .label = "mvp_uniforms", .type = SHADER_BINDING_BYTES, .stores_data = has_data, .data = { .bytes = { .size = sizeof(mvp_uniforms) } } }; + + shader_binding b2 = { .label = "texture_sampler", + .type = SHADER_BINDING_TEXTURE, + .stores_data = has_data + }; if (has_data) { - b1.data.bytes.data = d; + b1.data.bytes.data = &d->mvp; + b2.data.texture.handle = d->tex; } - return (shader_data_layout){ .name = "global_ubo", .bindings = { b1 }, .bindings_count = 1 }; + return (shader_data_layout){ .name = "global_ubo", .bindings = { b1, b2 }, .bindings_count = 2 }; } int main() { @@ -60,7 +70,7 @@ int main() { gpu_renderpass* renderpass = gpu_renderpass_create(&pass_description); str8 vert_path = str8lit("build/linux/x86_64/debug/cube.vert.spv"); - str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); + str8 frag_path = str8lit("build/linux/x86_64/debug/cube.frag.spv"); str8_opt vertex_shader = str8_from_file(&scratch, vert_path); str8_opt fragment_shader = str8_from_file(&scratch, frag_path); if (!vertex_shader.has_value || !fragment_shader.has_value) { @@ -93,6 +103,7 @@ int main() { // Texture texture_data tex_data = texture_data_load("assets/textures/texture.jpg", false); texture_handle texture = texture_data_upload(tex_data, true); + printf("Texture %d", texture.raw); // Main loop while (!should_exit(&g_core)) { @@ -118,7 +129,11 @@ int main() { camera_view_projection(&cam, g_core.renderer.swapchain.extent.width, g_core.renderer.swapchain.extent.height, &view, &proj); mvp_uniforms mvp_data = { .model = model, .view = view, .projection = proj }; - mvp_uniforms_data.data = &mvp_data; + my_shader_bind_group shader_bind_data = { + .mvp = mvp_data, + .tex = texture + }; + mvp_uniforms_data.data = &shader_bind_data; encode_bind_shader_data(enc, 0, &mvp_uniforms_data); // Record draw calls diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 33e0860..e8b54d9 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -92,8 +92,12 @@ VkShaderModule create_shader_module(str8 spirv); /** @brief Helper function for creating array of all extensions we want */ cstr_darray* get_all_extensions(); +void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkImageLayout old_layout, + VkImageLayout new_layout); + // --- Handy macros #define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) +#define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) bool gpu_backend_init(const char* window_name, GLFWwindow* window) { memset(&context, 0, sizeof(vulkan_context)); @@ -571,24 +575,24 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip // assert(description.data_layouts_count == 1); printf("data layouts %d\n", description.data_layouts_count); - for (u32 i = 0; i < description.data_layouts_count; i++) { - shader_data_layout sdl = description.data_layouts[i].shader_data_get_layout(NULL); + for (u32 layout_i = 0; layout_i < description.data_layouts_count; layout_i++) { + shader_data_layout sdl = description.data_layouts[layout_i].shader_data_get_layout(NULL); + TRACE("Got shader data layout %d's bindings! . found %d", layout_i, sdl.bindings_count); - // NOTE: is using VLA generally ok? - VkDescriptorSetLayoutBinding desc_set_bindings[description.data_layouts_count]; + VkDescriptorSetLayoutBinding desc_set_bindings[sdl.bindings_count]; // Bindings - assert(sdl.bindings_count == 1); - for (u32 j = 0; j < sdl.bindings_count; j++) { - desc_set_bindings[j].binding = j; - desc_set_bindings[j].descriptorCount = 1; - switch (sdl.bindings[j].type) { + assert(sdl.bindings_count == 2); + for (u32 binding_j = 0; binding_j < sdl.bindings_count; binding_j++) { + desc_set_bindings[binding_j].binding = binding_j; + desc_set_bindings[binding_j].descriptorCount = 1; + switch (sdl.bindings[binding_j].type) { case SHADER_BINDING_BUFFER: case SHADER_BINDING_BYTES: - desc_set_bindings[j].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // FIXME: dont hardcode + desc_set_bindings[binding_j].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; // FIXME: dont hardcode - u64 buffer_size = sdl.bindings[j].data.bytes.size; + u64 buffer_size = sdl.bindings[binding_j].data.bytes.size; VkDeviceSize uniform_buf_size = buffer_size; // TODO: Create backing buffer @@ -617,18 +621,24 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip sizeof(uniform_buf_mem_mappings)); uniform_data.size = buffer_size; - pipeline->uniform_pointers[j] = uniform_data; + pipeline->uniform_pointers[binding_j] = uniform_data; + + break; + case SHADER_BINDING_TEXTURE: + desc_set_bindings[binding_j].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; // FIXME: dont hardcode + desc_set_bindings[binding_j].pImmutableSamplers = NULL; break; default: ERROR_EXIT("Unimplemented binding type!! in backend_vulkan"); } - switch (sdl.bindings[j].vis) { + switch (sdl.bindings[binding_j].vis) { case VISIBILITY_VERTEX: - desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; break; case VISIBILITY_FRAGMENT: - desc_set_bindings[j].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + desc_set_bindings[binding_j].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; break; case VISIBILITY_COMPUTE: WARN("Compute is not implemented yet"); @@ -643,7 +653,7 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip desc_set_layout_info.pBindings = desc_set_bindings; VK_CHECK(vkCreateDescriptorSetLayout(context.device->logical_device, &desc_set_layout_info, - context.allocator, &desc_set_layouts[i])); + context.allocator, &desc_set_layouts[layout_i])); } printf("Descriptor set layouts\n"); @@ -683,17 +693,15 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; pipeline_create_info.basePipelineIndex = -1; - printf("Here\n"); + printf("About to create graphics pipeline\n"); VkResult result = vkCreateGraphicsPipelines(context.device->logical_device, VK_NULL_HANDLE, 1, &pipeline_create_info, context.allocator, &pipeline->handle); if (result != VK_SUCCESS) { - printf("BAD\n"); FATAL("graphics pipeline creation failed. its fked mate"); ERROR_EXIT("Doomed"); } - printf("Here2\n"); TRACE("Vulkan Graphics pipeline created"); // once the pipeline has been created we can destroy these @@ -810,13 +818,17 @@ gpu_cmd_encoder gpu_cmd_encoder_create() { VK_CHECK(vkAllocateCommandBuffers(context.device->logical_device, &allocate_info, &encoder.cmd_buffer);); - VkDescriptorPoolSize uniform_pool_size; - uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - uniform_pool_size.descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; + VkDescriptorPoolSize pool_sizes[2]; + // Uniforms pool + pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + pool_sizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; + // Samplers pool + pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_sizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; VkDescriptorPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; - pool_info.poolSizeCount = 1; - pool_info.pPoolSizes = &uniform_pool_size; + pool_info.poolSizeCount = 2; + pool_info.pPoolSizes = pool_sizes; pool_info.maxSets = 100; VK_CHECK(vkCreateDescriptorPool(context.device->logical_device, &pool_info, context.allocator, @@ -875,6 +887,8 @@ void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipe } void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data) { + arena tmp = arena_create(malloc(1024), 1024); + assert(data->data != NULL); // Update the local buffer @@ -886,44 +900,62 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d alloc_info.descriptorSetCount = 1; alloc_info.pSetLayouts = &encoder->pipeline->desc_set_layouts[group]; - VkDescriptorSet sets[1]; + shader_data_layout sdl = data->shader_data_get_layout(data->data); + size_t binding_count = sdl.bindings_count; + assert(binding_count == 2); + + VkDescriptorSet sets[0]; VK_CHECK(vkAllocateDescriptorSets(context.device->logical_device, &alloc_info, sets)); + // FIXME: hardcoded VkDescriptorSet_darray_push(context.free_set_queue, sets[0]); + /* VkDescriptorSet_darray_push(context.free_set_queue, sets[1]); */ - shader_data_layout sdl = data->shader_data_get_layout(NULL); - assert(sdl.bindings_count == 1); - - VkWriteDescriptorSet write_sets[1]; - memset(&write_sets, 0, sizeof(write_sets)); + VkWriteDescriptorSet write_sets[binding_count]; + memset(&write_sets, 0, binding_count * sizeof(VkWriteDescriptorSet)); - assert(sdl.bindings_count == 1); for (u32 i = 0; i < sdl.bindings_count; i++) { shader_binding binding = sdl.bindings[i]; if (binding.type == SHADER_BINDING_BUFFER || binding.type == SHADER_BINDING_BYTES) { - VkDescriptorBufferInfo buffer_info; - buffer_info.buffer = ubo.buffers[context.current_frame]; - buffer_info.offset = 0; - buffer_info.range = binding.data.bytes.size; - - write_sets[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_sets[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write_sets[0].descriptorCount = 1; - write_sets[0].dstSet = sets[0]; - write_sets[0].dstBinding = 0; - write_sets[0].dstArrayElement = 0; - write_sets[0].pBufferInfo = &buffer_info; - } else { + VkDescriptorBufferInfo* buffer_info = arena_alloc(&tmp, sizeof(VkDescriptorBufferInfo)); + buffer_info->buffer = ubo.buffers[context.current_frame]; + buffer_info->offset = 0; + buffer_info->range = binding.data.bytes.size; + + write_sets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_sets[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + write_sets[i].descriptorCount = 1; + write_sets[i].dstSet = sets[0]; + write_sets[i].dstBinding = i; + write_sets[i].dstArrayElement = 0; + write_sets[i].pBufferInfo = buffer_info; + } else if (binding.type == SHADER_BINDING_TEXTURE) { + gpu_texture* texture = TEXTURE_GET(binding.data.texture.handle); + VkDescriptorImageInfo* image_info = arena_alloc(&tmp, sizeof(VkDescriptorImageInfo)); + image_info->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + image_info->imageView = texture->view; + image_info->sampler = texture->sampler; + + write_sets[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_sets[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_sets[i].descriptorCount = 1; + write_sets[i].dstSet = sets[0]; + write_sets[i].dstBinding = i; + write_sets[i].dstArrayElement = 0; + write_sets[i].pImageInfo = image_info; + }else { WARN("Unknown binding"); } } // Update - vkUpdateDescriptorSets(context.device->logical_device, 1, write_sets, 0, NULL); + vkUpdateDescriptorSets(context.device->logical_device, binding_count, write_sets, 0, NULL); // Bind vkCmdBindDescriptorSets(encoder->cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, encoder->pipeline->layout_handle, 0, 1, sets, 0, NULL); + + arena_free_storage(&tmp); } void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf) { @@ -1453,19 +1485,15 @@ void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst) { vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); } -texture_handle gpu_texture_create(texture_desc desc, const void* data) { +texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) { VkDeviceSize image_size = desc.extents.x * desc.extents.y * 4; - TRACE("Uploading pixel data to texture using staging buffer"); - // Create a staging buffer - buffer_handle staging = - gpu_buffer_create(image_size, CEL_BUFFER_DEFAULT, CEL_BUFFER_FLAG_CPU, NULL); - // Copy data into it - buffer_upload_bytes(staging, (bytebuffer){ .buf = (u8*)data, .size = image_size }, 0, image_size); - VkImage image; VkDeviceMemory image_memory; + // FIXME: get from desc + VkFormat format = VK_FORMAT_R8G8B8A8_SRGB; + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.extent.width = desc.extents.x; @@ -1473,7 +1501,7 @@ texture_handle gpu_texture_create(texture_desc desc, const void* data) { image_create_info.extent.depth = 1; image_create_info.mipLevels = 1; image_create_info.arrayLayers = 1; - image_create_info.format = VK_FORMAT_R8G8B8A8_SRGB; + image_create_info.format = format; image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; @@ -1494,13 +1522,71 @@ texture_handle gpu_texture_create(texture_desc desc, const void* data) { vkBindImageMemory(context.device->logical_device, image, image_memory, 0); - gpu_buffer_destroy(staging); - texture_handle handle; gpu_texture* texture = texture_pool_alloc(&context.resource_pools->textures, &handle); + DEBUG("Allocated texture with handle %d", handle.raw); texture->handle = image; + texture->debug_label = "Test Texture"; + texture->desc = desc; texture->memory = image_memory; texture->size = image_size; + + if (data) { + TRACE("Uploading pixel data to texture using staging buffer"); + // Create a staging buffer + buffer_handle staging = + gpu_buffer_create(image_size, CEL_BUFFER_DEFAULT, CEL_BUFFER_FLAG_CPU, NULL); + // Copy data into it + vulkan_transition_image_layout(texture, format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + buffer_upload_bytes(staging, (bytebuffer){ .buf = (u8*)data, .size = image_size }, 0, image_size); + copy_buffer_to_image_oneshot(staging, handle); + vulkan_transition_image_layout(texture, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + gpu_buffer_destroy(staging); + } + + // Texture View + if (create_view) { + VkImageViewCreateInfo view_create_info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + view_create_info.image = image; + view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_create_info.format = format; + view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + view_create_info.subresourceRange.baseMipLevel = 0; + view_create_info.subresourceRange.levelCount = 1; + view_create_info.subresourceRange.baseArrayLayer = 0; + view_create_info.subresourceRange.layerCount = 1; + + VK_CHECK(vkCreateImageView(context.device->logical_device, &view_create_info, context.allocator, + &texture->view)); + } + + // Sampler + VkSamplerCreateInfo sampler_info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.anisotropyEnable = VK_TRUE; + sampler_info.maxAnisotropy = 16; + sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; + sampler_info.unnormalizedCoordinates = VK_FALSE; + sampler_info.compareEnable = VK_FALSE; + sampler_info.compareOp = VK_COMPARE_OP_ALWAYS; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.mipLodBias = 0.0; + sampler_info.minLod = 0.0; + sampler_info.maxLod = 0.0; + + VkResult res = vkCreateSampler(context.device->logical_device, &sampler_info, context.allocator, + &texture->sampler); + if (res != VK_SUCCESS) { + ERROR("Error creating texture sampler for image %s", texture->debug_label); + return; + } + return handle; } diff --git a/src/renderer/backends/backend_vulkan.h b/src/renderer/backends/backend_vulkan.h index 1e36ca3..dc0f7bd 100644 --- a/src/renderer/backends/backend_vulkan.h +++ b/src/renderer/backends/backend_vulkan.h @@ -109,4 +109,7 @@ typedef struct gpu_texture { VkDeviceMemory memory; u64 size; texture_desc desc; + VkImageView view; + VkSampler sampler; + char* debug_label; } gpu_texture; diff --git a/src/renderer/ral.h b/src/renderer/ral.h index a82a2ba..3697ea5 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -147,7 +147,7 @@ void gpu_buffer_upload(); void gpu_buffer_bind(buffer_handle buffer); // Textures -texture_handle gpu_texture_create(texture_desc desc, const void* data); +texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data); void gpu_texture_destroy(); void gpu_texture_upload(); diff --git a/src/renderer/ral_types.h b/src/renderer/ral_types.h index 8339625..62a2f1d 100644 --- a/src/renderer/ral_types.h +++ b/src/renderer/ral_types.h @@ -139,6 +139,7 @@ typedef struct custom_vertex { } custom_vertex; // Vertex attributes +/// @strip_prefix(ATTR_) typedef enum vertex_attrib_type { ATTR_F32, ATTR_F32x2, @@ -211,7 +212,10 @@ typedef struct shader_binding { void* data; size_t size; } bytes; - } data; /** @brief */ + struct { + texture_handle handle; + } texture; + } data; /** @brief can store any kind of data that we can bind to a shader / descriptor set */ } shader_binding; #define MAX_LAYOUT_BINDINGS 8 diff --git a/src/renderer/render.c b/src/renderer/render.c index 9f9a97c..5723c9e 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -230,8 +230,9 @@ texture_data texture_data_load(const char* path, bool invert_y) { } texture_handle texture_data_upload(texture_data data, bool free_on_upload) { - texture_handle handle = gpu_texture_create(data.description, data.image_data); + texture_handle handle = gpu_texture_create(data.description, true, data.image_data); if (free_on_upload) { + TRACE("Freed stb_image data"); stbi_image_free(data.image_data); } return handle; diff --git a/xmake.lua b/xmake.lua index 9b06db0..40ef961 100644 --- a/xmake.lua +++ b/xmake.lua @@ -123,6 +123,7 @@ target("core_config") add_files("assets/shaders/triangle.vert") add_files("assets/shaders/triangle.frag") add_files("assets/shaders/cube.vert") + add_files("assets/shaders/cube.frag") -- add_files("assets/shaders/*.frag") if is_plat("windows") then add_includedirs("$(env VULKAN_SDK)/Include", {public = true}) -- cgit v1.2.3-70-g09d2 From 63de5753d03dd7fe1f60b98e3825023d5b3392d6 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sun, 19 May 2024 23:26:32 +1000 Subject: wip: depth --- assets/shaders/cube.frag | 2 +- assets/shaders/cube.vert | 3 +- examples/cube/ex_cube.c | 8 +--- src/renderer/backends/backend_vulkan.c | 80 +++++++++++++++++++++++++--------- 4 files changed, 64 insertions(+), 29 deletions(-) (limited to 'examples/cube/ex_cube.c') diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag index 11f1efa..292578f 100644 --- a/assets/shaders/cube.frag +++ b/assets/shaders/cube.frag @@ -8,5 +8,5 @@ layout(binding = 1) uniform sampler2D texSampler; layout(location = 0) out vec4 outColor; void main() { - outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); + outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0); } diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert index fa9f85b..dc625ec 100644 --- a/assets/shaders/cube.vert +++ b/assets/shaders/cube.vert @@ -4,7 +4,8 @@ layout(binding = 0) uniform UniformBufferObject { mat4 model; mat4 view; mat4 proj; -} ubo; +} +ubo; layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; diff --git a/examples/cube/ex_cube.c b/examples/cube/ex_cube.c index 5d6cbbe..fc59e2d 100644 --- a/examples/cube/ex_cube.c +++ b/examples/cube/ex_cube.c @@ -39,8 +39,7 @@ shader_data_layout mvp_uniforms_layout(void* data) { shader_binding b2 = { .label = "texture_sampler", .type = SHADER_BINDING_TEXTURE, - .stores_data = has_data - }; + .stores_data = has_data }; if (has_data) { b1.data.bytes.data = &d->mvp; b2.data.texture.handle = d->tex; @@ -129,10 +128,7 @@ int main() { camera_view_projection(&cam, g_core.renderer.swapchain.extent.width, g_core.renderer.swapchain.extent.height, &view, &proj); mvp_uniforms mvp_data = { .model = model, .view = view, .projection = proj }; - my_shader_bind_group shader_bind_data = { - .mvp = mvp_data, - .tex = texture - }; + my_shader_bind_group shader_bind_data = { .mvp = mvp_data, .tex = texture }; mvp_uniforms_data.data = &shader_bind_data; encode_bind_shader_data(enc, 0, &mvp_uniforms_data); diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index e8b54d9..fc6d961 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -92,6 +92,7 @@ VkShaderModule create_shader_module(str8 spirv); /** @brief Helper function for creating array of all extensions we want */ cstr_darray* get_all_extensions(); +VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat format ,VkImageUsageFlags usage); void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkImageLayout old_layout, VkImageLayout new_layout); @@ -432,19 +433,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip size_t this_offset = vertex_attrib_size(description.vertex_desc.attributes[i]); printf("offset total %d this attr %ld\n", offset, this_offset); printf("sizeof vertex %ld\n", sizeof(vertex)); - /* printf("%d \n", offsetof(vertex, static_3d)); */ offset += this_offset; } - /* printf("Vertex attributes\n"); */ - /* attribute_descs[0].binding = 0; */ - /* attribute_descs[0].location = 0; */ - /* attribute_descs[0].format = VK_FORMAT_R32G32B32_SFLOAT; */ - /* attribute_descs[0].offset = 0; // offsetof(custom_vertex, pos); */ - - /* attribute_descs[1].binding = 0; */ - /* attribute_descs[1].location = 1; */ - /* attribute_descs[1].format = VK_FORMAT_R32G32B32_SFLOAT; */ - /* attribute_descs[1].offset = 12; // offsetof(custom_vertex, color); */ // Vertex input // TODO: Generate this from descroiption now @@ -735,6 +725,10 @@ gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { // TEMP: allocate with malloc. in the future we will have a pool allocator on the context gpu_renderpass* renderpass = malloc(sizeof(gpu_renderpass)); + // attachments + u32 attachment_desc_count = 2; + VkAttachmentDescription attachment_descriptions[2]; + // Colour attachment VkAttachmentDescription color_attachment; color_attachment.format = context.swapchain->image_format.format; @@ -747,16 +741,34 @@ gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; color_attachment.flags = 0; - // attachment_descriptions[0] = color_attachment; + 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; - - // TODO: Depth attachment + // Depth attachment + u32x2 ext = { .x = context.swapchain_support.capabilities.currentExtent.width, .y = context.swapchain_support.capabilities.currentExtent.height}; + texture_desc depth_desc = { .extents = ext, .format = CEL_TEXTURE_FORMAT_DEPTH_DEFAULT, .tex_type = CEL_TEXTURE_TYPE_2D}; + texture_handle depth_texture_handle = gpu_texture_create(depth_desc, true, NULL); + gpu_texture* depth = TEXTURE_GET(depth_texture_handle); + + VkAttachmentDescription depth_attachment; + depth_attachment.format = // TODO: 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; // main subpass VkSubpassDescription subpass = { 0 }; @@ -1485,15 +1497,38 @@ void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst) { vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); } +VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat format ,VkImageUsageFlags usage) { + VkImage image; + + VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + image_create_info.imageType = VK_IMAGE_TYPE_2D; + image_create_info.extent.width = dimensions.x; + image_create_info.extent.height = dimensions.y; + image_create_info.extent.depth = 1; + image_create_info.mipLevels = 1; + image_create_info.arrayLayers = 1; + image_create_info.format = format; + image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + image_create_info.usage = usage; // VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + + VK_CHECK( + vkCreateImage(context.device->logical_device, &image_create_info, context.allocator, &image)); + + return image; +} + texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data) { VkDeviceSize image_size = desc.extents.x * desc.extents.y * 4; + // FIXME: handle this properly + VkFormat format = desc.format == CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM ? VK_FORMAT_R8G8B8A8_SRGB : + VK_FORMAT_D32_SFLOAT; - VkImage image; + VkImage image; //vulkan_image_create(desc.extents, VK_IMAGE_TYPE_2D, format, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); VkDeviceMemory image_memory; - // FIXME: get from desc - VkFormat format = VK_FORMAT_R8G8B8A8_SRGB; - VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.extent.width = desc.extents.x; @@ -1505,6 +1540,9 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; image_create_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + if (format == VK_FORMAT_D32_SFLOAT) { + image_create_info.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } image_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; @@ -1551,7 +1589,7 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi view_create_info.image = image; view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_create_info.format = format; - view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_create_info.subresourceRange.aspectMask = format == VK_FORMAT_D32_SFLOAT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; view_create_info.subresourceRange.baseMipLevel = 0; view_create_info.subresourceRange.levelCount = 1; -- cgit v1.2.3-70-g09d2