diff --git a/examples/pumexcrowd/pumexcrowd.cpp b/examples/pumexcrowd/pumexcrowd.cpp index 78885d3..ddde48d 100644 --- a/examples/pumexcrowd/pumexcrowd.cpp +++ b/examples/pumexcrowd/pumexcrowd.cpp @@ -589,18 +589,11 @@ int main(int argc, char * argv[]) { SET_LOG_INFO; - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; args::ArgumentParser parser("pumex example : multithreaded crowd rendering on more than one window"); args::HelpFlag help(parser, "help", "display this help menu", {'h', "help"}); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", {'d'}); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", {'f'}); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); args::Flag renderVRwindows(parser, "vrwindows", "create two halfscreen windows for VR", { 'v' }); args::Flag render3windows(parser, "three_windows", "render in three windows", {'t'}); diff --git a/examples/pumexdeferred/pumexdeferred.cpp b/examples/pumexdeferred/pumexdeferred.cpp index e1023fa..d66f3ee 100644 --- a/examples/pumexdeferred/pumexdeferred.cpp +++ b/examples/pumexdeferred/pumexdeferred.cpp @@ -197,13 +197,6 @@ int main( int argc, char * argv[] ) { SET_LOG_INFO; - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; std::unordered_map availableSamplesPerPixel { { "1", VK_SAMPLE_COUNT_1_BIT }, @@ -216,7 +209,7 @@ int main( int argc, char * argv[] ) args::HelpFlag help(parser, "help", "display this help menu", { 'h', "help" }); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", { 'd' }); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", { 'f' }); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); args::Flag skipDepthPrepass(parser, "nodp", "skip depth prepass", { 'n' }); args::MapFlag samplesPerPixel(parser, "samples", "samples per pixel (1,2,4,8)", { 's' }, availableSamplesPerPixel, VK_SAMPLE_COUNT_4_BIT); diff --git a/examples/pumexgpucull/pumexgpucull.cpp b/examples/pumexgpucull/pumexgpucull.cpp index cbf92fa..d7657bd 100644 --- a/examples/pumexgpucull/pumexgpucull.cpp +++ b/examples/pumexgpucull/pumexgpucull.cpp @@ -1230,18 +1230,11 @@ int main(int argc, char * argv[]) { SET_LOG_INFO; - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; args::ArgumentParser parser("pumex example : instanced rendering for static and dynamic objects"); args::HelpFlag help(parser, "help", "display this help menu", { 'h', "help" }); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", { 'd' }); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", { 'f' }); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); args::Flag renderVRwindows(parser, "vrwindows", "create two halfscreen windows for VR", { 'v' }); args::Flag render3windows(parser, "three_windows", "render in three windows", { 't' }); diff --git a/examples/pumexmultiview/pumexmultiview.cpp b/examples/pumexmultiview/pumexmultiview.cpp index 5bb814c..8b42764 100644 --- a/examples/pumexmultiview/pumexmultiview.cpp +++ b/examples/pumexmultiview/pumexmultiview.cpp @@ -234,18 +234,11 @@ int main( int argc, char * argv[] ) { SET_LOG_INFO; - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; args::ArgumentParser parser("pumex example : multiview deferred rendering with PBR and antialiasing"); args::HelpFlag help(parser, "help", "display this help menu", { 'h', "help" }); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", { 'd' }); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", { 'f' }); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); try { diff --git a/examples/pumexviewer/pumexviewer.cpp b/examples/pumexviewer/pumexviewer.cpp index 24688a8..668a404 100644 --- a/examples/pumexviewer/pumexviewer.cpp +++ b/examples/pumexviewer/pumexviewer.cpp @@ -140,18 +140,11 @@ int main( int argc, char * argv[] ) SET_LOG_INFO; // process command line using args library - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; args::ArgumentParser parser("pumex example : minimal 3D model viewer without textures"); args::HelpFlag help(parser, "help", "display this help menu", { 'h', "help" }); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", { 'd' }); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", { 'f' }); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); args::Positional modelNameArg(parser, "model", "3D model filename"); args::Positional animationNameArg(parser, "animation", "3D model with animation"); @@ -418,4 +411,4 @@ int main( int argc, char * argv[] ) viewer->cleanup(); FLUSH_LOG; return 0; -} +} diff --git a/examples/pumexvoxelizer/pumexvoxelizer.cpp b/examples/pumexvoxelizer/pumexvoxelizer.cpp index 86d4fcf..a84f565 100644 --- a/examples/pumexvoxelizer/pumexvoxelizer.cpp +++ b/examples/pumexvoxelizer/pumexvoxelizer.cpp @@ -184,18 +184,11 @@ int main( int argc, char * argv[] ) { SET_LOG_INFO; - std::unordered_map availablePresentationModes - { - { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, - { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, - { "fifo", VK_PRESENT_MODE_FIFO_KHR }, - { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } - }; args::ArgumentParser parser("pumex example : model voxelization and rendering"); args::HelpFlag help(parser, "help", "display this help menu", { 'h', "help" }); args::Flag enableDebugging(parser, "debug", "enable Vulkan debugging", { 'd' }); args::Flag useFullScreen(parser, "fullscreen", "create fullscreen window", { 'f' }); - args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, availablePresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); + args::MapFlag presentationMode(parser, "presentation_mode", "presentation mode (immediate, mailbox, fifo, fifo_relaxed)", { 'p' }, pumex::Surface::nameToPresentationModes, VK_PRESENT_MODE_MAILBOX_KHR); args::ValueFlag updatesPerSecond(parser, "update_frequency", "number of update calls per second", { 'u' }, 60); args::Positional modelNameArg(parser, "model", "3D model filename" ); args::Positional animationNameArg(parser, "animation", "3D model with animation"); diff --git a/include/pumex/Surface.h b/include/pumex/Surface.h index 4d198b0..23b3c78 100644 --- a/include/pumex/Surface.h +++ b/include/pumex/Surface.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -182,6 +183,11 @@ class PUMEX_EXPORT Surface : public std::enable_shared_from_this void createSwapChain(); bool checkWorkflow(); + +public: + static const std::unordered_map nameToPresentationModes; + static const std::unordered_map presentationModeNames; + static const std::unordered_map> replacementModes; }; bool Surface::isRealized() const { return realized; } diff --git a/src/pumex/Surface.cpp b/src/pumex/Surface.cpp index 17e1376..ab603e3 100644 --- a/src/pumex/Surface.cpp +++ b/src/pumex/Surface.cpp @@ -41,6 +41,31 @@ SurfaceTraits::SurfaceTraits(uint32_t ic, VkColorSpaceKHR ics, uint32_t ial, VkP { } +const std::unordered_map Surface::nameToPresentationModes +{ + { "immediate", VK_PRESENT_MODE_IMMEDIATE_KHR }, + { "mailbox", VK_PRESENT_MODE_MAILBOX_KHR }, + { "fifo", VK_PRESENT_MODE_FIFO_KHR }, + { "fifo_relaxed", VK_PRESENT_MODE_FIFO_RELAXED_KHR } +}; + +const std::unordered_map Surface::presentationModeNames +{ + { VK_PRESENT_MODE_IMMEDIATE_KHR, "immediate" }, + { VK_PRESENT_MODE_MAILBOX_KHR, "mailbox" }, + { VK_PRESENT_MODE_FIFO_KHR, "fifo" }, + { VK_PRESENT_MODE_FIFO_RELAXED_KHR, "fifo_relaxed" } +}; + +const std::unordered_map> Surface::replacementModes +{ + { VK_PRESENT_MODE_IMMEDIATE_KHR,{ VK_PRESENT_MODE_MAILBOX_KHR , VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR } }, + { VK_PRESENT_MODE_MAILBOX_KHR,{ VK_PRESENT_MODE_IMMEDIATE_KHR , VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR } }, + { VK_PRESENT_MODE_FIFO_KHR,{ VK_PRESENT_MODE_FIFO_RELAXED_KHR , VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR } }, + { VK_PRESENT_MODE_FIFO_RELAXED_KHR,{ VK_PRESENT_MODE_FIFO_KHR , VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_MAILBOX_KHR } } +}; + + Surface::Surface(std::shared_ptr v, std::shared_ptr w, std::shared_ptr d, VkSurfaceKHR s, const SurfaceTraits& st) : viewer{ v }, window{ w }, device{ d }, surface{ s }, surfaceTraits(st) { @@ -79,12 +104,37 @@ void Surface::realize() // collect surface properties VK_CHECK_LOG_THROW( vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phDev, surface, &surfaceCapabilities), "failed vkGetPhysicalDeviceSurfaceCapabilitiesKHR for surface " << getID() ); + + // collect available presentation modes uint32_t presentModeCount; VK_CHECK_LOG_THROW( vkGetPhysicalDeviceSurfacePresentModesKHR(phDev, surface, &presentModeCount, nullptr), "Could not get present modes for surface " << getID()); CHECK_LOG_THROW( presentModeCount == 0, "No present modes defined for this surface" ); presentModes.resize(presentModeCount); VK_CHECK_LOG_THROW( vkGetPhysicalDeviceSurfacePresentModesKHR(phDev, surface, &presentModeCount, presentModes.data()), "Could not get present modes " << presentModeCount << " for surface " << getID()); + // check if presentation mode from surface traits is available + auto presentIt = std::find(begin(presentModes), end(presentModes), surfaceTraits.swapchainPresentMode); + if (presentIt == end(presentModes)) + { + // presentation mode from surface traits is not available. Choose the most appropriate one and inform user about the change + + auto prefIt = replacementModes.find(surfaceTraits.swapchainPresentMode); + CHECK_LOG_THROW(prefIt == end(replacementModes), "Presentation mode <" < not available on GPU and not recognized by library"); + VkPresentModeKHR finalPresentationMode = surfaceTraits.swapchainPresentMode; + for (auto it = begin(prefIt->second); it != end(prefIt->second); ++it) + { + auto secondChoiceIt = std::find(begin(presentModes), end(presentModes), *it); + if (secondChoiceIt == end(presentModes)) + continue; + finalPresentationMode = *it; + break; + } + CHECK_LOG_THROW(finalPresentationMode == surfaceTraits.swapchainPresentMode, "Presentation mode <" << surfaceTraits.swapchainPresentMode << "> not available on GPU. Library cannot find the replacement"); + + LOG_WARNING << "Warning : <" << presentationModeNames.at(surfaceTraits.swapchainPresentMode) <<"> presentation mode not available. Library will use <" << presentationModeNames.at(finalPresentationMode) << "> presentation mode instead." << std::endl ; + surfaceTraits.swapchainPresentMode = finalPresentationMode; + } + uint32_t surfaceFormatCount; VK_CHECK_LOG_THROW( vkGetPhysicalDeviceSurfaceFormatsKHR(phDev, surface, &surfaceFormatCount, nullptr), "Could not get surface formats for surface " << getID()); CHECK_LOG_THROW(surfaceFormatCount == 0, "No surface formats defined for surface " << getID());