386 lines
12 KiB
C
386 lines
12 KiB
C
#include "render.h"
|
|
#include "arpa/inet.h"
|
|
#include "pipeline.h"
|
|
#include "vk_mem_alloc.h"
|
|
#include "vulkan/vk_enum_string_helper.h"
|
|
#include "vulkan/vulkan_core.h"
|
|
|
|
#include "ft2build.h"
|
|
#include FT_FREETYPE_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;
|
|
}
|
|
|
|
typedef struct TextPointersMemoryStruct {
|
|
VmaAllocation pointers_memory;
|
|
VmaAllocation draw_memory;
|
|
VmaAllocation strings_memory;
|
|
VmaAllocation codes_memory;
|
|
VmaAllocation characters_memory;
|
|
VmaAllocation draw_clear_memory;
|
|
|
|
VkBuffer pointers_buffer;
|
|
VkBuffer draw_buffer;
|
|
VkBuffer draw_clear_buffer;
|
|
VkBuffer strings_buffer;
|
|
VkBuffer codes_buffer;
|
|
VkBuffer characters_buffer;
|
|
} TextPointersMemory;
|
|
|
|
VkResult create_text_pointers(
|
|
uint32_t max_strings,
|
|
uint32_t max_characters,
|
|
VkDevice device,
|
|
VmaAllocator allocator,
|
|
VkCommandPool transfer_pool,
|
|
Queue transfer_queue,
|
|
TextPointersMemory* memory,
|
|
VkDeviceAddress* address) {
|
|
VkResult result;
|
|
|
|
VmaAllocationCreateInfo memory_info = {
|
|
.usage = VMA_MEMORY_USAGE_GPU_ONLY,
|
|
};
|
|
|
|
VkBufferCreateInfo pointers_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = sizeof(StringPointers),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &pointers_info, &memory_info, &memory->pointers_buffer, &memory->pointers_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferCreateInfo draw_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = sizeof(DrawCommand),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &draw_info, &memory_info, &memory->draw_buffer, &memory->draw_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferCreateInfo draw_clear_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = sizeof(DrawCommand),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &draw_clear_info, &memory_info, &memory->draw_clear_buffer, &memory->draw_clear_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferCreateInfo strings_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = max_strings*sizeof(String),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &strings_info, &memory_info, &memory->strings_buffer, &memory->strings_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferCreateInfo codes_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = max_characters*sizeof(DrawCommand),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &codes_info, &memory_info, &memory->codes_buffer, &memory->codes_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferCreateInfo characters_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.size = max_characters*sizeof(DrawCommand),
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
};
|
|
|
|
result = vmaCreateBuffer(allocator, &characters_info, &memory_info, &memory->characters_buffer, &memory->characters_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBufferDeviceAddressInfo pointers_address = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
.buffer = memory->pointers_buffer,
|
|
};
|
|
|
|
VkBufferDeviceAddressInfo strings_address = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
.buffer = memory->strings_buffer,
|
|
};
|
|
|
|
VkBufferDeviceAddressInfo codes_address = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
.buffer = memory->codes_buffer,
|
|
};
|
|
|
|
VkBufferDeviceAddressInfo characters_address = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
.buffer = memory->characters_buffer,
|
|
};
|
|
|
|
VkBufferDeviceAddressInfo draw_address = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,
|
|
.buffer = memory->draw_buffer,
|
|
};
|
|
|
|
VkBuffer temp_buffer;
|
|
VmaAllocation temp_memory;
|
|
VkBufferCreateInfo temp_buffer_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
.size = sizeof(StringPointers) +
|
|
sizeof(DrawCommand),
|
|
};
|
|
VmaAllocationCreateInfo temp_memory_info = {
|
|
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
|
|
};
|
|
result = vmaCreateBuffer(allocator, &temp_buffer_info, &temp_memory_info, &temp_buffer, &temp_memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
void* mapped;
|
|
result = vmaMapMemory(allocator, temp_memory, &mapped);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
DrawCommand draw = {
|
|
.index_count = 6,
|
|
};
|
|
|
|
memcpy(mapped + 0, &draw, sizeof(DrawCommand));
|
|
StringPointers pointers = {
|
|
.strings = vkGetBufferDeviceAddress(device, &strings_address),
|
|
.codes = vkGetBufferDeviceAddress(device, &codes_address),
|
|
.characters = vkGetBufferDeviceAddress(device, &characters_address),
|
|
.draw = vkGetBufferDeviceAddress(device, &draw_address),
|
|
};
|
|
memcpy(mapped + sizeof(DrawCommand), &pointers, sizeof(StringPointers));
|
|
vmaUnmapMemory(allocator, temp_memory);
|
|
|
|
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
|
|
VkBufferCopy copy_draw = {
|
|
.size = sizeof(DrawCommand),
|
|
.srcOffset = 0,
|
|
};
|
|
vkCmdCopyBuffer(command_buffer, temp_buffer, memory->draw_buffer, 1, ©_draw);
|
|
vkCmdCopyBuffer(command_buffer, temp_buffer, memory->draw_clear_buffer, 1, ©_draw);
|
|
VkBufferCopy copy_pointers = {
|
|
.size = sizeof(StringPointers),
|
|
.srcOffset = sizeof(DrawCommand),
|
|
};
|
|
vkCmdCopyBuffer(command_buffer, temp_buffer, memory->pointers_buffer, 1, ©_pointers);
|
|
result = command_end_single(device, command_buffer, transfer_pool, transfer_queue);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
vmaDestroyBuffer(allocator, temp_buffer, temp_memory);
|
|
*address = vkGetBufferDeviceAddress(device, &pointers_address);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult create_transfer_buffer(VkDeviceSize size, VmaAllocator allocator, VkBuffer* buffer, VmaAllocation* memory, void** mapped) {
|
|
VkBufferCreateInfo buffer_info = {
|
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
.size = size,
|
|
};
|
|
VmaAllocationCreateInfo memory_info = {
|
|
.usage = VMA_MEMORY_USAGE_CPU_TO_GPU,
|
|
};
|
|
|
|
VkResult result = vmaCreateBuffer(allocator, &buffer_info, &memory_info, buffer, memory, NULL);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
result = vmaMapMemory(allocator, *memory, mapped);
|
|
if(result != VK_SUCCESS) {
|
|
vmaDestroyBuffer(allocator, *buffer, *memory);
|
|
return result;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult render_thread(GLFWwindow* window, RenderContext* render_context) {
|
|
VkResult result;
|
|
UIContext ui_context;
|
|
VkBuffer colored_rect_buffer;
|
|
VmaAllocation colored_rect_memory;
|
|
|
|
result = init_pipelines(render_context->device, render_context->allocator, render_context->swapchain_extent, render_context->window_scale, render_context->render_pass, render_context->transfer_queue, render_context->transfer_pool, &ui_context);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
FT_Library library;
|
|
if(FT_Init_FreeType(&library) != FT_Err_Ok) {
|
|
return VK_ERROR_UNKNOWN;
|
|
}
|
|
|
|
FontDescriptor test_font;
|
|
uint32_t* charmap;
|
|
result = load_font(render_context->device, render_context->allocator, ui_context.font_layout, ui_context.font_pool, render_context->transfer_pool, render_context->transfer_queue, library, "test.ttf", 16, VK_TRUE, &charmap, &test_font);
|
|
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);
|
|
|
|
TextPointersMemory text_pointers;
|
|
VkDeviceAddress text_pointers_address;
|
|
result = create_text_pointers(10, 100, render_context->device, render_context->allocator, render_context->transfer_pool, render_context->transfer_queue, &text_pointers, &text_pointers_address);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
VkBuffer temp_buffer;
|
|
VmaAllocation temp_memory;
|
|
void* mapped;
|
|
result = create_transfer_buffer(sizeof(String) + 100*sizeof(uint32_t), render_context->allocator, &temp_buffer, &temp_memory, (void**)&mapped);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
String* mapped_string = (String*)mapped;
|
|
mapped_string->pos[0] = 200.0;
|
|
mapped_string->pos[1] = 200.0;
|
|
mapped_string->pos[2] = 0.5;
|
|
mapped_string->color[0] = 1.0;
|
|
mapped_string->color[1] = 1.0;
|
|
mapped_string->color[2] = 1.0;
|
|
mapped_string->color[3] = 1.0;
|
|
mapped_string->size = 50.0;
|
|
mapped_string->length = 100;
|
|
mapped_string->offset = 0;
|
|
|
|
uint32* mapped_codes = (uint32_t*)(mapped + sizeof(String));
|
|
for(uint32_t i = 0; i < 100; i++) {
|
|
mapped_codes[i] = i;
|
|
}
|
|
|
|
VkCommandBuffer command_buffer = command_begin_single(render_context->device, render_context->transfer_pool);
|
|
VkBufferCopy copy_string = {
|
|
.size = sizeof(String),
|
|
.srcOffset = 0,
|
|
};
|
|
vkCmdCopyBuffer(command_buffer, temp_buffer, text_pointers.strings_buffer, 1, ©_string);
|
|
VkBufferCopy copy_codes = {
|
|
.size = 100*sizeof(uint32_t),
|
|
.srcOffset = sizeof(String),
|
|
};
|
|
vkCmdCopyBuffer(command_buffer, temp_buffer, text_pointers.codes_buffer, 1, ©_codes);
|
|
result = command_end_single(render_context->device, command_buffer, render_context->transfer_pool, render_context->transfer_queue);
|
|
if(result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
vkQueueWaitIdle(render_context->transfer_queue.handle);
|
|
vmaUnmapMemory(render_context->allocator, temp_memory);
|
|
vmaDestroyBuffer(render_context->allocator, temp_buffer, temp_memory);
|
|
|
|
UILayer test_layer = {
|
|
.colored_rects = colored_rect_buffer,
|
|
.colored_rect_count = 3,
|
|
|
|
.font = test_font,
|
|
.chars_size = 10*sizeof(Character),
|
|
.chars = text_pointers.characters_buffer,
|
|
.string_count = 1,
|
|
.string_pointers = text_pointers_address,
|
|
.string_draw = text_pointers.draw_buffer,
|
|
.string_draw_clear = text_pointers.draw_clear_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;
|
|
}
|