aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine.cpp501
-rw-r--r--src/fb/pixfb.cpp12
-rw-r--r--src/shaders/shader.slang7
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.);
}