Compare commits

...

2 Commits

Author SHA1 Message Date
noah metz e4649bc5f1 Fixed vertex shader test 2024-10-24 20:50:27 -06:00
noah metz cc06265ca6 Pass time to shaders 2024-10-24 20:49:59 -06:00
11 changed files with 204 additions and 167 deletions

@ -6,10 +6,7 @@
VkResult draw_frame(
RenderContext* context,
UIContext* ui,
double time);
VkResult record_draw_commands(
RenderContext* context,
UIContext* ui_context);
#endif

@ -24,20 +24,20 @@
#include <cglm/quat.h>
#include <cglm/cam.h>
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;

@ -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 {

@ -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;
}
}

@ -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

@ -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,24 +30,23 @@ 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);
@ -60,11 +54,11 @@ void main() {
fragUV = pos;
}
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;
}

@ -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;

@ -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,19 +85,36 @@ 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(
VkResult draw_frame(
RenderContext* context,
UIContext* ui_context) {
UIContext* ui,
double time) {
VkResult result;
for(uint32_t image_index = 0; image_index < context->swapchain_image_count; image_index++) {
result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX);
if(result != VK_SUCCESS) {
return result;
}
result = vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]);
if(result != VK_SUCCESS) {
return result;
}
uint32_t image_index;
result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, context->image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index);
if(result != VK_SUCCESS) {
return result;
}
VkCommandBuffer command_buffer = context->swapchain_command_buffers[image_index];
VK_RESULT(vkResetCommandBuffer(command_buffer, 0));
@ -125,42 +148,16 @@ VkResult record_draw_commands(
.pClearValues = clear_values,
};
record_ui_compute(command_buffer, ui_context);
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_context);
record_ui_draw(command_buffer, ui, time);
vkCmdEndRenderPass(command_buffer);
VK_RESULT(vkEndCommandBuffer(command_buffer));
}
return VK_SUCCESS;
}
VkResult draw_frame(
RenderContext* context,
double time) {
(void)time;
VkResult result;
result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX);
if(result != VK_SUCCESS) {
return result;
}
result = vkResetFences(context->device, 1, &context->in_flight_fences[context->current_frame]);
if(result != VK_SUCCESS) {
return result;
}
uint32_t image_index;
result = vkAcquireNextImageKHR(context->device, context->swapchain, UINT64_MAX, context->image_available_semaphores[context->current_frame], VK_NULL_HANDLE, &image_index);
if(result != VK_SUCCESS) {
return result;
}
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submit_info = {

@ -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, &copy);
}
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 = {

@ -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;
return NULL;
}
typedef enum ClientAuthStateEnum {
AUTH_SAVED,
AUTH_CREDENTIALS,
AUTH_ATTEMPT,
AUTH_ERROR,
AUTH_SUCCESS,
} ClientAuthState;
void* network_thread(void* data) {
ClientContext* context = (ClientContext*)data;
(void)context;
typedef struct ClientStateStruct {
return NULL;
}
} ClientState;
int main_thread(void* data) {
ClientContext* context = (ClientContext*)data;
int logic_thread() {
return 0;
}
while(glfwWindowShouldClose(context->window) == 0) {
glfwPollEvents();
}
int network_thread() {
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;

@ -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;
}