diff options
| -rw-r--r-- | include/utils.hpp | 4 | ||||
| -rw-r--r-- | include/vk-renderer.hpp | 2 | ||||
| -rw-r--r-- | shaders/compute.comp | 22 | ||||
| -rw-r--r-- | src/main.cpp | 14 | ||||
| -rw-r--r-- | src/utils.cpp | 7 | ||||
| -rw-r--r-- | src/vk-api.cpp | 2 | ||||
| -rw-r--r-- | src/vk-renderer.cpp | 23 |
7 files changed, 50 insertions, 24 deletions
diff --git a/include/utils.hpp b/include/utils.hpp index 830b006..85b50cf 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -27,11 +27,13 @@ struct input_data { // Output image resolution uint32_t width; uint32_t height; + + uint32_t sample_index; }; std::vector<uint8_t> get_shader_code(const char* path); -struct input_data create_inputs(uint32_t width, uint32_t height); +struct input_data create_inputs(uint32_t width, uint32_t height, uint32_t samples_per_pixel); #define PI 3.14159265359 diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp index 1180d0a..318e6cc 100644 --- a/include/vk-renderer.hpp +++ b/include/vk-renderer.hpp @@ -15,7 +15,7 @@ class vkrenderer { ~vkrenderer(); - void compute(uint32_t width, uint32_t height); + void compute(uint32_t width, uint32_t height, bool clear); void recreate_swapchain(); diff --git a/shaders/compute.comp b/shaders/compute.comp index 1e903b0..01a0f71 100644 --- a/shaders/compute.comp +++ b/shaders/compute.comp @@ -62,9 +62,12 @@ layout(set = 0, binding = 0) buffer Inputs { uint samples_per_pixel; uint width; uint height; + + uint sample_index; + uint[3] padding; }; -layout(set = 0, binding = 1, rgba8) uniform writeonly image2D output_image; +layout(set = 0, binding = 1, rgba8) uniform image2D output_image; vec3 at(ray r, float t) { return r.origin + r.direction * t; @@ -214,16 +217,15 @@ void main() { vec4 out_color = vec4(0.0); - for (uint sample_index = 0; sample_index < samples_per_pixel; sample_index++) { - vec2 jittered_uvs = uv + vec2(random_disk[sample_index].x / (width - 1), random_disk[sample_index].y / (height - 1)); - vec2 lens_disk = random_disk[sample_index] * cam.lens_radius; - vec3 offset = lens_disk.x * cam.right.xyz + lens_disk.y * cam.up.xyz; - vec4 proj_plane_pos = cam.first_pixel + jittered_uvs.x * cam.horizontal + jittered_uvs.y * cam.vertical; - ray r = ray(cam.position.xyz + offset, proj_plane_pos.xyz - cam.position.xyz - offset); + vec2 jittered_uvs = uv + vec2(random_disk[sample_index].x / (width - 1), random_disk[sample_index].y / (height - 1)); + vec2 lens_disk = random_disk[sample_index] * cam.lens_radius; + vec3 offset = lens_disk.x * cam.right.xyz + lens_disk.y * cam.up.xyz; + vec4 proj_plane_pos = cam.first_pixel + jittered_uvs.x * cam.horizontal + jittered_uvs.y * cam.vertical; + ray r = ray(cam.position.xyz + offset, proj_plane_pos.xyz - cam.position.xyz - offset); - out_color += ray_color(r, sample_index); - } + out_color += ray_color(r, sample_index); float spp_scale = (1.0 / samples_per_pixel); - imageStore(output_image, ivec2(x, y), sqrt(out_color * spp_scale)); + vec4 acc_color = imageLoad(output_image, ivec2(x, y)); + imageStore(output_image, ivec2(x, y), acc_color + (out_color * spp_scale)); } diff --git a/src/main.cpp b/src/main.cpp index 37ebddb..c87e57a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,13 +46,14 @@ int main() { const float aspect_ratio = 16.0 / 9.0; uint32_t width = 400; uint32_t height = width / aspect_ratio; + const uint32_t samples_per_pixel = 10; window wnd { width , height }; float delta_time = 0.f; auto start = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now(); - auto inputs = create_inputs(width, height); + auto inputs = create_inputs(width, height, samples_per_pixel); auto canRender = true; vkrenderer renderer { wnd, inputs }; @@ -113,6 +114,10 @@ int main() { ((input_data*) renderer.compute_shader_buffer.mapped_ptr)->cam.move(move_vec); + if (!move_vec.near_zero()) { + ((input_data*) renderer.compute_shader_buffer.mapped_ptr)->sample_index = 0; + } + break; } default: @@ -129,7 +134,12 @@ int main() { if(rdoc_api) rdoc_api->StartFrameCapture(NULL, NULL); if (canRender) { - renderer.compute(width, height); + if (((input_data*) renderer.compute_shader_buffer.mapped_ptr)->sample_index < samples_per_pixel) { + bool clear = ((input_data*) renderer.compute_shader_buffer.mapped_ptr)->sample_index == 0; + renderer.compute(width, height, clear); + + ((input_data*) renderer.compute_shader_buffer.mapped_ptr)->sample_index++; + } } // stop the capture diff --git a/src/utils.cpp b/src/utils.cpp index 00745dc..a2cf8f9 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -89,11 +89,10 @@ void random_scene(sphere *world) { world[world_sphere_index + 2] = { { 4, 1, 0 }, material3, 1.0 }; } -struct input_data create_inputs(uint32_t width, uint32_t height) { +struct input_data create_inputs(uint32_t width, uint32_t height, uint32_t samples_per_pixel) { // Image dimensions const float aspect_ratio = (float)width / (float) height; - const uint32_t samples_per_pixel = 10; const uint32_t max_depth = 5; const vec3 camera_position{ 13.0, 2.0, 3.0 }; @@ -113,7 +112,9 @@ struct input_data create_inputs(uint32_t width, uint32_t height) { .max_bounce = max_depth, .samples_per_pixel = samples_per_pixel, .width = width, - .height = height + .height = height, + + .sample_index = 0, }; // Random numbers pools diff --git a/src/vk-api.cpp b/src/vk-api.cpp index 2ecd06f..92e9a80 100644 --- a/src/vk-api.cpp +++ b/src/vk-api.cpp @@ -123,7 +123,7 @@ Image vkapi::create_image(VkExtent3D size, VkFormat format, VkImageUsageFlags us return std::move(image); } void vkapi::destroy_image(Image &image) { - vkDestroyImage(context.device, image.handle, nullptr); + vmaDestroyImage(context.allocator, image.handle, image.alloc); vkDestroyImageView(context.device, image.view, nullptr); } diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp index 2054ae3..32bee48 100644 --- a/src/vk-renderer.cpp +++ b/src/vk-renderer.cpp @@ -50,7 +50,7 @@ vkrenderer::vkrenderer(window& wnd, const input_data& inputs) { .height = swapchain.extent.height, .depth = 1, }; - accumulation_image = api.create_image(image_size, swapchain.surface_format.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + accumulation_image = api.create_image(image_size, swapchain.surface_format.format, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); submission_fences = api.create_fences(swapchain.image_count); execution_semaphores = api.create_semaphores(swapchain.image_count); @@ -74,6 +74,7 @@ vkrenderer::~vkrenderer() { api.destroy_semaphores(acquire_semaphores); api.destroy_descriptor_sets(compute_shader_sets); + api.destroy_image(accumulation_image); api.destroy_command_buffers(command_buffers); api.destroy_compute_pipeline(compute_pipeline); @@ -82,7 +83,8 @@ vkrenderer::~vkrenderer() { api.destroy_surface(platform_surface); } -void vkrenderer::compute(uint32_t width, uint32_t height) { + +void vkrenderer::compute(uint32_t width, uint32_t height, bool clear) { VKRESULT(vkWaitForFences(api.context.device, 1, &submission_fences[frame_index], VK_TRUE, UINT64_MAX)) VKRESULT(vkResetFences(api.context.device, 1, &submission_fences[frame_index])) @@ -94,16 +96,25 @@ void vkrenderer::compute(uint32_t width, uint32_t height) { api.start_record(cmd_buf); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, VK_ACCESS_SHADER_WRITE_BIT, accumulation_image); + if (clear) { + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, accumulation_image); + + VkClearColorValue color = { 0.f, 0.f, 0.f, 1.f }; + vkCmdClearColorImage(cmd_buf, accumulation_image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &accumulation_image.subresource_range); + + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT, accumulation_image); + } else { + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, VK_ACCESS_SHADER_WRITE_BIT, accumulation_image); + } api.run_compute_pipeline(cmd_buf, compute_pipeline, compute_shader_sets[swapchain_image_index], width / 8, height / 8, 1); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, accumulation_image); + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, accumulation_image); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, swapchain.images[swapchain_image_index]); + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, swapchain.images[swapchain_image_index]); api.blit_full(cmd_buf, accumulation_image, swapchain.images[swapchain_image_index]); - api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, swapchain.images[swapchain_image_index]); + api.image_barrier(cmd_buf, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, swapchain.images[swapchain_image_index]); api.end_record(cmd_buf); |
