From 35f0ffb46c205e7b1ac8696cac5c5c39dcca5a84 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Mon, 21 Oct 2024 09:20:50 -0600 Subject: [PATCH] Fixed UI scale --- client/include/ui.h | 31 ++++++ client/shader_src/ui.frag | 2 +- client/shader_src/ui.vert | 2 +- client/shader_src/ui_common.glsl | 1 + client/src/main.c | 2 +- client/src/ui.c | 163 ++++++++++++++++++++++++++++++- 6 files changed, 193 insertions(+), 8 deletions(-) diff --git a/client/include/ui.h b/client/include/ui.h index cdb72d4..ab05f0e 100644 --- a/client/include/ui.h +++ b/client/include/ui.h @@ -59,6 +59,14 @@ typedef struct FontStorageStruct { uint32_t index; } FontStorage; +typedef struct TextureStorageStruct { + VmaAllocation image_memory; + VkImage image; + VkImageView view; + VkSampler sampler; + uint32_t index; +} TextureStorage; + typedef struct UIStringStruct { vec2 pos; vec4 color; @@ -126,6 +134,7 @@ typedef struct UIContainerStorageStruct { typedef struct UIContextStruct { VkDeviceAddress font_infos; + vec2 screen; vec2 scale; } UIContext; @@ -174,6 +183,16 @@ VkResult load_font( VkBool32 antialias, FontStorage* memory); +VkResult load_texture( + VkDevice device, + VmaAllocator allocator, + UIContextStorage* context, + uint32_t index, + VkCommandPool transfer_pool, + Queue transfer_queue, + const char* png_file, + TextureStorage* memory); + VkResult create_container( float x, float y, @@ -208,6 +227,18 @@ void set_ui_rect( float a, UIDrawable* drawable); +void set_ui_image( + float x, + float y, + float width, + float height, + float r, + float g, + float b, + float a, + uint32_t index, + UIDrawable* drawable); + void set_ui_string( float x, float y, diff --git a/client/shader_src/ui.frag b/client/shader_src/ui.frag index d9f9e9c..9105e3a 100644 --- a/client/shader_src/ui.frag +++ b/client/shader_src/ui.frag @@ -21,7 +21,7 @@ layout(location = 4) flat in uint type; layout(location = 0) out vec4 outColor; void main() { - vec2 pos = gl_FragCoord.xy - vec2(0.5, 0.5); + vec2 pos = (gl_FragCoord.xy - vec2(0.5, 0.5))/pc.context.scale; vec2 min = pc.layer.container.pos; 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 61a56b7..e15d397 100644 --- a/client/shader_src/ui.vert +++ b/client/shader_src/ui.vert @@ -38,7 +38,7 @@ void main() { pos = pos * vec2(symbol.width, symbol.height) + vec2(symbol.left, -symbol.top); } - gl_Position = vec4((pos * drawable.size + drawable.pos + pc.layer.container.pos) * pc.context.scale, 0.0, 1.0) - vec4(1.0, 1.0, 0.0, 0.0); + gl_Position = vec4((pos * drawable.size + drawable.pos + pc.layer.container.pos) * pc.context.screen * 2, 0.0, 1.0) - vec4(1.0, 1.0, 0.0, 0.0); fragColor = drawable.color; code = drawable.code; diff --git a/client/shader_src/ui_common.glsl b/client/shader_src/ui_common.glsl index 6b74da1..ac43abf 100644 --- a/client/shader_src/ui_common.glsl +++ b/client/shader_src/ui_common.glsl @@ -90,5 +90,6 @@ layout(std430, buffer_reference) readonly buffer Layer { layout(std430, buffer_reference) buffer Context { FontList fonts; + vec2 screen; vec2 scale; }; diff --git a/client/src/main.c b/client/src/main.c index ac4bdf8..ce78614 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -52,7 +52,7 @@ VkResult render_thread(GLFWwindow* window, RenderContext* render) { mapped_count[0] = 1; mapped_count[1] = 1; UIDrawable* mapped_drawable = (UIDrawable*)(mapped + 2*sizeof(uint32_t)); - set_ui_rect( 0.0, 0.0, 100.0, 200.0, 1.0, 0.0, 0.0, 1.0, &mapped_drawable[0]); + set_ui_image(0.0, 0.0, 100.0, 200.0, 1.0, 1.0, 1.0, 1.0, 0, &mapped_drawable[0]); set_ui_rect(100.0, 0.0, 100.0, 200.0, 0.0, 1.0, 0.0, 1.0, &mapped_drawable[1]); UIString* mapped_string = (UIString*)(mapped + 2*sizeof(uint32_t) + 2*sizeof(UIDrawable)); diff --git a/client/src/ui.c b/client/src/ui.c index 450ece9..d1019f0 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -8,6 +8,7 @@ #include "string.h" #include "vk_mem_alloc.h" #include "vulkan/vulkan_core.h" +#include "spng.h" VkShaderModule load_shader_file(const char* path, VkDevice device) { FILE* file; @@ -366,6 +367,134 @@ VkResult create_layer( return VK_SUCCESS; } +VkResult load_texture( + VkDevice device, + VmaAllocator allocator, + UIContextStorage* context, + uint32_t index, + VkCommandPool transfer_pool, + Queue transfer_queue, + const char* png_path, + TextureStorage* memory) { + spng_ctx* spng = spng_ctx_new(0); + if(spng == NULL) { + return VK_ERROR_UNKNOWN; + } + + FILE* png_file = fopen(png_path, "rb"); + if(png_file == NULL) { + return VK_ERROR_UNKNOWN; + } + + fseek(png_file, 0, SEEK_END); + int error = fseek(png_file, 0, SEEK_END); + if(error != 0) { + return VK_ERROR_UNKNOWN; + } + + size_t png_size = ftell(png_file); + + error = fseek(png_file, 0, SEEK_SET); + if(error != 0) { + return VK_ERROR_UNKNOWN; + } + + + void* png = malloc(png_size); + if(png == NULL) { + return VK_ERROR_UNKNOWN; + } + + size_t read = fread(png, png_size, 1, png_file); + if(read != png_size) { + return VK_ERROR_UNKNOWN; + } + + fclose(png_file); + + spng_set_png_buffer(spng, png, png_size); + size_t out_size; + spng_decoded_image_size(spng, SPNG_FMT_RGBA8, &out_size); + struct spng_ihdr ihdr; + spng_get_ihdr(spng, &ihdr); + void* image_buffer = malloc(out_size); + if(image_buffer == NULL) { + return VK_ERROR_UNKNOWN; + } + + spng_decode_image(spng, image_buffer, out_size, SPNG_FMT_RGBA8, 0); + + VkResult result; + + VkImageCreateInfo image_info = { + .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, + .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + .extent = { + .width = ihdr.width, + .height = ihdr.height, + .depth = 1, + }, + .mipLevels = 1, + .arrayLayers = 1, + .format = VK_FORMAT_R8G8B8A8_SRGB, + .tiling = VK_IMAGE_TILING_OPTIMAL, + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .samples = VK_SAMPLE_COUNT_1_BIT, + .imageType = VK_IMAGE_TYPE_2D, + }; + + VmaAllocationCreateInfo memory_info = { + .usage = VMA_MEMORY_USAGE_GPU_ONLY, + }; + + VkBuffer transfer; + VmaAllocation transfer_memory; + void* mapped; + + VK_RESULT(vmaCreateImage(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)); + memcpy(mapped, image_buffer, sizeof(uint32_t)*ihdr.height*ihdr.width); + VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); + + VkImageMemoryBarrier first_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .image = memory->image, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1, + }, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, + }; + + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &first_barrier); + VkBufferImageCopy image_copy = { + .imageExtent = { + + }, + }; + vkCmdCopyBufferToImage(command_buffer, transfer, memory->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); + + VkImageMemoryBarrier second_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + }; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, &second_barrier); + + + VK_RESULT(command_end_single(device, command_buffer, transfer_pool, transfer_queue)); + vkQueueWaitIdle(transfer_queue.handle); + + destroy_transfer_buffer(allocator, transfer, transfer_memory); + free(image_buffer); + free(png); + spng_ctx_free(spng); +} + VkResult load_font( VkDevice device, VmaAllocator allocator, @@ -462,7 +591,6 @@ VkResult load_font( VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, .extent.depth = 1, .extent.width = info.width, @@ -564,8 +692,8 @@ VkResult load_font( VkSamplerCreateInfo sampler_info = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = VK_FILTER_CUBIC_IMG, - .minFilter = VK_FILTER_CUBIC_IMG, + .magFilter = VK_FILTER_NEAREST, + .minFilter = VK_FILTER_NEAREST, .addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT, .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT, @@ -754,8 +882,10 @@ VkResult create_ui_context( VK_RESULT(create_transfer_buffer(allocator, sizeof(UIContext), &transfer, &transfer_memory, (void**)&mapped)); memory->data.font_infos = buffer_address(device, memory->font_infos); - memory->data.scale[0] = window_scale[0] / swapchain_extent.width; - memory->data.scale[1] = window_scale[1] / swapchain_extent.height; + memory->data.screen[0] = window_scale[0] / swapchain_extent.width; + memory->data.screen[1] = window_scale[1] / swapchain_extent.height; + memory->data.scale[0] = window_scale[0]; + memory->data.scale[1] = window_scale[1]; memcpy(mapped, &memory->data, sizeof(UIContext)); VkCommandBuffer command_buffer = command_begin_single(device, transfer_pool); @@ -793,6 +923,29 @@ void set_ui_rect( drawable->code = 0; } +void set_ui_image( + float x, + float y, + float width, + float height, + float r, + float g, + float b, + float a, + uint32_t index, + UIDrawable* drawable) { + drawable->pos[0] = x; + drawable->pos[1] = y; + drawable->size[0] = width; + drawable->size[1] = height; + drawable->color[0] = r; + drawable->color[1] = g; + drawable->color[2] = b; + drawable->color[3] = a; + drawable->type = 2; + drawable->code = index; +} + void set_ui_string( float x, float y,