From cc06265ca68129df2015316d44ffc1a8cba07e9c Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Thu, 24 Oct 2024 20:49:59 -0600 Subject: [PATCH] Pass time to shaders --- client/include/draw.h | 5 +- client/include/gpu.h | 14 ++-- client/include/ui.h | 14 +++- client/shader_src/string.comp | 11 +-- client/shader_src/ui.frag | 7 +- client/shader_src/ui.vert | 27 +++--- client/shader_src/ui_common.glsl | 25 ++++-- client/src/draw.c | 121 ++++++++++++++------------- client/src/gpu.c | 10 +-- client/src/main.c | 136 ++++++++++++++++++++----------- client/src/ui.c | 2 +- 11 files changed, 205 insertions(+), 167 deletions(-) diff --git a/client/include/draw.h b/client/include/draw.h index 00f00eb..bca234e 100644 --- a/client/include/draw.h +++ b/client/include/draw.h @@ -6,10 +6,7 @@ VkResult draw_frame( RenderContext* context, + UIContext* ui, double time); -VkResult record_draw_commands( - RenderContext* context, - UIContext* ui_context); - #endif diff --git a/client/include/gpu.h b/client/include/gpu.h index 5d629df..7019288 100644 --- a/client/include/gpu.h +++ b/client/include/gpu.h @@ -24,20 +24,20 @@ #include #include -typedef struct QueueStruct { +typedef struct GPUQueueStruct { VkQueue handle; uint32_t family; uint32_t index; -} Queue; +} GPUQueue; VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool); -VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue transfer_queue); +VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, GPUQueue transfer_queue); void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer dst, VkDeviceSize src_offset, VkDeviceSize dst_offset, VkDeviceSize size); -VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, Queue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags); +VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, GPUQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags); #define VK_RESULT(x) {\ result = x;\ @@ -66,9 +66,9 @@ typedef struct RenderContextStruct { VkPhysicalDevice physical_device; VkPhysicalDeviceMemoryProperties memories; VkSurfaceKHR surface; - Queue graphics_queue; - Queue present_queue; - Queue transfer_queue; + GPUQueue graphics_queue; + GPUQueue present_queue; + GPUQueue transfer_queue; VkDevice device; VmaAllocator allocator; diff --git a/client/include/ui.h b/client/include/ui.h index 87b317c..7c560e1 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -38,6 +38,12 @@ typedef struct DispatchCommandStruct { uint32_t z; } DispatchCommand; +typedef struct UIPushConstantStruct { + VkDeviceAddress layer; + float time; + float pad; +} UIPushConstant; + typedef struct GPUFontStruct { VkDeviceAddress symbol_list; uint32_t num_symbols; @@ -91,8 +97,10 @@ typedef struct GPUDrawableStruct { vec2 size; vec4 color; uint32_t type; - uint32_t code; - uint32_t index; + uint32_t var1; + uint32_t var2; + float var3; + float var4; uint32_t id; } GPUDrawable; @@ -147,6 +155,8 @@ typedef struct GPUContainerStruct { vec2 offset; vec2 size; uint32_t anchor; + + VkDeviceAddress context; } GPUContainer; typedef struct ContainerStruct { diff --git a/client/shader_src/string.comp b/client/shader_src/string.comp index fea255d..c1a0ec5 100644 --- a/client/shader_src/string.comp +++ b/client/shader_src/string.comp @@ -3,17 +3,12 @@ #include "ui_common.glsl" -layout(std430, push_constant) uniform PushConstant { - Context context; - Layer layer; -} pc; - layout(local_size_x = 1) in; void main() { uint gID = gl_GlobalInvocationID.x; String string = pc.layer.strings.s[gID]; - Font font = pc.context.fonts.f[string.font]; + Font font = pc.layer.container.context.fonts.f[string.font]; uint buffer_pos = atomicAdd(pc.layer.draw.instance_count, string.len); vec2 pen = vec2(0.0, 0.0); @@ -24,8 +19,8 @@ void main() { pen += string.size*symbol.advance; pc.layer.drawables.d[buffer_pos + i].size = vec2(string.size, string.size); pc.layer.drawables.d[buffer_pos + i].color = string.color; - pc.layer.drawables.d[buffer_pos + i].code = pc.layer.codes.c[string.offset + i]; - pc.layer.drawables.d[buffer_pos + i].index = string.font; + pc.layer.drawables.d[buffer_pos + i].var1 = pc.layer.codes.c[string.offset + i]; + pc.layer.drawables.d[buffer_pos + i].var2 = string.font; pc.layer.drawables.d[buffer_pos + i].type = 1; } } diff --git a/client/shader_src/ui.frag b/client/shader_src/ui.frag index 9fd2d34..fcc04cd 100644 --- a/client/shader_src/ui.frag +++ b/client/shader_src/ui.frag @@ -4,11 +4,6 @@ #include "ui_common.glsl" -layout(std430, push_constant) uniform PushConstant { - Context context; - Layer layer; -} pc; - layout(set = 0, binding = 0) uniform sampler font_samplers[]; layout(set = 1, binding = 0) uniform texture2DArray font_textures[]; @@ -25,7 +20,7 @@ layout(location = 5) flat in vec2 container_offset; layout(location = 0) out vec4 outColor; void main() { - vec2 pos = (gl_FragCoord.xy - vec2(0.5, 0.5))/pc.context.scale; + vec2 pos = (gl_FragCoord.xy - vec2(0.5, 0.5))/pc.layer.container.context.scale; vec2 min = container_offset; vec2 max = min + pc.layer.container.size; if(pos.x < min.x || pos.y < min.y diff --git a/client/shader_src/ui.vert b/client/shader_src/ui.vert index 3324214..9651374 100644 --- a/client/shader_src/ui.vert +++ b/client/shader_src/ui.vert @@ -3,15 +3,10 @@ #include "ui_common.glsl" -layout(std430, push_constant) uniform PushConstant { - Context context; - Layer layer; -} pc; - layout(location = 0) out vec4 fragColor; layout(location = 1) out vec2 fragUV; -layout(location = 2) out flat uint code; -layout(location = 3) out flat uint index; +layout(location = 2) out flat uint var1; +layout(location = 3) out flat uint var2; layout(location = 4) out flat uint type; layout(location = 5) out flat vec2 container_offset; @@ -35,36 +30,36 @@ void main() { // Top Right if(pc.layer.container.anchor == 1) { - container_offset = pc.layer.container.offset + vec2(pc.context.extent.x - pc.layer.container.size.x, 0); + container_offset = pc.layer.container.offset + vec2(pc.layer.container.context.extent.x - pc.layer.container.size.x, 0); } // Bottom Left if(pc.layer.container.anchor == 2) { - container_offset = pc.layer.container.offset + vec2(0, pc.context.extent.y - pc.layer.container.size.y); + container_offset = pc.layer.container.offset + vec2(0, pc.layer.container.context.extent.y - pc.layer.container.size.y); } // Bottom Right if(pc.layer.container.anchor == 3) { - container_offset = pc.layer.container.offset + vec2(pc.context.extent.x - pc.layer.container.size.x, pc.context.extent.y - pc.layer.container.size.y); + container_offset = pc.layer.container.offset + vec2(pc.layer.container.context.extent.x - pc.layer.container.size.x, pc.layer.container.context.extent.y - pc.layer.container.size.y); } - if(drawable.type == 1){ // Glyph - Font font = pc.context.fonts.f[drawable.index]; - Symbol symbol = font.symbols.s[drawable.code]; + Font font = pc.layer.container.context.fonts.f[drawable.var2]; + Symbol symbol = font.symbols.s[drawable.var1]; fragUV = pos * vec2(symbol.width, symbol.height); pos = pos * vec2(symbol.width, symbol.height) + vec2(symbol.left, -symbol.top); } else { fragUV = pos; } + pos += vec2(pc.time, 0); - gl_Position = vec4((pos * drawable.size + drawable.pos + container_offset) * pc.context.screen * 2, 0.0, 1.0) - vec4(1.0, 1.0, 0.0, 0.0); + gl_Position = vec4((pos * drawable.size + drawable.pos + container_offset) * pc.layer.container.context.screen * 2, 0.0, 1.0) - vec4(1.0, 1.0, 0.0, 0.0); fragColor = drawable.color; - code = drawable.code; type = drawable.type; - index = drawable.index; + var1 = drawable.var1; + var2 = drawable.var2; } diff --git a/client/shader_src/ui_common.glsl b/client/shader_src/ui_common.glsl index 0a19e5f..a316118 100644 --- a/client/shader_src/ui_common.glsl +++ b/client/shader_src/ui_common.glsl @@ -61,8 +61,10 @@ struct Drawable { vec2 size; vec4 color; uint type; - uint code; - uint index; + uint var1; + uint var2; + float var3; + float var4; uint id; }; @@ -70,10 +72,19 @@ layout(std430, buffer_reference) readonly buffer DrawableList { Drawable d[]; }; +layout(std430, buffer_reference) buffer Context { + FontList fonts; + vec2 screen; + vec2 extent; + vec2 scale; +}; + layout(std430, buffer_reference) readonly buffer Container { vec2 offset; vec2 size; uint anchor; + + Context context; }; layout(std430, buffer_reference) readonly buffer Layer { @@ -92,9 +103,7 @@ layout(std430, buffer_reference) readonly buffer Layer { Container container; }; -layout(std430, buffer_reference) buffer Context { - FontList fonts; - vec2 screen; - vec2 extent; - vec2 scale; -}; +layout(std430, push_constant) uniform PushConstant { + Layer layer; + float time; +} pc; diff --git a/client/src/draw.c b/client/src/draw.c index 1ab2be7..5deef30 100644 --- a/client/src/draw.c +++ b/client/src/draw.c @@ -8,14 +8,17 @@ * - ui_context->containers[*].layers[*].address <- device address * Basically, needs to be re-run whenever the number of layers/containers changes */ -void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { - VkDeviceAddress push[2] = {ui_context->address, 0}; +void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context, double time) { + UIPushConstant push = { + .time = (float)time, + .layer = 0, + }; vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline); for(uint32_t i = 0; i < ui_context->max_containers; i++) { if(ui_context->containers[i].id != 0x00000000) { for(uint32_t j = 0; j < ui_context->containers[i].layer_count; j++) { - push[1] = ui_context->containers[i].layers[j].address; + push.layer = ui_context->containers[i].layers[j].address; VkBufferMemoryBarrier draw_command_barrier_1 = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, .buffer = ui_context->containers[i].layers[j].layer, @@ -35,7 +38,7 @@ void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, }; vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 1, &draw_command_barrier_2, 0, NULL); - vkCmdPushConstants(command_buffer, ui_context->string_pipeline.layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, push); + vkCmdPushConstants(command_buffer, ui_context->string_pipeline.layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, 16, &push); vkCmdDispatchIndirect(command_buffer, ui_context->containers[i].layers[j].layer, offsetof(GPULayer, dispatch_strings)); VkBufferMemoryBarrier draw_command_barrier_3 = { .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, @@ -68,8 +71,11 @@ void record_ui_compute(VkCommandBuffer command_buffer, UIContext* ui_context) { * - ui_context->containers[*].layers[*].address <- device address * Basically, needs to be re-run whenever the number of layers/containers changes */ -void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context) { - VkDeviceAddress push[2] = {ui_context->address, 0}; +void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context, double time) { + UIPushConstant push = { + .time = (float)time, + .layer = 0, + }; vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline); vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL); @@ -79,71 +85,18 @@ void record_ui_draw(VkCommandBuffer command_buffer, UIContext* ui_context) { for(uint32_t i = 0; i < ui_context->max_containers; i++) { if(ui_context->containers[i].id != 0x00000000) { for(uint32_t j = 0; j < ui_context->containers[i].layer_count; j++) { - push[1] = ui_context->containers[i].layers[j].address; - vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push); + push.layer = ui_context->containers[i].layers[j].address; + vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, &push); vkCmdDrawIndirect(command_buffer, ui_context->containers[i].layers[j].layer, offsetof(GPULayer, draw), 1, 0); } } } } -VkResult record_draw_commands( - RenderContext* context, - UIContext* ui_context) { - VkResult result; - for(uint32_t image_index = 0; image_index < context->swapchain_image_count; image_index++) { - VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index]; - VK_RESULT(vkResetCommandBuffer(command_buffer, 0)); - - VkCommandBufferBeginInfo begin_info = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - }; - VK_RESULT(vkBeginCommandBuffer(command_buffer, &begin_info)); - - VkViewport viewport = { - .width = context->swapchain_extent.width, - .height = context->swapchain_extent.height, - .maxDepth = 1.0f, - .minDepth = 0.0f, - }; - vkCmdSetViewport(command_buffer, 0, 1, &viewport); - - VkRect2D scissor = { - .extent = context->swapchain_extent, - }; - vkCmdSetScissor(command_buffer, 0, 1, &scissor); - - VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 0.0f}}}, {.depthStencil={1.0f, 0.0f}}}; - - VkRenderPassBeginInfo render_pass_begin = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = context->render_pass, - .framebuffer = context->swapchain_framebuffers[image_index], - .renderArea.offset = {0, 0}, - .renderArea.extent = context->swapchain_extent, - .clearValueCount = 2, - .pClearValues = clear_values, - }; - - record_ui_compute(command_buffer, ui_context); - vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); - // Render World - vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); - // Render UI - record_ui_draw(command_buffer, ui_context); - vkCmdEndRenderPass(command_buffer); - - VK_RESULT(vkEndCommandBuffer(command_buffer)); - } - - - return VK_SUCCESS; -} - VkResult draw_frame( RenderContext* context, + UIContext* ui, double time) { - (void)time; VkResult result; result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); @@ -162,6 +115,50 @@ VkResult draw_frame( return result; } + VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index]; + VK_RESULT(vkResetCommandBuffer(command_buffer, 0)); + + VkCommandBufferBeginInfo begin_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + VK_RESULT(vkBeginCommandBuffer(command_buffer, &begin_info)); + + VkViewport viewport = { + .width = context->swapchain_extent.width, + .height = context->swapchain_extent.height, + .maxDepth = 1.0f, + .minDepth = 0.0f, + }; + vkCmdSetViewport(command_buffer, 0, 1, &viewport); + + VkRect2D scissor = { + .extent = context->swapchain_extent, + }; + vkCmdSetScissor(command_buffer, 0, 1, &scissor); + + VkClearValue clear_values[2] = {{.color={{0.0f, 0.0f, 0.0f, 0.0f}}}, {.depthStencil={1.0f, 0.0f}}}; + + VkRenderPassBeginInfo render_pass_begin = { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, + .renderPass = context->render_pass, + .framebuffer = context->swapchain_framebuffers[image_index], + .renderArea.offset = {0, 0}, + .renderArea.extent = context->swapchain_extent, + .clearValueCount = 2, + .pClearValues = clear_values, + }; + + record_ui_compute(command_buffer, ui, time); + + vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); + // Render World + vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE); + // Render UI + record_ui_draw(command_buffer, ui, time); + vkCmdEndRenderPass(command_buffer); + + VK_RESULT(vkEndCommandBuffer(command_buffer)); + VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, diff --git a/client/src/gpu.c b/client/src/gpu.c index a7e3e4b..654ce29 100644 --- a/client/src/gpu.c +++ b/client/src/gpu.c @@ -58,7 +58,7 @@ GLFWwindow* init_window() { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); // TODO: recreate the framebuffer on resize - glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); GLFWwindow* window = glfwCreateWindow(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT, "roleplay", 0, 0); glfwSetWindowSizeLimits(window, WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE); @@ -232,7 +232,7 @@ VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device) return VK_SUCCESS; } -VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR surface, Queue* graphics_queue, Queue* present_queue, Queue* transfer_queue, VkDevice* device) { +VkResult create_logical_device(VkPhysicalDevice physical_device, VkSurfaceKHR surface, GPUQueue* graphics_queue, GPUQueue* present_queue, GPUQueue* transfer_queue, VkDevice* device) { if(graphics_queue == NULL || present_queue == NULL || transfer_queue == NULL || device == NULL) { return VK_ERROR_VALIDATION_FAILED_EXT; } @@ -778,7 +778,7 @@ VkCommandBuffer* create_command_buffers(VkDevice device, VkCommandPool command_p return command_buffers; } -VkResult create_depth_image(VkDevice device, VkFormat depth_format, VkExtent2D swapchain_extent, VmaAllocator allocator, VkCommandPool extra_graphics_pool, Queue graphics_queue, VkImage* depth_image, VmaAllocation* depth_image_memory, VkImageView* depth_image_view) { +VkResult create_depth_image(VkDevice device, VkFormat depth_format, VkExtent2D swapchain_extent, VmaAllocator allocator, VkCommandPool extra_graphics_pool, GPUQueue graphics_queue, VkImage* depth_image, VmaAllocation* depth_image_memory, VkImageView* depth_image_view) { VkExtent3D depth_extent = { .width = swapchain_extent.width, @@ -1077,7 +1077,7 @@ VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_poo return command_buffer; } -VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue transfer_queue) { +VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, GPUQueue transfer_queue) { VkResult result = vkEndCommandBuffer(command_buffer); if(result != VK_SUCCESS) { vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer); @@ -1110,7 +1110,7 @@ void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer vkCmdCopyBuffer(command_buffer, src, dst, 1, ©); } -VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, Queue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags) { +VkResult command_transition_image_layout(VkDevice device, VkCommandPool transfer_pool, GPUQueue transfer_queue, VkImageLayout old_layout, VkImageLayout new_layout, VkImage image, VkAccessFlags src_mask, VkAccessFlags dst_mask, VkPipelineStageFlags source, VkPipelineStageFlags dest, uint32_t source_family, uint32_t dest_family, VkImageAspectFlags aspect_flags) { VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkImageMemoryBarrier barrier = { diff --git a/client/src/main.c b/client/src/main.c index 3b06960..7edcd53 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -1,3 +1,4 @@ +#include "GLFW/glfw3.h" #include "ui.h" #include "gpu.h" #include "draw.h" @@ -6,6 +7,14 @@ #include "vk_mem_alloc.h" #include "vulkan/vk_enum_string_helper.h" #include "vulkan/vulkan_core.h" +#include "pthread.h" +#include "stdatomic.h" + +typedef struct ClientContextStruct { + GLFWwindow* window; + RenderContext render; + UIContext ui; +} ClientContext; VkResult test_ui(RenderContext* render, UIContext* ui) { VkResult result; @@ -35,21 +44,12 @@ VkResult test_ui(RenderContext* render, UIContext* ui) { .length = strlen("Example Text"), .font = 2, }, - { - .pos = {0, 128}, - .size = 32, - .color = {1.0, 1.0, 1.0, 1.0}, - .offset = 3*strlen("Example Text"), - .length = strlen("Example Text"), - .font = 3, - }, }; uint32_t context_codes[256]; map_string("Example Text", context_codes, 0, 0, ui); map_string("Example Text", context_codes, strlen("Example Text"), 1, ui); map_string("Example Text", context_codes, 2*strlen("Example Text"), 2, ui); - map_string("Example Text", context_codes, 3*strlen("Example Text"), 3, ui); LayerInput context_layers[] = { { @@ -151,49 +151,56 @@ VkResult test_ui(RenderContext* render, UIContext* ui) { VK_RESULT(create_container(&inventory_info, render, ui)); VK_RESULT(create_container(&chat_info, render, ui)); - VK_RESULT(record_draw_commands(render, ui)); - return VK_SUCCESS; } -VkResult render_thread(GLFWwindow* window, RenderContext* render) { - - VkResult result; +// Threads: +// 1. render +// - Submits the draw buffer to the GPU as soon as it can +// 2. network +// - Handles packets to/from the network to/from the main thread +// 3. main +// - updates the data in the GPU that's being drawn from +// - updates the data in the GPU from network requests +// +// Data: +// Render thread reads Render and UI context +// Main thread reads and writes UI context + +void* render_thread(void* data) { + ClientContext* context = (ClientContext*)data; double last_frame_time = glfwGetTime(); - while(glfwWindowShouldClose(window) == 0) { - glfwPollEvents(); - + while(glfwWindowShouldClose(context->window) == 0) { double frame_time = glfwGetTime(); double delta_time = frame_time - last_frame_time; (void)delta_time; - result = draw_frame(render, frame_time); + + VkResult result = draw_frame(&context->render, &context->ui, frame_time); if(result != VK_SUCCESS) { fprintf(stderr, "draw_frame error: %s\n", string_VkResult(result)); - return result; + glfwDestroyWindow(context->window); } last_frame_time = frame_time; } - return 0; -} -typedef enum ClientAuthStateEnum { - AUTH_SAVED, - AUTH_CREDENTIALS, - AUTH_ATTEMPT, - AUTH_ERROR, - AUTH_SUCCESS, -} ClientAuthState; + return NULL; +} -typedef struct ClientStateStruct { - -} ClientState; +void* network_thread(void* data) { + ClientContext* context = (ClientContext*)data; + (void)context; -int logic_thread() { - return 0; + return NULL; } -int network_thread() { +int main_thread(void* data) { + ClientContext* context = (ClientContext*)data; + + while(glfwWindowShouldClose(context->window) == 0) { + glfwPollEvents(); + } + return 0; } @@ -206,7 +213,10 @@ void key_callback(GLFWwindow* window, int key, int scancode, int action, int mod } void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { + ClientContext* context = (ClientContext*)glfwGetWindowUserPointer(window); + (void)mods; + (void)context; switch(button) { // Handle camera hover case GLFW_MOUSE_BUTTON_MIDDLE: @@ -218,6 +228,10 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) break; case GLFW_MOUSE_BUTTON_LEFT: if(action == GLFW_PRESS) { + // NOTE: this logic is the same as it would be for right-click(just with different outcomes), so dont repeat yourself + // 1. Search through the UI context for the first element that the contains the mouse point + // 2. If no UI element intersection, cast a ray through the world scene to find the "clicked entity" + // 3. Based on what was clicked, start the mouse click animation at the target area } break; case GLFW_MOUSE_BUTTON_RIGHT: @@ -240,35 +254,61 @@ void cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { } int main() { - GLFWwindow* window = init_window(); - if(window == NULL) { + ClientContext context = {}; + context.window = init_window(); + if(context.window == NULL) { return 1; } - glfwSetKeyCallback(window, key_callback); - glfwSetMouseButtonCallback(window, mouse_button_callback); - glfwSetScrollCallback(window, scroll_callback); - glfwSetCursorPosCallback(window, cursor_pos_callback); + glfwSetWindowUserPointer(context.window, &context); + glfwSetKeyCallback(context.window, key_callback); + glfwSetMouseButtonCallback(context.window, mouse_button_callback); + glfwSetScrollCallback(context.window, scroll_callback); + glfwSetCursorPosCallback(context.window, cursor_pos_callback); - RenderContext render = {}; - UIContext ui = {}; + int error; VkResult result; - VK_RESULT(init_vulkan(window, &render)); + VK_RESULT(init_vulkan(context.window, &context.render)); // TODO: make # of fonts/textures/containers scaling, recreate GPU buffers as necessary - VK_RESULT(create_ui_context(10, 10, 10, &render, &ui)); + VK_RESULT(create_ui_context(10, 10, 10, &context.render, &context.ui)); ////////////////////////////////// - /// Test Code + /// Test UI Code ////////////////////////////////// - VK_RESULT(test_ui(&render, &ui)); + VK_RESULT(test_ui(&context.render, &context.ui)); ////////////////////////////////// - if(render_thread(window, &render) != VK_SUCCESS) { - return 3; + // Start threads + pthread_t render_thread_handle; + pthread_t network_thread_handle; + + error = pthread_create(&render_thread_handle, NULL, &render_thread, &context); + if(error != 0) { + return error; + } + + error = pthread_create(&network_thread_handle, NULL, &network_thread, &context); + if(error != 0) { + return error; + } + + error = main_thread(&context); + if(error != 0) { + return error; + } + + error = pthread_join(render_thread_handle, NULL); + if(error != 0) { + return error; + } + + error = pthread_join(network_thread_handle, NULL); + if(error != 0) { + return error; } return 0; diff --git a/client/src/ui.c b/client/src/ui.c index 2e83b51..d978eac 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -304,6 +304,7 @@ VkResult create_container( context->containers[index].data.size[0] = container->size[0]; context->containers[index].data.size[1] = container->size[1]; context->containers[index].data.anchor = container->anchor; + context->containers[index].data.context = context->address; memcpy(mapped, &context->containers[index].data, sizeof(GPUContainer)); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool); @@ -1111,7 +1112,6 @@ VkResult create_ui_context( VK_RESULT(load_font(0, "fonts/eracake.ttf", 256, VK_TRUE, gpu, context)); VK_RESULT(load_font(1, "fonts/yumoda.ttf", 256, VK_TRUE, gpu, context)); VK_RESULT(load_font(2, "fonts/runescape.ttf", 16, VK_FALSE, gpu, context)); - VK_RESULT(load_font(3, "fonts/apple_2.ttf", 256, VK_FALSE, gpu, context)); return VK_SUCCESS; }