diff --git a/CMakeLists.txt b/CMakeLists.txt index da150fcbeafec3be555d4bbefdab37dbdedf277f..2a0858b970dead0233261c4f3c126a0bf64732f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,9 +34,9 @@ set(vkcv_flags ${CMAKE_CXX_FLAGS}) if (vkcv_build_debug) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") #set(vkcv_flags ${vkcv_flags} " -Weverything") - set(vkcv_flags ${vkcv_flags} " -Wextra -Wall") + set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -Wno-unused-parameter") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic") + set(vkcv_flags ${vkcv_flags} " -Wextra -Wall -pedantic -Wno-unused-parameter") else() set(vkcv_flags ${vkcv_flags} " -W4") endif() diff --git a/config/Sources.cmake b/config/Sources.cmake index 7f94800e45b70b19158481f52a3d696588737297..606dc4c97d62ed284d5967707e07237ebd2f7580 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -51,11 +51,15 @@ set(vkcv_sources ${vkcv_include}/vkcv/ShaderProgram.hpp ${vkcv_source}/vkcv/ShaderProgram.cpp - ${vkcv_include}/vkcv/PipelineConfig.hpp + ${vkcv_include}/vkcv/GraphicsPipelineConfig.hpp + ${vkcv_include}/vkcv/ComputePipelineConfig.hpp + + ${vkcv_source}/vkcv/ComputePipelineManager.hpp + ${vkcv_source}/vkcv/ComputePipelineManager.cpp + + ${vkcv_source}/vkcv/GraphicsPipelineManager.hpp + ${vkcv_source}/vkcv/GraphicsPipelineManager.cpp - ${vkcv_source}/vkcv/PipelineManager.hpp - ${vkcv_source}/vkcv/PipelineManager.cpp - ${vkcv_include}/vkcv/CommandResources.hpp ${vkcv_source}/vkcv/CommandResources.cpp diff --git a/include/vkcv/ComputePipelineConfig.hpp b/include/vkcv/ComputePipelineConfig.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a99d75e6a0e4ec332588e7ff48a7d1ca112eccb4 --- /dev/null +++ b/include/vkcv/ComputePipelineConfig.hpp @@ -0,0 +1,17 @@ +#pragma once +/** + * @authors Mark Mints + * @file src/vkcv/ComputePipelineConfig.hpp + * @brief Compute Pipeline Config Struct to hand over required information to Pipeline Creation. + */ + +#include <vector> +#include "ShaderProgram.hpp" + +namespace vkcv +{ + struct ComputePipelineConfig { + ShaderProgram& m_ShaderProgram; + std::vector<vk::DescriptorSetLayout> m_DescriptorSetLayouts; + }; +} \ No newline at end of file diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index adaa1cd4dfba51b6fa5b722950fc9ce444463584..d6e47d26e5c26dab7929ac5905938c2ac0c80125 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -14,7 +14,8 @@ #include "Handles.hpp" #include "Buffer.hpp" #include "Image.hpp" -#include "PipelineConfig.hpp" +#include "GraphicsPipelineConfig.hpp" +#include "ComputePipelineConfig.hpp" #include "CommandResources.hpp" #include "SyncResources.hpp" #include "Result.hpp" @@ -33,7 +34,8 @@ namespace vkcv // forward declarations class PassManager; - class PipelineManager; + class GraphicsPipelineManager; + class ComputePipelineManager; class DescriptorManager; class BufferManager; class SamplerManager; @@ -65,15 +67,16 @@ namespace vkcv Context m_Context; - std::unique_ptr<PassManager> m_PassManager; - std::unique_ptr<PipelineManager> m_PipelineManager; - std::unique_ptr<DescriptorManager> m_DescriptorManager; - std::unique_ptr<BufferManager> m_BufferManager; - std::unique_ptr<SamplerManager> m_SamplerManager; - std::unique_ptr<ImageManager> m_ImageManager; - std::unique_ptr<CommandStreamManager> m_CommandStreamManager; - std::unique_ptr<WindowManager> m_WindowManager; - std::unique_ptr<SwapchainManager> m_SwapchainManager; + std::unique_ptr<PassManager> m_PassManager; + std::unique_ptr<GraphicsPipelineManager> m_PipelineManager; + std::unique_ptr<ComputePipelineManager> m_ComputePipelineManager; + std::unique_ptr<DescriptorManager> m_DescriptorManager; + std::unique_ptr<BufferManager> m_BufferManager; + std::unique_ptr<SamplerManager> m_SamplerManager; + std::unique_ptr<ImageManager> m_ImageManager; + std::unique_ptr<CommandStreamManager> m_CommandStreamManager; + std::unique_ptr<WindowManager> m_WindowManager; + std::unique_ptr<SwapchainManager> m_SwapchainManager; CommandResources m_CommandResources; SyncResources m_SyncResources; @@ -154,20 +157,17 @@ namespace vkcv * @return True if pipeline creation was successful, False if not */ [[nodiscard]] - PipelineHandle createGraphicsPipeline(const PipelineConfig &config); + GraphicsPipelineHandle createGraphicsPipeline(const GraphicsPipelineConfig &config); /** * Creates a basic vulkan compute pipeline using @p shader program and returns it using the @p handle. * Fixed Functions for pipeline are set with standard values. * - * @param shader program that hold the compiles compute shader - * @param handle a handle to return the created vulkan handle + * @param config Contains the compiles compute shader and the corresponding descriptor set layout * @return True if pipeline creation was successful, False if not */ [[nodiscard]] - PipelineHandle createComputePipeline( - const ShaderProgram &shaderProgram, - const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts); + ComputePipelineHandle createComputePipeline(const ComputePipelineConfig &config); /** * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle. @@ -325,7 +325,7 @@ namespace vkcv void recordDrawcallsToCmdStream( const CommandStreamHandle& cmdStreamHandle, const PassHandle& renderpassHandle, - const PipelineHandle pipelineHandle, + const GraphicsPipelineHandle &pipelineHandle, const PushConstants &pushConstants, const std::vector<DrawcallInfo> &drawcalls, const std::vector<ImageHandle> &renderTargets, @@ -334,7 +334,7 @@ namespace vkcv void recordMeshShaderDrawcalls( const CommandStreamHandle& cmdStreamHandle, const PassHandle& renderpassHandle, - const PipelineHandle pipelineHandle, + const GraphicsPipelineHandle &pipelineHandle, const PushConstants& pushConstantData, const std::vector<MeshShaderDrawcall>& drawcalls, const std::vector<ImageHandle>& renderTargets, @@ -342,7 +342,7 @@ namespace vkcv void recordComputeDispatchToCmdStream( CommandStreamHandle cmdStream, - PipelineHandle computePipeline, + ComputePipelineHandle computePipeline, const uint32_t dispatchCount[3], const std::vector<DescriptorSetUsage> &descriptorSetUsages, const PushConstants& pushConstants); @@ -355,7 +355,7 @@ namespace vkcv void recordComputeIndirectDispatchToCmdStream( const CommandStreamHandle cmdStream, - const PipelineHandle computePipeline, + const ComputePipelineHandle computePipeline, const vkcv::BufferHandle buffer, const size_t bufferArgOffset, const std::vector<DescriptorSetUsage>& descriptorSetUsages, @@ -405,7 +405,8 @@ namespace vkcv void setDebugLabel(const BufferHandle &handle, const std::string &label); void setDebugLabel(const PassHandle &handle, const std::string &label); - void setDebugLabel(const PipelineHandle &handle, const std::string &label); + void setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label); + void setDebugLabel(const ComputePipelineHandle &handle, const std::string &label); void setDebugLabel(const DescriptorSetHandle &handle, const std::string &label); void setDebugLabel(const SamplerHandle &handle, const std::string &label); void setDebugLabel(const ImageHandle &handle, const std::string &label); diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index cf945d7498fec83f0b128294caa3ba267b69a6b3..600abc9e975ca9ed902fbc27c285315d0d6c0a9a 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -117,6 +117,10 @@ namespace vkcv { featureFunction(features); if (!checkSupport(features, required)) { + if (required) { + throw std::runtime_error("Required feature is not supported!"); + } + return false; } diff --git a/include/vkcv/PipelineConfig.hpp b/include/vkcv/GraphicsPipelineConfig.hpp similarity index 91% rename from include/vkcv/PipelineConfig.hpp rename to include/vkcv/GraphicsPipelineConfig.hpp index 5e6dbaa3306f8d2aa6fc44d7dd1fadd9b79be3b4..6d466c4aa3893049eb0b3e770c2e4dde6b6199e3 100644 --- a/include/vkcv/PipelineConfig.hpp +++ b/include/vkcv/GraphicsPipelineConfig.hpp @@ -1,8 +1,8 @@ #pragma once /** * @authors Mara Vogt, Mark Mints - * @file src/vkcv/Pipeline.hpp - * @brief Pipeline class to handle shader stages + * @file src/vkcv/PipelineConfig.hpp + * @brief Graphics Pipeline Config Struct to hand over required information to Pipeline Creation */ #include <vector> @@ -22,7 +22,7 @@ namespace vkcv { // alternatively we could expose the blend factors directly enum class BlendMode{ None, Additive }; - struct PipelineConfig { + struct GraphicsPipelineConfig { ShaderProgram m_ShaderProgram; uint32_t m_Width; uint32_t m_Height; diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index c68d4bd4b5c76add61e6cb0c236c4e160f42fab2..1e6091c97dbe8dfc31013b653f175acede76070b 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -73,11 +73,17 @@ namespace vkcv using Handle::Handle; }; - class PipelineHandle : public Handle { - friend class PipelineManager; + class GraphicsPipelineHandle : public Handle { + friend class GraphicsPipelineManager; private: using Handle::Handle; }; + + class ComputePipelineHandle : public Handle { + friend class ComputePipelineManager; + private: + using Handle::Handle; + }; class DescriptorSetHandle : public Handle { friend class DescriptorManager; @@ -99,6 +105,7 @@ namespace vkcv class ImageHandle : public Handle { friend class ImageManager; + private: using Handle::Handle; public: [[nodiscard]] diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp index 0dfa7811f0a7cca9107676438c0c66ade4519828..095c5e278e9e3f76544e884bdb87cea10770307a 100644 --- a/modules/scene/include/vkcv/scene/Scene.hpp +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -58,7 +58,7 @@ namespace vkcv::scene { void recordDrawcalls(CommandStreamHandle &cmdStream, const camera::Camera &camera, const PassHandle &pass, - const PipelineHandle &pipeline, + const GraphicsPipelineHandle &pipeline, size_t pushConstantsSizePerDrawcall, const RecordMeshDrawcallFunction &record, const std::vector<ImageHandle> &renderTargets, diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index f4318f42ddd2a14b6f87eefdd46d20df5fc98c44..cd02004f56ea3dfddcd20618b7859a0699d92d71 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -112,7 +112,7 @@ namespace vkcv::scene { void Scene::recordDrawcalls(CommandStreamHandle &cmdStream, const camera::Camera &camera, const PassHandle &pass, - const PipelineHandle &pipeline, + const GraphicsPipelineHandle &pipeline, size_t pushConstantsSizePerDrawcall, const RecordMeshDrawcallFunction &record, const std::vector<ImageHandle> &renderTargets, diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp index 241544c79545384d14a2599fb718cd3992455705..4d3316718bf995f5cc8ccddde8c74575beba7745 100644 --- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp @@ -30,10 +30,12 @@ namespace vkcv::upscaling { class FSRUpscaling : public Upscaling { private: - PipelineHandle m_easuPipeline; - PipelineHandle m_rcasPipeline; + + ComputePipelineHandle m_easuPipeline; + ComputePipelineHandle m_rcasPipeline; DescriptorSetLayoutHandle m_easuDescriptorSetLayout; + DescriptorSetHandle m_easuDescriptorSet; DescriptorSetLayoutHandle m_rcasDescriptorSetLayout; diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp index 88436c148d711638554f82a0cfb7be2dc81c998e..e4aae60b595d50d7e859199079714e91f5e5a694 100644 --- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp +++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp @@ -1,4 +1,3 @@ - #include "vkcv/upscaling/FSRUpscaling.hpp" #include <stdint.h> @@ -226,13 +225,14 @@ namespace vkcv::upscaling { { ShaderProgram program; compileFSRShader(easuCompiler, [&program](vkcv::ShaderStage shaderStage, - const std::filesystem::path& path) { + const std::filesystem::path& path) { program.addShader(shaderStage, path); }); - - m_easuPipeline = m_core.createComputePipeline(program, { - m_core.getDescriptorSetLayout(m_easuDescriptorSetLayout).vulkanHandle + + m_easuPipeline = m_core.createComputePipeline({ program, + {m_core.getDescriptorSetLayout(m_easuDescriptorSetLayout).vulkanHandle} }); + DescriptorWrites writes; writes.uniformBufferWrites.emplace_back( @@ -250,11 +250,11 @@ namespace vkcv::upscaling { const std::filesystem::path& path) { program.addShader(shaderStage, path); }); - - m_rcasPipeline = m_core.createComputePipeline(program, { - m_core.getDescriptorSetLayout(m_rcasDescriptorSetLayout).vulkanHandle - }); - + + m_rcasPipeline = m_core.createComputePipeline({ program, { + m_core.getDescriptorSetLayout(m_rcasDescriptorSetLayout).vulkanHandle + }}); + DescriptorWrites writes; writes.uniformBufferWrites.emplace_back( 0, m_rcasConstants.getHandle(),true diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index e381cab6315bdb86a6c28ba0fa4b0a6388c50a38..5ef277dfedbfa823a2b6fa55c5a6303117ddaa52 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -109,7 +109,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(setLayoutHandle); - const vkcv::PipelineConfig firstMeshPipelineConfig { + const vkcv::GraphicsPipelineConfig firstMeshPipelineConfig { firstMeshProgram, UINT32_MAX, UINT32_MAX, @@ -118,7 +118,7 @@ int main(int argc, const char** argv) { { core.getDescriptorSetLayout(setLayoutHandle).vulkanHandle }, true }; - vkcv::PipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); + vkcv::GraphicsPipelineHandle firstMeshPipeline = core.createGraphicsPipeline(firstMeshPipelineConfig); if (!firstMeshPipeline) { std::cerr << "Error. Could not create graphics pipeline. Exiting." << std::endl; diff --git a/projects/first_scene/src/main.cpp b/projects/first_scene/src/main.cpp index cf238375c4107ecbc1fc7f587734d51a41255752..4891fecbf8e0fc5dee3f9930b477aa03115916d2 100644 --- a/projects/first_scene/src/main.cpp +++ b/projects/first_scene/src/main.cpp @@ -78,7 +78,7 @@ int main(int argc, const char** argv) { const auto& material0 = scene.getMaterial(0); - const vkcv::PipelineConfig scenePipelineDefinition{ + const vkcv::GraphicsPipelineConfig scenePipelineDefinition{ sceneShaderProgram, UINT32_MAX, UINT32_MAX, @@ -86,7 +86,7 @@ int main(int argc, const char** argv) { {sceneLayout}, { core.getDescriptorSetLayout(material0.getDescriptorSetLayout()).vulkanHandle }, true }; - vkcv::PipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition); + vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition); if (!scenePipeline) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index cad1a54a6de599ddc3d2c911a6deca53a634faab..1725b5c84dea931fe785880e3cd423cbb5f04a46 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -59,7 +59,7 @@ int main(int argc, const char** argv) { const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); - const vkcv::PipelineConfig trianglePipelineDefinition { + const vkcv::GraphicsPipelineConfig trianglePipelineDefinition { triangleShaderProgram, swapchainExtent.width, swapchainExtent.height, @@ -69,7 +69,7 @@ int main(int argc, const char** argv) { false }; - vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); + vkcv::GraphicsPipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); if (!trianglePipeline) { diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index 8b2db80a002a520571c91aa157bde685203bd96a..d4afc61c7421bd45c773bbdbc3da796b868869d2 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -4,6 +4,21 @@ #include <vkcv/gui/GUI.hpp> #include <functional> +const char* MotionVectorVisualisationModeLabels[6] = { + "None", + "Full resolution", + "Max tile", + "Tile neighbourhood max", + "Min Tile", + "Tile neighbourhood min" +}; + +const char* MotionBlurModeLabels[3] = { + "Default", + "Disabled", + "Tile visualisation" +}; + App::App() : m_applicationName("Indirect Dispatch"), m_windowWidth(AppConfig::defaultWindowWidth), diff --git a/projects/indirect_dispatch/src/App.hpp b/projects/indirect_dispatch/src/App.hpp index 9c2d43bd762ecbaa57a27edd6dd6499edb3593af..a35c2342c4c90e39b089a7c33a73c3aa7ce8a83f 100644 --- a/projects/indirect_dispatch/src/App.hpp +++ b/projects/indirect_dispatch/src/App.hpp @@ -12,8 +12,8 @@ public: private: const char* m_applicationName; - int m_windowWidth; - int m_windowHeight; + uint32_t m_windowWidth; + uint32_t m_windowHeight; vkcv::Core m_core; vkcv::WindowHandle m_windowHandle; diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp index 729072cfabd2c7ac109b121ac4bc5e0304b9662e..e1b29ad5990d371535794fa72a1d80e2b653045b 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -131,7 +131,7 @@ bool loadGraphicPass( } - vkcv::PipelineConfig pipelineConfig{ + vkcv::GraphicsPipelineConfig pipelineConfig{ shaderProgram, UINT32_MAX, UINT32_MAX, @@ -258,9 +258,9 @@ bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, Comput outComputePass->descriptorSetLayout = core.createDescriptorSetLayout(shaderProgram.getReflectedDescriptors().at(0)); outComputePass->descriptorSet = core.createDescriptorSet(outComputePass->descriptorSetLayout); - outComputePass->pipeline = core.createComputePipeline( + outComputePass->pipeline = core.createComputePipeline({ shaderProgram, - { core.getDescriptorSetLayout(outComputePass->descriptorSetLayout).vulkanHandle }); + { core.getDescriptorSetLayout(outComputePass->descriptorSetLayout).vulkanHandle }}); if (!outComputePass->pipeline) { vkcv_log(vkcv::LogLevel::ERROR, "Compute shader pipeline creation failed"); diff --git a/projects/indirect_dispatch/src/AppSetup.hpp b/projects/indirect_dispatch/src/AppSetup.hpp index 162a6c6126f39adb85da7e419ef4e5b9793dc5ad..b0ade4317b125fea581016bf9924cd740a443c35 100644 --- a/projects/indirect_dispatch/src/AppSetup.hpp +++ b/projects/indirect_dispatch/src/AppSetup.hpp @@ -8,14 +8,14 @@ struct AppRenderTargets { }; struct GraphicPassHandles { - vkcv::PipelineHandle pipeline; + vkcv::GraphicsPipelineHandle pipeline; vkcv::PassHandle renderPass; vkcv::DescriptorSetLayoutHandle descriptorSetLayout; vkcv::DescriptorSetHandle descriptorSet; }; struct ComputePassHandles { - vkcv::PipelineHandle pipeline; + vkcv::ComputePipelineHandle pipeline; vkcv::DescriptorSetLayoutHandle descriptorSetLayout; vkcv::DescriptorSetHandle descriptorSet; }; @@ -33,10 +33,10 @@ bool loadImage(vkcv::Core& core, const std::filesystem::path& path, vkcv::ImageH bool loadGraphicPass( vkcv::Core& core, - const std::filesystem::path vertexPath, - const std::filesystem::path fragmentPath, + std::filesystem::path vertexPath, + std::filesystem::path fragmentPath, const vkcv::PassConfig& passConfig, - const vkcv::DepthTest depthTest, + vkcv::DepthTest depthTest, GraphicPassHandles* outPassHandles); bool loadMeshPass (vkcv::Core& core, GraphicPassHandles* outHandles); diff --git a/projects/indirect_dispatch/src/MotionBlur.hpp b/projects/indirect_dispatch/src/MotionBlur.hpp index b50f0af60d566dc0e4fc00c31b7b834e11679bf5..4e6003799237f69f4a422dd9c20f99255fe711fa 100644 --- a/projects/indirect_dispatch/src/MotionBlur.hpp +++ b/projects/indirect_dispatch/src/MotionBlur.hpp @@ -13,25 +13,12 @@ enum class eMotionVectorVisualisationMode : int { MinTileNeighbourhood = 5, OptionCount = 6 }; -static const char* MotionVectorVisualisationModeLabels[6] = { - "None", - "Full resolution", - "Max tile", - "Tile neighbourhood max", - "Min Tile", - "Tile neighbourhood min"}; - enum class eMotionBlurMode : int { Default = 0, Disabled = 1, TileVisualisation = 2, OptionCount = 3 }; -static const char* MotionBlurModeLabels[3] = { - "Default", - "Disabled", - "Tile visualisation" }; - class MotionBlur { public: diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp index 0bd279130f35d4c67fa61a1c00469ffa93c2bd5c..0ee16b99822e0c8fbeaf58af57f02255493b0fb5 100644 --- a/projects/mesh_shader/src/main.cpp +++ b/projects/mesh_shader/src/main.cpp @@ -205,7 +205,7 @@ int main(int argc, const char** argv) { auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); - const vkcv::PipelineConfig bunnyPipelineDefinition { + const vkcv::GraphicsPipelineConfig bunnyPipelineDefinition { bunnyShaderProgram, swapchainExtent.width, swapchainExtent.height, @@ -226,7 +226,7 @@ int main(int argc, const char** argv) { vertexShaderDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, matrixBuffer.getHandle()) }; core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites); - vkcv::PipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition); + vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition); if (!bunnyPipeline) { @@ -255,7 +255,7 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet(meshShaderDescriptorSetLayout); const vkcv::VertexLayout meshShaderLayout(bindings); - const vkcv::PipelineConfig meshShaderPipelineDefinition{ + const vkcv::GraphicsPipelineConfig meshShaderPipelineDefinition{ meshShaderProgram, swapchainExtent.width, swapchainExtent.height, @@ -265,7 +265,7 @@ int main(int argc, const char** argv) { false }; - vkcv::PipelineHandle meshShaderPipeline = core.createGraphicsPipeline(meshShaderPipelineDefinition); + vkcv::GraphicsPipelineHandle meshShaderPipeline = core.createGraphicsPipeline(meshShaderPipelineDefinition); if (!meshShaderPipeline) { diff --git a/projects/particle_simulation/src/BloomAndFlares.cpp b/projects/particle_simulation/src/BloomAndFlares.cpp index 68a553574eddd668f7c0360b91d4da448c5b8cf8..d0f25122c443eef847ce190c099eef95e8ecc0c8 100644 --- a/projects/particle_simulation/src/BloomAndFlares.cpp +++ b/projects/particle_simulation/src/BloomAndFlares.cpp @@ -36,8 +36,9 @@ BloomAndFlares::BloomAndFlares( m_DownsampleDescSets.push_back( p_Core->createDescriptorSet(m_DownsampleDescSetLayouts.back())); } - m_DownsamplePipe = p_Core->createComputePipeline( - dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }); + + m_DownsamplePipe = p_Core->createComputePipeline({ + dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }}); // UPSAMPLE vkcv::ShaderProgram usProg; @@ -54,8 +55,9 @@ BloomAndFlares::BloomAndFlares( m_UpsampleDescSets.push_back( p_Core->createDescriptorSet(m_UpsampleDescSetLayouts.back())); } - m_UpsamplePipe = p_Core->createComputePipeline( - usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }); + + m_UpsamplePipe = p_Core->createComputePipeline({ + usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }}); // LENS FEATURES vkcv::ShaderProgram lensProg; @@ -65,10 +67,11 @@ BloomAndFlares::BloomAndFlares( { lensProg.addShader(shaderStage, path); }); + m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0)); m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout); - m_LensFlarePipe = p_Core->createComputePipeline( - lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle }); + m_LensFlarePipe = p_Core->createComputePipeline({ + lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle }}); // COMPOSITE vkcv::ShaderProgram compProg; @@ -78,10 +81,11 @@ BloomAndFlares::BloomAndFlares( { compProg.addShader(shaderStage, path); }); + m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0)); m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout); - m_CompositePipe = p_Core->createComputePipeline( - compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle }); + m_CompositePipe = p_Core->createComputePipeline({ + compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle }}); } void BloomAndFlares::execDownsamplePipe(const vkcv::CommandStreamHandle &cmdStream, diff --git a/projects/particle_simulation/src/BloomAndFlares.hpp b/projects/particle_simulation/src/BloomAndFlares.hpp index 21f69f43511fabb920fd85c9e07f3fd0e5a355f3..2692034db51cf341e7ede2a26f5724c92dccbfed 100644 --- a/projects/particle_simulation/src/BloomAndFlares.hpp +++ b/projects/particle_simulation/src/BloomAndFlares.hpp @@ -24,20 +24,19 @@ private: vkcv::Image m_Blur; vkcv::Image m_LensFeatures; - - vkcv::PipelineHandle m_DownsamplePipe; + vkcv::ComputePipelineHandle m_DownsamplePipe; std::vector<vkcv::DescriptorSetLayoutHandle> m_DownsampleDescSetLayouts; std::vector<vkcv::DescriptorSetHandle> m_DownsampleDescSets; // per mip desc set - vkcv::PipelineHandle m_UpsamplePipe; + vkcv::ComputePipelineHandle m_UpsamplePipe; std::vector<vkcv::DescriptorSetLayoutHandle> m_UpsampleDescSetLayouts; std::vector<vkcv::DescriptorSetHandle> m_UpsampleDescSets; // per mip desc set - vkcv::PipelineHandle m_LensFlarePipe; + vkcv::ComputePipelineHandle m_LensFlarePipe; vkcv::DescriptorSetLayoutHandle m_LensFlareDescSetLayout; vkcv::DescriptorSetHandle m_LensFlareDescSet; - vkcv::PipelineHandle m_CompositePipe; + vkcv::ComputePipelineHandle m_CompositePipe; vkcv::DescriptorSetLayoutHandle m_CompositeDescSetLayout; vkcv::DescriptorSetHandle m_CompositeDescSet; diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index afb1c177805d5a06202c7d5a267ecf99e05bef6a..ddbe6195e66e78504d4bccb32b3b09ff680ab414 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -115,7 +115,7 @@ int main(int argc, const char **argv) { const vkcv::VertexLayout particleLayout(bindings); - vkcv::PipelineConfig particlePipelineDefinition{ + vkcv::GraphicsPipelineConfig particlePipelineDefinition{ particleShaderProgram, UINT32_MAX, UINT32_MAX, @@ -131,9 +131,9 @@ int main(int argc, const char **argv) { vertexBuffer.fill(vertices); - vkcv::PipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition); + vkcv::GraphicsPipelineHandle particlePipeline = core.createGraphicsPipeline(particlePipelineDefinition); - vkcv::PipelineHandle computePipeline = core.createComputePipeline(computeShaderProgram, {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} ); + vkcv::ComputePipelineHandle computePipeline = core.createComputePipeline({ computeShaderProgram, {core.getDescriptorSetLayout(computeDescriptorSetLayout).vulkanHandle} }); vkcv::Buffer<glm::vec4> color = core.createBuffer<glm::vec4>( vkcv::BufferType::UNIFORM, @@ -236,9 +236,9 @@ int main(int argc, const char **argv) { vkcv::DescriptorSetLayoutHandle tonemappingDescriptorLayout = core.createDescriptorSetLayout(tonemappingShader.getReflectedDescriptors().at(0)); vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout); - vkcv::PipelineHandle tonemappingPipe = core.createComputePipeline( + vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({ tonemappingShader, - { core.getDescriptorSetLayout(tonemappingDescriptorLayout).vulkanHandle }); + { core.getDescriptorSetLayout(tonemappingDescriptorLayout).vulkanHandle }}); std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; diff --git a/projects/voxelization/src/BloomAndFlares.cpp b/projects/voxelization/src/BloomAndFlares.cpp index 6a7eae3b90e83722a7a1c45ed95e96d4291b28ec..d47f61d0dc7fea4e38508b7b1d6c040595e2944a 100644 --- a/projects/voxelization/src/BloomAndFlares.cpp +++ b/projects/voxelization/src/BloomAndFlares.cpp @@ -49,8 +49,10 @@ BloomAndFlares::BloomAndFlares( ); m_DownsampleDescSets.push_back(p_Core->createDescriptorSet(m_DownsampleDescSetLayouts.back())); } - m_DownsamplePipe = p_Core->createComputePipeline( - dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle }); + + m_DownsamplePipe = p_Core->createComputePipeline({ + dsProg, { p_Core->getDescriptorSetLayout(m_DownsampleDescSetLayouts[0]).vulkanHandle } + }); // UPSAMPLE vkcv::ShaderProgram usProg; @@ -74,8 +76,9 @@ BloomAndFlares::BloomAndFlares( p_Core->createDescriptorSet(m_UpsampleLensFlareDescSetLayouts.back())); } - m_UpsamplePipe = p_Core->createComputePipeline( - usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle }); + m_UpsamplePipe = p_Core->createComputePipeline({ + usProg, { p_Core->getDescriptorSetLayout(m_UpsampleDescSetLayouts[0]).vulkanHandle } + }); // LENS FEATURES vkcv::ShaderProgram lensProg; @@ -85,10 +88,12 @@ BloomAndFlares::BloomAndFlares( { lensProg.addShader(shaderStage, path); }); + m_LensFlareDescSetLayout = p_Core->createDescriptorSetLayout(lensProg.getReflectedDescriptors().at(0)); m_LensFlareDescSet = p_Core->createDescriptorSet(m_LensFlareDescSetLayout); m_LensFlarePipe = p_Core->createComputePipeline( - lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle }); + { lensProg, { p_Core->getDescriptorSetLayout(m_LensFlareDescSetLayout).vulkanHandle } }); + // COMPOSITE vkcv::ShaderProgram compProg; @@ -102,7 +107,7 @@ BloomAndFlares::BloomAndFlares( m_CompositeDescSetLayout = p_Core->createDescriptorSetLayout(compProg.getReflectedDescriptors().at(0)); m_CompositeDescSet = p_Core->createDescriptorSet(m_CompositeDescSetLayout); m_CompositePipe = p_Core->createComputePipeline( - compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle }); + { compProg, { p_Core->getDescriptorSetLayout(m_CompositeDescSetLayout).vulkanHandle } }); // radial LUT const auto texture = vkcv::asset::loadTexture("assets/RadialLUT.png"); @@ -318,9 +323,9 @@ void BloomAndFlares::execCompositePipe(const vkcv::CommandStreamHandle &cmdStrea static_cast<uint32_t>(glm::ceil(dispatchCountY)), 1 }; - - vkcv::PushConstants pushConstants (sizeof(cameraForward)); - pushConstants.appendDrawcall(cameraForward); + + vkcv::PushConstants pushConstants(sizeof(cameraForward)); + pushConstants.appendDrawcall(cameraForward); // bloom composite dispatch p_Core->recordComputeDispatchToCmdStream( @@ -348,6 +353,4 @@ void BloomAndFlares::updateImageDimensions(uint32_t width, uint32_t height) p_Core->getContext().getDevice().waitIdle(); m_Blur = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false); m_LensFeatures = p_Core->createImage(m_ColorBufferFormat, m_Width, m_Height, 1, true, true, false); -} - - +} \ No newline at end of file diff --git a/projects/voxelization/src/BloomAndFlares.hpp b/projects/voxelization/src/BloomAndFlares.hpp index 133a82cbe85a2fd4fd9965874a36faa5369013b9..3d63d9f37b4733eaea170a3e4561774c0d53208b 100644 --- a/projects/voxelization/src/BloomAndFlares.hpp +++ b/projects/voxelization/src/BloomAndFlares.hpp @@ -29,22 +29,22 @@ private: vkcv::Image m_radialLut; vkcv::Image m_lensDirt; - vkcv::PipelineHandle m_DownsamplePipe; + vkcv::ComputePipelineHandle m_DownsamplePipe; std::vector<vkcv::DescriptorSetLayoutHandle> m_DownsampleDescSetLayouts; std::vector<vkcv::DescriptorSetHandle> m_DownsampleDescSets; // per mip desc set std::vector<vkcv::DescriptorSetLayoutHandle> m_UpsampleLensFlareDescSetLayouts; std::vector<vkcv::DescriptorSetHandle> m_UpsampleLensFlareDescSets; // per mip desc set - vkcv::PipelineHandle m_UpsamplePipe; + vkcv::ComputePipelineHandle m_UpsamplePipe; std::vector<vkcv::DescriptorSetLayoutHandle> m_UpsampleDescSetLayouts; std::vector<vkcv::DescriptorSetHandle> m_UpsampleDescSets; // per mip desc set - vkcv::PipelineHandle m_LensFlarePipe; + vkcv::ComputePipelineHandle m_LensFlarePipe; vkcv::DescriptorSetLayoutHandle m_LensFlareDescSetLayout; vkcv::DescriptorSetHandle m_LensFlareDescSet; - vkcv::PipelineHandle m_CompositePipe; + vkcv::ComputePipelineHandle m_CompositePipe; vkcv::DescriptorSetLayoutHandle m_CompositeDescSetLayout; vkcv::DescriptorSetHandle m_CompositeDescSet; diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp index 3f764618da0d3736dcd4cae212e95faeb834d68a..d8041c1e9935d148ded8fb1ca8f0e4d8b79fce71 100644 --- a/projects/voxelization/src/ShadowMapping.cpp +++ b/projects/voxelization/src/ShadowMapping.cpp @@ -166,7 +166,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert m_shadowMapPass = corePtr->createPass(shadowPassConfig); // pipeline - vkcv::PipelineConfig shadowPipeConfig{ + vkcv::GraphicsPipelineConfig shadowPipeConfig{ shadowShader, shadowMapResolution, shadowMapResolution, @@ -189,9 +189,10 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert // depth to moments vkcv::ShaderProgram depthToMomentsShader = loadDepthToMomentsShader(); + m_depthToMomentsDescriptorSetLayout = corePtr->createDescriptorSetLayout(depthToMomentsShader.getReflectedDescriptors().at(0)); m_depthToMomentsDescriptorSet = corePtr->createDescriptorSet(m_depthToMomentsDescriptorSetLayout); - m_depthToMomentsPipe = corePtr->createComputePipeline(depthToMomentsShader, { corePtr->getDescriptorSetLayout(m_depthToMomentsDescriptorSetLayout).vulkanHandle }); + m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { corePtr->getDescriptorSetLayout(m_depthToMomentsDescriptorSetLayout).vulkanHandle }}); vkcv::DescriptorWrites depthToMomentDescriptorWrites; depthToMomentDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) }; @@ -203,7 +204,7 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::ShaderProgram shadowBlurXShader = loadShadowBlurXShader(); m_shadowBlurXDescriptorSetLayout = corePtr->createDescriptorSetLayout(shadowBlurXShader.getReflectedDescriptors().at(0)); m_shadowBlurXDescriptorSet = corePtr->createDescriptorSet(m_shadowBlurXDescriptorSetLayout); - m_shadowBlurXPipe = corePtr->createComputePipeline(shadowBlurXShader, { corePtr->getDescriptorSetLayout(m_shadowBlurXDescriptorSetLayout).vulkanHandle }); + m_shadowBlurXPipe = corePtr->createComputePipeline({ shadowBlurXShader, { corePtr->getDescriptorSetLayout(m_shadowBlurXDescriptorSetLayout).vulkanHandle }}); vkcv::DescriptorWrites shadowBlurXDescriptorWrites; shadowBlurXDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) }; @@ -215,9 +216,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert vkcv::ShaderProgram shadowBlurYShader = loadShadowBlurYShader(); m_shadowBlurYDescriptorSetLayout = corePtr->createDescriptorSetLayout(shadowBlurYShader.getReflectedDescriptors().at(0)); m_shadowBlurYDescriptorSet = corePtr->createDescriptorSet(m_shadowBlurYDescriptorSetLayout); - m_shadowBlurYPipe = corePtr->createComputePipeline(shadowBlurYShader, { corePtr->getDescriptorSetLayout(m_shadowBlurYDescriptorSetLayout).vulkanHandle }); + m_shadowBlurYPipe = corePtr->createComputePipeline({ shadowBlurYShader, { corePtr->getDescriptorSetLayout(m_shadowBlurYDescriptorSetLayout).vulkanHandle }}); - vkcv::DescriptorWrites shadowBlurYDescriptorWrites; + vkcv::DescriptorWrites shadowBlurYDescriptorWrites; shadowBlurYDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) }; shadowBlurYDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) }; shadowBlurYDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) }; diff --git a/projects/voxelization/src/ShadowMapping.hpp b/projects/voxelization/src/ShadowMapping.hpp index 7f77b5bf8c35b2784dc58ec9ce664a0e32e640c0..7de83b800ce073f5541a889b87a7f0cd763ffa69 100644 --- a/projects/voxelization/src/ShadowMapping.hpp +++ b/projects/voxelization/src/ShadowMapping.hpp @@ -44,17 +44,17 @@ private: vkcv::Buffer<LightInfo> m_lightInfoBuffer; vkcv::PassHandle m_shadowMapPass; - vkcv::PipelineHandle m_shadowMapPipe; + vkcv::GraphicsPipelineHandle m_shadowMapPipe; - vkcv::PipelineHandle m_depthToMomentsPipe; + vkcv::ComputePipelineHandle m_depthToMomentsPipe; vkcv::DescriptorSetLayoutHandle m_depthToMomentsDescriptorSetLayout; vkcv::DescriptorSetHandle m_depthToMomentsDescriptorSet; - vkcv::PipelineHandle m_shadowBlurXPipe; + vkcv::ComputePipelineHandle m_shadowBlurXPipe; vkcv::DescriptorSetLayoutHandle m_shadowBlurXDescriptorSetLayout; vkcv::DescriptorSetHandle m_shadowBlurXDescriptorSet; - vkcv::PipelineHandle m_shadowBlurYPipe; + vkcv::ComputePipelineHandle m_shadowBlurYPipe; vkcv::DescriptorSetLayoutHandle m_shadowBlurYDescriptorSetLayout; vkcv::DescriptorSetHandle m_shadowBlurYDescriptorSet; }; \ No newline at end of file diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp index 783eb8b2edf4ad9310295a1f716ec3394c2b4c2e..3cbff0df84757fb370a0372ddd45a9df401d4b60 100644 --- a/projects/voxelization/src/Voxelization.cpp +++ b/projects/voxelization/src/Voxelization.cpp @@ -83,12 +83,12 @@ Voxelization::Voxelization( vkcv::SamplerHandle voxelSampler, vkcv::Multisampling msaa) : - m_corePtr(corePtr), - m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)), + m_corePtr(corePtr), m_voxelImageIntermediate(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)), + m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)), + m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)), m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)), - m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)), - m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){ + m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)) { const vkcv::ShaderProgram voxelizationShader = loadVoxelizationShader(); @@ -104,7 +104,7 @@ Voxelization::Voxelization( vkcv::DescriptorSetLayoutHandle dummyPerMeshDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(voxelizationShader.getReflectedDescriptors().at(1)); vkcv::DescriptorSetHandle dummyPerMeshDescriptorSet = m_corePtr->createDescriptorSet(dummyPerMeshDescriptorSetLayout); - const vkcv::PipelineConfig voxelizationPipeConfig{ + const vkcv::GraphicsPipelineConfig voxelizationPipeConfig{ voxelizationShader, voxelResolution, voxelResolution, @@ -150,7 +150,7 @@ Voxelization::Voxelization( voxelVisualisationPassDefinition.msaa = msaa; m_visualisationPass = m_corePtr->createPass(voxelVisualisationPassDefinition); - vkcv::PipelineConfig voxelVisualisationPipeConfig{ + vkcv::GraphicsPipelineConfig voxelVisualisationPipeConfig{ voxelVisualisationShader, 0, 0, @@ -164,8 +164,8 @@ Voxelization::Voxelization( m_visualisationPipe = m_corePtr->createGraphicsPipeline(voxelVisualisationPipeConfig); std::vector<uint16_t> voxelIndexData; - for (int i = 0; i < voxelCount; i++) { - voxelIndexData.push_back(i); + for (uint32_t i = 0; i < voxelCount; i++) { + voxelIndexData.push_back(static_cast<uint16_t>(i)); } const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle); @@ -174,9 +174,9 @@ Voxelization::Voxelization( m_voxelResetDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(resetVoxelShader.getReflectedDescriptors().at(0)); m_voxelResetDescriptorSet = m_corePtr->createDescriptorSet(m_voxelResetDescriptorSetLayout); - m_voxelResetPipe = m_corePtr->createComputePipeline( + m_voxelResetPipe = m_corePtr->createComputePipeline({ resetVoxelShader, - { m_corePtr->getDescriptorSetLayout(m_voxelResetDescriptorSetLayout).vulkanHandle }); + { m_corePtr->getDescriptorSetLayout(m_voxelResetDescriptorSetLayout).vulkanHandle }}); vkcv::DescriptorWrites resetVoxelWrites; resetVoxelWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; @@ -187,9 +187,9 @@ Voxelization::Voxelization( m_bufferToImageDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(bufferToImageShader.getReflectedDescriptors().at(0)); m_bufferToImageDescriptorSet = m_corePtr->createDescriptorSet(m_bufferToImageDescriptorSetLayout); - m_bufferToImagePipe = m_corePtr->createComputePipeline( + m_bufferToImagePipe = m_corePtr->createComputePipeline({ bufferToImageShader, - { m_corePtr->getDescriptorSetLayout(m_bufferToImageDescriptorSetLayout).vulkanHandle }); + { m_corePtr->getDescriptorSetLayout(m_bufferToImageDescriptorSetLayout).vulkanHandle }}); vkcv::DescriptorWrites bufferToImageDescriptorWrites; bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; @@ -201,9 +201,9 @@ Voxelization::Voxelization( m_secondaryBounceDescriptorSetLayout = m_corePtr->createDescriptorSetLayout(secondaryBounceShader.getReflectedDescriptors().at(0)); m_secondaryBounceDescriptorSet = m_corePtr->createDescriptorSet(m_secondaryBounceDescriptorSetLayout); - m_secondaryBouncePipe = m_corePtr->createComputePipeline( + m_secondaryBouncePipe = m_corePtr->createComputePipeline({ secondaryBounceShader, - { m_corePtr->getDescriptorSetLayout(m_secondaryBounceDescriptorSetLayout).vulkanHandle }); + { m_corePtr->getDescriptorSetLayout(m_secondaryBounceDescriptorSetLayout).vulkanHandle }}); vkcv::DescriptorWrites secondaryBounceDescriptorWrites; secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) }; diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp index b332cca0effec7b34f85b4fa83626658d986232a..d5f41123b527f2919dec678d0337ee25ea6fa2c6 100644 --- a/projects/voxelization/src/Voxelization.hpp +++ b/projects/voxelization/src/Voxelization.hpp @@ -57,22 +57,22 @@ private: vkcv::Image m_dummyRenderTarget; vkcv::PassHandle m_voxelizationPass; - vkcv::PipelineHandle m_voxelizationPipe; + vkcv::GraphicsPipelineHandle m_voxelizationPipe; vkcv::DescriptorSetLayoutHandle m_voxelizationDescriptorSetLayout; vkcv::DescriptorSetHandle m_voxelizationDescriptorSet; - vkcv::PipelineHandle m_voxelResetPipe; + vkcv::ComputePipelineHandle m_voxelResetPipe; vkcv::DescriptorSetLayoutHandle m_voxelResetDescriptorSetLayout; vkcv::DescriptorSetHandle m_voxelResetDescriptorSet; - vkcv::PipelineHandle m_bufferToImagePipe; + vkcv::ComputePipelineHandle m_bufferToImagePipe; vkcv::DescriptorSetLayoutHandle m_bufferToImageDescriptorSetLayout; vkcv::DescriptorSetHandle m_bufferToImageDescriptorSet; vkcv::PassHandle m_visualisationPass; - vkcv::PipelineHandle m_visualisationPipe; + vkcv::GraphicsPipelineHandle m_visualisationPipe; - vkcv::PipelineHandle m_secondaryBouncePipe; + vkcv::ComputePipelineHandle m_secondaryBouncePipe; vkcv::DescriptorSetLayoutHandle m_secondaryBounceDescriptorSetLayout; vkcv::DescriptorSetHandle m_secondaryBounceDescriptorSet; diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 1411e327216e1045847c66c7f40446a2ebbbb1bb..a7798813a52429d31f207ae24af6a3effb90c17c 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -300,7 +300,7 @@ int main(int argc, const char** argv) { auto swapchainExtent = core.getSwapchain(windowHandle).getExtent(); - vkcv::PipelineConfig prepassPipelineConfig{ + vkcv::GraphicsPipelineConfig prepassPipelineConfig{ depthPrepassShader, swapchainExtent.width, swapchainExtent.height, @@ -315,10 +315,10 @@ int main(int argc, const char** argv) { prepassPipelineConfig.m_depthTest = vkcv::DepthTest::LessEqual; prepassPipelineConfig.m_alphaToCoverage = true; - vkcv::PipelineHandle prepassPipeline = core.createGraphicsPipeline(prepassPipelineConfig); + vkcv::GraphicsPipelineHandle prepassPipeline = core.createGraphicsPipeline(prepassPipelineConfig); // forward pipeline - vkcv::PipelineConfig forwardPipelineConfig { + vkcv::GraphicsPipelineConfig forwardPipelineConfig { forwardProgram, swapchainExtent.width, swapchainExtent.height, @@ -334,7 +334,7 @@ int main(int argc, const char** argv) { forwardPipelineConfig.m_depthTest = vkcv::DepthTest::Equal; forwardPipelineConfig.m_depthWrite = false; - vkcv::PipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig); + vkcv::GraphicsPipelineHandle forwardPipeline = core.createGraphicsPipeline(forwardPipelineConfig); if (!forwardPipeline) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; @@ -373,7 +373,7 @@ int main(int argc, const char** argv) { skyShader.addShader(shaderStage, path); }); - vkcv::PipelineConfig skyPipeConfig; + vkcv::GraphicsPipelineConfig skyPipeConfig; skyPipeConfig.m_ShaderProgram = skyShader; skyPipeConfig.m_Width = swapchainExtent.width; skyPipeConfig.m_Height = swapchainExtent.height; @@ -384,7 +384,7 @@ int main(int argc, const char** argv) { skyPipeConfig.m_multisampling = msaa; skyPipeConfig.m_depthWrite = false; - vkcv::PipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig); + vkcv::GraphicsPipelineHandle skyPipe = core.createGraphicsPipeline(skyPipeConfig); // render targets vkcv::ImageHandle depthBuffer = core.createImage( @@ -451,12 +451,13 @@ int main(int argc, const char** argv) { [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { tonemappingProgram.addShader(shaderStage, path); }); + vkcv::DescriptorSetLayoutHandle tonemappingDescriptorSetLayout = core.createDescriptorSetLayout( tonemappingProgram.getReflectedDescriptors().at(0)); vkcv::DescriptorSetHandle tonemappingDescriptorSet = core.createDescriptorSet(tonemappingDescriptorSetLayout); - vkcv::PipelineHandle tonemappingPipeline = core.createComputePipeline( + vkcv::ComputePipelineHandle tonemappingPipeline = core.createComputePipeline({ tonemappingProgram, - { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }); + { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }}); // tonemapping compute shader vkcv::ShaderProgram postEffectsProgram; @@ -464,12 +465,13 @@ int main(int argc, const char** argv) { [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { postEffectsProgram.addShader(shaderStage, path); }); + vkcv::DescriptorSetLayoutHandle postEffectsDescriptorSetLayout = core.createDescriptorSetLayout( postEffectsProgram.getReflectedDescriptors().at(0)); vkcv::DescriptorSetHandle postEffectsDescriptorSet = core.createDescriptorSet(postEffectsDescriptorSetLayout); - vkcv::PipelineHandle postEffectsPipeline = core.createComputePipeline( + vkcv::ComputePipelineHandle postEffectsPipeline = core.createComputePipeline({ postEffectsProgram, - { core.getDescriptorSetLayout(postEffectsDescriptorSetLayout).vulkanHandle }); + { core.getDescriptorSetLayout(postEffectsDescriptorSetLayout).vulkanHandle }}); // resolve compute shader vkcv::ShaderProgram resolveProgram; @@ -477,12 +479,13 @@ int main(int argc, const char** argv) { [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { resolveProgram.addShader(shaderStage, path); }); + vkcv::DescriptorSetLayoutHandle resolveDescriptorSetLayout = core.createDescriptorSetLayout( - resolveProgram.getReflectedDescriptors().at(0)); + resolveProgram.getReflectedDescriptors().at(0)); vkcv::DescriptorSetHandle resolveDescriptorSet = core.createDescriptorSet(resolveDescriptorSetLayout); - vkcv::PipelineHandle resolvePipeline = core.createComputePipeline( + vkcv::ComputePipelineHandle resolvePipeline = core.createComputePipeline({ resolveProgram, - { core.getDescriptorSetLayout(resolveDescriptorSetLayout).vulkanHandle }); + { core.getDescriptorSetLayout(resolveDescriptorSetLayout).vulkanHandle }}); vkcv::SamplerHandle resolveSampler = core.createSampler( vkcv::SamplerFilterType::NEAREST, @@ -960,7 +963,7 @@ int main(int argc, const char** argv) { newForwardProgram.addShader(shaderStage, path); }); forwardPipelineConfig.m_ShaderProgram = newForwardProgram; - vkcv::PipelineHandle newPipeline = core.createGraphicsPipeline(forwardPipelineConfig); + vkcv::GraphicsPipelineHandle newPipeline = core.createGraphicsPipeline(forwardPipelineConfig); if (newPipeline) { forwardPipeline = newPipeline; @@ -973,9 +976,10 @@ int main(int argc, const char** argv) { [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { newProgram.addShader(shaderStage, path); }); - vkcv::PipelineHandle newPipeline = core.createComputePipeline( + + vkcv::ComputePipelineHandle newPipeline = core.createComputePipeline({ newProgram, - { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }); + { core.getDescriptorSetLayout(tonemappingDescriptorSetLayout).vulkanHandle }}); if (newPipeline) { tonemappingPipeline = newPipeline; diff --git a/src/vkcv/ComputePipelineManager.cpp b/src/vkcv/ComputePipelineManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f090b6dbe7e05f488958c072a758fbf2d2938ab5 --- /dev/null +++ b/src/vkcv/ComputePipelineManager.cpp @@ -0,0 +1,118 @@ +#include "ComputePipelineManager.hpp" + +namespace vkcv +{ + + ComputePipelineManager::ComputePipelineManager(vk::Device device) noexcept : + m_Device{device}, + m_Pipelines{} + {} + + ComputePipelineManager::~ComputePipelineManager() noexcept + { + for (uint64_t id = 0; id < m_Pipelines.size(); id++) { + destroyPipelineById(id); + } + } + + vk::Pipeline ComputePipelineManager::getVkPipeline(const ComputePipelineHandle &handle) const + { + const uint64_t id = handle.getId(); + + if (id >= m_Pipelines.size()) { + return nullptr; + } + + auto& pipeline = m_Pipelines[id]; + + return pipeline.m_handle; + } + + vk::PipelineLayout ComputePipelineManager::getVkPipelineLayout(const ComputePipelineHandle &handle) const + { + const uint64_t id = handle.getId(); + + if (id >= m_Pipelines.size()) { + return nullptr; + } + + auto& pipeline = m_Pipelines[id]; + + return pipeline.m_layout; + } + + ComputePipelineHandle ComputePipelineManager::createComputePipeline(const ComputePipelineConfig& config) { + + // Temporally handing over the Shader Program instead of a pipeline config + vk::ShaderModule computeModule{}; + if (createShaderModule(computeModule, config.m_ShaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess) + return ComputePipelineHandle(); + + vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo( + {}, + vk::ShaderStageFlagBits::eCompute, + computeModule, + "main", + nullptr + ); + + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, config.m_DescriptorSetLayouts); + + const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize(); + vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize); + if (pushConstantSize > 0) { + pipelineLayoutCreateInfo.setPushConstantRangeCount(1); + pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange); + } + + vk::PipelineLayout vkPipelineLayout{}; + if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != + vk::Result::eSuccess) { + m_Device.destroy(computeModule); + return ComputePipelineHandle(); + } + + vk::ComputePipelineCreateInfo computePipelineCreateInfo{}; + computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo; + computePipelineCreateInfo.layout = vkPipelineLayout; + + vk::Pipeline vkPipeline; + if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline) != + vk::Result::eSuccess) { + m_Device.destroy(computeModule); + return ComputePipelineHandle(); + } + + m_Device.destroy(computeModule); + + const uint64_t id = m_Pipelines.size(); + m_Pipelines.push_back({vkPipeline, vkPipelineLayout}); + + return ComputePipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); }); + } + + void vkcv::ComputePipelineManager::destroyPipelineById(uint64_t id) { + if (id >= m_Pipelines.size()) { + return; + } + + auto& pipeline = m_Pipelines[id]; + + if (pipeline.m_handle) { + m_Device.destroy(pipeline.m_handle); + pipeline.m_handle = nullptr; + } + + if (pipeline.m_layout) { + m_Device.destroy(pipeline.m_layout); + pipeline.m_layout = nullptr; + } + } + + vk::Result ComputePipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage) + { + std::vector<char> code = shaderProgram.getShader(stage).shaderCode; + vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data())); + return m_Device.createShaderModule(&moduleInfo, nullptr, &module); + } +} \ No newline at end of file diff --git a/src/vkcv/ComputePipelineManager.hpp b/src/vkcv/ComputePipelineManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..527243e6ec43850d416a7d929e01351454c40086 --- /dev/null +++ b/src/vkcv/ComputePipelineManager.hpp @@ -0,0 +1,72 @@ +#pragma once + +/** + * @authors Mark Mints + * @file src/vkcv/ComputePipelineManager.hpp + * @brief Creation and handling of Compute Pipelines + */ + +#include <vulkan/vulkan.hpp> +#include <vector> + +#include "vkcv/Handles.hpp" +#include "vkcv/ShaderProgram.hpp" +#include "vkcv/ComputePipelineConfig.hpp" + +namespace vkcv +{ + + class ComputePipelineManager + { + public: + ComputePipelineManager() = delete; // no default ctor + explicit ComputePipelineManager(vk::Device device) noexcept; // ctor + ~ComputePipelineManager() noexcept; // dtor + + ComputePipelineManager(const ComputePipelineManager &other) = delete; // copy-ctor + ComputePipelineManager(ComputePipelineManager &&other) = delete; // move-ctor; + + ComputePipelineManager & operator=(const ComputePipelineManager &other) = delete; // copy-assign op + ComputePipelineManager & operator=(ComputePipelineManager &&other) = delete; // move-assign op + + /** + * Returns a vk::Pipeline object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::Pipeline. + */ + [[nodiscard]] + vk::Pipeline getVkPipeline(const ComputePipelineHandle &handle) const; + + /** + * Returns a vk::PipelineLayout object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::PipelineLayout. + */ + [[nodiscard]] + vk::PipelineLayout getVkPipelineLayout(const ComputePipelineHandle &handle) const; + + /** + * Creates a Compute Pipeline based on the set shader stages in the Config Struct. + * This function is wrapped in /src/vkcv/Core.cpp by Core::createComputePipeline(const ComputePipelineConfig &config). + * On application level it is necessary first to fill a ComputePipelineConfig Struct. + * @param config Hands over all needed information for pipeline creation. + * @return A Handler to the created Compute Pipeline Object. + */ + ComputePipelineHandle createComputePipeline(const ComputePipelineConfig& config); + + private: + struct ComputePipeline { + vk::Pipeline m_handle; + vk::PipelineLayout m_layout; + }; + + vk::Device m_Device; + std::vector<ComputePipeline> m_Pipelines; + + void destroyPipelineById(uint64_t id); + + vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage); + + }; + +} diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index 906c6fe73c206048e5b06d03f3bf6a02ffdaf13b..01f6039eba5646bc99780415b7c41f0a02d65fe6 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -123,16 +123,17 @@ namespace vkcv /** * @brief All existing physical devices will be evaluated by deviceScore. * @param instance The instance - * @return The optimal physical device + * @param physicalDevice The optimal physical device + * @return Returns if a suitable GPU is found as physical device * @see Context.deviceScore */ - vk::PhysicalDevice pickPhysicalDevice(vk::Instance& instance) + bool pickPhysicalDevice(const vk::Instance& instance, vk::PhysicalDevice& physicalDevice) { - vk::PhysicalDevice phyDevice; - std::vector<vk::PhysicalDevice> devices = instance.enumeratePhysicalDevices(); + const std::vector<vk::PhysicalDevice>& devices = instance.enumeratePhysicalDevices(); if (devices.empty()) { - throw std::runtime_error("failed to find GPUs with Vulkan support!"); + vkcv_log(LogLevel::ERROR, "Failed to find GPUs with Vulkan support"); + return false; } int max_score = -1; @@ -140,15 +141,16 @@ namespace vkcv int score = deviceScore(device); if (score > max_score) { max_score = score; - phyDevice = device; + physicalDevice = device; } } if (max_score == -1) { - throw std::runtime_error("failed to find a suitable GPU!"); + vkcv_log(LogLevel::ERROR, "Failed to find a suitable GPU"); + return false; + } else { + return true; } - - return phyDevice; } /** @@ -260,7 +262,11 @@ namespace vkcv vk::Instance instance = vk::createInstance(instanceCreateInfo); std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices(); - vk::PhysicalDevice physicalDevice = pickPhysicalDevice(instance); + vk::PhysicalDevice physicalDevice; + + if (!pickPhysicalDevice(instance, physicalDevice)) { + throw std::runtime_error("Picking suitable GPU as physical device failed!"); + } FeatureManager featureManager (physicalDevice); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index ccbdf85f63cf5bc598d18511028ec1f154bf6fd2..21435c818451d1bea796b862cbb57ebeea8f0abd 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -8,7 +8,8 @@ #include "vkcv/Core.hpp" #include "PassManager.hpp" -#include "PipelineManager.hpp" +#include "GraphicsPipelineManager.hpp" +#include "ComputePipelineManager.hpp" #include "vkcv/BufferManager.hpp" #include "SamplerManager.hpp" #include "ImageManager.hpp" @@ -51,7 +52,8 @@ namespace vkcv Core::Core(Context &&context, const CommandResources& commandResources, const SyncResources& syncResources) noexcept : m_Context(std::move(context)), m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, - m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, + m_PipelineManager{std::make_unique<GraphicsPipelineManager>(m_Context.m_Device)}, + m_ComputePipelineManager{std::make_unique<ComputePipelineManager>(m_Context.m_Device)}, m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)), m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())}, m_SamplerManager(std::unique_ptr<SamplerManager>(new SamplerManager(m_Context.m_Device))), @@ -75,17 +77,15 @@ namespace vkcv destroyCommandResources(m_Context.getDevice(), m_CommandResources); destroySyncResources(m_Context.getDevice(), m_SyncResources); } - - PipelineHandle Core::createGraphicsPipeline(const PipelineConfig &config) + + GraphicsPipelineHandle Core::createGraphicsPipeline(const GraphicsPipelineConfig &config) { return m_PipelineManager->createPipeline(config, *m_PassManager); } - PipelineHandle Core::createComputePipeline( - const ShaderProgram &shaderProgram, - const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts) + ComputePipelineHandle Core::createComputePipeline(const ComputePipelineConfig &config) { - return m_PipelineManager->createComputePipeline(shaderProgram, descriptorSetLayouts); + return m_ComputePipelineManager->createComputePipeline(config); } PassHandle Core::createPass(const PassConfig &config) @@ -265,7 +265,7 @@ namespace vkcv void Core::recordDrawcallsToCmdStream( const CommandStreamHandle& cmdStreamHandle, const PassHandle& renderpassHandle, - const PipelineHandle pipelineHandle, + const GraphicsPipelineHandle &pipelineHandle, const PushConstants &pushConstantData, const std::vector<DrawcallInfo> &drawcalls, const std::vector<ImageHandle> &renderTargets, @@ -310,7 +310,7 @@ namespace vkcv cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); - const PipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle); + const GraphicsPipelineConfig &pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle); if (pipeConfig.m_UseDynamicViewport) { recordDynamicViewport(cmdBuffer, width, height); } @@ -333,7 +333,7 @@ namespace vkcv void Core::recordMeshShaderDrawcalls( const CommandStreamHandle& cmdStreamHandle, const PassHandle& renderpassHandle, - const PipelineHandle pipelineHandle, + const GraphicsPipelineHandle &pipelineHandle, const PushConstants& pushConstantData, const std::vector<MeshShaderDrawcall>& drawcalls, const std::vector<ImageHandle>& renderTargets, @@ -378,7 +378,7 @@ namespace vkcv cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); - const PipelineConfig& pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle); + const GraphicsPipelineConfig& pipeConfig = m_PipelineManager->getPipelineConfig(pipelineHandle); if (pipeConfig.m_UseDynamicViewport) { recordDynamicViewport(cmdBuffer, width, height); } @@ -407,16 +407,16 @@ namespace vkcv void Core::recordComputeDispatchToCmdStream( CommandStreamHandle cmdStreamHandle, - PipelineHandle computePipeline, + ComputePipelineHandle computePipeline, const uint32_t dispatchCount[3], const std::vector<DescriptorSetUsage>& descriptorSetUsages, const PushConstants& pushConstants) { auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { - const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline); + const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline); - cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline)); + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline)); for (const auto& usage : descriptorSetUsages) { cmdBuffer.bindDescriptorSets( vk::PipelineBindPoint::eCompute, @@ -485,7 +485,7 @@ namespace vkcv void Core::recordComputeIndirectDispatchToCmdStream( const CommandStreamHandle cmdStream, - const PipelineHandle computePipeline, + const ComputePipelineHandle computePipeline, const vkcv::BufferHandle buffer, const size_t bufferArgOffset, const std::vector<DescriptorSetUsage>& descriptorSetUsages, @@ -493,9 +493,9 @@ namespace vkcv auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) { - const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline); + const auto pipelineLayout = m_ComputePipelineManager->getVkPipelineLayout(computePipeline); - cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline)); + cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_ComputePipelineManager->getVkPipeline(computePipeline)); for (const auto& usage : descriptorSetUsages) { cmdBuffer.bindDescriptorSets( vk::PipelineBindPoint::eCompute, @@ -907,7 +907,7 @@ namespace vkcv ); } - void Core::setDebugLabel(const PipelineHandle &handle, const std::string &label) { + void Core::setDebugLabel(const GraphicsPipelineHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); return; @@ -923,6 +923,22 @@ namespace vkcv ); } + void Core::setDebugLabel(const ComputePipelineHandle &handle, const std::string &label) { + if (!handle) { + vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); + return; + } + + setDebugObjectLabel( + m_Context.getDevice(), + vk::ObjectType::ePipeline, + uint64_t(static_cast<VkPipeline>( + m_ComputePipelineManager->getVkPipeline(handle) + )), + label + ); + } + void Core::setDebugLabel(const DescriptorSetHandle &handle, const std::string &label) { if (!handle) { vkcv_log(LogLevel::WARNING, "Can't set debug label to invalid handle"); diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index 60e2b6622b36e170963ccc3c86dc6f9ac58f2761..b8d50c21c288735fa621d7d158493e0eb4fab4b0 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -49,7 +49,7 @@ namespace vkcv DescriptorSetLayoutHandle DescriptorManager::createDescriptorSetLayout(const DescriptorBindings &setBindingsMap) { - for (auto i = 0; i < m_DescriptorSetLayouts.size(); i++) + for (size_t i = 0; i < m_DescriptorSetLayouts.size(); i++) { if(m_DescriptorSetLayouts[i].descriptorBindings.size() != setBindingsMap.size()) continue; @@ -296,7 +296,7 @@ namespace vkcv } void DescriptorManager::destroyDescriptorSetLayoutById(uint64_t id) { - if (id >= m_DescriptorSets.size()) { + if (id >= m_DescriptorSetLayouts.size()) { vkcv_log(LogLevel::ERROR, "Invalid id"); return; } diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index 18307999bb28ed60791a801b952619eeeba51a53..cfe8464d3fe3d0eedda2182e8e678e93c13dbf7a 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -395,6 +395,10 @@ m_physicalDevice.getFeatures2(&query) extension.c_str()); delete[] clone; + if (required) { + throw std::runtime_error("Required extension is not supported!"); + } + return false; } diff --git a/src/vkcv/GraphicsPipelineManager.cpp b/src/vkcv/GraphicsPipelineManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb7dd31dddd3a5c0742f95e8429175724aa26454 --- /dev/null +++ b/src/vkcv/GraphicsPipelineManager.cpp @@ -0,0 +1,681 @@ +#include "GraphicsPipelineManager.hpp" +#include "vkcv/Image.hpp" +#include "vkcv/Logger.hpp" + +namespace vkcv +{ + + GraphicsPipelineManager::GraphicsPipelineManager(vk::Device device) noexcept : + m_Device{device}, + m_Pipelines{} + {} + + GraphicsPipelineManager::~GraphicsPipelineManager() noexcept + { + for (uint64_t id = 0; id < m_Pipelines.size(); id++) { + destroyPipelineById(id); + } + } + + // currently assuming default 32 bit formats, no lower precision or normalized variants supported + vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) { + switch (format) { + case VertexAttachmentFormat::FLOAT: + return vk::Format::eR32Sfloat; + case VertexAttachmentFormat::FLOAT2: + return vk::Format::eR32G32Sfloat; + case VertexAttachmentFormat::FLOAT3: + return vk::Format::eR32G32B32Sfloat; + case VertexAttachmentFormat::FLOAT4: + return vk::Format::eR32G32B32A32Sfloat; + case VertexAttachmentFormat::INT: + return vk::Format::eR32Sint; + case VertexAttachmentFormat::INT2: + return vk::Format::eR32G32Sint; + case VertexAttachmentFormat::INT3: + return vk::Format::eR32G32B32Sint; + case VertexAttachmentFormat::INT4: + return vk::Format::eR32G32B32A32Sint; + default: + vkcv_log(LogLevel::WARNING, "Unknown vertex format"); + return vk::Format::eUndefined; + } + } + + vk::PrimitiveTopology primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) { + switch (topology) { + case(PrimitiveTopology::PointList): + return vk::PrimitiveTopology::ePointList; + case(PrimitiveTopology::LineList): + return vk::PrimitiveTopology::eLineList; + case(PrimitiveTopology::TriangleList): + return vk::PrimitiveTopology::eTriangleList; + default: + vkcv_log(LogLevel::ERROR, "Unknown primitive topology type"); + return vk::PrimitiveTopology::eTriangleList; + } + } + + vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) { + switch (depthTest) { + case(DepthTest::None): + return vk::CompareOp::eAlways; + case(DepthTest::Less): + return vk::CompareOp::eLess; + case(DepthTest::LessEqual): + return vk::CompareOp::eLessOrEqual; + case(DepthTest::Greater): + return vk::CompareOp::eGreater; + case(DepthTest::GreatherEqual): + return vk::CompareOp::eGreaterOrEqual; + case(DepthTest::Equal): + return vk::CompareOp::eEqual; + default: + vkcv_log(LogLevel::ERROR, "Unknown depth test enum"); + return vk::CompareOp::eAlways; + } + } + + vk::ShaderStageFlagBits shaderStageToVkShaderStage(ShaderStage stage) { + switch (stage) { + case ShaderStage::VERTEX: + return vk::ShaderStageFlagBits::eVertex; + case ShaderStage::FRAGMENT: + return vk::ShaderStageFlagBits::eFragment; + case ShaderStage::GEOMETRY: + return vk::ShaderStageFlagBits::eGeometry; + case ShaderStage::TESS_CONTROL: + return vk::ShaderStageFlagBits::eTessellationControl; + case ShaderStage::TESS_EVAL: + return vk::ShaderStageFlagBits::eTessellationEvaluation; + case ShaderStage::COMPUTE: + return vk::ShaderStageFlagBits::eCompute; + case ShaderStage::TASK: + return vk::ShaderStageFlagBits::eTaskNV; + case ShaderStage::MESH: + return vk::ShaderStageFlagBits::eMeshNV; + default: + vkcv_log(LogLevel::ERROR, "Unknown shader stage"); + return vk::ShaderStageFlagBits::eAll; + } + } + + bool createPipelineShaderStageCreateInfo( + const ShaderProgram& shaderProgram, + ShaderStage stage, + vk::Device device, + vk::PipelineShaderStageCreateInfo* outCreateInfo) { + + assert(outCreateInfo); + std::vector<char> code = shaderProgram.getShader(stage).shaderCode; + vk::ShaderModuleCreateInfo vertexModuleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data())); + vk::ShaderModule shaderModule; + if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess) + return false; + + const static auto entryName = "main"; + + *outCreateInfo = vk::PipelineShaderStageCreateInfo( + {}, + shaderStageToVkShaderStage(stage), + shaderModule, + entryName, + nullptr); + return true; + } + + /** + * Fills Vertex Attribute and Binding Description with the corresponding objects form the Vertex Layout. + * @param vertexAttributeDescriptions + * @param vertexBindingDescriptions + * @param existsVertexShader + * @param config + */ + void fillVertexInputDescription( + std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, + std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions, + const bool existsVertexShader, + const GraphicsPipelineConfig &config) { + + if (existsVertexShader) { + const VertexLayout& layout = config.m_VertexLayout; + + // iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer + for (const auto& vertexBinding : layout.vertexBindings) + { + vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation, + vertexBinding.stride, + vk::VertexInputRate::eVertex); + + // iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex + for (const auto& vertexAttachment : vertexBinding.vertexAttachments) + { + vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation, + vertexBinding.bindingLocation, + vertexFormatToVulkanFormat(vertexAttachment.format), + vertexAttachment.offset % vertexBinding.stride); + } + } + } + } + + /** + * Creates a Pipeline Vertex Input State Create Info Struct and fills it with Attribute and Binding data. + * @param vertexAttributeDescriptions + * @param vertexBindingDescriptions + * @return Pipeline Vertex Input State Create Info Struct + */ + vk::PipelineVertexInputStateCreateInfo createPipelineVertexInputStateCreateInfo( + std::vector<vk::VertexInputAttributeDescription> &vertexAttributeDescriptions, + std::vector<vk::VertexInputBindingDescription> &vertexBindingDescriptions) { + + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo( + {}, + vertexBindingDescriptions.size(), + vertexBindingDescriptions.data(), + vertexAttributeDescriptions.size(), + vertexAttributeDescriptions.data() + ); + return pipelineVertexInputStateCreateInfo; + } + + /** + * Creates a Pipeline Input Assembly State Create Info Struct with 'Primitive Restart' disabled. + * @param config provides data for primitive topology. + * @return Pipeline Input Assembly State Create Info Struct + */ + vk::PipelineInputAssemblyStateCreateInfo createPipelineInputAssemblyStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo( + {}, + primitiveTopologyToVulkanPrimitiveTopology(config.m_PrimitiveTopology), + false + ); + + return pipelineInputAssemblyStateCreateInfo; + } + + /** + * Creates a Pipeline Viewport State Create Info Struct with default set viewport and scissor settings. + * @param config provides with and height of the output window + * @return Pipeline Viewport State Create Info Struct + */ + vk::PipelineViewportStateCreateInfo createPipelineViewportStateCreateInfo(const GraphicsPipelineConfig &config) { + static vk::Viewport viewport; + static vk::Rect2D scissor; + + viewport = vk::Viewport( + 0.f, 0.f, + static_cast<float>(config.m_Width), + static_cast<float>(config.m_Height), + 0.f, 1.f + ); + + scissor = vk::Rect2D( + { 0,0 }, + { config.m_Width, config.m_Height } + ); + + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo( + {}, + 1, + &viewport, + 1, + &scissor + ); + + return pipelineViewportStateCreateInfo; + } + + /** + * Creates a Pipeline Rasterization State Create Info Struct with default values set to: + * Rasterizer Discard: Disabled + * Polygon Mode: Fill + * Front Face: Counter Clockwise + * Depth Bias: Disabled + * Line Width: 1.0 + * Depth Clamping and Culling Mode ist set by the Pipeline Config + * @param config sets Depth Clamping and Culling Mode + * @return Pipeline Rasterization State Create Info Struct + */ + vk::PipelineRasterizationStateCreateInfo createPipelineRasterizationStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::CullModeFlags cullMode; + switch (config.m_culling) { + case CullMode::None: + cullMode = vk::CullModeFlagBits::eNone; + break; + case CullMode::Front: + cullMode = vk::CullModeFlagBits::eFront; + break; + case CullMode::Back: + cullMode = vk::CullModeFlagBits::eBack; + break; + default: + vkcv_log(LogLevel::ERROR, "Unknown CullMode"); + cullMode = vk::CullModeFlagBits::eNone; + } + + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo ( + {}, + config.m_EnableDepthClamping, + false, + vk::PolygonMode::eFill, + cullMode, + vk::FrontFace::eCounterClockwise, + false, + 0.f, + 0.f, + 0.f, + 1.f + ); + + static vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization; + + if (config.m_UseConservativeRasterization) { + conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT( + {}, + vk::ConservativeRasterizationModeEXT::eOverestimate, + 0.f + ); + + pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization; + } + + return pipelineRasterizationStateCreateInfo; + } + + /** + * Creates a Pipeline Multisample State Create Info Struct. + * @param config set MSAA Sample Count Flag + * @return Pipeline Multisample State Create Info Struct + */ + vk::PipelineMultisampleStateCreateInfo createPipelineMultisampleStateCreateInfo(const GraphicsPipelineConfig &config) { + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( + {}, + msaaToVkSampleCountFlag(config.m_multisampling), + false, + 0.f, + nullptr, + config.m_alphaToCoverage, + false + ); + + return pipelineMultisampleStateCreateInfo; + } + + /** + * Creates a Pipeline Color Blend State Create Info Struct. + * Currently only one blend mode is supported! There for, blending is set to additive. + * @param config sets blend mode + * @return + */ + vk::PipelineColorBlendStateCreateInfo createPipelineColorBlendStateCreateInfo(const GraphicsPipelineConfig &config) { + // currently set to additive, if not disabled + // BlendFactors must be set as soon as additional BlendModes are added + static vk::PipelineColorBlendAttachmentState colorBlendAttachmentState ( + config.m_blendMode != BlendMode::None, + vk::BlendFactor::eOne, + vk::BlendFactor::eOne, + vk::BlendOp::eAdd, + vk::BlendFactor::eOne, + vk::BlendFactor::eOne, + vk::BlendOp::eAdd, + vk::ColorComponentFlags( + VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT + ) + ); + + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( + {}, + false, + vk::LogicOp::eClear, + 1, //TODO: hardcoded to one + &colorBlendAttachmentState, + { 1.f,1.f,1.f,1.f } + ); + + return pipelineColorBlendStateCreateInfo; + } + + /** + * Creates a Pipeline Layout Create Info Struct. + * @param config sets Push Constant Size and Descriptor Layouts. + * @return Pipeline Layout Create Info Struct + */ + vk::PipelineLayoutCreateInfo createPipelineLayoutCreateInfo(const GraphicsPipelineConfig &config) { + static vk::PushConstantRange pushConstantRange; + + const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize(); + pushConstantRange = vk::PushConstantRange( + vk::ShaderStageFlagBits::eAll, 0, pushConstantSize + ); + + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( + {}, + (config.m_DescriptorLayouts), + (pushConstantRange) + ); + + if (pushConstantSize == 0) { + pipelineLayoutCreateInfo.pushConstantRangeCount = 0; + } + + return pipelineLayoutCreateInfo; + } + + /** + * Creates a Pipeline Depth Stencil State Create Info Struct. + * @param config sets if depth test in enabled or not. + * @return Pipeline Layout Create Info Struct + */ + vk::PipelineDepthStencilStateCreateInfo createPipelineDepthStencilStateCreateInfo(const GraphicsPipelineConfig &config) { + const vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilCreateInfo( + vk::PipelineDepthStencilStateCreateFlags(), + config.m_depthTest != DepthTest::None, + config.m_depthWrite, + depthTestToVkCompareOp(config.m_depthTest), + false, + false, + {}, + {}, + 0.0f, + 1.0f + ); + + return pipelineDepthStencilCreateInfo; + } + + /** + * Creates a Pipeline Dynamic State Create Info Struct. + * @param config sets whenever a dynamic viewport is used or not. + * @return Pipeline Dynamic State Create Info Struct + */ + vk::PipelineDynamicStateCreateInfo createPipelineDynamicStateCreateInfo(const GraphicsPipelineConfig &config) { + static std::vector<vk::DynamicState> dynamicStates; + dynamicStates.clear(); + + if(config.m_UseDynamicViewport) { + dynamicStates.push_back(vk::DynamicState::eViewport); + dynamicStates.push_back(vk::DynamicState::eScissor); + } + + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo( + {}, + static_cast<uint32_t>(dynamicStates.size()), + dynamicStates.data() + ); + + return dynamicStateCreateInfo; + } + + GraphicsPipelineHandle GraphicsPipelineManager::createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager) { + const vk::RenderPass &pass = passManager.getVkPass(config.m_PassHandle); + + const bool existsTaskShader = config.m_ShaderProgram.existsShader(ShaderStage::TASK); + const bool existsMeshShader = config.m_ShaderProgram.existsShader(ShaderStage::MESH); + const bool existsVertexShader = config.m_ShaderProgram.existsShader(ShaderStage::VERTEX); + const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT); + const bool existsGeometryShader = config.m_ShaderProgram.existsShader(ShaderStage::GEOMETRY); + const bool validGeometryStages = existsVertexShader || (existsTaskShader && existsMeshShader); + + if (!validGeometryStages) + { + vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader"); + return GraphicsPipelineHandle(); + } + + if (!existsFragmentShader) { + vkcv_log(LogLevel::ERROR, "Requires fragment shader code"); + return GraphicsPipelineHandle(); + } + + std::vector<vk::PipelineShaderStageCreateInfo> shaderStages; + auto destroyShaderModules = [&shaderStages, this] { + for (auto stage : shaderStages) { + m_Device.destroyShaderModule(stage.module); + } + shaderStages.clear(); + }; + + if (existsVertexShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::VERTEX, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + if (existsTaskShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::TASK, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + if (existsMeshShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::MESH, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::FRAGMENT, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + if (existsGeometryShader) { + vk::PipelineShaderStageCreateInfo createInfo; + const bool success = createPipelineShaderStageCreateInfo( + config.m_ShaderProgram, + ShaderStage::GEOMETRY, + m_Device, + &createInfo); + + if (success) { + shaderStages.push_back(createInfo); + } + else { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + } + + // vertex input state + // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers + std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions; + std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions; + fillVertexInputDescription(vertexAttributeDescriptions, vertexBindingDescriptions, existsVertexShader, config); + + // Handover Containers to PipelineVertexInputStateCreateIngo Struct + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = + createPipelineVertexInputStateCreateInfo(vertexAttributeDescriptions, + vertexBindingDescriptions); + + // input assembly state + vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = + createPipelineInputAssemblyStateCreateInfo(config); + + // viewport state + vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = + createPipelineViewportStateCreateInfo(config); + + // rasterization state + vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = + createPipelineRasterizationStateCreateInfo(config); + + // multisample state + vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = + createPipelineMultisampleStateCreateInfo(config); + + // color blend state + vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = + createPipelineColorBlendStateCreateInfo(config); + + // Dynamic State + vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo = + createPipelineDynamicStateCreateInfo(config); + + // pipeline layout + vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = + createPipelineLayoutCreateInfo(config); + + vk::PipelineLayout vkPipelineLayout{}; + if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) { + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + + // Depth Stencil + const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo = + createPipelineDepthStencilStateCreateInfo(config); + + const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr; + const PassConfig& passConfig = passManager.getPassConfig(config.m_PassHandle); + + for (const auto& attachment : passConfig.attachments) { + if (isDepthFormat(attachment.format)) { + p_depthStencilCreateInfo = &depthStencilCreateInfo; + break; + } + } + + // Get all setting structs together and create the Pipeline + const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( + {}, + static_cast<uint32_t>(shaderStages.size()), + shaderStages.data(), + &pipelineVertexInputStateCreateInfo, + &pipelineInputAssemblyStateCreateInfo, + nullptr, + &pipelineViewportStateCreateInfo, + &pipelineRasterizationStateCreateInfo, + &pipelineMultisampleStateCreateInfo, + p_depthStencilCreateInfo, + &pipelineColorBlendStateCreateInfo, + &dynamicStateCreateInfo, + vkPipelineLayout, + pass, + 0, + {}, + 0 + ); + + vk::Pipeline vkPipeline{}; + if (m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess) + { + // Catch runtime error if the creation of the pipeline fails. + // Destroy everything to keep the memory clean. + destroyShaderModules(); + return GraphicsPipelineHandle(); + } + + // Clean Up + destroyShaderModules(); + + // Hand over Handler to main Application + const uint64_t id = m_Pipelines.size(); + m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, config }); + return GraphicsPipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); }); + } + + vk::Pipeline GraphicsPipelineManager::getVkPipeline(const GraphicsPipelineHandle &handle) const + { + const uint64_t id = handle.getId(); + + if (id >= m_Pipelines.size()) { + return nullptr; + } + + auto& pipeline = m_Pipelines[id]; + + return pipeline.m_handle; + } + + vk::PipelineLayout GraphicsPipelineManager::getVkPipelineLayout(const GraphicsPipelineHandle &handle) const + { + const uint64_t id = handle.getId(); + + if (id >= m_Pipelines.size()) { + return nullptr; + } + + auto& pipeline = m_Pipelines[id]; + + return pipeline.m_layout; + } + + void GraphicsPipelineManager::destroyPipelineById(uint64_t id) { + if (id >= m_Pipelines.size()) { + return; + } + + auto& pipeline = m_Pipelines[id]; + + if (pipeline.m_handle) { + m_Device.destroy(pipeline.m_handle); + pipeline.m_handle = nullptr; + } + + if (pipeline.m_layout) { + m_Device.destroy(pipeline.m_layout); + pipeline.m_layout = nullptr; + } + } + + const GraphicsPipelineConfig& GraphicsPipelineManager::getPipelineConfig(const GraphicsPipelineHandle &handle) const + { + const uint64_t id = handle.getId(); + + if (id >= m_Pipelines.size()) { + static GraphicsPipelineConfig dummyConfig; + vkcv_log(LogLevel::ERROR, "Invalid handle"); + return dummyConfig; + } + + return m_Pipelines[id].m_config; + } +} diff --git a/src/vkcv/GraphicsPipelineManager.hpp b/src/vkcv/GraphicsPipelineManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a08e64939dc967511095f22862c52de05148d7e9 --- /dev/null +++ b/src/vkcv/GraphicsPipelineManager.hpp @@ -0,0 +1,80 @@ +#pragma once + +/** + * @authors Mark Mints + * @file src/vkcv/PipelineManager.hpp + * @brief Creation and handling of Graphic Pipelines + */ +// TODO: Edit @brief: add graphics pipeline, but only then when the compute part is in an own class. +// TODO: More authors? Do we need authors (general question)? + +#include <vulkan/vulkan.hpp> +#include <vector> +#include "vkcv/Handles.hpp" +#include "vkcv/GraphicsPipelineConfig.hpp" +#include "PassManager.hpp" + +namespace vkcv +{ + class GraphicsPipelineManager + { + public: + GraphicsPipelineManager() = delete; // no default ctor + explicit GraphicsPipelineManager(vk::Device device) noexcept; // ctor + ~GraphicsPipelineManager() noexcept; // dtor + + GraphicsPipelineManager(const GraphicsPipelineManager &other) = delete; // copy-ctor + GraphicsPipelineManager(GraphicsPipelineManager &&other) = delete; // move-ctor; + + GraphicsPipelineManager & operator=(const GraphicsPipelineManager &other) = delete; // copy-assign op + GraphicsPipelineManager & operator=(GraphicsPipelineManager &&other) = delete; // move-assign op + + /** + * Creates a Graphics Pipeline based on the set shader stages in the Config Struct. + * This function is wrapped in /src/vkcv/Core.cpp by Core::createGraphicsPipeline(const PipelineConfig &config). + * Therefore the passManager is filled already by the overall context of an application. + * On application level it is necessary first to fill a PipelineConfig Struct. + * @param config Hands over all needed information for pipeline creation. + * @param passManager Hands over the corresponding render pass. + * @return A Handler to the created Graphics Pipeline Object. + */ + GraphicsPipelineHandle createPipeline(const GraphicsPipelineConfig &config, PassManager& passManager); + + /** + * Returns a vk::Pipeline object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::Pipeline. + */ + [[nodiscard]] + vk::Pipeline getVkPipeline(const GraphicsPipelineHandle &handle) const; + + /** + * Returns a vk::PipelineLayout object by handle. + * @param handle Directing to the requested pipeline. + * @return vk::PipelineLayout. + */ + [[nodiscard]] + vk::PipelineLayout getVkPipelineLayout(const GraphicsPipelineHandle &handle) const; + + /** + * Returns the corresponding Pipeline Config Struct of a pipeline object directed by the given Handler. + * @param handle Directing to the requested pipeline. + * @return Pipeline Config Struct + */ + [[nodiscard]] + const GraphicsPipelineConfig &getPipelineConfig(const GraphicsPipelineHandle &handle) const; + + private: + struct GraphicsPipeline { + vk::Pipeline m_handle; + vk::PipelineLayout m_layout; + GraphicsPipelineConfig m_config; + }; + + vk::Device m_Device; + std::vector<GraphicsPipeline> m_Pipelines; + + void destroyPipelineById(uint64_t id); + + }; +} diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp index e50f800a482460cdb81687c76f8b1318598f689c..5eb727c75f9ec7e6f4cc3fa8fd8118a1a05f036f 100644 --- a/src/vkcv/PassManager.cpp +++ b/src/vkcv/PassManager.cpp @@ -3,26 +3,6 @@ namespace vkcv { - static vk::ImageLayout getVkLayoutFromAttachLayout(AttachmentLayout layout) - { - switch(layout) - { - case AttachmentLayout::GENERAL: - return vk::ImageLayout::eGeneral; - case AttachmentLayout::COLOR_ATTACHMENT: - return vk::ImageLayout::eColorAttachmentOptimal; - case AttachmentLayout::SHADER_READ_ONLY: - return vk::ImageLayout::eShaderReadOnlyOptimal; - case AttachmentLayout::DEPTH_STENCIL_ATTACHMENT: - return vk::ImageLayout::eDepthStencilAttachmentOptimal; - case AttachmentLayout::DEPTH_STENCIL_READ_ONLY: - return vk::ImageLayout::eDepthStencilReadOnlyOptimal; - case AttachmentLayout::PRESENTATION: - return vk::ImageLayout::ePresentSrcKHR; - default: - return vk::ImageLayout::eUndefined; - } - } static vk::AttachmentStoreOp getVkStoreOpFromAttachOp(AttachmentOperation op) { diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp deleted file mode 100644 index 244f6723f70e5ea938c005b74b286e192d68443c..0000000000000000000000000000000000000000 --- a/src/vkcv/PipelineManager.cpp +++ /dev/null @@ -1,548 +0,0 @@ -#include "PipelineManager.hpp" -#include "vkcv/Image.hpp" -#include "vkcv/Logger.hpp" - -namespace vkcv -{ - - PipelineManager::PipelineManager(vk::Device device) noexcept : - m_Device{device}, - m_Pipelines{} - {} - - PipelineManager::~PipelineManager() noexcept - { - for (uint64_t id = 0; id < m_Pipelines.size(); id++) { - destroyPipelineById(id); - } - } - - // currently assuming default 32 bit formats, no lower precision or normalized variants supported - vk::Format vertexFormatToVulkanFormat(const VertexAttachmentFormat format) { - switch (format) { - case VertexAttachmentFormat::FLOAT: - return vk::Format::eR32Sfloat; - case VertexAttachmentFormat::FLOAT2: - return vk::Format::eR32G32Sfloat; - case VertexAttachmentFormat::FLOAT3: - return vk::Format::eR32G32B32Sfloat; - case VertexAttachmentFormat::FLOAT4: - return vk::Format::eR32G32B32A32Sfloat; - case VertexAttachmentFormat::INT: - return vk::Format::eR32Sint; - case VertexAttachmentFormat::INT2: - return vk::Format::eR32G32Sint; - case VertexAttachmentFormat::INT3: - return vk::Format::eR32G32B32Sint; - case VertexAttachmentFormat::INT4: - return vk::Format::eR32G32B32A32Sint; - default: - vkcv_log(LogLevel::WARNING, "Unknown vertex format"); - return vk::Format::eUndefined; - } - } - - vk::PrimitiveTopology primitiveTopologyToVulkanPrimitiveTopology(const PrimitiveTopology topology) { - switch (topology) { - case(PrimitiveTopology::PointList): return vk::PrimitiveTopology::ePointList; - case(PrimitiveTopology::LineList): return vk::PrimitiveTopology::eLineList; - case(PrimitiveTopology::TriangleList): return vk::PrimitiveTopology::eTriangleList; - default: std::cout << "Error: Unknown primitive topology type" << std::endl; return vk::PrimitiveTopology::eTriangleList; - } - } - - vk::CompareOp depthTestToVkCompareOp(DepthTest depthTest) { - switch (depthTest) { - case(DepthTest::None): return vk::CompareOp::eAlways; - case(DepthTest::Less): return vk::CompareOp::eLess; - case(DepthTest::LessEqual): return vk::CompareOp::eLessOrEqual; - case(DepthTest::Greater): return vk::CompareOp::eGreater; - case(DepthTest::GreatherEqual): return vk::CompareOp::eGreaterOrEqual; - case(DepthTest::Equal): return vk::CompareOp::eEqual; - default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown depth test enum"); return vk::CompareOp::eAlways; - } - } - - vk::ShaderStageFlagBits shaderStageToVkShaderStage(vkcv::ShaderStage stage) { - switch (stage) { - case vkcv::ShaderStage::VERTEX: return vk::ShaderStageFlagBits::eVertex; - case vkcv::ShaderStage::FRAGMENT: return vk::ShaderStageFlagBits::eFragment; - case vkcv::ShaderStage::GEOMETRY: return vk::ShaderStageFlagBits::eGeometry; - case vkcv::ShaderStage::TESS_CONTROL: return vk::ShaderStageFlagBits::eTessellationControl; - case vkcv::ShaderStage::TESS_EVAL: return vk::ShaderStageFlagBits::eTessellationEvaluation; - case vkcv::ShaderStage::COMPUTE: return vk::ShaderStageFlagBits::eCompute; - case vkcv::ShaderStage::TASK: return vk::ShaderStageFlagBits::eTaskNV; - case vkcv::ShaderStage::MESH: return vk::ShaderStageFlagBits::eMeshNV; - default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown shader stage"); return vk::ShaderStageFlagBits::eAll; - } - } - - bool createPipelineShaderStageCreateInfo( - const vkcv::ShaderProgram& shaderProgram, - ShaderStage stage, - vk::Device device, - vk::PipelineShaderStageCreateInfo* outCreateInfo) { - - assert(outCreateInfo); - std::vector<char> code = shaderProgram.getShader(stage).shaderCode; - vk::ShaderModuleCreateInfo vertexModuleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data())); - vk::ShaderModule shaderModule; - if (device.createShaderModule(&vertexModuleInfo, nullptr, &shaderModule) != vk::Result::eSuccess) - return false; - - const static auto entryName = "main"; - - *outCreateInfo = vk::PipelineShaderStageCreateInfo( - {}, - shaderStageToVkShaderStage(stage), - shaderModule, - entryName, - nullptr); - return true; - } - - PipelineHandle PipelineManager::createPipeline(const PipelineConfig &config, PassManager& passManager) - { - const vk::RenderPass &pass = passManager.getVkPass(config.m_PassHandle); - - const bool existsTaskShader = config.m_ShaderProgram.existsShader(ShaderStage::TASK); - const bool existsMeshShader = config.m_ShaderProgram.existsShader(ShaderStage::MESH); - - const bool existsVertexShader = config.m_ShaderProgram.existsShader(ShaderStage::VERTEX); - - const bool validGeometryStages = existsVertexShader || (existsTaskShader && existsMeshShader); - - const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT); - if (!validGeometryStages) - { - vkcv_log(LogLevel::ERROR, "Requires vertex or task and mesh shader"); - return PipelineHandle(); - } - if (!existsFragmentShader) { - vkcv_log(LogLevel::ERROR, "Requires fragment shader code"); - return PipelineHandle(); - } - - std::vector<vk::PipelineShaderStageCreateInfo> shaderStages; - auto destroyShaderModules = [&shaderStages, this] { - for (auto stage : shaderStages) { - m_Device.destroyShaderModule(stage.module); - } - shaderStages.clear(); - }; - - if (existsVertexShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - config.m_ShaderProgram, - vkcv::ShaderStage::VERTEX, - m_Device, - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } - else { - destroyShaderModules(); - return PipelineHandle(); - } - } - - if (existsTaskShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - config.m_ShaderProgram, - vkcv::ShaderStage::TASK, - m_Device, - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } - else { - destroyShaderModules(); - return PipelineHandle(); - } - } - - if (existsMeshShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - config.m_ShaderProgram, - vkcv::ShaderStage::MESH, - m_Device, - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } - else { - destroyShaderModules(); - return PipelineHandle(); - } - } - - // fragment shader stage - { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - config.m_ShaderProgram, - vkcv::ShaderStage::FRAGMENT, - m_Device, - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } - else { - destroyShaderModules(); - return PipelineHandle(); - } - } - - // vertex input state - - // Fill up VertexInputBindingDescription and VertexInputAttributeDescription Containers - std::vector<vk::VertexInputAttributeDescription> vertexAttributeDescriptions; - std::vector<vk::VertexInputBindingDescription> vertexBindingDescriptions; - - if (existsVertexShader) { - const VertexLayout& layout = config.m_VertexLayout; - - // iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer - for (const auto& vertexBinding : layout.vertexBindings) - { - vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation, - vertexBinding.stride, - vk::VertexInputRate::eVertex); - - // iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex - for (const auto& vertexAttachment : vertexBinding.vertexAttachments) - { - vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation, - vertexBinding.bindingLocation, - vertexFormatToVulkanFormat(vertexAttachment.format), - vertexAttachment.offset % vertexBinding.stride); - - } - } - - } - - // Handover Containers to PipelineVertexInputStateCreateIngo Struct - vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo( - {}, - vertexBindingDescriptions.size(), - vertexBindingDescriptions.data(), - vertexAttributeDescriptions.size(), - vertexAttributeDescriptions.data() - ); - - // input assembly state - vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo( - {}, - primitiveTopologyToVulkanPrimitiveTopology(config.m_PrimitiveTopology), - false - ); - - // viewport state - vk::Viewport viewport(0.f, 0.f, static_cast<float>(config.m_Width), static_cast<float>(config.m_Height), 0.f, 1.f); - vk::Rect2D scissor({ 0,0 }, { config.m_Width, config.m_Height }); - vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo({}, 1, &viewport, 1, &scissor); - - vk::CullModeFlags cullMode; - switch (config.m_culling) { - case CullMode::None: cullMode = vk::CullModeFlagBits::eNone; break; - case CullMode::Front: cullMode = vk::CullModeFlagBits::eFront; break; - case CullMode::Back: cullMode = vk::CullModeFlagBits::eBack; break; - default: vkcv_log(vkcv::LogLevel::ERROR, "Unknown CullMode"); cullMode = vk::CullModeFlagBits::eNone; - } - - // rasterization state - vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo( - {}, - config.m_EnableDepthClamping, - false, - vk::PolygonMode::eFill, - cullMode, - vk::FrontFace::eCounterClockwise, - false, - 0.f, - 0.f, - 0.f, - 1.f - ); - vk::PipelineRasterizationConservativeStateCreateInfoEXT conservativeRasterization; - if (config.m_UseConservativeRasterization) { - conservativeRasterization = vk::PipelineRasterizationConservativeStateCreateInfoEXT( - {}, - vk::ConservativeRasterizationModeEXT::eOverestimate, - 0.f); - pipelineRasterizationStateCreateInfo.pNext = &conservativeRasterization; - } - - // multisample state - vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( - {}, - msaaToVkSampleCountFlag(config.m_multisampling), - false, - 0.f, - nullptr, - config.m_alphaToCoverage, - false - ); - - // color blend state - vk::ColorComponentFlags colorWriteMask(VK_COLOR_COMPONENT_R_BIT | - VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | - VK_COLOR_COMPONENT_A_BIT); - - // currently set to additive, if not disabled - // BlendFactors must be set as soon as additional BlendModes are added - vk::PipelineColorBlendAttachmentState colorBlendAttachmentState( - config.m_blendMode != BlendMode::None, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - vk::BlendFactor::eOne, - vk::BlendFactor::eOne, - vk::BlendOp::eAdd, - colorWriteMask - ); - vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo( - {}, - false, - vk::LogicOp::eClear, - 1, //TODO: hardcoded to one - &colorBlendAttachmentState, - { 1.f,1.f,1.f,1.f } - ); - - const size_t pushConstantSize = config.m_ShaderProgram.getPushConstantSize(); - const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, pushConstantSize); - - // pipeline layout - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( - {}, - (config.m_DescriptorLayouts), - (pushConstantRange)); - if (pushConstantSize == 0) { - pipelineLayoutCreateInfo.pushConstantRangeCount = 0; - } - - - vk::PipelineLayout vkPipelineLayout{}; - if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) - { - destroyShaderModules(); - return PipelineHandle(); - } - - const vk::PipelineDepthStencilStateCreateInfo depthStencilCreateInfo( - vk::PipelineDepthStencilStateCreateFlags(), - config.m_depthTest != DepthTest::None, - config.m_depthWrite, - depthTestToVkCompareOp(config.m_depthTest), - false, - false, - {}, - {}, - 0.0f, - 1.0f - ); - - const vk::PipelineDepthStencilStateCreateInfo* p_depthStencilCreateInfo = nullptr; - - const PassConfig& passConfig = passManager.getPassConfig(config.m_PassHandle); - - for (const auto& attachment : passConfig.attachments) { - if (isDepthFormat(attachment.format)) { - p_depthStencilCreateInfo = &depthStencilCreateInfo; - break; - } - } - - std::vector<vk::DynamicState> dynamicStates = {}; - if(config.m_UseDynamicViewport) - { - dynamicStates.push_back(vk::DynamicState::eViewport); - dynamicStates.push_back(vk::DynamicState::eScissor); - } - - vk::PipelineDynamicStateCreateInfo dynamicStateCreateInfo( - {}, - static_cast<uint32_t>(dynamicStates.size()), - dynamicStates.data()); - - const bool existsGeometryShader = config.m_ShaderProgram.existsShader(vkcv::ShaderStage::GEOMETRY); - if (existsGeometryShader) { - vk::PipelineShaderStageCreateInfo createInfo; - const bool success = createPipelineShaderStageCreateInfo( - config.m_ShaderProgram, - vkcv::ShaderStage::GEOMETRY, - m_Device, - &createInfo); - - if (success) { - shaderStages.push_back(createInfo); - } - else { - destroyShaderModules(); - return PipelineHandle(); - } - } - - const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( - {}, - static_cast<uint32_t>(shaderStages.size()), - shaderStages.data(), - &pipelineVertexInputStateCreateInfo, - &pipelineInputAssemblyStateCreateInfo, - nullptr, - &pipelineViewportStateCreateInfo, - &pipelineRasterizationStateCreateInfo, - &pipelineMultisampleStateCreateInfo, - p_depthStencilCreateInfo, - &pipelineColorBlendStateCreateInfo, - &dynamicStateCreateInfo, - vkPipelineLayout, - pass, - 0, - {}, - 0 - ); - - vk::Pipeline vkPipeline{}; - if (m_Device.createGraphicsPipelines(nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &vkPipeline) != vk::Result::eSuccess) - { - destroyShaderModules(); - return PipelineHandle(); - } - - destroyShaderModules(); - - const uint64_t id = m_Pipelines.size(); - m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, config }); - return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); }); - } - - vk::Pipeline PipelineManager::getVkPipeline(const PipelineHandle &handle) const - { - const uint64_t id = handle.getId(); - - if (id >= m_Pipelines.size()) { - return nullptr; - } - - auto& pipeline = m_Pipelines[id]; - - return pipeline.m_handle; - } - - vk::PipelineLayout PipelineManager::getVkPipelineLayout(const PipelineHandle &handle) const - { - const uint64_t id = handle.getId(); - - if (id >= m_Pipelines.size()) { - return nullptr; - } - - auto& pipeline = m_Pipelines[id]; - - return pipeline.m_layout; - } - - void PipelineManager::destroyPipelineById(uint64_t id) { - if (id >= m_Pipelines.size()) { - return; - } - - auto& pipeline = m_Pipelines[id]; - - if (pipeline.m_handle) { - m_Device.destroy(pipeline.m_handle); - pipeline.m_handle = nullptr; - } - - if (pipeline.m_layout) { - m_Device.destroy(pipeline.m_layout); - pipeline.m_layout = nullptr; - } - } - - const PipelineConfig& PipelineManager::getPipelineConfig(const PipelineHandle &handle) const - { - const uint64_t id = handle.getId(); - - if (id >= m_Pipelines.size()) { - static PipelineConfig dummyConfig; - vkcv_log(LogLevel::ERROR, "Invalid handle"); - return dummyConfig; - } - - return m_Pipelines[id].m_config; - } - - PipelineHandle PipelineManager::createComputePipeline( - const ShaderProgram &shaderProgram, - const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) { - - // Temporally handing over the Shader Program instead of a pipeline config - vk::ShaderModule computeModule{}; - if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess) - return PipelineHandle(); - - vk::PipelineShaderStageCreateInfo pipelineComputeShaderStageInfo( - {}, - vk::ShaderStageFlagBits::eCompute, - computeModule, - "main", - nullptr - ); - - vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts); - - const size_t pushConstantSize = shaderProgram.getPushConstantSize(); - vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize); - if (pushConstantSize > 0) { - pipelineLayoutCreateInfo.setPushConstantRangeCount(1); - pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange); - } - - vk::PipelineLayout vkPipelineLayout{}; - if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess) - { - m_Device.destroy(computeModule); - return PipelineHandle(); - } - - vk::ComputePipelineCreateInfo computePipelineCreateInfo{}; - computePipelineCreateInfo.stage = pipelineComputeShaderStageInfo; - computePipelineCreateInfo.layout = vkPipelineLayout; - - vk::Pipeline vkPipeline; - if (m_Device.createComputePipelines(nullptr, 1, &computePipelineCreateInfo, nullptr, &vkPipeline)!= vk::Result::eSuccess) - { - m_Device.destroy(computeModule); - return PipelineHandle(); - } - - m_Device.destroy(computeModule); - - const uint64_t id = m_Pipelines.size(); - m_Pipelines.push_back({ vkPipeline, vkPipelineLayout, PipelineConfig() }); - - return PipelineHandle(id, [&](uint64_t id) { destroyPipelineById(id); }); - } - - // There is an issue for refactoring the Pipeline Manager. - // While including Compute Pipeline Creation, some private helper functions where introduced: - - vk::Result PipelineManager::createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, const ShaderStage stage) - { - std::vector<char> code = shaderProgram.getShader(stage).shaderCode; - vk::ShaderModuleCreateInfo moduleInfo({}, code.size(), reinterpret_cast<uint32_t*>(code.data())); - return m_Device.createShaderModule(&moduleInfo, nullptr, &module); - } -} diff --git a/src/vkcv/PipelineManager.hpp b/src/vkcv/PipelineManager.hpp deleted file mode 100644 index b153eb4632b844e84b92953fe8abf6666a13e0c9..0000000000000000000000000000000000000000 --- a/src/vkcv/PipelineManager.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include <vulkan/vulkan.hpp> -#include <vector> -#include "vkcv/Handles.hpp" -#include "vkcv/PipelineConfig.hpp" -#include "PassManager.hpp" - -namespace vkcv -{ - class PipelineManager - { - private: - struct Pipeline { - vk::Pipeline m_handle; - vk::PipelineLayout m_layout; - PipelineConfig m_config; - }; - - vk::Device m_Device; - std::vector<Pipeline> m_Pipelines; - - void destroyPipelineById(uint64_t id); - - vk::Result createShaderModule(vk::ShaderModule &module, const ShaderProgram &shaderProgram, ShaderStage stage); - - public: - PipelineManager() = delete; // no default ctor - explicit PipelineManager(vk::Device device) noexcept; // ctor - ~PipelineManager() noexcept; // dtor - - PipelineManager(const PipelineManager &other) = delete; // copy-ctor - PipelineManager(PipelineManager &&other) = delete; // move-ctor; - - PipelineManager & operator=(const PipelineManager &other) = delete; // copy-assign op - PipelineManager & operator=(PipelineManager &&other) = delete; // move-assign op - - PipelineHandle createPipeline(const PipelineConfig &config, PassManager& passManager); - - PipelineHandle createComputePipeline( - const ShaderProgram& shaderProgram, - const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts); - - [[nodiscard]] - vk::Pipeline getVkPipeline(const PipelineHandle &handle) const; - - [[nodiscard]] - vk::PipelineLayout getVkPipelineLayout(const PipelineHandle &handle) const; - - [[nodiscard]] - const PipelineConfig &getPipelineConfig(const PipelineHandle &handle) const; - }; -} diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index 2cfd0d7a832129b6f3bbdbeaf17494d0af3c928e..ff134041bdc6279d312df668cab448a50750f1c3 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -149,7 +149,8 @@ namespace vkcv { } break; default: - throw std::runtime_error("Invalid input for queue flag bits. Valid inputs are 'vk::QueueFlagBits::eGraphics', 'vk::QueueFlagBits::eCompute' and 'vk::QueueFlagBits::eTransfer'."); + vkcv_log(LogLevel::ERROR, "Invalid input for queue flag bits: %s", vk::to_string(qFlag).c_str()); + break; } } diff --git a/src/vkcv/Swapchain.cpp b/src/vkcv/Swapchain.cpp index 90f589266cf51cbb3ef98edb5d64362c0a650c14..483732927bc2cc507f0868226b65bf4d49e27048 100644 --- a/src/vkcv/Swapchain.cpp +++ b/src/vkcv/Swapchain.cpp @@ -73,12 +73,7 @@ namespace vkcv * @param window of the current application * @return chosen Extent for the surface */ - vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window){ - vk::SurfaceCapabilitiesKHR surfaceCapabilities; - if(physicalDevice.getSurfaceCapabilitiesKHR(surface,&surfaceCapabilities) != vk::Result::eSuccess){ - throw std::runtime_error("cannot get surface capabilities. There is an issue with the surface."); - } - + vk::Extent2D chooseExtent(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface, const Window &window) { int fb_width, fb_height; window.getFramebufferSize(fb_width, fb_height); @@ -86,9 +81,17 @@ namespace vkcv static_cast<uint32_t>(fb_width), static_cast<uint32_t>(fb_height) }; - - extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); - extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); + + vk::SurfaceCapabilitiesKHR surfaceCapabilities; + if(physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities) != vk::Result::eSuccess) { + vkcv_log(LogLevel::WARNING, "The capabilities of the surface can not be retrieved"); + + extent2D.width = std::max(MIN_SWAPCHAIN_SIZE, extent2D.width); + extent2D.height = std::max(MIN_SWAPCHAIN_SIZE, extent2D.height); + } else { + extent2D.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, extent2D.width)); + extent2D.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, extent2D.height)); + } return extent2D; }