diff options
| author | vimene <vincent.menegaux@gmail.com> | 2025-12-31 18:34:54 +0100 |
|---|---|---|
| committer | vimene <vincent.menegaux@gmail.com> | 2025-12-31 18:34:54 +0100 |
| commit | f9c6bd77af826423fba4aeec86b227ccd7102b4e (patch) | |
| tree | ea54539034d4494df761d8fea3901acbf5803588 /src | |
| parent | 8ab4780f134c33a9e11ac0fe0bd866e17d3ee650 (diff) | |
| download | engine-vulkan.tar.gz | |
added back the software renderervulkan
Diffstat (limited to 'src')
| -rw-r--r-- | src/engine.cpp | 501 | ||||
| -rw-r--r-- | src/fb/pixfb.cpp | 12 | ||||
| -rw-r--r-- | src/shaders/shader.slang | 7 |
3 files changed, 367 insertions, 153 deletions
diff --git a/src/engine.cpp b/src/engine.cpp index c556592..69fa839 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -337,6 +337,11 @@ struct PhysicalDeviceEntry { VkFormat depth_format; }; +enum class GraphicalRendererMode { + hardware, + software, +}; + static bool check_validation_layer_support() { auto avail_layers = [&]() { uint32_t avail_layers_count; @@ -1185,6 +1190,15 @@ static int main_graphical(Scene& scene) { return surface_capabilities; }(); + { + // VK_IMAGE_USAGE_TRANSFER_DST_BIT is for the software renderer + VkImageUsageFlags required_surface_usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + if ((surface_capabilities.supportedUsageFlags & required_surface_usage) != required_surface_usage) { + std::cerr << "required surface usage flags not present" << std::endl; + exit(EXIT_FAILURE); + } + } + swapchain_extent = [&]() { if (surface_capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) return surface_capabilities.currentExtent; @@ -1269,7 +1283,8 @@ static int main_graphical(Scene& scene) { .imageColorSpace = surface_format.colorSpace, .imageExtent = swapchain_extent, .imageArrayLayers = 1, - .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + // VK_IMAGE_USAGE_TRANSFER_DST_BIT is for the software renderer + .imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, .imageSharingMode = {}, .queueFamilyIndexCount = {}, .pQueueFamilyIndices = {}, @@ -1342,6 +1357,8 @@ static int main_graphical(Scene& scene) { recreate_swapchain(); + auto renderer_mode = GraphicalRendererMode::software; + // create descriptor set layout auto descriptor_set_layout = [&]() { std::array descriptor_set_layout_bindings { @@ -2054,6 +2071,49 @@ static int main_graphical(Scene& scene) { } std::cout << " ]" << std::endl; + // init software renderer + // TODO: resize buffer when surface extent change + Renderer<PixelFrameBuffer> software_renderer { PixelFrameBuffer { + static_cast<unsigned int>(swapchain_extent.width), + static_cast<unsigned int>(swapchain_extent.height), + } }; + + bool first_software_renderer_buf_creation = true; + std::array<VkBuffer, max_frames_in_flight> software_renderer_bufs; + std::array<VkDeviceMemory, max_frames_in_flight> software_renderer_buf_device_mems; + std::array<void*, max_frames_in_flight> software_renderer_buf_mems; + + auto destroy_software_renderer_bufs = [&]() { + for (size_t i = max_frames_in_flight; i > 0; i--) { + vkUnmapMemory(device, software_renderer_buf_device_mems[i - 1]); + vkFreeMemory(device, software_renderer_buf_device_mems[i - 1], nullptr); + vkDestroyBuffer(device, software_renderer_bufs[i - 1], nullptr); + } + }; + + auto recreate_software_renderer_bufs = [&]() { + if (!first_software_renderer_buf_creation) { + destroy_software_renderer_bufs(); + if (software_renderer.width() != swapchain_extent.width || software_renderer.height() != swapchain_extent.height) + software_renderer.resize(swapchain_extent.width, swapchain_extent.height); + } else { + first_software_renderer_buf_creation = false; + } + const VkDeviceSize software_renderer_buf_size = swapchain_extent.width * swapchain_extent.height * 4; + for (size_t i = 0; i < max_frames_in_flight; i++) { + std::tie(software_renderer_bufs[i], software_renderer_buf_device_mems[i]) = create_buf(physical_device, device, software_renderer_buf_size, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + if (VkResult res = vkMapMemory(device, software_renderer_buf_device_mems[i], 0, software_renderer_buf_size, + 0, &software_renderer_buf_mems[i]); res != VK_SUCCESS) { + std::cerr << "failed to create software renderer's buffer #" << i << ", error code: " << string_VkResult(res) << std::endl; + exit(EXIT_FAILURE); + } + } + return std::tuple { software_renderer_bufs, software_renderer_buf_device_mems, software_renderer_buf_mems }; + }; + + recreate_software_renderer_bufs(); + uint32_t frame_idx = 0; double mouse_x, mouse_y; @@ -2109,6 +2169,33 @@ static int main_graphical(Scene& scene) { glfwSetWindowShouldClose(window, GLFW_TRUE); break; } + // TODO: very ugly, improve + static bool last_frame_toggle_renderer_mode = false; + switch (glfwGetKey(window, GLFW_KEY_O)) { + case GLFW_PRESS: + { + if (!last_frame_toggle_renderer_mode) { + last_frame_toggle_renderer_mode = true; + switch (renderer_mode) { + case GraphicalRendererMode::hardware: + { + renderer_mode = GraphicalRendererMode::software; + } + break; + case GraphicalRendererMode::software: + { + renderer_mode = GraphicalRendererMode::hardware; + } + break; + } + } + } + break; + default: + { + last_frame_toggle_renderer_mode = false; + } + } double new_mouse_x, new_mouse_y; glfwGetCursorPos(window, &new_mouse_x, &new_mouse_y); @@ -2130,7 +2217,7 @@ static int main_graphical(Scene& scene) { // render_and_present_frame [&](const Matrix4& view_mat, const Matrix4& proj_mat, float /* time */, float ellapsed_time) { if (show_fps) - std::cout << "\rfps: " << (1.f / ellapsed_time); + std::cout << "\rfps: " << (1.f / ellapsed_time) << " "; if (VkResult res = vkWaitForFences(device, 1, &fences_in_flight[frame_idx], VK_TRUE, std::numeric_limits<uint64_t>::max()); res != VK_SUCCESS) { std::cerr << "failed to wait for draw fence, error code: " << string_VkResult(res) << std::endl; @@ -2147,6 +2234,7 @@ static int main_graphical(Scene& scene) { break; case VK_ERROR_OUT_OF_DATE_KHR: recreate_swapchain(); + recreate_software_renderer_bufs(); return; default: std::cerr << "failed to acquire next image, error code: " << string_VkResult(res) << std::endl; @@ -2154,17 +2242,53 @@ static int main_graphical(Scene& scene) { } } - // update uniform buffers - for (size_t i = 0; i < scene.objs.size(); i++) { - // TODO: should use push constants - engine::vk::UniformBufferObject ubo { - .model = scene.objs[i].transform.to_mat4(), - .view = view_mat, - .proj = proj_mat, - .camera_rot = Matrix4::from_quaternion(scene.camera.transform.rot), - .camera_loc = scene.camera.transform.loc, - }; - memcpy(uniform_buf_mems[frame_idx * scene.objs.size() + i], &ubo, sizeof(engine::vk::UniformBufferObject)); + // TODO: this is where we set uniform buffers for the hardware renderer, and where we + // render for the software renderer. We should do approximately the same thing in the + // same place for both renderers + switch (renderer_mode) { + case GraphicalRendererMode::hardware: + { + // update uniform buffers + for (size_t i = 0; i < scene.objs.size(); i++) { + // TODO: should use push constants + engine::vk::UniformBufferObject ubo { + .model = scene.objs[i].transform.to_mat4(), + .view = view_mat, + .proj = proj_mat, + .camera_rot = Matrix4::from_quaternion(scene.camera.transform.rot), + .camera_loc = scene.camera.transform.loc, + }; + memcpy(uniform_buf_mems[frame_idx * scene.objs.size() + i], &ubo, sizeof(engine::vk::UniformBufferObject)); + } + } + break; + case GraphicalRendererMode::software: + { + // TODO: this is a copy-paste of the code in render_software, which is obviously + // bad + auto proj_view_mat = proj_mat * view_mat; + software_renderer.clear(); + for (const auto& obj : scene.objs) { + auto model_mat = obj.transform.to_mat4(); + auto final_mat = proj_view_mat * model_mat; + const auto& mesh = obj.mesh; + std::vector<Vector4> vertices; + std::vector<VertexData> vertices_data; + for (const auto& vertex : mesh.vertices) { + vertices.push_back(final_mat * Vector4 { vertex, 1.f }); + vertices_data.push_back(VertexData((model_mat * vertex).xyz())); + } + for (const auto& triangle_indices : mesh.indices) { + [&]<std::size_t... j>(std::integer_sequence<std::size_t, j...>) { + software_renderer.draw_triangle( + {{vertices[triangle_indices[j][0]], mesh.normals[triangle_indices[j][1]], vertices_data[triangle_indices[j][0]]}...} + ); + }(std::make_integer_sequence<std::size_t, 3>()); + } + } + memcpy(software_renderer_buf_mems[frame_idx], software_renderer.fb.pixels(), swapchain_extent.width * swapchain_extent.height * 4); + } + break; } // implicit command buffer reset @@ -2189,148 +2313,229 @@ static int main_graphical(Scene& scene) { } // transition layouts - [&]() { - std::array img_mem_barriers { - VkImageMemoryBarrier2 { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - .srcAccessMask = {}, - .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = swapchain_imgs[img_idx], - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }, - VkImageMemoryBarrier2 { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, - .srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, - .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = (has_stencil(depth_format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL), - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = depth_img, - .subresourceRange = { - .aspectMask = static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT | (has_stencil(depth_format) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)), - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }, - }; - VkDependencyInfo dependency_info { - .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, - .pNext = nullptr, - .dependencyFlags = {}, - .memoryBarrierCount = 0, - .pMemoryBarriers = {}, - .bufferMemoryBarrierCount = 0, - .pBufferMemoryBarriers = {}, - .imageMemoryBarrierCount = img_mem_barriers.size(), - .pImageMemoryBarriers = img_mem_barriers.data(), - }; - vkCmdPipelineBarrier2(cmd_bufs[frame_idx], &dependency_info); - }(); - - { - VkClearValue clear_color_val { .color { .float32 = { 0.f, 0.f, 0.f, 1.f } } }; - VkClearValue clear_depth_val { .depthStencil { .depth = 1.f, .stencil = 0 } }; - VkRenderingAttachmentInfo rendering_color_info { - .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .pNext = nullptr, - .imageView = swapchain_img_views[img_idx], - .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .resolveMode = {}, - .resolveImageView = {}, - .resolveImageLayout = {}, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = clear_color_val, - }; - VkRenderingAttachmentInfo rendering_depth_info { - .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .pNext = nullptr, - .imageView = depth_img_view, - .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, - .resolveMode = {}, - .resolveImageView = {}, - .resolveImageLayout = {}, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, - .clearValue = clear_depth_val, - }; - VkRenderingInfo render_info { - .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, - .pNext = nullptr, - .flags = {}, - .renderArea = { .offset { 0, 0 }, .extent = swapchain_extent }, - .layerCount = 1, - .viewMask = {}, - .colorAttachmentCount = 1, - .pColorAttachments = &rendering_color_info, - .pDepthAttachment = &rendering_depth_info, - .pStencilAttachment = {}, - }; - vkCmdBeginRendering(cmd_bufs[frame_idx], &render_info); - } + switch (renderer_mode) { + case GraphicalRendererMode::hardware: + { + { + std::array img_mem_barriers { + VkImageMemoryBarrier2 { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = {}, + .dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = swapchain_imgs[img_idx], + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + VkImageMemoryBarrier2 { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + .srcAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + .dstAccessMask = VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = + (has_stencil(depth_format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL), + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = depth_img, + .subresourceRange = { + .aspectMask = + static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT | (has_stencil(depth_format) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0)), + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }, + }; + VkDependencyInfo dependency_info { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = {}, + .memoryBarrierCount = 0, + .pMemoryBarriers = {}, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = {}, + .imageMemoryBarrierCount = img_mem_barriers.size(), + .pImageMemoryBarriers = img_mem_barriers.data(), + }; + vkCmdPipelineBarrier2(cmd_bufs[frame_idx], &dependency_info); + } - vkCmdBindPipeline(cmd_bufs[frame_idx], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pl); + { + VkClearValue clear_color_val { .color { .float32 = { 0.f, 0.f, 0.f, 1.f } } }; + VkClearValue clear_depth_val { .depthStencil { .depth = 1.f, .stencil = 0 } }; + VkRenderingAttachmentInfo rendering_color_info { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = swapchain_img_views[img_idx], + .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .resolveMode = {}, + .resolveImageView = {}, + .resolveImageLayout = {}, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = clear_color_val, + }; + VkRenderingAttachmentInfo rendering_depth_info { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = depth_img_view, + .imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + .resolveMode = {}, + .resolveImageView = {}, + .resolveImageLayout = {}, + .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .clearValue = clear_depth_val, + }; + VkRenderingInfo render_info { + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .pNext = nullptr, + .flags = {}, + .renderArea = { .offset { 0, 0 }, .extent = swapchain_extent }, + .layerCount = 1, + .viewMask = {}, + .colorAttachmentCount = 1, + .pColorAttachments = &rendering_color_info, + .pDepthAttachment = &rendering_depth_info, + .pStencilAttachment = {}, + }; + vkCmdBeginRendering(cmd_bufs[frame_idx], &render_info); + } - { - VkViewport viewport { - .x = 0.f, - .y = 0.f, - .width = static_cast<float>(swapchain_extent.width), - .height = static_cast<float>(swapchain_extent.height), - .minDepth = 0.f, - .maxDepth = 1.f, - }; - vkCmdSetViewport(cmd_bufs[frame_idx], 0, 1, &viewport); - } + vkCmdBindPipeline(cmd_bufs[frame_idx], VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pl); + + { + VkViewport viewport { + .x = 0.f, + .y = 0.f, + .width = static_cast<float>(swapchain_extent.width), + .height = static_cast<float>(swapchain_extent.height), + .minDepth = 0.f, + .maxDepth = 1.f, + }; + vkCmdSetViewport(cmd_bufs[frame_idx], 0, 1, &viewport); + } - { - VkRect2D scissor { - .offset = { 0, 0 }, - .extent = swapchain_extent, - }; - vkCmdSetScissor(cmd_bufs[frame_idx], 0, 1, &scissor); - } + { + VkRect2D scissor { + .offset = { 0, 0 }, + .extent = swapchain_extent, + }; + vkCmdSetScissor(cmd_bufs[frame_idx], 0, 1, &scissor); + } - // TODO: not sure if we can just loop through every objects without worrying about it - for (size_t i = 0; i < scene.objs.size(); i++) { - const auto& vertex_buf = vertex_bufs[i]; - const auto& index_buf = index_bufs[i]; - const auto& indices = meshes_indices[i]; + // TODO: not sure if we can just loop through every objects without worrying about it + for (size_t i = 0; i < scene.objs.size(); i++) { + const auto& vertex_buf = vertex_bufs[i]; + const auto& index_buf = index_bufs[i]; + const auto& indices = meshes_indices[i]; - VkDeviceSize vertex_buf_offset = 0; - vkCmdBindVertexBuffers(cmd_bufs[frame_idx], 0, 1, &vertex_buf, &vertex_buf_offset); + VkDeviceSize vertex_buf_offset = 0; + vkCmdBindVertexBuffers(cmd_bufs[frame_idx], 0, 1, &vertex_buf, &vertex_buf_offset); - vkCmdBindIndexBuffer(cmd_bufs[frame_idx], index_buf, 0, VK_INDEX_TYPE_UINT16); - vkCmdBindDescriptorSets(cmd_bufs[frame_idx], VK_PIPELINE_BIND_POINT_GRAPHICS, pl_layout, 0, 1, - &descriptor_sets[frame_idx * scene.objs.size() + i], 0, nullptr); - vkCmdDrawIndexed(cmd_bufs[frame_idx], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0); - } + vkCmdBindIndexBuffer(cmd_bufs[frame_idx], index_buf, 0, VK_INDEX_TYPE_UINT16); + vkCmdBindDescriptorSets(cmd_bufs[frame_idx], VK_PIPELINE_BIND_POINT_GRAPHICS, pl_layout, 0, 1, + &descriptor_sets[frame_idx * scene.objs.size() + i], 0, nullptr); + vkCmdDrawIndexed(cmd_bufs[frame_idx], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0); + } - vkCmdEndRendering(cmd_bufs[frame_idx]); + vkCmdEndRendering(cmd_bufs[frame_idx]); - transition_image_layout(cmd_bufs[frame_idx], swapchain_imgs[img_idx], - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, {}, - VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); + transition_image_layout(cmd_bufs[frame_idx], swapchain_imgs[img_idx], + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, {}, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); + } + break; + case GraphicalRendererMode::software: + { + { + VkImageMemoryBarrier2 img_mem_barrier { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + .srcAccessMask = {}, + .dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = swapchain_imgs[img_idx], + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + VkDependencyInfo dependency_info { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = {}, + .memoryBarrierCount = 0, + .pMemoryBarriers = {}, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = {}, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &img_mem_barrier, + }; + vkCmdPipelineBarrier2(cmd_bufs[frame_idx], &dependency_info); + } + copy_buf_to_img(cmd_bufs[frame_idx], software_renderer_bufs[frame_idx], swapchain_imgs[img_idx], swapchain_extent.width, swapchain_extent.height); + { + VkImageMemoryBarrier2 img_mem_barrier { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT, + .srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, + .dstAccessMask = {}, + .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = swapchain_imgs[img_idx], + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + VkDependencyInfo dependency_info { + .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, + .pNext = nullptr, + .dependencyFlags = {}, + .memoryBarrierCount = 0, + .pMemoryBarriers = {}, + .bufferMemoryBarrierCount = 0, + .pBufferMemoryBarriers = {}, + .imageMemoryBarrierCount = 1, + .pImageMemoryBarriers = &img_mem_barrier, + }; + vkCmdPipelineBarrier2(cmd_bufs[frame_idx], &dependency_info); + } + } + break; + } if (VkResult res = vkEndCommandBuffer(cmd_bufs[frame_idx]); res != VK_SUCCESS) { std::cerr << "failed to end command buffer, error code: " << string_VkResult(res) << std::endl; @@ -2376,6 +2581,7 @@ static int main_graphical(Scene& scene) { if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR || fb_resized) { fb_resized = false; recreate_swapchain(); + recreate_software_renderer_bufs(); } else if (res != VK_SUCCESS) { std::cerr << "failed to present, error code: " << string_VkResult(res) << std::endl; exit(EXIT_FAILURE); @@ -2395,6 +2601,7 @@ static int main_graphical(Scene& scene) { } // cleanup + destroy_software_renderer_bufs(); for (auto it_fence = fences_in_flight.rbegin(); it_fence != fences_in_flight.rend(); ++it_fence) vkDestroyFence(device, *it_fence, nullptr); for (auto it_sem = sems_render_finished.rbegin(); it_sem != sems_render_finished.rend(); ++it_sem) diff --git a/src/fb/pixfb.cpp b/src/fb/pixfb.cpp index 55c356f..b38ec30 100644 --- a/src/fb/pixfb.cpp +++ b/src/fb/pixfb.cpp @@ -24,7 +24,7 @@ void PixelFrameBuffer::resize(unsigned int w, unsigned int h) { } void PixelFrameBuffer::clear() { - std::fill(pixels_vector.begin(), pixels_vector.end(), 0x000000FF); + std::fill(pixels_vector.begin(), pixels_vector.end(), 0xff000000); } extern Camera* camera; @@ -41,8 +41,14 @@ void PixelFrameBuffer::draw_point(int x, int y, const Vector3& loc, const Vertex else attenuation = (attenuation - .7f) / .1f; float light = -normal.dot(u) / u_len_sq; if (light < 0.f) light = 0.f; - float final_light = .05f + light * attenuation * .8f * .95f; + float final_light = .003f + light * attenuation * .8f * .997f; if (final_light > 1.f) final_light = 1.f; + // gamma correction + // TODO: improve, we shouldn't do it here + if (final_light <= .0031308f) + final_light = final_light * 12.92f; + else + final_light = 1.055f * pow(final_light, 1.f / 2.4f) - .055f; std::uint32_t c = (int) (final_light * 255.f); - pixels_vector[x + y * w] = c << 24 | c << 16 | c << 8 | 0xff; + pixels_vector[x + y * w] = 0xff000000 | c << 16 | c << 8 | c; } diff --git a/src/shaders/shader.slang b/src/shaders/shader.slang index 5598e1e..e92f5aa 100644 --- a/src/shaders/shader.slang +++ b/src/shaders/shader.slang @@ -20,8 +20,9 @@ struct VertexOutput { [shader("vertex")] VertexOutput vert_main(VertexInput vi) { VertexOutput vo; - vo.pos = mul(ubo.proj, mul(ubo.view, mul(ubo.model, float4(vi.pos, 1.)))); - vo.world_loc = vi.pos; + float4 world_loc = mul(ubo.model, float4(vi.pos, 1.)); + vo.pos = mul(ubo.proj, mul(ubo.view, world_loc)); + vo.world_loc = world_loc.xyz; vo.normal = vi.normal; return vo; } @@ -39,7 +40,7 @@ float4 frag_main(VertexOutput vo) : SV_Target { else attenuation = (attenuation - .7) / .1; float light = -dot(vo.normal, u) / u_len_sq; if (light < 0.) light = 0.; - float final_light = .05 + light * attenuation * .8 * .95; + float final_light = .003 + light * attenuation * .8 * .997; if (final_light > 1.) final_light = 1.; return float4(final_light, final_light, final_light, 1.); } |
