#include "render.h" #include "pipeline.h" #include "vk_mem_alloc.h" #include "vulkan/vk_enum_string_helper.h" #include "vulkan/vulkan_core.h" #include "spng.h" ColoredRect colored_rect(float width, float height, float r, float g, float b, float a, float x, float y, float z) { ColoredRect rect = { .size = {width, height}, .pos = {x, y, z}, .color = {r, g, b, a}, }; return rect; } VkResult load_font(const char* atlas_file, const char* metadata_file, FontData* font, SymbolInfo** symbols, uint32_t** image) { FILE* atlas = fopen(atlas_file, "rb"); if(atlas == NULL) { return VK_ERROR_UNKNOWN; } fseek(atlas, 0L, SEEK_END); size_t buf_size = ftell(atlas); void* buf = malloc(buf_size); fseek(atlas, 0L, SEEK_SET); size_t read = fread(buf, buf_size, 1, atlas); if(read != 1) { return VK_ERROR_UNKNOWN; } fclose(atlas); size_t out_size = 0; spng_ctx *ctx = spng_ctx_new(0); int result = 0; result = spng_set_png_buffer(ctx, buf, buf_size); if(result != SPNG_OK) { return VK_ERROR_UNKNOWN; } result = spng_decoded_image_size(ctx, SPNG_FMT_RGBA8, &out_size); if(result != SPNG_OK) { return VK_ERROR_UNKNOWN; } *image = malloc(out_size); result = spng_decode_image(ctx, *image, out_size, SPNG_FMT_RGBA8, 0); if(result != SPNG_OK) { return VK_ERROR_UNKNOWN; } struct spng_ihdr ihdr; result = spng_get_ihdr(ctx, &ihdr); if(result != SPNG_OK) { return VK_ERROR_UNKNOWN; } font->info.height = ihdr.height; font->info.width = ihdr.width; spng_ctx_free(ctx); free(buf); FILE* metadata = fopen(metadata_file, "rb"); if(atlas == NULL) { return VK_ERROR_UNKNOWN; } uint16_t symbol_count; uint8_t ascent, descent; fread(&symbol_count, 2, 1, metadata); fread(&ascent, 1, 1, metadata); fread(&descent, 1, 1, metadata); font->info.num_symbols = ntohs(symbol_count); *symbols = malloc(sizeof(SymbolInfo)*symbol_count); font->codes = malloc(sizeof(uint16_t)*symbol_count); uint8_t width; uint8_t top; uint16_t code; uint32_t x; for(uint16_t i = 0; i < symbol_count; i++) { fread(&code, 2, 1, metadata); font->codes[i] = ntohs(code); fread(&x, 4, 1, metadata); (*symbols)[i].x = ntohl(x); fread(&width, 1, 1, metadata); (*symbols)[i].width = width; fread(&top, 1, 1, metadata); (*symbols)[i].top = top; } fclose(metadata); return VK_SUCCESS; } VkResult render_thread(GLFWwindow* window, RenderContext* render_context) { VkResult result; UIContext ui_context; VkBuffer colored_rect_buffer; VkBuffer text_buffer; VmaAllocation colored_rect_memory; VmaAllocation text_memory; result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->world_render_pass, render_context->transfer_queue, render_context->transfer_pool, &ui_context); if(result != VK_SUCCESS) { return result; } FontData test_font = {}; uint32_t* test_atlas; SymbolInfo* test_symbols; result = load_font("tools/test.png", "tools/test.meta", &test_font, &test_symbols, &test_atlas); if(result != VK_SUCCESS) { return result; } FontDescriptor test_font_descriptor; result = create_text_descriptor(render_context->device, render_context->allocator, ui_context.font_layout, ui_context.font_pool, &test_font, test_symbols, test_atlas, render_context->transfer_pool, render_context->transfer_queue, &test_font_descriptor); if(result != VK_SUCCESS) { return result; } VkBufferCreateInfo colored_rect_buffer_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, .size = 3*sizeof(ColoredRect), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; VmaAllocationCreateInfo colored_rect_memory_info = { .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, }; result = vmaCreateBuffer(render_context->allocator, &colored_rect_buffer_info, &colored_rect_memory_info, &colored_rect_buffer, &colored_rect_memory, NULL); if(result != VK_SUCCESS) { return result; } ColoredRect* colored_rects; result = vmaMapMemory(render_context->allocator, colored_rect_memory, (void**)&colored_rects); if(result != VK_SUCCESS) { return result; } colored_rects[0] = colored_rect(100.0, 100.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.5); colored_rects[1] = colored_rect(100.0, 100.0, 0.0, 1.0, 0.0, 1.0, 0.0, 100.0, 0.5); colored_rects[2] = colored_rect(100.0, 100.0, 0.0, 0.0, 1.0, 1.0, 100.0, 0.0, 0.5); vmaUnmapMemory(render_context->allocator, colored_rect_memory); VkBufferCreateInfo text_buffer_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, .size = 2*sizeof(Char), .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; VmaAllocationCreateInfo text_memory_info = { .usage = VMA_MEMORY_USAGE_CPU_TO_GPU, }; result = vmaCreateBuffer(render_context->allocator, &text_buffer_info, &text_memory_info, &text_buffer, &text_memory, NULL); if(result != VK_SUCCESS) { return result; } Char* text; result = vmaMapMemory(render_context->allocator, text_memory, (void**)&text); if(result != VK_SUCCESS) { return result; } text[0].size[0] = 200.0f; text[0].size[1] = 200.0f; text[0].color[0] = 1.0f; text[0].color[1] = 1.0f; text[0].color[2] = 1.0f; text[0].color[3] = 1.0f; text[0].pos[0] = 200.0f; text[0].pos[1] = 200.0f; text[0].code = 0; text[1].size[0] = 200.0f; text[1].size[1] = 200.0f; text[1].color[0] = 1.0f; text[1].color[1] = 1.0f; text[1].color[2] = 1.0f; text[1].color[3] = 1.0f; text[1].pos[0] = 400.0f; text[1].pos[1] = 200.0f; text[1].code = 1; vmaUnmapMemory(render_context->allocator, text_memory); UILayer test_layer = { .colored_rects = colored_rect_buffer, .colored_rect_count = 3, .font = test_font_descriptor, .text_count = 2, .texts = text_buffer, }; while(glfwWindowShouldClose(window) == 0) { glfwPollEvents(); result = draw_frame(render_context, &ui_context, &test_layer, 1); if(result != VK_SUCCESS) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); return result; } } return 0; } int logic_thread() { return 0; } int network_thread() { return 0; } int main() { GLFWwindow* window = init_window(); if(window == NULL) { return 1; } RenderContext render_context = {}; if(init_vulkan(window, &render_context) != VK_SUCCESS) { return 2; } if(render_thread(window, &render_context) != VK_SUCCESS) { return 3; } return 0; }