diff options
author | gramanas <anastasis.gramm2@gmail.com> | 2024-05-21 01:35:20 +0300 |
---|---|---|
committer | gramanas <anastasis.gramm2@gmail.com> | 2024-05-21 01:35:20 +0300 |
commit | 7c26dcc4480025b5d11e315273541b3fb2c34a09 (patch) | |
tree | 0fe3f3ff8cdd0d728f15f6cec4cca4d39aa8cb71 /src | |
parent | 9ead62940aecb7793b3d82c9c8eb73bc9eb4f60f (diff) | |
download | cgame-7c26dcc4480025b5d11e315273541b3fb2c34a09.tar.gz cgame-7c26dcc4480025b5d11e315273541b3fb2c34a09.tar.bz2 cgame-7c26dcc4480025b5d11e315273541b3fb2c34a09.zip |
ez going
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 7 | ||||
-rw-r--r-- | src/game.c | 461 | ||||
-rw-r--r-- | src/shader.frag | 27 | ||||
-rw-r--r-- | src/shader.vert | 3 | ||||
-rw-r--r-- | src/state.h | 69 | ||||
-rw-r--r-- | src/vkutil.h | 2 |
6 files changed, 339 insertions, 230 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 44c7cc1..7ef364b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,9 @@ bin_PROGRAMS = game common_sources = state.h + +AM_LDFLAGS = -fuse-ld=lld -flto + # -fwhole-program allows cross-file inlining, but only works when you put all # the source files on one gcc command-line. -flto is another way to get the # same effect. (Link-Time Optimization). clang supports -flto but not @@ -15,5 +18,9 @@ common_sources = state.h AM_CFLAGS = -march=native -fno-math-errno -funroll-loops -flto -pthread -ggdb -DVKDEBUG # AM_CFLAGS = -O0 -march=native -fno-math-errno -funroll-loops -flto -pthread -ggdb -fsanitize=address +AM_CXXFLAGS = -Wall -Wextra -O2 -g -std=c++17 + game_SOURCES = game.c cplusplus.cpp $(common_sources) game_LDADD = -lSDL2 -lm -lSDL2_image -lvulkan -lshaderc_shared -lstdc++ + +cplusplus.$(OBJEXT) : CXXFLAGS += -Wno-nullability-completeness -Wno-unused-function -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-variable @@ -29,8 +29,8 @@ uint32_t currentFrame = 0; state_t s; -const uint32_t validationLayerCount = 1; -const char *const validationLayers[] = { +const uint32_t validation_layer_count = 1; +const char *const validation_layers[] = { "VK_LAYER_KHRONOS_validation" }; @@ -65,11 +65,11 @@ typedef struct { /* (Vertex) { (V2) {-0.2f, -0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */ /* (Vertex) { (V2) {0.5f, 0.3f}, (V3) {0.0f, 0.0f, 1.0f}}, */ /* (Vertex) { (V2) {-0.5f, 0.7f}, (V3) {1.0f, 0.0f, 0.0f}}, */ - + /* (Vertex) { (V2) {0.2f, -0.5f}, (V3) {0.0f, 0.0f, 1.0f}}, */ /* (Vertex) { (V2) {0.5f, 0.7f}, (V3) {1.0f, 0.0f, 0.0f}}, */ /* (Vertex) { (V2) {-0.5f, 0.3f}, (V3) {0.0f, 1.0f, 0.0f}}, */ - + /* (Vertex) { (V2) {0.0f, -0.5f}, (V3) {1.0f, 0.0f, 0.0f}}, */ /* (Vertex) { (V2) {0.5f, 0.5f}, (V3) {0.0f, 1.0f, 0.0f}}, */ /* (Vertex) { (V2) {-0.5f, 0.5f}, (V3) {0.0f, 0.0f, 1.0f}}, */ @@ -103,11 +103,11 @@ init() } s.sdl_window = SDL_CreateWindow("Vulkanizater", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - s.window_w, - s.window_h, - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + s.window_w, + s.window_h, + SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_VULKAN); if (s.sdl_window == NULL) { vk_log(VK_INFO, "Window could not be created! SDL_Error: %s\n", SDL_GetError()); return false; @@ -133,11 +133,11 @@ checkValidationLayerSupport() VkLayerProperties availableLayers[layerCount]; vkEnumerateInstanceLayerProperties(&layerCount, availableLayers); - for (uint32_t i = 0; i < validationLayerCount; i++) { + for (uint32_t i = 0; i < validation_layer_count; i++) { bool layerFound = false; for (uint32_t j = 0; j < layerCount; j++) { - if (strcmp(validationLayers[i], availableLayers[j].layerName) == 0) { + if (strcmp(validation_layers[i], availableLayers[j].layerName) == 0) { layerFound = true; break; } @@ -176,7 +176,7 @@ vulkan_setup_debug_messenger() // TODO: func pointers returned are NULL s.pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkCreateDebugUtilsMessengerEXT"); s.pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(s.vk_instance, "vkDestroyDebugUtilsMessengerEXT"); - + VkResult result = s.pfnCreateDebugUtilsMessengerEXT(s.vk_instance, &createInfo, NULL, &s.vk_debug_messenger); if (result != VK_SUCCESS) { vk_log(VK_WARN, "failed to set up debug messenger! %s\n", string_VkResult(result)); @@ -255,8 +255,8 @@ vulkan_create_instance() }; if (enableValidationLayers) { - createInfo.enabledLayerCount = validationLayerCount; - createInfo.ppEnabledLayerNames = validationLayers; + createInfo.enabledLayerCount = validation_layer_count; + createInfo.ppEnabledLayerNames = validation_layers; } if (vkCreateInstance(&createInfo, NULL, &s.vk_instance) != VK_SUCCESS) { @@ -329,6 +329,7 @@ typedef struct SwapChainSupportDetails { SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { + // TODO Make SwapChainSupportDetails malloc it;s arrays and free it after it is used. SwapChainSupportDetails details; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, s.vk_surface, &details.capabilities); @@ -520,42 +521,37 @@ vulkan_create_logical_device() } void -handle_input(bool * quit) +update_camera(float xoffset, float yoffset) { - SDL_Event e; + s.camera.yaw += xoffset; + s.camera.pitch += yoffset; + + // Make sure that when pitch is out of bounds, the screen doesn't get flipped + if (s.camera.pitch > 89.0f) + s.camera.pitch = 89.0f; + if (s.camera.pitch < -89.0f) + s.camera.pitch = -89.0f; + + /* vec3 front; */ + /* front[0] = -sin(glm_rad(s.camera.yaw)) * cos(glm_rad(s.camera.pitch)); */ + /* front[1] = sin(glm_rad(s.camera.pitch)); */ + /* front[2] = -cos(glm_rad(s.camera.yaw)) * cos(glm_rad(s.camera.pitch)); */ + /* glm_normalize_to(front, s.camera.front); */ +} - while (SDL_PollEvent(&e) != 0) { - // User requests quit - if (e.type == SDL_QUIT) { - *quit = true; - } - // User presses a key - else if (e.type == SDL_KEYDOWN) { - switch (e.key.keysym.sym) { - case SDLK_UP: - s.x += .1f; - break; - case SDLK_DOWN: - s.x -= .1f; - break; - case SDLK_LEFT: - break; - case SDLK_RIGHT: - break; - } - } - else if (e.type == SDL_MOUSEWHEEL) { - if(e.wheel.y > 0) // scroll up - { - s.zoom += 1; - } - else if(e.wheel.y < 0) // scroll down - { - s.zoom -= 1; - if (s.zoom == -100) s.zoom = 1; - } - } - } +void +mouseCallback(SDL_Event *event) +{ + if (event->type != SDL_MOUSEMOTION) return; + if (!s.mouse_pressed) return; + float xoffset = event->motion.xrel; + float yoffset = -event->motion.yrel; // Reversed since y-coordinates range from bottom to top + + float sensitivity = 0.1f; // Change this value to your liking + xoffset *= sensitivity; + yoffset *= sensitivity; + + update_camera(xoffset, yoffset); } void @@ -619,10 +615,10 @@ vulkan_create_swap_chain() /* vk_log(VK_ERROR, "ERROR: failed to create swap chain! %s\n", string_VkResult(result)); */ /* } */ - vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, NULL); + VK_CHECK(vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, NULL)); //vk_log(VK_INFO, "vk_swap_chain_images count: %d\n", s.vk_swap_chain_image_count); // todo alloc space for images - vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, s.vk_swap_chain_images); + VK_CHECK(vkGetSwapchainImagesKHR(s.vk_device, s.vk_swap_chain, &s.vk_swap_chain_image_count, s.vk_swap_chain_images)); s.vk_swap_chain_image_format = surfaceFormat.format; s.vk_swap_chain_extent = extent; @@ -728,13 +724,13 @@ load_compile_shader_data(const char * path, shaderc_shader_kind shader_kind) void vulkan_create_graphics_pipeline() { - shaderc_compilation_result_t vert_result = load_compile_shader_data("shader.vert", shaderc_vertex_shader); + shaderc_compilation_result_t vert_result = load_compile_shader_data("src/shader.vert", shaderc_vertex_shader); if (!vert_result) { - vk_log(VK_ERROR, "Can't load vertex shader"); + vk_log(VK_ERROR, "Can't load vertex shader\n"); } - shaderc_compilation_result_t frag_result = load_compile_shader_data("shader.frag", shaderc_fragment_shader); + shaderc_compilation_result_t frag_result = load_compile_shader_data("src/shader.frag", shaderc_fragment_shader); if (!frag_result) { - vk_log(VK_ERROR, "Can't load fragment shader"); + vk_log(VK_ERROR, "Can't load fragment shader\n"); } const char * vert_data = shaderc_result_get_bytes(vert_result); @@ -826,8 +822,8 @@ vulkan_create_graphics_pipeline() rasterizer.polygonMode = VK_POLYGON_MODE_FILL; rasterizer.lineWidth = 1.0f; rasterizer.cullMode = VK_CULL_MODE_NONE; -// rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + //rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + //rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rasterizer.depthBiasEnable = VK_FALSE; rasterizer.depthBiasConstantFactor = 0.0f; // Optional rasterizer.depthBiasClamp = 0.0f; // Optional @@ -973,11 +969,8 @@ vulkan_create_framebuffers() framebufferInfo.height = s.vk_swap_chain_extent.height; framebufferInfo.layers = 1; - if (vkCreateFramebuffer(s.vk_device, &framebufferInfo, NULL, &s.vk_swap_chain_framebuffers[i]) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create framebuffer!\n"); - } + VK_CHECK(vkCreateFramebuffer(s.vk_device, &framebufferInfo, NULL, &s.vk_swap_chain_framebuffers[i])); } - } void @@ -990,23 +983,21 @@ vulkan_create_command_pool() poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; - if (vkCreateCommandPool(s.vk_device, &poolInfo, NULL, &s.vk_command_pool) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create command pool!\n"); - } - + VK_CHECK(vkCreateCommandPool(s.vk_device, &poolInfo, NULL, &s.vk_command_pool)); } void vulkan_create_command_buffer() { - VkCommandBufferAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = s.vk_command_pool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = MAX_FRAMES_IN_FLIGHT; + // TODO Find a way to group allocation + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + VkCommandBufferAllocateInfo allocInfo = {0}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = s.vk_command_pool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = 1; - if (vkAllocateCommandBuffers(s.vk_device, &allocInfo, s.vk_command_buffers) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to allocate command buffers!\n"); + VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &s.frames[i].vk_command_buffer)); } } @@ -1018,9 +1009,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) beginInfo.flags = 0; // Optional beginInfo.pInheritanceInfo = NULL; // Optional - if (vkBeginCommandBuffer(commandBuffer, &beginInfo) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to begin recording command buffer!\n"); - } + VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); VkRenderPassBeginInfo renderPassInfo = {0}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; @@ -1050,7 +1039,7 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) /* renderingInfo.pColorAttachments = &colorAttachment; */ /* vkCmdBeginRendering(commandBuffer, &renderingInfo); */ - /* .... */ + /* .... */ /* vkCmdEndRendering(commandBuffer); */ vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -1075,15 +1064,13 @@ recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex) VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); vkCmdBindIndexBuffer(commandBuffer, s.vk_index_buffer, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, s.vk_pipeline_layout, 0, 1, &s.vk_descriptor_sets[currentFrame], 0, NULL); - + vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, s.vk_pipeline_layout, 0, 1, &s.frames[currentFrame].vk_descriptor_set, 0, NULL); + vkCmdDrawIndexed(commandBuffer, INDICES_SIZE, 1, 0, 0, 0); vkCmdEndRenderPass(commandBuffer); - if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to record command buffer!\n"); - } + VK_CHECK(vkEndCommandBuffer(commandBuffer)); } void @@ -1097,11 +1084,9 @@ vulkan_create_sync_objects() fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.renderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(s.vk_device, &fenceInfo, NULL, &s.inFlightFences[i]) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create semaphores!\n"); - } + VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].image_available_semaphore)); + VK_CHECK(vkCreateSemaphore(s.vk_device, &semaphoreInfo, NULL, &s.frames[i].render_finished_semaphore)); + VK_CHECK(vkCreateFence(s.vk_device, &fenceInfo, NULL, &s.frames[i].in_flight_fence)); } } @@ -1133,9 +1118,7 @@ createBuffer(VkDeviceSize size, bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(s.vk_device, &bufferInfo, NULL, buffer) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create buffer!\n"); - } + VK_CHECK(vkCreateBuffer(s.vk_device, &bufferInfo, NULL, buffer)); VkMemoryRequirements memRequirements; vkGetBufferMemoryRequirements(s.vk_device, *buffer, &memRequirements); @@ -1145,30 +1128,14 @@ createBuffer(VkDeviceSize size, allocInfo.allocationSize = memRequirements.size; allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties); - // TODO: allocations limited by hardware - if (vkAllocateMemory(s.vk_device, &allocInfo, NULL, bufferMemory) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to allocate buffer memory!\n"); - } + // TODO: group allocations etc... (allocations limited by hardware) + VK_CHECK(vkAllocateMemory(s.vk_device, &allocInfo, NULL, bufferMemory)); - vkBindBufferMemory(s.vk_device, *buffer, *bufferMemory, 0); + VK_CHECK(vkBindBufferMemory(s.vk_device, *buffer, *bufferMemory, 0)); } -/* void */ -/* vulkan_create_vertex_buffer() */ -/* { */ -/* VkDeviceSize bufferSize = sizeof(vertices[0]) * VERTICES_SIZE; */ -/* createBuffer(bufferSize, */ -/* VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, */ -/* VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, */ -/* &s.vk_vertex_buffer, &s.vk_vertex_buffer_memory); */ - -/* void* data; */ -/* vkMapMemory(s.vk_device, s.vk_vertex_buffer_memory, 0, bufferSize, 0, &data); */ -/* memcpy(data, vertices, (size_t) bufferSize); */ -/* vkUnmapMemory(s.vk_device, s.vk_vertex_buffer_memory); */ -/* } */ void -copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { +copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { VkCommandBufferAllocateInfo allocInfo = {0}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; @@ -1176,33 +1143,31 @@ copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { allocInfo.commandBufferCount = 1; VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(s.vk_device, &allocInfo, &commandBuffer); + VK_CHECK(vkAllocateCommandBuffers(s.vk_device, &allocInfo, &commandBuffer)); VkCommandBufferBeginInfo beginInfo = {0}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; - vkBeginCommandBuffer(commandBuffer, &beginInfo); + VK_CHECK(vkBeginCommandBuffer(commandBuffer, &beginInfo)); VkBufferCopy copyRegion = {0}; copyRegion.srcOffset = 0; // Optional copyRegion.dstOffset = 0; // Optional copyRegion.size = size; vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); - vkEndCommandBuffer(commandBuffer); + VK_CHECK(vkEndCommandBuffer(commandBuffer)); VkSubmitInfo submitInfo = {0}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; - vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(s.vk_graphics_queue); + VK_CHECK(vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, VK_NULL_HANDLE)); + VK_CHECK(vkQueueWaitIdle(s.vk_graphics_queue)); vkFreeCommandBuffers(s.vk_device, s.vk_command_pool, 1, &commandBuffer); } - - void vulkan_create_vertex_buffer() { @@ -1215,9 +1180,9 @@ vulkan_create_vertex_buffer() VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, &stagingBufferMemory); - + void* data; - vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data); + VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); memcpy(data, vertices, (size_t) bufferSize); vkUnmapMemory(s.vk_device, stagingBufferMemory); @@ -1226,7 +1191,7 @@ vulkan_create_vertex_buffer() VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_vertex_buffer, &s.vk_vertex_buffer_memory); - copyBuffer(stagingBuffer, s.vk_vertex_buffer, bufferSize); + copy_buffer(stagingBuffer, s.vk_vertex_buffer, bufferSize); vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); @@ -1244,9 +1209,9 @@ vulkan_create_index_buffer() VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffer, &stagingBufferMemory); - + void* data; - vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data); + VK_CHECK(vkMapMemory(s.vk_device, stagingBufferMemory, 0, bufferSize, 0, &data)); memcpy(data, indices, (size_t) bufferSize); vkUnmapMemory(s.vk_device, stagingBufferMemory); @@ -1255,7 +1220,7 @@ vulkan_create_index_buffer() VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &s.vk_index_buffer, &s.vk_index_buffer_memory); - copyBuffer(stagingBuffer, s.vk_index_buffer, bufferSize); + copy_buffer(stagingBuffer, s.vk_index_buffer, bufferSize); vkDestroyBuffer(s.vk_device, stagingBuffer, NULL); vkFreeMemory(s.vk_device, stagingBufferMemory, NULL); @@ -1276,9 +1241,7 @@ vulkan_create_descriptor_set_layout() layoutInfo.bindingCount = 1; layoutInfo.pBindings = &uboLayoutBinding; - if (vkCreateDescriptorSetLayout(s.vk_device, &layoutInfo, NULL, &s.vk_descriptor_set_layout) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create descriptor set layout!\n"); - } + VK_CHECK(vkCreateDescriptorSetLayout(s.vk_device, &layoutInfo, NULL, &s.vk_descriptor_set_layout)); } void @@ -1290,9 +1253,9 @@ vulkan_create_uniform_buffers() createBuffer(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &s.vk_uniform_buffers[i], &s.vk_uniform_buffers_memory[i]); + &s.frames[i].vk_uniform_buffer, &s.frames[i].vk_uniform_buffer_memory); - vkMapMemory(s.vk_device, s.vk_uniform_buffers_memory[i], 0, bufferSize, 0, &s.vk_uniform_buffers_mapped[i]); + VK_CHECK(vkMapMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, 0, bufferSize, 0, &s.frames[i].vk_uniform_buffer_mapped)); } } @@ -1309,12 +1272,10 @@ vulkan_create_descriptor_pool() poolInfo.pPoolSizes = &poolSize; poolInfo.maxSets = MAX_FRAMES_IN_FLIGHT; - if (vkCreateDescriptorPool(s.vk_device, &poolInfo, NULL, &s.vk_descriptor_pool) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to create descriptor pool!\n"); - } - + VK_CHECK(vkCreateDescriptorPool(s.vk_device, &poolInfo, NULL, &s.vk_descriptor_pool)); } +VkDescriptorSet * temp_set; void vulkan_create_descriptor_sets() { @@ -1324,30 +1285,31 @@ vulkan_create_descriptor_sets() layouts[i] = s.vk_descriptor_set_layout; } - VkDescriptorSetAllocateInfo allocInfo = {0}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = s.vk_descriptor_pool; - allocInfo.descriptorSetCount = MAX_FRAMES_IN_FLIGHT; - allocInfo.pSetLayouts = layouts; + // TODO Find a way to group allocation + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { + VkDescriptorSetAllocateInfo allocInfo = {0}; + allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + allocInfo.descriptorPool = s.vk_descriptor_pool; + allocInfo.descriptorSetCount = 1; + allocInfo.pSetLayouts = layouts; - if (vkAllocateDescriptorSets(s.vk_device, &allocInfo, s.vk_descriptor_sets) != VK_SUCCESS) { - vk_log(VK_ERROR, "failed to allocate descriptor sets!\n"); + VK_CHECK(vkAllocateDescriptorSets(s.vk_device, &allocInfo, &s.frames[i].vk_descriptor_set)); } for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { VkDescriptorBufferInfo bufferInfo = {0}; - bufferInfo.buffer = s.vk_uniform_buffers[i]; + bufferInfo.buffer = s.frames[i].vk_uniform_buffer; bufferInfo.offset = 0; bufferInfo.range = sizeof(UniformBufferObject); VkWriteDescriptorSet descriptorWrite = {0}; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = s.vk_descriptor_sets[i]; + descriptorWrite.dstSet = s.frames[i].vk_descriptor_set; descriptorWrite.dstBinding = 0; descriptorWrite.dstArrayElement = 0; descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; + descriptorWrite.pBufferInfo = &bufferInfo; descriptorWrite.pImageInfo = NULL; // Optional descriptorWrite.pTexelBufferView = NULL; // Optional @@ -1356,6 +1318,103 @@ vulkan_create_descriptor_sets() } void +cleanupSwapChain() +{ + for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) { + vkDestroyFramebuffer(s.vk_device, s.vk_swap_chain_framebuffers[i], NULL); + } + for (uint32_t i = 0; i < s.vk_swap_chain_image_count; i++) { + vkDestroyImageView(s.vk_device, s.vk_swap_chain_image_views[i], NULL); + } + vkDestroySwapchainKHR(s.vk_device, s.vk_swap_chain, NULL); +} + +void +recreateSwapChain() +{ + vkDeviceWaitIdle(s.vk_device); + + cleanupSwapChain(); + + vulkan_create_swap_chain(); + vulkan_create_image_views(); + vulkan_create_framebuffers(); +} + +void +handle_input(bool * quit) +{ + SDL_Event e; + + while (SDL_PollEvent(&e) != 0) { + // User requests quit + if (e.type == SDL_QUIT) { + *quit = true; + } + // User presses a key + else if (e.type == SDL_KEYDOWN) { + switch (e.key.keysym.sym) { + case SDLK_w: + s.camera.pos[0] += 0.1f; + break; + case SDLK_s: + s.camera.pos[0] -= 0.1f; + break; + case SDLK_LEFT: + break; + case SDLK_g: // reload shaders + recreateSwapChain(); + vkDestroyPipeline(s.vk_device, s.vk_graphics_pipeline, NULL); + vkDestroyPipelineLayout(s.vk_device, s.vk_pipeline_layout, NULL); + vulkan_create_graphics_pipeline(); + break; + case SDLK_l: + s.rotate = s.rotate ? 0 : 1; + break; + case SDLK_r: + s.camera.pos[0] = 1.0f; + s.camera.pos[1] = 1.0f; + s.camera.pos[2] = 1.0f; + + s.camera.front[0] = 0.0f; + s.camera.front[1] = 0.0f; + s.camera.front[2] = 0.0f; + + s.camera.up[0] = 0.0f; + s.camera.up[1] = 0.0f; + s.camera.up[2] = 1.0f; + + s.camera.yaw = 0.0f; + s.camera.pitch = 90.0f; + s.camera.lastX = 400.0f; + s.camera.lastY = 300.0f; + s.camera.fov = 45.0f; + update_camera(0,0); + break; + } + } + else if (e.type == SDL_MOUSEWHEEL) { + if(e.wheel.y > 0) // scroll up + { + s.zoom += 1; + } + else if(e.wheel.y < 0) // scroll down + { + s.zoom -= 1; + if (s.zoom == -100) s.zoom = 1; + } + } + else if (e.type == SDL_MOUSEBUTTONDOWN) { + s.mouse_pressed = 1; + } + else if (e.type == SDL_MOUSEBUTTONUP) { + s.mouse_pressed = 0; + } + mouseCallback(&e); + } +} + +void init_vulkan() { vk_log(VK_WARN, "====================================\n"); @@ -1384,38 +1443,14 @@ init_vulkan() } void -cleanupSwapChain() -{ - for (size_t i = 0; i < s.vk_swap_chain_image_count; i++) { - vkDestroyFramebuffer(s.vk_device, s.vk_swap_chain_framebuffers[i], NULL); - } - for (uint32_t i = 0; i < s.vk_swap_chain_image_count; i++) { - vkDestroyImageView(s.vk_device, s.vk_swap_chain_image_views[i], NULL); - } - vkDestroySwapchainKHR(s.vk_device, s.vk_swap_chain, NULL); -} - -void -recreateSwapChain() -{ - vkDeviceWaitIdle(s.vk_device); - - cleanupSwapChain(); - - vulkan_create_swap_chain(); - vulkan_create_image_views(); - vulkan_create_framebuffers(); -} - -void close_vulkan() { vkDeviceWaitIdle(s.vk_device); // Cleanup for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(s.vk_device, s.imageAvailableSemaphores[i], NULL); - vkDestroySemaphore(s.vk_device, s.renderFinishedSemaphores[i], NULL); - vkDestroyFence(s.vk_device, s.inFlightFences[i], NULL); + vkDestroySemaphore(s.vk_device, s.frames[i].image_available_semaphore, NULL); + vkDestroySemaphore(s.vk_device, s.frames[i].render_finished_semaphore, NULL); + vkDestroyFence(s.vk_device, s.frames[i].in_flight_fence, NULL); } vkDestroyCommandPool(s.vk_device, s.vk_command_pool, NULL); @@ -1423,12 +1458,12 @@ close_vulkan() cleanupSwapChain(); for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroyBuffer(s.vk_device, s.vk_uniform_buffers[i], NULL); - vkFreeMemory(s.vk_device, s.vk_uniform_buffers_memory[i], NULL); + vkDestroyBuffer(s.vk_device, s.frames[i].vk_uniform_buffer, NULL); + vkFreeMemory(s.vk_device, s.frames[i].vk_uniform_buffer_memory, NULL); } vkDestroyDescriptorPool(s.vk_device, s.vk_descriptor_pool, NULL); vkDestroyDescriptorSetLayout(s.vk_device, s.vk_descriptor_set_layout, NULL); - + vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); @@ -1451,7 +1486,7 @@ current_time() { static struct timespec startTime; static int isStartTimeInitialized = 0; - + if (!isStartTimeInitialized) { clock_gettime(CLOCK_MONOTONIC, &startTime); isStartTimeInitialized = 1; @@ -1460,40 +1495,44 @@ current_time() struct timespec currentTime; clock_gettime(CLOCK_MONOTONIC, ¤tTime); - return (currentTime.tv_sec - startTime.tv_sec) + + return (currentTime.tv_sec - startTime.tv_sec) + (currentTime.tv_nsec - startTime.tv_nsec) / 1e9f; } - void updateUniformBuffer(uint32_t currentImage) { - float time = current_time(); - + UniformBufferObject ubo = {0}; glm_mat4_identity(ubo.model); - glm_rotate(ubo.model, glm_rad(100 * time * glm_rad(90.0f)), GLM_ZUP); - vec3 eye = {1.0f + s.x, 1.0f + s.x, 1.0f + s.x}; // GLM_VEC3_ONE_INIT; + if (s.rotate) + glm_rotate(ubo.model, glm_rad(50 * time * glm_rad(90.0f)), GLM_ZUP); + + vec3 eye = GLM_VEC3_ONE_INIT; vec3 center = GLM_VEC3_ZERO_INIT; - vec3 up = {0.0f, 0.0f, 1.0f};//GLM_ZUP; - glm_lookat(eye, center, up, ubo.view); +// vk_log(VK_INFO, "{%.2f, %.2f, %.2f}\n", s.camera.front[0], s.camera.front[1], s.camera.front[2]); + /* glm_vec3_add(s.camera.pos, s.camera.front, center); */ + glm_lookat(s.camera.pos, s.camera.front, s.camera.up, ubo.view); + + /* glm_lookat(eye, center, GLM_ZUP, ubo.view); */ + float aspect = s.vk_swap_chain_extent.width / (float)s.vk_swap_chain_extent.height; glm_perspective(glm_rad(55.0f - s.zoom ), aspect, 0.1f, 100.0f, ubo.proj); - + // Inverting the Y axis for Vulkan ubo.proj[1][1] *= -1; - memcpy(s.vk_uniform_buffers_mapped[currentImage], &ubo, sizeof(ubo)); + memcpy(s.frames[currentImage].vk_uniform_buffer_mapped, &ubo, sizeof(ubo)); } void draw_frame() { - vkWaitForFences(s.vk_device, 1, &s.inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + vkWaitForFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence, VK_TRUE, UINT64_MAX); uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(s.vk_device, s.vk_swap_chain, UINT64_MAX, s.imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + VkResult result = vkAcquireNextImageKHR(s.vk_device, s.vk_swap_chain, UINT64_MAX, s.frames[currentFrame].image_available_semaphore, VK_NULL_HANDLE, &imageIndex); if (result == VK_ERROR_OUT_OF_DATE_KHR) { recreateSwapChain(); @@ -1504,28 +1543,27 @@ draw_frame() { updateUniformBuffer(currentFrame); - vkResetFences(s.vk_device, 1, &s.inFlightFences[currentFrame]); + vkResetFences(s.vk_device, 1, &s.frames[currentFrame].in_flight_fence); - vkResetCommandBuffer(s.vk_command_buffers[currentFrame], 0); - recordCommandBuffer(s.vk_command_buffers[currentFrame], imageIndex); + vkResetCommandBuffer(s.frames[currentFrame].vk_command_buffer, 0); + recordCommandBuffer(s.frames[currentFrame].vk_command_buffer, imageIndex); - VkSubmitInfo submitInfo = {0}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - VkSemaphore waitSemaphores[] = {s.imageAvailableSemaphores[currentFrame]}; + VkSemaphore waitSemaphores[] = {s.frames[currentFrame].image_available_semaphore}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &s.vk_command_buffers[currentFrame]; + submitInfo.pCommandBuffers = &s.frames[currentFrame].vk_command_buffer; - VkSemaphore signalSemaphores[] = {s.renderFinishedSemaphores[currentFrame]}; + VkSemaphore signalSemaphores[] = {s.frames[currentFrame].render_finished_semaphore}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - if (vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, s.inFlightFences[currentFrame]) != VK_SUCCESS) { + if (vkQueueSubmit(s.vk_graphics_queue, 1, &submitInfo, s.frames[currentFrame].in_flight_fence) != VK_SUCCESS) { vk_log(VK_ERROR, "failed to submit draw command buffer!\n"); } @@ -1562,29 +1600,30 @@ main(int argc, char* args[]) bool quit = false; - + /* VMA POC */ - /* VmaVulkanFunctions vulkanFunctions = {0}; */ - /* vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; */ - /* vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; */ - - /* VmaAllocatorCreateInfo allocatorCreateInfo = {0}; */ - /* allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; */ - /* allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2; */ - /* allocatorCreateInfo.physicalDevice = s.vk_physical_device; */ - /* allocatorCreateInfo.device = s.vk_device; */ - /* allocatorCreateInfo.instance = s.vk_instance; */ - /* allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; */ - - /* VmaAllocator allocator; */ - /* vmaCreateAllocator(&allocatorCreateInfo, &allocator); */ - - /* // Entire program... */ - - /* // At the end, don't forget to: */ - /* vmaDestroyAllocator(allocator); */ + VmaVulkanFunctions vulkanFunctions = {0}; + vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr; + vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr; + + VmaAllocatorCreateInfo allocatorCreateInfo = {0}; + allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; + allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2; + allocatorCreateInfo.physicalDevice = s.vk_physical_device; + allocatorCreateInfo.device = s.vk_device; + allocatorCreateInfo.instance = s.vk_instance; + allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions; + + VmaAllocator allocator; + vmaCreateAllocator(&allocatorCreateInfo, &allocator); + + // Entire program... + + // At the end, don't forget to: + vmaDestroyAllocator(allocator); // Game loop + update_camera(0, 0); while (!quit) { handle_input(&quit); draw_frame(); diff --git a/src/shader.frag b/src/shader.frag index 7c5b0e7..cad317c 100644 --- a/src/shader.frag +++ b/src/shader.frag @@ -1,9 +1,34 @@ #version 450 layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragPos; layout(location = 0) out vec4 outColor; +// void main() { +// outColor = vec4(fragColor, 1.0); +// } +vec3 mandel(vec2 z0) { + float k = 0.0; + vec2 z = vec2(0.0); + for(int i = 0; i < 420; ++i) { + z = vec2(z.x*z.x-z.y*z.y, z.x*z.y*2.0) + z0; + if (length(z) > 20.0) break; + k += 1.0; + } + float mu = k + 1.0 - log2(log(length(z))); + return sin(mu*0.1 + vec3(0.0,0.5,1.0)); +} void main() { - outColor = vec4(fragColor, 1.0); + float ar = fragPos.x / fragPos.y; + vec2 uv = gl_FragCoord.xy / fragPos.yy - vec2(0.66 * ar, 0.5); + //uv = uv * 2.0 + vec2(-0.3, 1.0); + float p = 30.0; + float t = mod(13.0, p); + if (t > p/2.0) t = p - t; + float scale = 0.5 + pow(4.0, t); + vec2 offset = vec2(-1.36799, .01); + uv += offset*scale; + uv /= scale; + outColor = vec4(mandel(uv), 1.0); } diff --git a/src/shader.vert b/src/shader.vert index 7ce15ef..76de53c 100644 --- a/src/shader.vert +++ b/src/shader.vert @@ -10,8 +10,11 @@ layout(location = 0) in vec2 inPosition; layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragPos; void main() { gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); + //gl_Position = vec4(inPosition * 1.5, 1.0, 1.0); fragColor = inColor; + fragPos = inPosition; } diff --git a/src/state.h b/src/state.h index cd5f44e..3890694 100644 --- a/src/state.h +++ b/src/state.h @@ -1,29 +1,55 @@ #include <SDL2/SDL.h> -#include "cq.h" #include "../lib/cglm/include/cglm/cglm.h" +#include <vulkan/vulkan.h> #pragma once #define MAX_FRAMES_IN_FLIGHT 2 typedef struct { + vec3 pos; + vec3 front; + vec3 up; + float yaw; + float pitch; + float lastX; + float lastY; + float fov; +} camera3d; + +typedef struct { mat4 model; mat4 view; mat4 proj; } UniformBufferObject; typedef struct { + VkCommandBuffer vk_command_buffer; + + VkSemaphore image_available_semaphore; + VkSemaphore render_finished_semaphore; + VkFence in_flight_fence; + + VkBuffer vk_uniform_buffer; + VkDeviceMemory vk_uniform_buffer_memory; + void * vk_uniform_buffer_mapped; + VkDescriptorSet vk_descriptor_set; } frame_data; typedef struct state { + camera3d camera; + int window_w, window_h; int cell_w, cell_h; int grid_w, grid_h; int char_w, char_h; int char_x, char_y; + int rotate; + int mouse_pressed; + UniformBufferObject ubo; float x; @@ -35,7 +61,7 @@ typedef struct state { VkDebugUtilsMessengerEXT vk_debug_messenger; PFN_vkCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT; PFN_vkDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT; - + VkPhysicalDevice vk_physical_device; VkDevice vk_device; VkQueue vk_graphics_queue; @@ -62,15 +88,8 @@ typedef struct state { uint32_t vk_swap_chain_framebuffers_count; VkCommandPool vk_command_pool; - VkCommandBuffer vk_command_buffers[MAX_FRAMES_IN_FLIGHT]; - - VkSemaphore imageAvailableSemaphores[MAX_FRAMES_IN_FLIGHT]; - VkSemaphore renderFinishedSemaphores[MAX_FRAMES_IN_FLIGHT]; - VkFence inFlightFences[MAX_FRAMES_IN_FLIGHT]; - VkBuffer vk_uniform_buffers[MAX_FRAMES_IN_FLIGHT]; - VkDeviceMemory vk_uniform_buffers_memory[MAX_FRAMES_IN_FLIGHT]; - void * vk_uniform_buffers_mapped[MAX_FRAMES_IN_FLIGHT]; + frame_data frames[MAX_FRAMES_IN_FLIGHT]; VkBuffer vk_vertex_buffer; VkDeviceMemory vk_vertex_buffer_memory; @@ -79,14 +98,32 @@ typedef struct state { VkDeviceMemory vk_index_buffer_memory; VkDescriptorPool vk_descriptor_pool; - VkDescriptorSet vk_descriptor_sets[MAX_FRAMES_IN_FLIGHT]; - - LIST test; } state_t ; -void +static void init_state(state_t * s) { + s->camera.pos[0] = 1.0f; + s->camera.pos[1] = 1.0f; + s->camera.pos[2] = 1.0f; + + s->camera.front[0] = 0.0f; + s->camera.front[1] = 0.0f; + s->camera.front[2] = 0.0f; + + s->camera.up[0] = 0.0f; + s->camera.up[1] = 0.0f; + s->camera.up[2] = 1.0f; + + s->camera.yaw = 0.0f; + s->camera.pitch = -90.0f; + s->camera.lastX = 400.0f; + s->camera.lastY = 300.0f; + s->camera.fov = 45.0f; + + s->rotate = 0; + s->mouse_pressed = 0; + s->window_w = 800; s->window_h = 600; s->cell_w = 10; @@ -100,13 +137,11 @@ init_state(state_t * s) s->zoom = 10; s->x = 0.0f; - + s->sdl_window = NULL; s->vk_swap_chain_image_count = 0; s->vk_physical_device = VK_NULL_HANDLE; s->vk_swap_chain_framebuffers_count = 0; - - list_init(VkImage *, s->test, 1024); } diff --git a/src/vkutil.h b/src/vkutil.h index 7ab19a0..9188a07 100644 --- a/src/vkutil.h +++ b/src/vkutil.h @@ -18,7 +18,7 @@ do { \ VkResult err = x; \ if (err) { \ fprintf(stderr, "%s:%d:0: vulkan error: %s \n", \ - __FILE__+3, __LINE__, string_VkResult(err)); \ + __FILE__, __LINE__, string_VkResult(err)); \ abort(); \ } \ } while (0) |