Pass RenderContext pointer in exposed API functions

main
noah metz 2024-10-21 12:52:45 -06:00
parent d4790a8d53
commit 1dbd924b8c
10 changed files with 375 additions and 417 deletions

@ -2,7 +2,7 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
CFLAGS = -I $(ROOT_DIR)/include -I/usr/local/include -O0 -g -Wall -Wextra -fsanitize=address CFLAGS = -I $(ROOT_DIR)/include -I/usr/local/include -O0 -g -Wall -Wextra -fsanitize=address
LDFLAGS = -lfreetype -lz -lglfw -lvulkan -ldl -Xlinker -rpath -Xlinker /opt/homebrew/lib LDFLAGS = -lfreetype -lz -lglfw -lvulkan -ldl -Xlinker -rpath -Xlinker /opt/homebrew/lib
SOURCES = src/main.c src/render.c src/ui.c src/command.c lib/spng.c lib/vma.cpp SOURCES = src/main.c src/draw.c src/ui.c src/gpu.c lib/spng.c lib/vma.cpp
OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) OBJECTS = $(addsuffix .o, $(basename $(SOURCES)))
VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader_src/*.vert))) VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader_src/*.vert)))
FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader_src/*.frag))) FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader_src/*.frag)))

@ -3,19 +3,4 @@
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
typedef struct QueueStruct {
VkQueue handle;
uint32_t family;
uint32_t index;
} Queue;
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool);
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue 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);
#endif #endif

@ -0,0 +1,13 @@
#ifndef RENDER_H
#define RENDER_H
#include "gpu.h"
#include "ui.h"
VkResult draw_frame(
RenderContext* context,
UIContextStorage* ui_context,
UILayerStorage* ui_layers,
uint32_t ui_layer_count);
#endif

@ -1,5 +1,5 @@
#ifndef RENDER_H #ifndef GPU_H
#define RENDER_H #define GPU_H
#define VK_USE_PLATFORM_MACOS_MVK #define VK_USE_PLATFORM_MACOS_MVK
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
@ -24,8 +24,20 @@
#include <cglm/quat.h> #include <cglm/quat.h>
#include <cglm/cam.h> #include <cglm/cam.h>
#include "ui.h" typedef struct QueueStruct {
#include "command.h" VkQueue handle;
uint32_t family;
uint32_t index;
} Queue;
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool);
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue 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);
#define VK_RESULT(x) {\ #define VK_RESULT(x) {\
result = x;\ result = x;\
@ -97,12 +109,6 @@ VkResult init_vulkan(
GLFWwindow* window, GLFWwindow* window,
RenderContext* context); RenderContext* context);
VkResult draw_frame(
RenderContext* context,
UIContextStorage* ui_context,
UILayerStorage* ui_layers,
uint32_t ui_layer_count);
VkResult create_transfer_buffer( VkResult create_transfer_buffer(
VmaAllocator allocator, VmaAllocator allocator,
VkDeviceSize size, VkDeviceSize size,

@ -4,7 +4,7 @@
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
#include "cglm/types.h" #include "cglm/types.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include "command.h" #include "gpu.h"
#include "ft2build.h" #include "ft2build.h"
#include FT_FREETYPE_H #include FT_FREETYPE_H
@ -130,6 +130,10 @@ typedef struct UIContainerStorageStruct {
VkDeviceAddress address; VkDeviceAddress address;
UIContainer data; UIContainer data;
uint32_t id;
uint32_t layer_count;
UILayerStorage* layers;
} UIContainerStorage; } UIContainerStorage;
typedef struct UIContextStruct { typedef struct UIContextStruct {
@ -169,37 +173,25 @@ typedef struct UIContextStorageStruct {
} UIContextStorage; } UIContextStorage;
VkResult create_ui_context( VkResult create_ui_context(
VkDevice device,
VmaAllocator allocator,
VkRenderPass render_pass,
uint32_t max_fonts, uint32_t max_fonts,
uint32_t max_textures, uint32_t max_textures,
VkExtent2D swapchain_extent, RenderContext* gpu,
vec2 window_scale,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContextStorage* memory); UIContextStorage* memory);
VkResult load_font( VkResult load_font(
VkDevice device,
VmaAllocator allocator,
UIContextStorage* context,
VkCommandPool transfer_pool,
Queue transfer_queue,
FT_Library library,
const char* ttf_file, const char* ttf_file,
uint32_t size, uint32_t size,
VkBool32 antialias, VkBool32 antialias,
FT_Library library,
RenderContext* gpu,
UIContextStorage* context,
uint32_t* index, uint32_t* index,
FontStorage* memory); FontStorage* memory);
VkResult load_texture( VkResult load_texture(
VkDevice device, const char* png_path,
VmaAllocator allocator, RenderContext* gpu,
UIContextStorage* context, UIContextStorage* context,
VkCommandPool transfer_pool,
Queue transfer_queue,
const char* png_file,
uint32_t* index, uint32_t* index,
TextureStorage* memory); TextureStorage* memory);
@ -208,10 +200,7 @@ VkResult create_container(
float y, float y,
float width, float width,
float height, float height,
VkDevice device, RenderContext* gpu,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* memory); UIContainerStorage* memory);
VkResult create_layer( VkResult create_layer(
@ -219,10 +208,7 @@ VkResult create_layer(
uint32_t max_codes, uint32_t max_codes,
uint32_t max_drawables, uint32_t max_drawables,
uint32_t font_index, uint32_t font_index,
VkDevice device, RenderContext* gpu,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* container, UIContainerStorage* container,
UILayerStorage* memory); UILayerStorage* memory);

@ -1,88 +0,0 @@
#include "command.h"
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool) {
VkCommandBufferAllocateInfo command_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandPool = transfer_pool,
.commandBufferCount = 1,
};
VkCommandBuffer command_buffer;
VkResult result = vkAllocateCommandBuffers(device, &command_info, &command_buffer);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
};
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return VK_NULL_HANDLE;
}
return command_buffer;
}
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue transfer_queue) {
VkResult result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
};
result = vkQueueSubmit(transfer_queue.handle, 1, &submit_info, 0);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
result = vkQueueWaitIdle(transfer_queue.handle);
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer dst, VkDeviceSize src_offset, VkDeviceSize dst_offset, VkDeviceSize size) {
VkBufferCopy copy = {
.srcOffset = src_offset,
.dstOffset = dst_offset,
.size = size,
};
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) {
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.oldLayout = old_layout,
.newLayout = new_layout,
.srcQueueFamilyIndex = source_family,
.dstQueueFamilyIndex = dest_family,
.image = image,
.subresourceRange = {
.aspectMask = aspect_flags,
.levelCount = 1,
.layerCount = 1,
.baseMipLevel = 0,
.baseArrayLayer = 0,
},
.srcAccessMask = src_mask,
.dstAccessMask = dst_mask,
};
vkCmdPipelineBarrier(command_buffer, source, dest, 0, 0, 0, 0, 0, 1, &barrier);
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
}

@ -0,0 +1,170 @@
#include "draw.h"
VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* layers, uint32_t layer_count) {
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;
VkCommandBuffer command_buffer = context->swapchain_command_buffers[context->current_frame];
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;
}
result = vkResetCommandBuffer(command_buffer, 0);
if(result != VK_SUCCESS) {
return result;
}
VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
};
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
return result;
}
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,
};
VkDeviceAddress push[2] = {ui_context->address, 0};
// Compute Pass
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline);
for(uint32_t i = 0; i < layer_count; i++) {
push[1] = layers[i].address;
VkBufferMemoryBarrier draw_command_barrier_1 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &draw_command_barrier_1, 0, NULL);
command_copy_buffer(command_buffer, layers[i].layer, layers[i].layer, offsetof(UILayer, num_drawables), offsetof(UILayer, draw) + offsetof(DrawCommand, instance_count), sizeof(uint32_t));
VkBufferMemoryBarrier draw_command_barrier_2 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.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);
vkCmdDispatchIndirect(command_buffer, layers[i].layer, offsetof(UILayer, dispatch_strings));
VkBufferMemoryBarrier draw_command_barrier_3 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, 0, NULL, 1, &draw_command_barrier_3, 0, NULL);
VkBufferMemoryBarrier drawables_barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].drawables,
.offset = 0,
.size = sizeof(UIDrawable)*layers[i].data.max_drawables,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &drawables_barrier, 0, NULL);
}
// Render Pass
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
// World subpass
vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE);
// UI subpass
for(uint32_t i = 0; i < layer_count; i++) {
push[1] = layers[i].address;
vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline);
if(i == 0) {
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 2, 1, &ui_context->samplers, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 3, 1, &ui_context->textures, 0, NULL);
}
vkCmdDrawIndirect(command_buffer, layers[i].layer, offsetof(UILayer, draw), 1, 0);
}
vkCmdEndRenderPass(command_buffer);
result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
return result;
}
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &context->image_available_semaphores[context->current_frame],
.pWaitDstStageMask = wait_stages,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &context->render_finished_semaphores[context->current_frame],
};
result = vkQueueSubmit(context->graphics_queue.handle, 1, &submit_info, context->in_flight_fences[context->current_frame]);
if(result != VK_SUCCESS) {
return result;
}
VkPresentInfoKHR present_info = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &context->render_finished_semaphores[context->current_frame],
.swapchainCount = 1,
.pSwapchains = &context->swapchain,
.pImageIndices = &image_index,
.pResults = 0,
};
result = vkQueuePresentKHR(context->present_queue.handle, &present_info);
if(result != VK_SUCCESS) {
return result;
}
context->current_frame = (context->current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
return VK_SUCCESS;
}

@ -1,4 +1,4 @@
#include "render.h" #include "gpu.h"
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
#include "stdio.h" #include "stdio.h"
#include "string.h" #include "string.h"
@ -978,175 +978,6 @@ VkResult init_vulkan(GLFWwindow* window, RenderContext* context) {
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult draw_frame(RenderContext* context, UIContextStorage* ui_context, UILayerStorage* layers, uint32_t layer_count) {
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;
VkCommandBuffer command_buffer = context->swapchain_command_buffers[context->current_frame];
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;
}
result = vkResetCommandBuffer(command_buffer, 0);
if(result != VK_SUCCESS) {
return result;
}
VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
};
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
return result;
}
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,
};
VkDeviceAddress push[2] = {ui_context->address, 0};
// Compute Pass
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, ui_context->string_pipeline.pipeline);
for(uint32_t i = 0; i < layer_count; i++) {
push[1] = layers[i].address;
VkBufferMemoryBarrier draw_command_barrier_1 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1, &draw_command_barrier_1, 0, NULL);
command_copy_buffer(command_buffer, layers[i].layer, layers[i].layer, offsetof(UILayer, num_drawables), offsetof(UILayer, draw) + offsetof(DrawCommand, instance_count), sizeof(uint32_t));
VkBufferMemoryBarrier draw_command_barrier_2 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
.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);
vkCmdDispatchIndirect(command_buffer, layers[i].layer, offsetof(UILayer, dispatch_strings));
VkBufferMemoryBarrier draw_command_barrier_3 = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].layer,
.offset = offsetof(UILayer, draw),
.size = sizeof(DrawCommand),
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, 0, NULL, 1, &draw_command_barrier_3, 0, NULL);
VkBufferMemoryBarrier drawables_barrier = {
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
.buffer = layers[i].drawables,
.offset = 0,
.size = sizeof(UIDrawable)*layers[i].data.max_drawables,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
};
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 0, NULL, 1, &drawables_barrier, 0, NULL);
}
// Render Pass
vkCmdBeginRenderPass(command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
// World subpass
vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE);
// UI subpass
for(uint32_t i = 0; i < layer_count; i++) {
push[1] = layers[i].address;
vkCmdPushConstants(command_buffer, ui_context->pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, push);
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.pipeline);
if(i == 0) {
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 0, 1, &ui_context->font_samplers, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 1, 1, &ui_context->font_textures, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 2, 1, &ui_context->samplers, 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, ui_context->pipeline.layout, 3, 1, &ui_context->textures, 0, NULL);
}
vkCmdDrawIndirect(command_buffer, layers[i].layer, offsetof(UILayer, draw), 1, 0);
}
vkCmdEndRenderPass(command_buffer);
result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
return result;
}
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &context->image_available_semaphores[context->current_frame],
.pWaitDstStageMask = wait_stages,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &context->render_finished_semaphores[context->current_frame],
};
result = vkQueueSubmit(context->graphics_queue.handle, 1, &submit_info, context->in_flight_fences[context->current_frame]);
if(result != VK_SUCCESS) {
return result;
}
VkPresentInfoKHR present_info = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.waitSemaphoreCount = 1,
.pWaitSemaphores = &context->render_finished_semaphores[context->current_frame],
.swapchainCount = 1,
.pSwapchains = &context->swapchain,
.pImageIndices = &image_index,
.pResults = 0,
};
result = vkQueuePresentKHR(context->present_queue.handle, &present_info);
if(result != VK_SUCCESS) {
return result;
}
context->current_frame = (context->current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
return VK_SUCCESS;
}
VkResult create_transfer_buffer( VkResult create_transfer_buffer(
VmaAllocator allocator, VmaAllocator allocator,
VkDeviceSize size, VkDeviceSize size,
@ -1212,3 +1043,90 @@ VkDeviceAddress buffer_address(VkDevice device, VkBuffer buffer) {
}; };
return vkGetBufferDeviceAddress(device, &info); return vkGetBufferDeviceAddress(device, &info);
} }
VkCommandBuffer command_begin_single(VkDevice device, VkCommandPool transfer_pool) {
VkCommandBufferAllocateInfo command_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
.commandPool = transfer_pool,
.commandBufferCount = 1,
};
VkCommandBuffer command_buffer;
VkResult result = vkAllocateCommandBuffers(device, &command_info, &command_buffer);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
VkCommandBufferBeginInfo begin_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
};
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return VK_NULL_HANDLE;
}
return command_buffer;
}
VkResult command_end_single(VkDevice device, VkCommandBuffer command_buffer, VkCommandPool transfer_pool, Queue transfer_queue) {
VkResult result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &command_buffer,
};
result = vkQueueSubmit(transfer_queue.handle, 1, &submit_info, 0);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
result = vkQueueWaitIdle(transfer_queue.handle);
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
void command_copy_buffer(VkCommandBuffer command_buffer, VkBuffer src, VkBuffer dst, VkDeviceSize src_offset, VkDeviceSize dst_offset, VkDeviceSize size) {
VkBufferCopy copy = {
.srcOffset = src_offset,
.dstOffset = dst_offset,
.size = size,
};
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) {
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool);
VkImageMemoryBarrier barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.oldLayout = old_layout,
.newLayout = new_layout,
.srcQueueFamilyIndex = source_family,
.dstQueueFamilyIndex = dest_family,
.image = image,
.subresourceRange = {
.aspectMask = aspect_flags,
.levelCount = 1,
.layerCount = 1,
.baseMipLevel = 0,
.baseArrayLayer = 0,
},
.srcAccessMask = src_mask,
.dstAccessMask = dst_mask,
};
vkCmdPipelineBarrier(command_buffer, source, dest, 0, 0, 0, 0, 0, 1, &barrier);
return command_end_single(device, command_buffer, transfer_pool, transfer_queue);
}

@ -1,7 +1,8 @@
#include "command.h"
#include "render.h"
#include "arpa/inet.h"
#include "ui.h" #include "ui.h"
#include "gpu.h"
#include "draw.h"
#include "arpa/inet.h"
#include "vk_mem_alloc.h" #include "vk_mem_alloc.h"
#include "vulkan/vk_enum_string_helper.h" #include "vulkan/vk_enum_string_helper.h"
#include "vulkan/vulkan_core.h" #include "vulkan/vulkan_core.h"
@ -28,29 +29,23 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) {
VkResult result; VkResult result;
VK_RESULT(create_ui_context( VK_RESULT(create_ui_context(
render->device,
render->allocator,
render->render_pass,
10, 10,
10, 10,
render->swapchain_extent, render,
render->window_scale,
render->transfer_pool,
render->transfer_queue,
&ui)); &ui));
if(FT_Init_FreeType(&library) != FT_Err_Ok) { if(FT_Init_FreeType(&library) != FT_Err_Ok) {
return VK_ERROR_UNKNOWN; return VK_ERROR_UNKNOWN;
} }
VK_RESULT(load_font(render->device, render->allocator, &ui, render->transfer_pool, render->transfer_queue, library, "test.ttf", 16, VK_TRUE, &font_index, &font)); VK_RESULT(load_font("test.ttf", 16, VK_TRUE, library, render, &ui, &font_index, &font));
VK_RESULT(load_texture(render->device, render->allocator, &ui, render->transfer_pool, render->transfer_queue, "test.png", &texture_index, &texture)); VK_RESULT(load_texture("test.png", render, &ui, &texture_index, &texture));
VK_RESULT(create_container(0, 0, 200, 200, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container)); VK_RESULT(create_container(0, 0, 200, 200, render, &container));
VK_RESULT(create_layer(10, 100, 10, font_index, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container, &layers[0])); VK_RESULT(create_layer(10, 100, 10, font_index, render, &container, &layers[0]));
VK_RESULT(create_layer(10, 100, 10, font_index, render->device, render->allocator, render->transfer_pool, render->transfer_queue, &container, &layers[1])); VK_RESULT(create_layer(10, 100, 10, font_index, render, &container, &layers[1]));
VK_RESULT(create_transfer_buffer(render->allocator, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(render->allocator, 2*sizeof(uint32_t) + 2*sizeof(UIDrawable) + sizeof(UIString) + 100*sizeof(uint32_t), &transfer, &transfer_memory, &mapped));

@ -1,8 +1,8 @@
#include "ui.h" #include "ui.h"
#include "gpu.h"
#include "cglm/affine.h" #include "cglm/affine.h"
#include "cglm/mat4.h" #include "cglm/mat4.h"
#include "command.h"
#include "render.h"
#include "stdio.h" #include "stdio.h"
#include "stdlib.h" #include "stdlib.h"
#include "string.h" #include "string.h"
@ -279,19 +279,16 @@ VkResult create_container(
float y, float y,
float width, float width,
float height, float height,
VkDevice device, RenderContext* gpu,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* memory) { UIContainerStorage* memory) {
VkResult result; VkResult result;
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIContainer), &memory->container, &memory->container_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(UIContainer), &memory->container, &memory->container_memory));
VkBuffer transfer; VkBuffer transfer;
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
void* mapped; void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContainer), &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(UIContainer), &transfer, &transfer_memory, &mapped));
memory->data.pos[0] = x; memory->data.pos[0] = x;
memory->data.pos[1] = y; memory->data.pos[1] = y;
@ -299,12 +296,12 @@ VkResult create_container(
memory->data.size[1] = height; memory->data.size[1] = height;
memcpy(mapped, &memory->data, sizeof(UIContainer)); memcpy(mapped, &memory->data, sizeof(UIContainer));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->container, 0, 0, sizeof(UIContainer)); command_copy_buffer(command_buffer, transfer, memory->container, 0, 0, sizeof(UIContainer));
VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue));
destroy_transfer_buffer(allocator, transfer, transfer_memory); destroy_transfer_buffer(gpu->allocator, transfer, transfer_memory);
memory->address = buffer_address(device, memory->container); memory->address = buffer_address(gpu->device, memory->container);
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -314,28 +311,25 @@ VkResult create_layer(
uint32_t max_codes, uint32_t max_codes,
uint32_t max_drawables, uint32_t max_drawables,
uint32_t font_index, uint32_t font_index,
VkDevice device, RenderContext* gpu,
VmaAllocator allocator,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContainerStorage* container, UIContainerStorage* container,
UILayerStorage* memory) { UILayerStorage* memory) {
VkResult result; VkResult result;
VK_RESULT(create_storage_buffer(allocator, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sizeof(UILayer), &memory->layer, &memory->layer_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, sizeof(UILayer), &memory->layer, &memory->layer_memory));
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIString)*max_strings, &memory->strings, &memory->strings_memory)) VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(UIString)*max_strings, &memory->strings, &memory->strings_memory))
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIDrawable)*(max_drawables + max_codes), &memory->drawables, &memory->drawables_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(UIDrawable)*(max_drawables + max_codes), &memory->drawables, &memory->drawables_memory));
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(uint32_t)*max_codes, &memory->codes, &memory->codes_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(uint32_t)*max_codes, &memory->codes, &memory->codes_memory));
VkBuffer transfer; VkBuffer transfer;
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
void* mapped; void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UILayer), &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(UILayer), &transfer, &transfer_memory, &mapped));
memory->data.strings = buffer_address(device, memory->strings); memory->data.strings = buffer_address(gpu->device, memory->strings);
memory->data.codes = buffer_address(device, memory->codes); memory->data.codes = buffer_address(gpu->device, memory->codes);
memory->data.drawables = buffer_address(device, memory->drawables); memory->data.drawables = buffer_address(gpu->device, memory->drawables);
memory->data.draw.first_vertex = 0; memory->data.draw.first_vertex = 0;
memory->data.draw.vertex_count = 6; memory->data.draw.vertex_count = 6;
@ -353,27 +347,24 @@ VkResult create_layer(
memory->data.container = container->address; memory->data.container = container->address;
memcpy(mapped, &memory->data, sizeof(UILayer)); memcpy(mapped, &memory->data, sizeof(UILayer));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer)); command_copy_buffer(command_buffer, transfer, memory->layer, 0, 0, sizeof(UILayer));
vkCmdFillBuffer(command_buffer, memory->strings, 0, sizeof(UIString)*max_strings, 0x00000000); vkCmdFillBuffer(command_buffer, memory->strings, 0, sizeof(UIString)*max_strings, 0x00000000);
vkCmdFillBuffer(command_buffer, memory->drawables, 0, sizeof(UIDrawable)*max_drawables, 0x00000000); vkCmdFillBuffer(command_buffer, memory->drawables, 0, sizeof(UIDrawable)*max_drawables, 0x00000000);
vkCmdFillBuffer(command_buffer, memory->codes, 0, sizeof(uint32_t)*max_codes, 0x00000000); vkCmdFillBuffer(command_buffer, memory->codes, 0, sizeof(uint32_t)*max_codes, 0x00000000);
VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue));
vkQueueWaitIdle(transfer_queue.handle); vkQueueWaitIdle(gpu->transfer_queue.handle);
destroy_transfer_buffer(allocator, transfer, transfer_memory); destroy_transfer_buffer(gpu->allocator, transfer, transfer_memory);
memory->address = buffer_address(device, memory->layer); memory->address = buffer_address(gpu->device, memory->layer);
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult load_texture( VkResult load_texture(
VkDevice device,
VmaAllocator allocator,
UIContextStorage* context,
VkCommandPool transfer_pool,
Queue transfer_queue,
const char* png_path, const char* png_path,
RenderContext* gpu,
UIContextStorage* context,
uint32_t* index, uint32_t* index,
TextureStorage* memory) { TextureStorage* memory) {
*index = 0xFFFFFFFF; *index = 0xFFFFFFFF;
@ -464,10 +455,10 @@ VkResult load_texture(
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
void* mapped; void* mapped;
VK_RESULT(vmaCreateImage(allocator, &image_info, &memory_info, &memory->image, &memory->image_memory, NULL)); VK_RESULT(vmaCreateImage(gpu->allocator, &image_info, &memory_info, &memory->image, &memory->image_memory, NULL));
VK_RESULT(create_transfer_buffer(allocator, sizeof(uint32_t)*ihdr.width*ihdr.height, &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(uint32_t)*ihdr.width*ihdr.height, &transfer, &transfer_memory, &mapped));
memcpy(mapped, image_buffer, sizeof(uint32_t)*ihdr.height*ihdr.width); memcpy(mapped, image_buffer, sizeof(uint32_t)*ihdr.height*ihdr.width);
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool);
VkImageMemoryBarrier first_barrier = { VkImageMemoryBarrier first_barrier = {
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
@ -515,9 +506,9 @@ VkResult load_texture(
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier); vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier);
VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue));
vkQueueWaitIdle(transfer_queue.handle); vkQueueWaitIdle(gpu->transfer_queue.handle);
destroy_transfer_buffer(allocator, transfer, transfer_memory); destroy_transfer_buffer(gpu->allocator, transfer, transfer_memory);
free(image_buffer); free(image_buffer);
free(png); free(png);
spng_ctx_free(spng); spng_ctx_free(spng);
@ -534,7 +525,7 @@ VkResult load_texture(
}, },
}; };
VK_RESULT(vkCreateImageView(device, &view_info, NULL, &memory->view)); VK_RESULT(vkCreateImageView(gpu->device, &view_info, NULL, &memory->view));
VkSamplerCreateInfo sampler_info = { VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
@ -545,7 +536,7 @@ VkResult load_texture(
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
}; };
VK_RESULT(vkCreateSampler(device, &sampler_info, NULL, &memory->sampler)); VK_RESULT(vkCreateSampler(gpu->device, &sampler_info, NULL, &memory->sampler));
VkDescriptorImageInfo desc_sampler_info = { VkDescriptorImageInfo desc_sampler_info = {
.sampler = memory->sampler, .sampler = memory->sampler,
@ -577,23 +568,20 @@ VkResult load_texture(
}, },
}; };
vkUpdateDescriptorSets(device, sizeof(desc_writes)/sizeof(VkWriteDescriptorSet), desc_writes, 0, NULL); vkUpdateDescriptorSets(gpu->device, sizeof(desc_writes)/sizeof(VkWriteDescriptorSet), desc_writes, 0, NULL);
return VK_SUCCESS; return VK_SUCCESS;
} }
VkResult load_font( VkResult load_font(
VkDevice device,
VmaAllocator allocator,
UIContextStorage* context,
VkCommandPool transfer_pool,
Queue transfer_queue,
FT_Library library,
const char* ttf_file, const char* ttf_file,
uint32_t size, uint32_t size,
VkBool32 antialias, VkBool32 antialias,
FT_Library library,
RenderContext* gpu,
UIContextStorage* context,
uint32_t* index, uint32_t* index,
FontStorage* memory) { FontStorage* memory){
FT_Face face; FT_Face face;
int error; int error;
@ -690,7 +678,7 @@ VkResult load_font(
} }
VkResult result; VkResult result;
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(SymbolInfo)*info.num_symbols, &memory->symbols, &memory->symbol_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(SymbolInfo)*info.num_symbols, &memory->symbols, &memory->symbol_memory));
VkImageCreateInfo image_info = { VkImageCreateInfo image_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
@ -711,14 +699,14 @@ VkResult load_font(
.usage = VMA_MEMORY_USAGE_GPU_ONLY, .usage = VMA_MEMORY_USAGE_GPU_ONLY,
}; };
VK_RESULT(vmaCreateImage(allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL)); VK_RESULT(vmaCreateImage(gpu->allocator, &image_info, &image_memory_info, &memory->image, &memory->image_memory, NULL));
VkBuffer transfer; VkBuffer transfer;
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
void* mapped; void* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols, &transfer, &transfer_memory, &mapped)); VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(Font) + image_size*info.num_symbols + sizeof(SymbolInfo)*info.num_symbols, &transfer, &transfer_memory, &mapped));
info.symbol_list = buffer_address(device, memory->symbols); info.symbol_list = buffer_address(gpu->device, memory->symbols);
memcpy(mapped, images, image_size*info.num_symbols); memcpy(mapped, images, image_size*info.num_symbols);
memcpy(mapped + image_size*info.num_symbols, &info, sizeof(Font)); memcpy(mapped + image_size*info.num_symbols, &info, sizeof(Font));
@ -727,7 +715,7 @@ VkResult load_font(
free(images); free(images);
free(symbols); free(symbols);
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool);
command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, *index*sizeof(Font), sizeof(Font)); command_copy_buffer(command_buffer, transfer, context->font_infos, image_size*info.num_symbols, *index*sizeof(Font), sizeof(Font));
command_copy_buffer(command_buffer, transfer, memory->symbols, image_size*info.num_symbols + sizeof(Font), 0, sizeof(SymbolInfo)*info.num_symbols); command_copy_buffer(command_buffer, transfer, memory->symbols, image_size*info.num_symbols + sizeof(Font), 0, sizeof(SymbolInfo)*info.num_symbols);
@ -768,12 +756,9 @@ VkResult load_font(
}; };
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier); vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier);
result = command_end_single(device, command_buffer, transfer_pool, transfer_queue); VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue));
if(result != VK_SUCCESS) { vkQueueWaitIdle(gpu->transfer_queue.handle);
return result; destroy_transfer_buffer(gpu->allocator, transfer, transfer_memory);
}
vkQueueWaitIdle(transfer_queue.handle);
destroy_transfer_buffer(allocator, transfer, transfer_memory);
VkImageViewCreateInfo view_info = { VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@ -788,10 +773,7 @@ VkResult load_font(
.baseArrayLayer = 0, .baseArrayLayer = 0,
}, },
}; };
result = vkCreateImageView(device, &view_info, NULL, &memory->view); VK_RESULT(vkCreateImageView(gpu->device, &view_info, NULL, &memory->view))
if(result != VK_SUCCESS) {
return result;
}
VkSamplerCreateInfo sampler_info = { VkSamplerCreateInfo sampler_info = {
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
@ -801,10 +783,7 @@ VkResult load_font(
.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT,
.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
}; };
result = vkCreateSampler(device, &sampler_info, NULL, &memory->sampler); VK_RESULT(vkCreateSampler(gpu->device, &sampler_info, NULL, &memory->sampler));
if(result != VK_SUCCESS) {
return result;
}
VkDescriptorImageInfo desc_sampler_info = { VkDescriptorImageInfo desc_sampler_info = {
.sampler = memory->sampler, .sampler = memory->sampler,
@ -836,7 +815,7 @@ VkResult load_font(
}, },
}; };
vkUpdateDescriptorSets(device, sizeof(descriptor_writes)/sizeof(VkWriteDescriptorSet), descriptor_writes, 0, NULL); vkUpdateDescriptorSets(gpu->device, sizeof(descriptor_writes)/sizeof(VkWriteDescriptorSet), descriptor_writes, 0, NULL);
return VK_SUCCESS; return VK_SUCCESS;
} }
@ -1023,44 +1002,38 @@ VkResult create_ui_descriptor(
} }
VkResult create_ui_context( VkResult create_ui_context(
VkDevice device,
VmaAllocator allocator,
VkRenderPass render_pass,
uint32_t max_fonts, uint32_t max_fonts,
uint32_t max_textures, uint32_t max_textures,
VkExtent2D swapchain_extent, RenderContext* gpu,
vec2 window_scale,
VkCommandPool transfer_pool,
Queue transfer_queue,
UIContextStorage* memory) { UIContextStorage* memory) {
VkResult result; VkResult result;
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(UIContext), &memory->context, &memory->context_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(UIContext), &memory->context, &memory->context_memory));
VK_RESULT(create_storage_buffer(allocator, 0, sizeof(Font)*max_fonts, &memory->font_infos, &memory->font_infos_memory)); VK_RESULT(create_storage_buffer(gpu->allocator, 0, sizeof(Font)*max_fonts, &memory->font_infos, &memory->font_infos_memory));
VkBuffer transfer; VkBuffer transfer;
VmaAllocation transfer_memory; VmaAllocation transfer_memory;
UIContext* mapped; UIContext* mapped;
VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContext), &transfer, &transfer_memory, (void**)&mapped)); VK_RESULT(create_transfer_buffer(gpu->allocator, sizeof(UIContext), &transfer, &transfer_memory, (void**)&mapped));
memory->data.font_infos = buffer_address(device, memory->font_infos); memory->data.font_infos = buffer_address(gpu->device, memory->font_infos);
memory->data.screen[0] = window_scale[0] / swapchain_extent.width; memory->data.screen[0] = gpu->window_scale[0] / gpu->swapchain_extent.width;
memory->data.screen[1] = window_scale[1] / swapchain_extent.height; memory->data.screen[1] = gpu->window_scale[1] / gpu->swapchain_extent.height;
memory->data.scale[0] = window_scale[0]; memory->data.scale[0] = gpu->window_scale[0];
memory->data.scale[1] = window_scale[1]; memory->data.scale[1] = gpu->window_scale[1];
memcpy(mapped, &memory->data, sizeof(UIContext)); memcpy(mapped, &memory->data, sizeof(UIContext));
VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); VkCommandBuffer command_buffer = command_begin_single(gpu->device, gpu->transfer_pool);
command_copy_buffer(command_buffer, transfer, memory->context, 0, 0, sizeof(UIContext)); command_copy_buffer(command_buffer, transfer, memory->context, 0, 0, sizeof(UIContext));
VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); VK_RESULT(command_end_single(gpu->device, command_buffer, gpu->transfer_pool, gpu->transfer_queue));
destroy_transfer_buffer(allocator, transfer, transfer_memory); destroy_transfer_buffer(gpu->allocator, transfer, transfer_memory);
memory->address = buffer_address(device, memory->context); memory->address = buffer_address(gpu->device, memory->context);
VK_RESULT(create_ui_descriptor(device, max_fonts, max_textures, &memory->samplers_layout, &memory->textures_layout, &memory->samplers, &memory->textures, &memory->font_samplers, &memory->font_textures, &memory->fonts_pool, &memory->textures_pool)); VK_RESULT(create_ui_descriptor(gpu->device, max_fonts, max_textures, &memory->samplers_layout, &memory->textures_layout, &memory->samplers, &memory->textures, &memory->font_samplers, &memory->font_textures, &memory->fonts_pool, &memory->textures_pool));
VK_RESULT(create_ui_pipeline(device, render_pass, memory->samplers_layout, memory->textures_layout, &memory->pipeline, &memory->string_pipeline)); VK_RESULT(create_ui_pipeline(gpu->device, gpu->render_pass, memory->samplers_layout, memory->textures_layout, &memory->pipeline, &memory->string_pipeline));
memory->max_textures = max_textures; memory->max_textures = max_textures;
memory->max_fonts = max_fonts; memory->max_fonts = max_fonts;