From fdda43f3d849c4c35084b198996f9aa37b16e10c Mon Sep 17 00:00:00 2001 From: loosche Date: Tue, 14 Apr 2026 22:26:11 -0700 Subject: [PATCH] Apply --screenshot to all Vulkan projects Adds SaveVulkanImageAsPNG to the shared vk_renderer, mirroring SaveMetalTextureAsPNG. Wires --screenshot / --auto-exit into the main loop of every Vulkan project: frameIndex tracking, auto-exit guard updated to respect screenshotFrame, and screenshot block inserted between WaitForGpu and SwapchainPresent. Also adds bitmap.h/bitmap.cpp to each project's CMakeLists (and the stb include path to early raytracing projects that were missing it). Co-Authored-By: Claude Sonnet 4.6 --- projects/common/vk_renderer.cpp | 108 ++++++++++++++++++ projects/common/vk_renderer.h | 9 ++ .../101_color_cube_vulkan.cpp | 19 ++- .../101_color_cube_vulkan/CMakeLists.txt | 2 + .../102_cornell_box_vulkan.cpp | 17 ++- .../102_cornell_box_vulkan/CMakeLists.txt | 2 + .../103_cone_vulkan/103_cone_vulkan.cpp | 19 ++- .../geometry/103_cone_vulkan/CMakeLists.txt | 2 + .../104_debug_tbn_vulkan.cpp | 17 ++- .../104_debug_tbn_vulkan/CMakeLists.txt | 2 + .../110_mesh_shader_triangle_vulkan.cpp | 19 ++- .../CMakeLists.txt | 2 + .../111_mesh_shader_meshlets_vulkan.cpp | 19 ++- .../CMakeLists.txt | 2 + .../112_mesh_shader_amplification_vulkan.cpp | 19 ++- .../CMakeLists.txt | 2 + .../113_mesh_shader_instancing_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../114_mesh_shader_culling_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../115_mesh_shader_lod_vulkan.cpp | 17 ++- .../115_mesh_shader_lod_vulkan/CMakeLists.txt | 2 + .../116_mesh_shader_calc_lod_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../117_mesh_shader_cull_lod_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../118_mesh_shader_vertex_attrs_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../119_mesh_shader_vertex_bary_vulkan.cpp | 17 ++- .../CMakeLists.txt | 2 + .../401_gltf_basic_geo_vulkan.cpp | 17 ++- .../402_gltf_basic_texture_vulkan.cpp | 17 ++- .../403_gltf_basic_material_vulkan.cpp | 17 ++- ...404_gltf_basic_material_texture_vulkan.cpp | 17 ++- .../405_gltf_full_material_test_vulkan.cpp | 17 ++- .../201_pbr_spheres_vulkan.cpp | 16 ++- .../202_pbr_camera_vulkan.cpp | 16 ++- .../203_pbr_align_vulkan.cpp | 16 ++- .../251_pbr_explorer_vulkan.cpp | 16 ++- .../252_pbr_material_properties_vulkan.cpp | 16 ++- .../253_pbr_material_textures_vulkan.cpp | 16 ++- .../000_raygen_uv_vulkan.cpp | 16 ++- .../000_raygen_uv_vulkan/CMakeLists.txt | 3 + .../001_raytracing_basic_vulkan.cpp | 16 ++- .../CMakeLists.txt | 3 + .../002_basic_procedural_vulkan.cpp | 16 ++- .../CMakeLists.txt | 3 + .../003_sphereflake_vulkan.cpp | 16 ++- .../003_sphereflake_vulkan/CMakeLists.txt | 3 + .../004_basic_reflection_vulkan.cpp | 16 ++- .../CMakeLists.txt | 3 + .../005_basic_shadow_vulkan.cpp | 16 ++- .../005_basic_shadow_vulkan/CMakeLists.txt | 3 + .../006_basic_shadow_dynamic_vulkan.cpp | 16 ++- .../CMakeLists.txt | 3 + .../021_raytracing_triangles_vulkan.cpp | 16 ++- .../CMakeLists.txt | 2 + .../022_raytracing_multi_geo_vulkan.cpp | 16 ++- .../CMakeLists.txt | 2 + .../023_raytracing_multi_instance_vulkan.cpp | 16 ++- .../CMakeLists.txt | 2 + .../024_raytracing_pbr_spheres_vulkan.cpp | 16 ++- .../025_raytracing_refract_vulkan.cpp | 16 ++- .../030_raytracing_path_trace_vulkan.cpp | 16 ++- .../030_raytracing_path_trace_vulkan_bof.cpp | 16 ++- .../031_raytracing_path_trace_pbr_vulkan.cpp | 16 ++- .../301_textured_cube_vulkan.cpp | 16 ++- .../302_lambert_textured_cube_vulkan.cpp | 16 ++- .../303_phong_textured_cube_vulkan.cpp | 16 ++- .../304_normal_map_vulkan.cpp | 16 ++- .../305_normal_map_explorer_vulkan.cpp | 16 ++- .../306_parallax_occlusion_map_vulkan.cpp | 16 ++- ...parallax_occlusion_map_explorer_vulkan.cpp | 16 ++- .../308_normal_map_vs_pom_vulkan.cpp | 16 ++- 74 files changed, 916 insertions(+), 53 deletions(-) diff --git a/projects/common/vk_renderer.cpp b/projects/common/vk_renderer.cpp index 10c0204..3049c1f 100644 --- a/projects/common/vk_renderer.cpp +++ b/projects/common/vk_renderer.cpp @@ -4149,3 +4149,111 @@ uint32_t BitsPerPixel(VkFormat fmt) return 0; } } + +bool SaveVulkanImageAsPNG( + VulkanRenderer* pRenderer, + VkImage image, + uint32_t width, + uint32_t height, + const std::filesystem::path& absPath) +{ + const size_t bufferSize = width * height * 4; + + // Create a CPU-readable staging buffer + VulkanBuffer readbackBuffer = {}; + VkResult vkres = CreateBuffer( + pRenderer, + bufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VMA_MEMORY_USAGE_GPU_TO_CPU, + 0, + &readbackBuffer); + if (vkres != VK_SUCCESS) + { + return false; + } + + // Create a transient command buffer + CommandObjects cmdBuf = {}; + vkres = CreateCommandBuffer(pRenderer, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, &cmdBuf); + if (vkres != VK_SUCCESS) + { + DestroyBuffer(pRenderer, &readbackBuffer); + return false; + } + + VkCommandBufferBeginInfo vkbi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; + vkbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + vkres = vkBeginCommandBuffer(cmdBuf.CommandBuffer, &vkbi); + if (vkres != VK_SUCCESS) + { + DestroyCommandBuffer(pRenderer, &cmdBuf); + DestroyBuffer(pRenderer, &readbackBuffer); + return false; + } + + // Transition: PRESENT -> TRANSFER_SRC + CmdTransitionImageLayout( + cmdBuf.CommandBuffer, + image, + GREX_ALL_SUBRESOURCES, + VK_IMAGE_ASPECT_COLOR_BIT, + RESOURCE_STATE_PRESENT, + RESOURCE_STATE_TRANSFER_SRC); + + // Copy image to staging buffer + VkBufferImageCopy region = {}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset = {0, 0, 0}; + region.imageExtent = {width, height, 1}; + + vkCmdCopyImageToBuffer( + cmdBuf.CommandBuffer, + image, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + readbackBuffer.Buffer, + 1, + ®ion); + + // Transition: TRANSFER_SRC -> PRESENT + CmdTransitionImageLayout( + cmdBuf.CommandBuffer, + image, + GREX_ALL_SUBRESOURCES, + VK_IMAGE_ASPECT_COLOR_BIT, + RESOURCE_STATE_TRANSFER_SRC, + RESOURCE_STATE_PRESENT); + + vkEndCommandBuffer(cmdBuf.CommandBuffer); + ExecuteCommandBuffer(pRenderer, &cmdBuf); + vkQueueWaitIdle(pRenderer->Queue); + DestroyCommandBuffer(pRenderer, &cmdBuf); + + // Map the buffer and convert BGRA -> RGBA (swapchain is B8G8R8A8_UNORM) + void* pMapped = nullptr; + vmaMapMemory(pRenderer->Allocator, readbackBuffer.Allocation, &pMapped); + + BitmapRGBA8u bitmap(width, height); + const uint8_t* pSrc = static_cast(pMapped); + uint8_t* pDst = reinterpret_cast(bitmap.GetPixels()); + + for (uint32_t i = 0; i < width * height; ++i) + { + pDst[i * 4 + 0] = pSrc[i * 4 + 2]; // R <- B + pDst[i * 4 + 1] = pSrc[i * 4 + 1]; // G <- G + pDst[i * 4 + 2] = pSrc[i * 4 + 0]; // B <- R + pDst[i * 4 + 3] = 255; // A <- 1 (force opaque) + } + + vmaUnmapMemory(pRenderer->Allocator, readbackBuffer.Allocation); + + bool ok = BitmapRGBA8u::Save(absPath, &bitmap); + DestroyBuffer(pRenderer, &readbackBuffer); + return ok; +} diff --git a/projects/common/vk_renderer.h b/projects/common/vk_renderer.h index 8155fda..0043fa5 100644 --- a/projects/common/vk_renderer.h +++ b/projects/common/vk_renderer.h @@ -1,11 +1,13 @@ #pragma once #include "config.h" +#include "bitmap.h" #include #include "vk_mem_alloc.h" #include +#include #define GREX_ALL_SUBRESOURCES 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS @@ -583,3 +585,10 @@ extern PFN_vkCmdSetDescriptorBufferOffsetsEXT fn_vkCmdSetDescriptorBuffe extern PFN_vkCmdDrawMeshTasksEXT fn_vkCmdDrawMeshTasksEXT; extern PFN_vkCmdPushDescriptorSetKHR fn_vkCmdPushDescriptorSetKHR; extern PFN_vkCmdDrawMeshTasksNV fn_vkCmdDrawMeshTasksNV; + +bool SaveVulkanImageAsPNG( + VulkanRenderer* pRenderer, + VkImage image, + uint32_t width, + uint32_t height, + const std::filesystem::path& absPath); diff --git a/projects/geometry/101_color_cube_vulkan/101_color_cube_vulkan.cpp b/projects/geometry/101_color_cube_vulkan/101_color_cube_vulkan.cpp index 6ed8e0a..7258745 100644 --- a/projects/geometry/101_color_cube_vulkan/101_color_cube_vulkan.cpp +++ b/projects/geometry/101_color_cube_vulkan/101_color_cube_vulkan.cpp @@ -215,8 +215,8 @@ int main(int argc, char** argv) // ************************************************************************* std::vector imageViews; std::vector depthViews; + std::vector images; { - std::vector images; CHECK_CALL(GetSwapchainImages(renderer.get(), images)); for (auto& image : images) @@ -286,9 +286,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -371,11 +373,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/101_color_cube_vulkan/CMakeLists.txt b/projects/geometry/101_color_cube_vulkan/CMakeLists.txt index 7e98d58..aa7755f 100644 --- a/projects/geometry/101_color_cube_vulkan/CMakeLists.txt +++ b/projects/geometry/101_color_cube_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/102_cornell_box_vulkan/102_cornell_box_vulkan.cpp b/projects/geometry/102_cornell_box_vulkan/102_cornell_box_vulkan.cpp index 47bcb80..f057562 100644 --- a/projects/geometry/102_cornell_box_vulkan/102_cornell_box_vulkan.cpp +++ b/projects/geometry/102_cornell_box_vulkan/102_cornell_box_vulkan.cpp @@ -358,9 +358,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -483,12 +485,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/102_cornell_box_vulkan/CMakeLists.txt b/projects/geometry/102_cornell_box_vulkan/CMakeLists.txt index b6b1437..2f1c15f 100644 --- a/projects/geometry/102_cornell_box_vulkan/CMakeLists.txt +++ b/projects/geometry/102_cornell_box_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/103_cone_vulkan/103_cone_vulkan.cpp b/projects/geometry/103_cone_vulkan/103_cone_vulkan.cpp index 42d935b..580781c 100644 --- a/projects/geometry/103_cone_vulkan/103_cone_vulkan.cpp +++ b/projects/geometry/103_cone_vulkan/103_cone_vulkan.cpp @@ -233,8 +233,8 @@ int main(int argc, char** argv) // ************************************************************************* std::vector imageViews; std::vector depthViews; + std::vector images; { - std::vector images; CHECK_CALL(GetSwapchainImages(renderer.get(), images)); for (auto& image : images) @@ -304,9 +304,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -399,12 +401,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/103_cone_vulkan/CMakeLists.txt b/projects/geometry/103_cone_vulkan/CMakeLists.txt index a795fc4..5ccfb17 100644 --- a/projects/geometry/103_cone_vulkan/CMakeLists.txt +++ b/projects/geometry/103_cone_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/104_debug_tbn_vulkan/104_debug_tbn_vulkan.cpp b/projects/geometry/104_debug_tbn_vulkan/104_debug_tbn_vulkan.cpp index 3b412a0..9d25148 100644 --- a/projects/geometry/104_debug_tbn_vulkan/104_debug_tbn_vulkan.cpp +++ b/projects/geometry/104_debug_tbn_vulkan/104_debug_tbn_vulkan.cpp @@ -367,9 +367,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -532,12 +534,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/104_debug_tbn_vulkan/CMakeLists.txt b/projects/geometry/104_debug_tbn_vulkan/CMakeLists.txt index 5c23d76..c400ff0 100644 --- a/projects/geometry/104_debug_tbn_vulkan/CMakeLists.txt +++ b/projects/geometry/104_debug_tbn_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/110_mesh_shader_triangle_vulkan/110_mesh_shader_triangle_vulkan.cpp b/projects/geometry/110_mesh_shader_triangle_vulkan/110_mesh_shader_triangle_vulkan.cpp index 5d96e20..cfa58ee 100644 --- a/projects/geometry/110_mesh_shader_triangle_vulkan/110_mesh_shader_triangle_vulkan.cpp +++ b/projects/geometry/110_mesh_shader_triangle_vulkan/110_mesh_shader_triangle_vulkan.cpp @@ -190,8 +190,8 @@ int main(int argc, char** argv) // ************************************************************************* std::vector imageViews; std::vector depthViews; + std::vector images; { - std::vector images; CHECK_CALL(GetSwapchainImages(renderer.get(), images)); for (auto& image : images) @@ -259,9 +259,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -326,11 +328,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/110_mesh_shader_triangle_vulkan/CMakeLists.txt b/projects/geometry/110_mesh_shader_triangle_vulkan/CMakeLists.txt index 783713d..d061ce9 100644 --- a/projects/geometry/110_mesh_shader_triangle_vulkan/CMakeLists.txt +++ b/projects/geometry/110_mesh_shader_triangle_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/111_mesh_shader_meshlets_vulkan/111_mesh_shader_meshlets_vulkan.cpp b/projects/geometry/111_mesh_shader_meshlets_vulkan/111_mesh_shader_meshlets_vulkan.cpp index 8541731..73dc80c 100644 --- a/projects/geometry/111_mesh_shader_meshlets_vulkan/111_mesh_shader_meshlets_vulkan.cpp +++ b/projects/geometry/111_mesh_shader_meshlets_vulkan/111_mesh_shader_meshlets_vulkan.cpp @@ -272,8 +272,8 @@ int main(int argc, char** argv) // ************************************************************************* std::vector imageViews; std::vector depthViews; + std::vector images; { - std::vector images; CHECK_CALL(GetSwapchainImages(renderer.get(), images)); for (auto& image : images) @@ -341,9 +341,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -420,11 +422,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/111_mesh_shader_meshlets_vulkan/CMakeLists.txt b/projects/geometry/111_mesh_shader_meshlets_vulkan/CMakeLists.txt index b4765ce..87f78c2 100644 --- a/projects/geometry/111_mesh_shader_meshlets_vulkan/CMakeLists.txt +++ b/projects/geometry/111_mesh_shader_meshlets_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/112_mesh_shader_amplification_vulkan/112_mesh_shader_amplification_vulkan.cpp b/projects/geometry/112_mesh_shader_amplification_vulkan/112_mesh_shader_amplification_vulkan.cpp index 57a9302..f0544a5 100644 --- a/projects/geometry/112_mesh_shader_amplification_vulkan/112_mesh_shader_amplification_vulkan.cpp +++ b/projects/geometry/112_mesh_shader_amplification_vulkan/112_mesh_shader_amplification_vulkan.cpp @@ -284,8 +284,8 @@ int main(int argc, char** argv) // ************************************************************************* std::vector imageViews; std::vector depthViews; + std::vector images; { - std::vector images; CHECK_CALL(GetSwapchainImages(renderer.get(), images)); for (auto& image : images) @@ -353,9 +353,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -434,11 +436,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/112_mesh_shader_amplification_vulkan/CMakeLists.txt b/projects/geometry/112_mesh_shader_amplification_vulkan/CMakeLists.txt index bda13f6..fc65a18 100644 --- a/projects/geometry/112_mesh_shader_amplification_vulkan/CMakeLists.txt +++ b/projects/geometry/112_mesh_shader_amplification_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/113_mesh_shader_instancing_vulkan/113_mesh_shader_instancing_vulkan.cpp b/projects/geometry/113_mesh_shader_instancing_vulkan/113_mesh_shader_instancing_vulkan.cpp index 4ea4e11..e0518c9 100644 --- a/projects/geometry/113_mesh_shader_instancing_vulkan/113_mesh_shader_instancing_vulkan.cpp +++ b/projects/geometry/113_mesh_shader_instancing_vulkan/113_mesh_shader_instancing_vulkan.cpp @@ -421,9 +421,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -651,11 +653,24 @@ int main(int argc, char** argv) // Command list execution is done we can read the pipeline stats hasPiplineStats = true; + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/113_mesh_shader_instancing_vulkan/CMakeLists.txt b/projects/geometry/113_mesh_shader_instancing_vulkan/CMakeLists.txt index 07a2a13..c1e44d5 100644 --- a/projects/geometry/113_mesh_shader_instancing_vulkan/CMakeLists.txt +++ b/projects/geometry/113_mesh_shader_instancing_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/114_mesh_shader_culling_vulkan/114_mesh_shader_culling_vulkan.cpp b/projects/geometry/114_mesh_shader_culling_vulkan/114_mesh_shader_culling_vulkan.cpp index 1d1d511..84ab436 100644 --- a/projects/geometry/114_mesh_shader_culling_vulkan/114_mesh_shader_culling_vulkan.cpp +++ b/projects/geometry/114_mesh_shader_culling_vulkan/114_mesh_shader_culling_vulkan.cpp @@ -550,9 +550,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -860,11 +862,24 @@ int main(int argc, char** argv) // Command list execution is done we can read the pipeline stats hasPiplineStats = true; + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/114_mesh_shader_culling_vulkan/CMakeLists.txt b/projects/geometry/114_mesh_shader_culling_vulkan/CMakeLists.txt index 5cb02fb..180037f 100644 --- a/projects/geometry/114_mesh_shader_culling_vulkan/CMakeLists.txt +++ b/projects/geometry/114_mesh_shader_culling_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/115_mesh_shader_lod_vulkan/115_mesh_shader_lod_vulkan.cpp b/projects/geometry/115_mesh_shader_lod_vulkan/115_mesh_shader_lod_vulkan.cpp index 914ec76..1d2667c 100644 --- a/projects/geometry/115_mesh_shader_lod_vulkan/115_mesh_shader_lod_vulkan.cpp +++ b/projects/geometry/115_mesh_shader_lod_vulkan/115_mesh_shader_lod_vulkan.cpp @@ -572,9 +572,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -866,11 +868,24 @@ int main(int argc, char** argv) // Command list execution is done we can read the pipeline stats hasPiplineStats = true; + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/115_mesh_shader_lod_vulkan/CMakeLists.txt b/projects/geometry/115_mesh_shader_lod_vulkan/CMakeLists.txt index 08d74ae..ee12bfb 100644 --- a/projects/geometry/115_mesh_shader_lod_vulkan/CMakeLists.txt +++ b/projects/geometry/115_mesh_shader_lod_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/116_mesh_shader_calc_lod_vulkan/116_mesh_shader_calc_lod_vulkan.cpp b/projects/geometry/116_mesh_shader_calc_lod_vulkan/116_mesh_shader_calc_lod_vulkan.cpp index a88413a..7b0f657 100644 --- a/projects/geometry/116_mesh_shader_calc_lod_vulkan/116_mesh_shader_calc_lod_vulkan.cpp +++ b/projects/geometry/116_mesh_shader_calc_lod_vulkan/116_mesh_shader_calc_lod_vulkan.cpp @@ -580,9 +580,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -879,11 +881,24 @@ int main(int argc, char** argv) // Command list execution is done we can read the pipeline stats hasPiplineStats = true; + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/116_mesh_shader_calc_lod_vulkan/CMakeLists.txt b/projects/geometry/116_mesh_shader_calc_lod_vulkan/CMakeLists.txt index b69feb3..2bccce4 100644 --- a/projects/geometry/116_mesh_shader_calc_lod_vulkan/CMakeLists.txt +++ b/projects/geometry/116_mesh_shader_calc_lod_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/117_mesh_shader_cull_lod_vulkan/117_mesh_shader_cull_lod_vulkan.cpp b/projects/geometry/117_mesh_shader_cull_lod_vulkan/117_mesh_shader_cull_lod_vulkan.cpp index 935513c..d4ff690 100644 --- a/projects/geometry/117_mesh_shader_cull_lod_vulkan/117_mesh_shader_cull_lod_vulkan.cpp +++ b/projects/geometry/117_mesh_shader_cull_lod_vulkan/117_mesh_shader_cull_lod_vulkan.cpp @@ -663,9 +663,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -991,11 +993,24 @@ int main(int argc, char** argv) // Command list execution is done we can read the pipeline stats hasPiplineStats = true; + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/117_mesh_shader_cull_lod_vulkan/CMakeLists.txt b/projects/geometry/117_mesh_shader_cull_lod_vulkan/CMakeLists.txt index da93f52..9e774a0 100644 --- a/projects/geometry/117_mesh_shader_cull_lod_vulkan/CMakeLists.txt +++ b/projects/geometry/117_mesh_shader_cull_lod_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/118_mesh_shader_vertex_attrs_vulkan.cpp b/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/118_mesh_shader_vertex_attrs_vulkan.cpp index ffd3be0..294ed5c 100644 --- a/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/118_mesh_shader_vertex_attrs_vulkan.cpp +++ b/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/118_mesh_shader_vertex_attrs_vulkan.cpp @@ -419,9 +419,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -588,11 +590,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/CMakeLists.txt b/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/CMakeLists.txt index 8f02e84..210ea73 100644 --- a/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/CMakeLists.txt +++ b/projects/geometry/118_mesh_shader_vertex_attrs_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${PROJECT_NAME} ${PROJECT_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/geometry/119_mesh_shader_vertex_bary_vulkan/119_mesh_shader_vertex_bary_vulkan.cpp b/projects/geometry/119_mesh_shader_vertex_bary_vulkan/119_mesh_shader_vertex_bary_vulkan.cpp index bc90433..093dfec 100644 --- a/projects/geometry/119_mesh_shader_vertex_bary_vulkan/119_mesh_shader_vertex_bary_vulkan.cpp +++ b/projects/geometry/119_mesh_shader_vertex_bary_vulkan/119_mesh_shader_vertex_bary_vulkan.cpp @@ -426,9 +426,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -595,11 +597,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/geometry/119_mesh_shader_vertex_bary_vulkan/CMakeLists.txt b/projects/geometry/119_mesh_shader_vertex_bary_vulkan/CMakeLists.txt index 541192e..8d0b181 100644 --- a/projects/geometry/119_mesh_shader_vertex_bary_vulkan/CMakeLists.txt +++ b/projects/geometry/119_mesh_shader_vertex_bary_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/io/401_gltf_basic_geo_vulkan/401_gltf_basic_geo_vulkan.cpp b/projects/io/401_gltf_basic_geo_vulkan/401_gltf_basic_geo_vulkan.cpp index ca93ab3..2626ddd 100644 --- a/projects/io/401_gltf_basic_geo_vulkan/401_gltf_basic_geo_vulkan.cpp +++ b/projects/io/401_gltf_basic_geo_vulkan/401_gltf_basic_geo_vulkan.cpp @@ -282,9 +282,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -353,12 +355,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/io/402_gltf_basic_texture_vulkan/402_gltf_basic_texture_vulkan.cpp b/projects/io/402_gltf_basic_texture_vulkan/402_gltf_basic_texture_vulkan.cpp index 62a1a25..b9fac15 100644 --- a/projects/io/402_gltf_basic_texture_vulkan/402_gltf_basic_texture_vulkan.cpp +++ b/projects/io/402_gltf_basic_texture_vulkan/402_gltf_basic_texture_vulkan.cpp @@ -283,9 +283,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -354,12 +356,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/io/403_gltf_basic_material_vulkan/403_gltf_basic_material_vulkan.cpp b/projects/io/403_gltf_basic_material_vulkan/403_gltf_basic_material_vulkan.cpp index ff811f1..0b10021 100644 --- a/projects/io/403_gltf_basic_material_vulkan/403_gltf_basic_material_vulkan.cpp +++ b/projects/io/403_gltf_basic_material_vulkan/403_gltf_basic_material_vulkan.cpp @@ -283,9 +283,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -354,12 +356,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/io/404_gltf_basic_material_texture_vulkan/404_gltf_basic_material_texture_vulkan.cpp b/projects/io/404_gltf_basic_material_texture_vulkan/404_gltf_basic_material_texture_vulkan.cpp index 92cdeba..4ca8131 100644 --- a/projects/io/404_gltf_basic_material_texture_vulkan/404_gltf_basic_material_texture_vulkan.cpp +++ b/projects/io/404_gltf_basic_material_texture_vulkan/404_gltf_basic_material_texture_vulkan.cpp @@ -398,9 +398,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -469,12 +471,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/io/405_gltf_full_material_test_vulkan/405_gltf_full_material_test_vulkan.cpp b/projects/io/405_gltf_full_material_test_vulkan/405_gltf_full_material_test_vulkan.cpp index 65c0e5c..5b3f291 100644 --- a/projects/io/405_gltf_full_material_test_vulkan/405_gltf_full_material_test_vulkan.cpp +++ b/projects/io/405_gltf_full_material_test_vulkan/405_gltf_full_material_test_vulkan.cpp @@ -606,9 +606,11 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; + while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -677,12 +679,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/201_pbr_spheres_vulkan/201_pbr_spheres_vulkan.cpp b/projects/pbr/201_pbr_spheres_vulkan/201_pbr_spheres_vulkan.cpp index 9bc0c63..2393251 100644 --- a/projects/pbr/201_pbr_spheres_vulkan/201_pbr_spheres_vulkan.cpp +++ b/projects/pbr/201_pbr_spheres_vulkan/201_pbr_spheres_vulkan.cpp @@ -490,9 +490,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -724,12 +725,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/202_pbr_camera_vulkan/202_pbr_camera_vulkan.cpp b/projects/pbr/202_pbr_camera_vulkan/202_pbr_camera_vulkan.cpp index fe1a542..2ef99e1 100644 --- a/projects/pbr/202_pbr_camera_vulkan/202_pbr_camera_vulkan.cpp +++ b/projects/pbr/202_pbr_camera_vulkan/202_pbr_camera_vulkan.cpp @@ -563,9 +563,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -781,12 +782,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/203_pbr_align_vulkan/203_pbr_align_vulkan.cpp b/projects/pbr/203_pbr_align_vulkan/203_pbr_align_vulkan.cpp index 8e31d46..6060cda 100644 --- a/projects/pbr/203_pbr_align_vulkan/203_pbr_align_vulkan.cpp +++ b/projects/pbr/203_pbr_align_vulkan/203_pbr_align_vulkan.cpp @@ -490,9 +490,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -765,12 +766,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/251_pbr_explorer_vulkan/251_pbr_explorer_vulkan.cpp b/projects/pbr/251_pbr_explorer_vulkan/251_pbr_explorer_vulkan.cpp index a854d6a..3aa6944 100644 --- a/projects/pbr/251_pbr_explorer_vulkan/251_pbr_explorer_vulkan.cpp +++ b/projects/pbr/251_pbr_explorer_vulkan/251_pbr_explorer_vulkan.cpp @@ -636,9 +636,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -1182,12 +1183,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/252_pbr_material_properties_vulkan/252_pbr_material_properties_vulkan.cpp b/projects/pbr/252_pbr_material_properties_vulkan/252_pbr_material_properties_vulkan.cpp index 813e786..8604577 100644 --- a/projects/pbr/252_pbr_material_properties_vulkan/252_pbr_material_properties_vulkan.cpp +++ b/projects/pbr/252_pbr_material_properties_vulkan/252_pbr_material_properties_vulkan.cpp @@ -462,9 +462,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -860,12 +861,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/pbr/253_pbr_material_textures_vulkan/253_pbr_material_textures_vulkan.cpp b/projects/pbr/253_pbr_material_textures_vulkan/253_pbr_material_textures_vulkan.cpp index ac31532..b6047d4 100644 --- a/projects/pbr/253_pbr_material_textures_vulkan/253_pbr_material_textures_vulkan.cpp +++ b/projects/pbr/253_pbr_material_textures_vulkan/253_pbr_material_textures_vulkan.cpp @@ -589,9 +589,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -1103,12 +1104,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/000_raygen_uv_vulkan/000_raygen_uv_vulkan.cpp b/projects/raytracing/000_raygen_uv_vulkan/000_raygen_uv_vulkan.cpp index f389435..aecfc1f 100644 --- a/projects/raytracing/000_raygen_uv_vulkan/000_raygen_uv_vulkan.cpp +++ b/projects/raytracing/000_raygen_uv_vulkan/000_raygen_uv_vulkan.cpp @@ -254,9 +254,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -343,11 +344,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/000_raygen_uv_vulkan/CMakeLists.txt b/projects/raytracing/000_raygen_uv_vulkan/CMakeLists.txt index 37b5dea..6db0419 100644 --- a/projects/raytracing/000_raygen_uv_vulkan/CMakeLists.txt +++ b/projects/raytracing/000_raygen_uv_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h @@ -32,6 +34,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/001_raytracing_basic_vulkan/001_raytracing_basic_vulkan.cpp b/projects/raytracing/001_raytracing_basic_vulkan/001_raytracing_basic_vulkan.cpp index 2ac35b1..b946fff 100644 --- a/projects/raytracing/001_raytracing_basic_vulkan/001_raytracing_basic_vulkan.cpp +++ b/projects/raytracing/001_raytracing_basic_vulkan/001_raytracing_basic_vulkan.cpp @@ -366,9 +366,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -462,11 +463,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/001_raytracing_basic_vulkan/CMakeLists.txt b/projects/raytracing/001_raytracing_basic_vulkan/CMakeLists.txt index 9ebb8ae..d13e894 100644 --- a/projects/raytracing/001_raytracing_basic_vulkan/CMakeLists.txt +++ b/projects/raytracing/001_raytracing_basic_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h @@ -32,6 +34,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/002_basic_procedural_vulkan/002_basic_procedural_vulkan.cpp b/projects/raytracing/002_basic_procedural_vulkan/002_basic_procedural_vulkan.cpp index 5c0d032..0649b1a 100644 --- a/projects/raytracing/002_basic_procedural_vulkan/002_basic_procedural_vulkan.cpp +++ b/projects/raytracing/002_basic_procedural_vulkan/002_basic_procedural_vulkan.cpp @@ -439,9 +439,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -535,11 +536,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/002_basic_procedural_vulkan/CMakeLists.txt b/projects/raytracing/002_basic_procedural_vulkan/CMakeLists.txt index d91273e..46f90bb 100644 --- a/projects/raytracing/002_basic_procedural_vulkan/CMakeLists.txt +++ b/projects/raytracing/002_basic_procedural_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h @@ -32,6 +34,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/003_sphereflake_vulkan/003_sphereflake_vulkan.cpp b/projects/raytracing/003_sphereflake_vulkan/003_sphereflake_vulkan.cpp index 70c1656..b33a5b4 100644 --- a/projects/raytracing/003_sphereflake_vulkan/003_sphereflake_vulkan.cpp +++ b/projects/raytracing/003_sphereflake_vulkan/003_sphereflake_vulkan.cpp @@ -489,9 +489,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -585,11 +586,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/003_sphereflake_vulkan/CMakeLists.txt b/projects/raytracing/003_sphereflake_vulkan/CMakeLists.txt index f0b5c00..227edbb 100644 --- a/projects/raytracing/003_sphereflake_vulkan/CMakeLists.txt +++ b/projects/raytracing/003_sphereflake_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/sphereflake.h ${GREX_PROJECTS_COMMON_DIR}/sphereflake.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h @@ -34,6 +36,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/004_basic_reflection_vulkan/004_basic_reflection_vulkan.cpp b/projects/raytracing/004_basic_reflection_vulkan/004_basic_reflection_vulkan.cpp index eac6c5a..13aedf9 100644 --- a/projects/raytracing/004_basic_reflection_vulkan/004_basic_reflection_vulkan.cpp +++ b/projects/raytracing/004_basic_reflection_vulkan/004_basic_reflection_vulkan.cpp @@ -575,9 +575,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -671,11 +672,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/004_basic_reflection_vulkan/CMakeLists.txt b/projects/raytracing/004_basic_reflection_vulkan/CMakeLists.txt index e507e47..beb450a 100644 --- a/projects/raytracing/004_basic_reflection_vulkan/CMakeLists.txt +++ b/projects/raytracing/004_basic_reflection_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/sphereflake.h ${GREX_PROJECTS_COMMON_DIR}/sphereflake.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h @@ -34,6 +36,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/005_basic_shadow_vulkan/005_basic_shadow_vulkan.cpp b/projects/raytracing/005_basic_shadow_vulkan/005_basic_shadow_vulkan.cpp index 10771ae..9b8d5e8 100644 --- a/projects/raytracing/005_basic_shadow_vulkan/005_basic_shadow_vulkan.cpp +++ b/projects/raytracing/005_basic_shadow_vulkan/005_basic_shadow_vulkan.cpp @@ -664,9 +664,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -761,11 +762,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/005_basic_shadow_vulkan/CMakeLists.txt b/projects/raytracing/005_basic_shadow_vulkan/CMakeLists.txt index d297456..7d82b59 100644 --- a/projects/raytracing/005_basic_shadow_vulkan/CMakeLists.txt +++ b/projects/raytracing/005_basic_shadow_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/sphereflake.h ${GREX_PROJECTS_COMMON_DIR}/sphereflake.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h @@ -34,6 +36,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/006_basic_shadow_dynamic_vulkan/006_basic_shadow_dynamic_vulkan.cpp b/projects/raytracing/006_basic_shadow_dynamic_vulkan/006_basic_shadow_dynamic_vulkan.cpp index ea5c83c..d0fe1cf 100644 --- a/projects/raytracing/006_basic_shadow_dynamic_vulkan/006_basic_shadow_dynamic_vulkan.cpp +++ b/projects/raytracing/006_basic_shadow_dynamic_vulkan/006_basic_shadow_dynamic_vulkan.cpp @@ -668,9 +668,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -779,11 +780,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[imageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), imageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } vmaUnmapMemory(renderer->Allocator, uniformBuffer.Allocation); diff --git a/projects/raytracing/006_basic_shadow_dynamic_vulkan/CMakeLists.txt b/projects/raytracing/006_basic_shadow_dynamic_vulkan/CMakeLists.txt index e31d253..3d72526 100644 --- a/projects/raytracing/006_basic_shadow_dynamic_vulkan/CMakeLists.txt +++ b/projects/raytracing/006_basic_shadow_dynamic_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/sphereflake.h ${GREX_PROJECTS_COMMON_DIR}/sphereflake.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h @@ -34,6 +36,7 @@ target_include_directories( ${VULKAN_INCLUDE_DIR} ${GREX_THIRD_PARTY_DIR}/VulkanMemoryAllocator/include ${GREX_THIRD_PARTY_DIR}/glm + ${GREX_THIRD_PARTY_DIR}/stb ) target_link_libraries( diff --git a/projects/raytracing/021_raytracing_triangles_vulkan/021_raytracing_triangles_vulkan.cpp b/projects/raytracing/021_raytracing_triangles_vulkan/021_raytracing_triangles_vulkan.cpp index 4871e9b..7c4a08f 100644 --- a/projects/raytracing/021_raytracing_triangles_vulkan/021_raytracing_triangles_vulkan.cpp +++ b/projects/raytracing/021_raytracing_triangles_vulkan/021_raytracing_triangles_vulkan.cpp @@ -286,9 +286,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -392,11 +393,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/021_raytracing_triangles_vulkan/CMakeLists.txt b/projects/raytracing/021_raytracing_triangles_vulkan/CMakeLists.txt index eed4528..373fed8 100644 --- a/projects/raytracing/021_raytracing_triangles_vulkan/CMakeLists.txt +++ b/projects/raytracing/021_raytracing_triangles_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/raytracing/022_raytracing_multi_geo_vulkan/022_raytracing_multi_geo_vulkan.cpp b/projects/raytracing/022_raytracing_multi_geo_vulkan/022_raytracing_multi_geo_vulkan.cpp index 3879edf..fd92d1b 100644 --- a/projects/raytracing/022_raytracing_multi_geo_vulkan/022_raytracing_multi_geo_vulkan.cpp +++ b/projects/raytracing/022_raytracing_multi_geo_vulkan/022_raytracing_multi_geo_vulkan.cpp @@ -296,9 +296,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -401,11 +402,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/022_raytracing_multi_geo_vulkan/CMakeLists.txt b/projects/raytracing/022_raytracing_multi_geo_vulkan/CMakeLists.txt index 35a70f8..d76a1cb 100644 --- a/projects/raytracing/022_raytracing_multi_geo_vulkan/CMakeLists.txt +++ b/projects/raytracing/022_raytracing_multi_geo_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/raytracing/023_raytracing_multi_instance_vulkan/023_raytracing_multi_instance_vulkan.cpp b/projects/raytracing/023_raytracing_multi_instance_vulkan/023_raytracing_multi_instance_vulkan.cpp index 1c68f28..d34cf6b 100644 --- a/projects/raytracing/023_raytracing_multi_instance_vulkan/023_raytracing_multi_instance_vulkan.cpp +++ b/projects/raytracing/023_raytracing_multi_instance_vulkan/023_raytracing_multi_instance_vulkan.cpp @@ -299,9 +299,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -404,11 +405,24 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/023_raytracing_multi_instance_vulkan/CMakeLists.txt b/projects/raytracing/023_raytracing_multi_instance_vulkan/CMakeLists.txt index f0f130a..dbb9a11 100644 --- a/projects/raytracing/023_raytracing_multi_instance_vulkan/CMakeLists.txt +++ b/projects/raytracing/023_raytracing_multi_instance_vulkan/CMakeLists.txt @@ -8,6 +8,8 @@ add_executable( ${TARGET_NAME} ${TARGET_NAME}.cpp ${GREX_PROJECTS_COMMON_DIR}/config.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.h + ${GREX_PROJECTS_COMMON_DIR}/bitmap.cpp ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.h ${GREX_PROJECTS_COMMON_DIR}/vk_renderer.cpp ${GREX_PROJECTS_COMMON_DIR}/window.h diff --git a/projects/raytracing/024_raytracing_pbr_spheres_vulkan/024_raytracing_pbr_spheres_vulkan.cpp b/projects/raytracing/024_raytracing_pbr_spheres_vulkan/024_raytracing_pbr_spheres_vulkan.cpp index 2845cb7..25c1318 100644 --- a/projects/raytracing/024_raytracing_pbr_spheres_vulkan/024_raytracing_pbr_spheres_vulkan.cpp +++ b/projects/raytracing/024_raytracing_pbr_spheres_vulkan/024_raytracing_pbr_spheres_vulkan.cpp @@ -439,9 +439,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -567,12 +568,25 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/025_raytracing_refract_vulkan/025_raytracing_refract_vulkan.cpp b/projects/raytracing/025_raytracing_refract_vulkan/025_raytracing_refract_vulkan.cpp index 6fe8878..bfde23a 100644 --- a/projects/raytracing/025_raytracing_refract_vulkan/025_raytracing_refract_vulkan.cpp +++ b/projects/raytracing/025_raytracing_refract_vulkan/025_raytracing_refract_vulkan.cpp @@ -438,9 +438,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -560,12 +561,25 @@ int main(int argc, char** argv) assert(false && "WaitForGpu failed"); } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/030_raytracing_path_trace_vulkan/030_raytracing_path_trace_vulkan.cpp b/projects/raytracing/030_raytracing_path_trace_vulkan/030_raytracing_path_trace_vulkan.cpp index ab7f01d..6ff02dc 100644 --- a/projects/raytracing/030_raytracing_path_trace_vulkan/030_raytracing_path_trace_vulkan.cpp +++ b/projects/raytracing/030_raytracing_path_trace_vulkan/030_raytracing_path_trace_vulkan.cpp @@ -585,9 +585,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -841,11 +842,24 @@ int main(int argc, char** argv) ++sampleCount; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/030_raytracing_path_trace_vulkan_bof/030_raytracing_path_trace_vulkan_bof.cpp b/projects/raytracing/030_raytracing_path_trace_vulkan_bof/030_raytracing_path_trace_vulkan_bof.cpp index 30a8ce4..b2c74c3 100644 --- a/projects/raytracing/030_raytracing_path_trace_vulkan_bof/030_raytracing_path_trace_vulkan_bof.cpp +++ b/projects/raytracing/030_raytracing_path_trace_vulkan_bof/030_raytracing_path_trace_vulkan_bof.cpp @@ -617,9 +617,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -945,11 +946,24 @@ int main(int argc, char** argv) gSelectedPixelChanged = false; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/raytracing/031_raytracing_path_trace_pbr_vulkan/031_raytracing_path_trace_pbr_vulkan.cpp b/projects/raytracing/031_raytracing_path_trace_pbr_vulkan/031_raytracing_path_trace_pbr_vulkan.cpp index 4379961..f44673e 100644 --- a/projects/raytracing/031_raytracing_path_trace_pbr_vulkan/031_raytracing_path_trace_pbr_vulkan.cpp +++ b/projects/raytracing/031_raytracing_path_trace_pbr_vulkan/031_raytracing_path_trace_pbr_vulkan.cpp @@ -628,9 +628,10 @@ int main(int argc, char** argv) // ************************************************************************* window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -912,11 +913,24 @@ int main(int argc, char** argv) ++sampleCount; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), swapchainImages[swapchainImageIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + if (!SwapchainPresent(renderer.get(), swapchainImageIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/301_textured_cube_vulkan/301_textured_cube_vulkan.cpp b/projects/texture/301_textured_cube_vulkan/301_textured_cube_vulkan.cpp index 27e55ca..67e01d6 100644 --- a/projects/texture/301_textured_cube_vulkan/301_textured_cube_vulkan.cpp +++ b/projects/texture/301_textured_cube_vulkan/301_textured_cube_vulkan.cpp @@ -293,9 +293,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -387,12 +388,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/302_lambert_textured_cube_vulkan/302_lambert_textured_cube_vulkan.cpp b/projects/texture/302_lambert_textured_cube_vulkan/302_lambert_textured_cube_vulkan.cpp index 8ebe0cb..799593c 100644 --- a/projects/texture/302_lambert_textured_cube_vulkan/302_lambert_textured_cube_vulkan.cpp +++ b/projects/texture/302_lambert_textured_cube_vulkan/302_lambert_textured_cube_vulkan.cpp @@ -321,9 +321,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -419,12 +420,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/303_phong_textured_cube_vulkan/303_phong_textured_cube_vulkan.cpp b/projects/texture/303_phong_textured_cube_vulkan/303_phong_textured_cube_vulkan.cpp index 3b75a87..aea49e0 100644 --- a/projects/texture/303_phong_textured_cube_vulkan/303_phong_textured_cube_vulkan.cpp +++ b/projects/texture/303_phong_textured_cube_vulkan/303_phong_textured_cube_vulkan.cpp @@ -335,9 +335,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -436,12 +437,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/304_normal_map_vulkan/304_normal_map_vulkan.cpp b/projects/texture/304_normal_map_vulkan/304_normal_map_vulkan.cpp index 21c5fba..7593e6f 100644 --- a/projects/texture/304_normal_map_vulkan/304_normal_map_vulkan.cpp +++ b/projects/texture/304_normal_map_vulkan/304_normal_map_vulkan.cpp @@ -312,9 +312,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -422,12 +423,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/305_normal_map_explorer_vulkan/305_normal_map_explorer_vulkan.cpp b/projects/texture/305_normal_map_explorer_vulkan/305_normal_map_explorer_vulkan.cpp index ef89e2f..6eb0e3a 100644 --- a/projects/texture/305_normal_map_explorer_vulkan/305_normal_map_explorer_vulkan.cpp +++ b/projects/texture/305_normal_map_explorer_vulkan/305_normal_map_explorer_vulkan.cpp @@ -355,9 +355,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -565,12 +566,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/306_parallax_occlusion_map_vulkan/306_parallax_occlusion_map_vulkan.cpp b/projects/texture/306_parallax_occlusion_map_vulkan/306_parallax_occlusion_map_vulkan.cpp index f1abbed..e712241 100644 --- a/projects/texture/306_parallax_occlusion_map_vulkan/306_parallax_occlusion_map_vulkan.cpp +++ b/projects/texture/306_parallax_occlusion_map_vulkan/306_parallax_occlusion_map_vulkan.cpp @@ -316,9 +316,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -426,12 +427,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/307_parallax_occlusion_map_explorer_vulkan/307_parallax_occlusion_map_explorer_vulkan.cpp b/projects/texture/307_parallax_occlusion_map_explorer_vulkan/307_parallax_occlusion_map_explorer_vulkan.cpp index c3e2952..7044207 100644 --- a/projects/texture/307_parallax_occlusion_map_explorer_vulkan/307_parallax_occlusion_map_explorer_vulkan.cpp +++ b/projects/texture/307_parallax_occlusion_map_explorer_vulkan/307_parallax_occlusion_map_explorer_vulkan.cpp @@ -356,9 +356,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -566,12 +567,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0; diff --git a/projects/texture/308_normal_map_vs_pom_vulkan/308_normal_map_vs_pom_vulkan.cpp b/projects/texture/308_normal_map_vs_pom_vulkan/308_normal_map_vs_pom_vulkan.cpp index ad687c8..7e721c2 100644 --- a/projects/texture/308_normal_map_vs_pom_vulkan/308_normal_map_vs_pom_vulkan.cpp +++ b/projects/texture/308_normal_map_vs_pom_vulkan/308_normal_map_vs_pom_vulkan.cpp @@ -455,9 +455,10 @@ int main(int argc, char** argv) window->ResetTimer(); + uint32_t frameIndex = 0; while (window->PollEvents()) { - if (args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) + if (args.screenshotFrame < 0 && args.autoExitSeconds >= 0 && window->GetElapsedSeconds() >= args.autoExitSeconds) { break; } @@ -715,12 +716,25 @@ int main(int argc, char** argv) break; } + if (!args.screenshotPath.empty() && + (args.screenshotFrame < 0 || (int)frameIndex == args.screenshotFrame)) + { + SaveVulkanImageAsPNG(renderer.get(), images[bufferIndex], gWindowWidth, gWindowHeight, args.screenshotPath); + args.screenshotPath.clear(); + if (args.screenshotFrame >= 0) + { + break; + } + } + // Present if (!SwapchainPresent(renderer.get(), bufferIndex)) { assert(false && "SwapchainPresent failed"); break; } + + ++frameIndex; } return 0;