From 519329e98467d0cdcc39720cef0f69c9936b6d55 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Fri, 17 May 2024 13:50:33 +1000 Subject: pool tests and try get macro working --- src/renderer/ral.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/renderer/ral.c (limited to 'src/renderer/ral.c') diff --git a/src/renderer/ral.c b/src/renderer/ral.c new file mode 100644 index 0000000..25c2909 --- /dev/null +++ b/src/renderer/ral.c @@ -0,0 +1,22 @@ +#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; +}; -- cgit v1.2.3-70-g09d2 From fcaf838886efc3c12f60b47c021c6a85965eb6e9 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Sat, 18 May 2024 14:15:23 +1000 Subject: initialise gpu resource pools in renderer --- assets/textures/texture.jpg | Bin 0 -> 77120 bytes scene.c | 1 + src/core.c | 4 +--- src/renderer/backends/backend_vulkan.c | 24 ++++++++++++++++++++++++ src/renderer/ral.c | 12 ++++++------ src/renderer/ral.h | 17 +++++++++++++++-- src/renderer/render.c | 19 ++++++++++++++----- src/renderer/render_types.h | 1 + src/scene.h | 6 ++++++ 9 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 assets/textures/texture.jpg create mode 100644 scene.c (limited to 'src/renderer/ral.c') diff --git a/assets/textures/texture.jpg b/assets/textures/texture.jpg new file mode 100644 index 0000000..975e338 Binary files /dev/null and b/assets/textures/texture.jpg differ diff --git a/scene.c b/scene.c new file mode 100644 index 0000000..69a8b3c --- /dev/null +++ b/scene.c @@ -0,0 +1 @@ +#include "scene.h" diff --git a/src/core.c b/src/core.c index 83c7b6e..84c9cae 100644 --- a/src/core.c +++ b/src/core.c @@ -78,6 +78,4 @@ void frame_begin() { render_frame_begin(&g_core.renderer); } void frame_draw() {} -void frame_end() { - render_frame_end(&g_core.renderer); -} +void frame_end() { render_frame_end(&g_core.renderer); } diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index 37f9b59..61527ee 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -65,6 +65,7 @@ typedef struct vulkan_context { gpu_buffer buffers[1024]; size_t buffer_count; VkDescriptorSet_darray* free_set_queue; + struct resource_pools* resource_pools; VkDebugUtilsMessengerEXT vk_debugger; } vulkan_context; @@ -1360,6 +1361,17 @@ void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_off context.buffers[dst.raw].handle, 1, ©_region); } +texture_handle gpu_texture_create(texture_desc desc, 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); +} + size_t vertex_attrib_size(vertex_attrib_type attr) { switch (attr) { case ATTR_F32: @@ -1392,3 +1404,15 @@ void vertex_desc_add(vertex_description* builder, const char* name, vertex_attri builder->attributes_count++; } + +/* TYPED_POOL(gpu_buffer, buffer); */ +/* TYPED_POOL(gpu_texture, texture); */ + +void resource_pools_init(arena* a, struct resource_pools* res_pools) { + buffer_pool buf_pool = buffer_pool_create(a, MAX_BUFFERS, sizeof(gpu_buffer)); + res_pools->buffers = buf_pool; + texture_pool tex_pool = texture_pool_create(a, MAX_TEXTURES, sizeof(gpu_texture)); + res_pools->textures = tex_pool; + + context.resource_pools = res_pools; +} diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 25c2909..6a417dd 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -13,10 +13,10 @@ /* } buffer_handle; */ /* typedef struct gpu_buffer gpu_buffer; */ -TYPED_POOL(gpu_buffer, buffer); -TYPED_POOL(gpu_texture, texture); +/* TYPED_POOL(gpu_buffer, buffer); */ +/* TYPED_POOL(gpu_texture, texture); */ -struct resource_pools { - buffer_pool buffers; - texture_pool textures; -}; +/* struct resource_pools { */ +/* buffer_pool buffers; */ +/* texture_pool textures; */ +/* }; */ diff --git a/src/renderer/ral.h b/src/renderer/ral.h index 03bdeab..da9eb93 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -32,6 +32,8 @@ typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer gpu_buffer; #define MAX_SHADER_DATA_LAYOUTS 5 +#define MAX_BUFFERS 256 +#define MAX_TEXTURES 256 /** @brief A*/ // typedef struct gpu_bind_group @@ -41,7 +43,7 @@ typedef struct gpu_backend_pools { // pools for each gpu structure } gpu_backend_pools; -typedef struct resource_pools resource_pools; +/* typedef struct resource_pools resource_pools; */ typedef enum pipeline_kind { PIPELINE_GRAPHICS, @@ -144,7 +146,7 @@ void gpu_buffer_upload(); void gpu_buffer_bind(buffer_handle buffer); // Textures -void gpu_texture_create(); +texture_handle gpu_texture_create(texture_desc desc, const void* data); void gpu_texture_destroy(); void gpu_texture_upload(); @@ -161,3 +163,14 @@ void vertex_desc_add(vertex_description* builder, const char* name, vertex_attri // TEMP void gpu_temp_draw(size_t n_verts); + +TYPED_POOL(gpu_buffer, buffer); +TYPED_POOL(gpu_texture, texture); + +struct resource_pools { + buffer_pool buffers; + texture_pool textures; +}; + +// Must be implemented by backends +void resource_pools_init(arena* a, struct resource_pools* res_pools); diff --git a/src/renderer/render.c b/src/renderer/render.c index 6eacc0d..c83678b 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -3,6 +3,7 @@ #include "camera.h" #include "file.h" #include "log.h" +#include "mem.h" #include "ral.h" #include "ral_types.h" @@ -46,6 +47,10 @@ bool renderer_init(renderer* ren) { gpu_device_create(&ren->device); // TODO: handle errors gpu_swapchain_create(&ren->swapchain); + DEBUG("Initialise GPU resource pools"); + arena pool_arena = arena_create(malloc(1024 * 1024), 1024 * 1024); + resource_pools_init(&pool_arena, ren->resource_pools); + // ren->blinn_phong = // shader_create_separate("assets/shaders/blinn_phong.vert", // "assets/shaders/blinn_phong.frag"); @@ -56,7 +61,7 @@ bool renderer_init(renderer* ren) { // default_material_init(); // Create default rendering pipeline - default_pipelines_init(ren); + /* default_pipelines_init(ren); */ return true; } @@ -75,11 +80,15 @@ void default_pipelines_init(renderer* ren) { ren->default_renderpass = *renderpass; - // str8 vert_path = str8lit("build/linux/x86_64/debug/triangle.vert.spv"); - // str8 frag_path = str8lit("build/linux/x86_64/debug/triangle.frag.spv"); printf("Load shaders\n"); - str8 vert_path = str8lit("/home/void/code/celeritas-engine/celeritas-core/build/linux/x86_64/debug/triangle.vert.spv"); - str8 frag_path = str8lit("/home/void/code/celeritas-engine/celeritas-core/build/linux/x86_64/debug/triangle.frag.spv"); + 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 vert_path = + * str8lit("/home/void/code/celeritas-engine/celeritas-core/build/linux/x86_64/debug/triangle.vert.spv"); + */ + /* str8 frag_path = + * str8lit("/home/void/code/celeritas-engine/celeritas-core/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) { diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index ac98627..bd9ef3c 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -35,6 +35,7 @@ typedef struct renderer { gpu_renderpass default_renderpass; gpu_pipeline static_opaque_pipeline; bool frame_aborted; + struct resource_pools* resource_pools; } renderer; typedef struct geometry_data { diff --git a/src/scene.h b/src/scene.h index 24429b3..5a85e2e 100644 --- a/src/scene.h +++ b/src/scene.h @@ -32,7 +32,13 @@ 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; */ void scene_set_dir_light(directional_light light); +void _scene_set_dir_light(vec3 ambient, vec3 diffuse, vec3 specular, vec3 direction); + void scene_add_point_light(point_light light); void scene_add_model(model_handle model, transform3d transform); bool scene_remove_model(model_handle model); -- 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 'src/renderer/ral.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 af65a3d6c3b5ed750af5bf08e04a4c7e4d0da239 Mon Sep 17 00:00:00 2001 From: Omniscient Date: Mon, 20 May 2024 10:43:32 +1000 Subject: cleanup ral.h --- README.md | 5 +- scene.c | 1 - scratchpad.md | 71 ----------------- src/renderer/backends/backend_vulkan.c | 136 +++++++++++++-------------------- src/renderer/ral.c | 33 ++++++++ src/renderer/ral.h | 96 ++++++++++------------- 6 files changed, 129 insertions(+), 213 deletions(-) delete mode 100644 scene.c delete mode 100644 scratchpad.md (limited to 'src/renderer/ral.c') diff --git a/README.md b/README.md index db00078..6a2545d 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ ![Backpack model with lighting](examples/obj_loading/backpack_screenshot.png) -Not all files are fleshed out right now. -**Work-in-progress**: porting over code from old repository. +**Work-in-progress**: This code is currently in flux as I port from OpenGL to a Vulkan backend with a homemade graphics API abstraction layer I'm developing named **RAL** (render abstraction layer) in the source code. All third-party dependencies are licensed under their own license. @@ -20,4 +19,4 @@ All third-party dependencies are licensed under their own license. * `xmake format` * Lint (no change) `find src/ -iname *.h -o -iname *.c | xargs clang-format --style=file --dry-run --Werror` * Format (edit in place) `find src/ \( -iname "*.h" -o -iname "*.c" \) | xargs clang-format -i --style=file` - * `clang-format` must be installed! \ No newline at end of file + * `clang-format` must be installed! diff --git a/scene.c b/scene.c deleted file mode 100644 index 69a8b3c..0000000 --- a/scene.c +++ /dev/null @@ -1 +0,0 @@ -#include "scene.h" diff --git a/scratchpad.md b/scratchpad.md deleted file mode 100644 index 19ad8b4..0000000 --- a/scratchpad.md +++ /dev/null @@ -1,71 +0,0 @@ - -```c -// engine.h -#pragma once - -#include -#include -#include -#include -#include "threadpool.h" - -typedef struct frame_stats {} frame_stats; - -typedef struct engine_stats { - frame_stats frame; -} engine_stats; - -typedef struct engine { - // timing - float startTime; - float deltaTime; // time between current frame and last frame - float lastFrame; - // stats - engine_stats stats; -} engine; - -static bool engine_init(engine *engine) { - engine->startTime = glfwGetTime(); - engine->deltaTime = 0.0f; - engine->lastFrame = 0.0f; - - return true; -} - -static inline void engine_tick_start(engine *engine) { - float currentFrame = glfwGetTime(); - engine->deltaTime = currentFrame - engine->lastFrame; - engine->lastFrame = currentFrame; -} - -static inline void engine_tick_end(engine *engine) { - // TODO: clear frame stats -} - -void celeritas_print_type_sizes(); -``` - -```c -// engine.c -#include "engine.h" - -#include - -#include "animation.h" -#include "application.h" - -void celeritas_print_type_sizes() { - printf("\e[1mType sizes: \e[m \n"); - printf("transform: %ld bytes\n", sizeof(transform)); - printf("mesh: %ld bytes\n", sizeof(mesh)); - printf("bh_material: %ld bytes\n", sizeof(bh_material)); - printf("animation: %ld bytes\n", sizeof(animation_clip)); - printf("model: %ld bytes\n", sizeof(model)); - printf("rend_buffer: %ld bytes\n", sizeof(rend_buffer)); - - printf("application: %ld bytes\n", sizeof(cel_application)); - printf("renderer: %ld bytes\n", sizeof(renderer)); - printf("threadpool: %ld bytes\n", sizeof(threadpool)); - printf("engine: %ld bytes\n", sizeof(engine)); -} -``` \ No newline at end of file diff --git a/src/renderer/backends/backend_vulkan.c b/src/renderer/backends/backend_vulkan.c index fc6d961..ef266e0 100644 --- a/src/renderer/backends/backend_vulkan.c +++ b/src/renderer/backends/backend_vulkan.c @@ -92,7 +92,8 @@ 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); +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); @@ -580,7 +581,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip case SHADER_BINDING_BUFFER: case SHADER_BINDING_BYTES: 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 + desc_set_bindings[binding_j].stageFlags = + VK_SHADER_STAGE_VERTEX_BIT; // FIXME: dont hardcode u64 buffer_size = sdl.bindings[binding_j].data.bytes.size; VkDeviceSize uniform_buf_size = buffer_size; @@ -616,7 +618,8 @@ gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc descrip 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].stageFlags = + VK_SHADER_STAGE_FRAGMENT_BIT; // FIXME: dont hardcode desc_set_bindings[binding_j].pImmutableSamplers = NULL; break; @@ -748,14 +751,17 @@ gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // 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}; + 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.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; @@ -808,15 +814,6 @@ gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { return renderpass; } -void encode_set_pipeline(gpu_cmd_encoder* encoder, gpu_pipeline* pipeline) { - // VK_PIPELINE_BIND_POINT_GRAPHICS, &shader->pipeline); - // if (kind == PIPELINE_GRAPHICS) { - // // ... - // } else { - // // ... - // } -} - gpu_cmd_encoder gpu_cmd_encoder_create() { // gpu_cmd_encoder* encoder = malloc(sizeof(gpu_cmd_encoder)); // TODO: fix leaking mem gpu_cmd_encoder encoder = { 0 }; @@ -834,7 +831,7 @@ gpu_cmd_encoder gpu_cmd_encoder_create() { // Uniforms pool pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; pool_sizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; - // Samplers pool + // Samplers pool pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; pool_sizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT * MAX_DESCRIPTOR_SETS; @@ -955,7 +952,7 @@ void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* d write_sets[i].dstBinding = i; write_sets[i].dstArrayElement = 0; write_sets[i].pImageInfo = image_info; - }else { + } else { WARN("Unknown binding"); } } @@ -1497,7 +1494,8 @@ 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 vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat format, + VkImageUsageFlags usage) { VkImage image; VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; @@ -1510,7 +1508,7 @@ VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat f 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.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; @@ -1523,10 +1521,11 @@ VkImage vulkan_image_create(u32x2 dimensions, VkImageType image_type, VkFormat f 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; + VkFormat format = desc.format == CEL_TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM ? VK_FORMAT_R8G8B8A8_SRGB + : VK_FORMAT_D32_SFLOAT; - VkImage image; //vulkan_image_create(desc.extents, VK_IMAGE_TYPE_2D, format, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + 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; VkImageCreateInfo image_create_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; @@ -1575,10 +1574,13 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi 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); + 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); + vulkan_transition_image_layout(texture, format, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); gpu_buffer_destroy(staging); } @@ -1589,7 +1591,8 @@ 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 = format == VK_FORMAT_D32_SFLOAT ? VK_IMAGE_ASPECT_DEPTH_BIT : 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; @@ -1601,29 +1604,29 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi } // 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; - } + 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; } @@ -1673,39 +1676,6 @@ void vulkan_transition_image_layout(gpu_texture* texture, VkFormat format, VkIma vulkan_command_buffer_finish_oneshot(temp_cmd_buffer); } -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++; -} - /* TYPED_POOL(gpu_buffer, buffer); */ /* TYPED_POOL(gpu_texture, texture); */ diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 304017d..2ae7c23 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -1 +1,34 @@ #include "ral.h" + +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.h b/src/renderer/ral.h index 3697ea5..4f23ad0 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -18,10 +18,9 @@ #include "str.h" // Unrelated forward declares -typedef struct arena arena; struct GLFWwindow; -// Forward declare structs +// Forward declare structs - these must be defined in the backend implementation typedef struct gpu_swapchain gpu_swapchain; typedef struct gpu_device gpu_device; typedef struct gpu_pipeline_layout gpu_pipeline_layout; @@ -36,15 +35,17 @@ typedef struct gpu_texture gpu_texture; #define MAX_BUFFERS 256 #define MAX_TEXTURES 256 -/** @brief A*/ -// typedef struct gpu_bind_group +TYPED_POOL(gpu_buffer, buffer); +TYPED_POOL(gpu_texture, texture); -// Pools -typedef struct gpu_backend_pools { - // pools for each gpu structure +// --- Pools +typedef struct gpu_backend_pools { /* TODO: pools for each gpu structure */ } gpu_backend_pools; -/* typedef struct resource_pools resource_pools; */ +struct resource_pools { + buffer_pool buffers; + texture_pool textures; +}; typedef enum pipeline_kind { PIPELINE_GRAPHICS, @@ -64,13 +65,10 @@ struct graphics_pipeline_desc { 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 ? + // - texture for shadow map shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; u32 data_layouts_count; @@ -81,30 +79,30 @@ struct graphics_pipeline_desc { bool depth_test; }; -typedef struct gpu_renderpass_desc { +typedef struct gpu_renderpass_desc { /* TODO */ } gpu_renderpass_desc; // --- Lifecycle functions - bool gpu_backend_init(const char* window_name, struct GLFWwindow* window); void gpu_backend_shutdown(); - -// TEMP -bool gpu_backend_begin_frame(); -void gpu_backend_end_frame(); +void resource_pools_init(arena* a, struct resource_pools* res_pools); bool gpu_device_create(gpu_device* out_device); void gpu_device_destroy(); -gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description); -void gpu_renderpass_destroy(gpu_renderpass* pass); - +// --- Render Pipeline gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description); void gpu_pipeline_destroy(gpu_pipeline* pipeline); +// --- Renderpass +gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description); +void gpu_renderpass_destroy(gpu_renderpass* pass); + +// --- Swapchain bool gpu_swapchain_create(gpu_swapchain* out_swapchain); void gpu_swapchain_destroy(gpu_swapchain* swapchain); +// --- Command buffer gpu_cmd_encoder gpu_cmd_encoder_create(); void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder); void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder); @@ -113,16 +111,20 @@ void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder); void gpu_cmd_encoder_begin_compute(); gpu_cmd_encoder* gpu_get_default_cmd_encoder(); -/* Actual commands that we can encode */ +// --- Data copy commands +/** @brief Copy data from one buffer to another */ void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset, buffer_handle dst, u64 dst_offset, u64 copy_size); -void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -void encode_set_pipeline(gpu_cmd_encoder* encoder, gpu_pipeline* pipeline); - /** @brief Upload CPU-side data as array of bytes to a GPU buffer */ void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size); -// render pass +/** @brief Copy data from buffer to buffer using a one time submit command buffer and a wait */ +void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, + u64 dst_offset, u64 copy_size); +/** @brief Copy data from buffer to an image using a one time submit command buffer */ +void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst); + +// --- Render commands void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline); void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data); void encode_set_default_settings(gpu_cmd_encoder* encoder); @@ -131,53 +133,37 @@ void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); void encode_set_bind_group(); // TODO void encode_draw(gpu_cmd_encoder* encoder); void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count); +void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -// FUTURE: compute passes /** @brief Finish recording and return a command buffer that can be submitted to a queue */ gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder); void gpu_queue_submit(gpu_cmd_buffer* buffer); -// Buffers +// --- Buffers buffer_handle gpu_buffer_create(u64 size, gpu_buffer_type buf_type, gpu_buffer_flags flags, const void* data); void gpu_buffer_destroy(buffer_handle buffer); -void gpu_buffer_upload(); -void gpu_buffer_bind(buffer_handle buffer); +void gpu_buffer_upload(const void* data); // Textures +/** @brief Create a new GPU texture resource. + * @param create_view creates a texture view (with same dimensions) at the same time + * @param data if not NULL then the data stored at the pointer will be uploaded to the GPU texture + * @note automatically creates a sampler for you */ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const void* data); -void gpu_texture_destroy(); -void gpu_texture_upload(); - -// Samplers -void gpu_sampler_create(); +void gpu_texture_destroy(texture_handle); +void gpu_texture_upload(texture_handle texture, const void* data); // --- 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 - +// --- TEMP +bool gpu_backend_begin_frame(); +void gpu_backend_end_frame(); void gpu_temp_draw(size_t n_verts); -TYPED_POOL(gpu_buffer, buffer); -TYPED_POOL(gpu_texture, texture); - -struct resource_pools { - buffer_pool buffers; - texture_pool textures; -}; - -// 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 +// TODO: --- Compute -- cgit v1.2.3-70-g09d2 From 73d4145f46d2305f45761b8e456df692d1962dfb Mon Sep 17 00:00:00 2001 From: Omniscient Date: Mon, 20 May 2024 10:49:57 +1000 Subject: move standard vertex desc to ral.c --- src/renderer/bind_group_layouts.h | 4 ++-- src/renderer/ral.c | 8 ++++++++ src/renderer/ral.h | 3 +++ src/renderer/standard_vertex_types.c | 11 ----------- 4 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 src/renderer/standard_vertex_types.c (limited to 'src/renderer/ral.c') diff --git a/src/renderer/bind_group_layouts.h b/src/renderer/bind_group_layouts.h index d2571ef..246d1ef 100644 --- a/src/renderer/bind_group_layouts.h +++ b/src/renderer/bind_group_layouts.h @@ -16,10 +16,10 @@ // 1. Scene / Global typedef struct bg_globals { - f32 total_time; - f32 delta_time; mat4 view; mat4 projection; + f32 total_time; + f32 delta_time; } bg_globals; // 2. Material (once per object) diff --git a/src/renderer/ral.c b/src/renderer/ral.c index 2ae7c23..7d868be 100644 --- a/src/renderer/ral.c +++ b/src/renderer/ral.c @@ -32,3 +32,11 @@ void vertex_desc_add(vertex_description* builder, const char* name, vertex_attri builder->attributes_count++; } + +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; +} diff --git a/src/renderer/ral.h b/src/renderer/ral.h index bd2d701..376898f 100644 --- a/src/renderer/ral.h +++ b/src/renderer/ral.h @@ -166,3 +166,6 @@ void gpu_backend_end_frame(); void gpu_temp_draw(size_t n_verts); // TODO: --- Compute + +// --- Helpers +vertex_description static_3d_vertex_description(); diff --git a/src/renderer/standard_vertex_types.c b/src/renderer/standard_vertex_types.c deleted file mode 100644 index 4973bf0..0000000 --- a/src/renderer/standard_vertex_types.c +++ /dev/null @@ -1,11 +0,0 @@ -#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 -- cgit v1.2.3-70-g09d2