mirror of
				https://github.com/PancakeTAS/lsfg-vk.git
				synced 2025-10-30 07:01:10 +00:00 
			
		
		
		
	multi frame generation for backend
This commit is contained in:
		
							parent
							
								
									3a6458ab7a
								
							
						
					
					
						commit
						f3b5cfc131
					
				
					 22 changed files with 402 additions and 239 deletions
				
			
		|  | @ -32,22 +32,24 @@ namespace LSFG { | |||
|         /// @param height Height of the input images.
 | ||||
|         /// @param in0 File descriptor for the first input image.
 | ||||
|         /// @param in1 File descriptor for the second input image.
 | ||||
|         /// @param out File descriptor for the output image.
 | ||||
|         /// @param outN File descriptor for the output image.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if the generator fails to initialize.
 | ||||
|         ///
 | ||||
|         Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out); | ||||
|         Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, | ||||
|             const std::vector<int>& outN); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Schedule the next generation.
 | ||||
|         ///
 | ||||
|         /// @param device The Vulkan device to use.
 | ||||
|         /// @param inSem Semaphore to wait on before starting the generation.
 | ||||
|         /// @param outSem Semaphore to signal when the generation is complete.
 | ||||
|         /// @param outSem Semaphores to signal after each generation is done.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if the generator fails to present.
 | ||||
|         ///
 | ||||
|         void present(const Core::Device& device, int inSem, int outSem); | ||||
|         void present(const Core::Device& device, int inSem, | ||||
|             const std::vector<int>& outSem); | ||||
| 
 | ||||
|         // Trivially copyable, moveable and destructible
 | ||||
|         Context(const Context&) = default; | ||||
|  | @ -61,8 +63,10 @@ namespace LSFG { | |||
| 
 | ||||
|         Core::Image inImg_0, inImg_1; // inImg_0 is next (inImg_1 prev) when fc % 2 == 0
 | ||||
|         std::array<Core::Semaphore, 8> inSemaphores; | ||||
|         std::array<Core::Semaphore, 8> outSemaphores; | ||||
|         std::array<Core::CommandBuffer, 8> cmdBuffers; | ||||
|         std::array<std::vector<Core::Semaphore>, 8> internalSemaphores; | ||||
|         std::vector<std::array<Core::Semaphore, 8>> outSemaphores; | ||||
|         std::array<Core::CommandBuffer, 8> cmdBuffers1; | ||||
|         std::vector<std::array<Core::CommandBuffer, 8>> cmdBuffers2; | ||||
|         uint64_t fc{0}; | ||||
| 
 | ||||
|         Shaderchains::Downsample downsampleChain; | ||||
|  |  | |||
|  | @ -32,23 +32,26 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImgs_0 The next input images to process (when fc % 3 == 0)
 | ||||
|         /// @param inImgs_1 The prev input images to process (when fc % 3 == 0)
 | ||||
|         /// @param inImgs_2 The prev prev input images to process (when fc % 3 == 0)
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Beta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             std::array<Core::Image, 4> inImgs_0, | ||||
|             std::array<Core::Image, 4> inImgs_1, | ||||
|             std::array<Core::Image, 4> inImgs_2); | ||||
|             std::array<Core::Image, 4> inImgs_2, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param fc The frame count, used to select the input images.
 | ||||
|         /// @param pass The pass number
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output images.
 | ||||
|         [[nodiscard]] const auto& getOutImages() const { return this->outImgs; } | ||||
|  | @ -62,9 +65,10 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         std::array<Core::ShaderModule, 5> shaderModules; | ||||
|         std::array<Core::Pipeline, 5> pipelines; | ||||
|         std::array<Core::DescriptorSet, 4> descriptorSets; // first shader has special logic
 | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; // first shader has special logic
 | ||||
|         std::array<Core::DescriptorSet, 3> specialDescriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::vector<Core::DescriptorSet> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 4> inImgs_0; | ||||
|         std::array<Core::Image, 4> inImgs_1; | ||||
|  |  | |||
|  | @ -31,21 +31,24 @@ namespace LSFG::Shaderchains { | |||
|         /// @param pool The descriptor pool to allocate in.
 | ||||
|         /// @param inImgs The input images to process.
 | ||||
|         /// @param optImg An optional additional input from the previous pass.
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Delta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             std::array<Core::Image, 2> inImgs, | ||||
|             std::optional<Core::Image> optImg); | ||||
|             std::optional<Core::Image> optImg, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output image.
 | ||||
|         [[nodiscard]] const auto& getOutImage() const { return this->outImg; } | ||||
|  | @ -59,8 +62,9 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         std::array<Core::ShaderModule, 4> shaderModules; | ||||
|         std::array<Core::Pipeline, 4> pipelines; | ||||
|         std::array<Core::DescriptorSet, 4> descriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; | ||||
|         std::vector<Core::DescriptorSet> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 2> inImgs; | ||||
|         std::optional<Core::Image> optImg; | ||||
|  |  | |||
|  | @ -30,11 +30,13 @@ namespace LSFG::Shaderchains { | |||
|         /// @param pool The descriptor pool to allocate in.
 | ||||
|         /// @param inImg_0 The next full image to downsample (when fc % 2 == 0)
 | ||||
|         /// @param inImg_1 The next full image to downsample (when fc % 2 == 1)
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Downsample(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             Core::Image inImg_0, Core::Image inImg_1); | ||||
|             Core::Image inImg_0, Core::Image inImg_1, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|  |  | |||
|  | @ -32,22 +32,25 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImgs1 The first set of input images to process.
 | ||||
|         /// @param inImg2 The second type image to process.
 | ||||
|         /// @param optImg An optional additional input from the previous pass.
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Epsilon(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             std::array<Core::Image, 3> inImgs1, | ||||
|             Core::Image inImg2, | ||||
|             std::optional<Core::Image> optImg); | ||||
|             std::optional<Core::Image> optImg, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output image.
 | ||||
|         [[nodiscard]] const auto& getOutImage() const { return this->outImg; } | ||||
|  | @ -61,8 +64,9 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         std::array<Core::ShaderModule, 4> shaderModules; | ||||
|         std::array<Core::Pipeline, 4> pipelines; | ||||
|         std::array<Core::DescriptorSet, 4> descriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; | ||||
|         std::vector<Core::DescriptorSet> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 3> inImgs1; | ||||
|         Core::Image inImg2; | ||||
|  |  | |||
|  | @ -30,22 +30,25 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImg1 The first set of input images to process.
 | ||||
|         /// @param inImg2 The second type image to process.
 | ||||
|         /// @param outExtent The extent of the output image.
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Extract(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             Core::Image inImg1, | ||||
|             Core::Image inImg2, | ||||
|             VkExtent2D outExtent); | ||||
|             VkExtent2D outExtent, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output image.
 | ||||
|         [[nodiscard]] const auto& getOutImage() const { return this->outImg; } | ||||
|  | @ -59,8 +62,8 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         Core::ShaderModule shaderModule; | ||||
|         Core::Pipeline pipeline; | ||||
|         Core::DescriptorSet descriptorSet; | ||||
|         Core::Buffer buffer; | ||||
|         std::vector<Core::DescriptorSet> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         Core::Image inImg1; | ||||
|         Core::Image inImg2; | ||||
|  |  | |||
|  | @ -38,6 +38,7 @@ namespace LSFG::Shaderchains { | |||
|         /// @param optImg1 An optional additional input from the previous pass.
 | ||||
|         /// @param optImg2 An optional additional input image for processing non-first passes.
 | ||||
|         /// @param outExtent The extent of the output image.
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|  | @ -48,17 +49,19 @@ namespace LSFG::Shaderchains { | |||
|             Core::Image inImg2, | ||||
|             std::optional<Core::Image> optImg1, | ||||
|             std::optional<Core::Image> optImg2, | ||||
|             VkExtent2D outExtent); | ||||
|             VkExtent2D outExtent, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param fc The frame count, used to select the input images.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the first output image.
 | ||||
|         [[nodiscard]] const auto& getOutImage1() const { return this->outImg1; } | ||||
|  | @ -74,9 +77,11 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         std::array<Core::ShaderModule, 6> shaderModules; | ||||
|         std::array<Core::Pipeline, 6> pipelines; | ||||
|         std::array<Core::DescriptorSet, 5> descriptorSets; // first shader has special logic
 | ||||
|         std::array<Core::DescriptorSet, 3> specialDescriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; // first shader has special logic
 | ||||
|         std::vector<Core::DescriptorSet> n1DescriptorSets; | ||||
|         std::vector<Core::DescriptorSet> n2DescriptorSets; | ||||
|         std::vector<std::array<Core::DescriptorSet, 3>> nSpecialDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 4> inImgs1_0; | ||||
|         std::array<Core::Image, 4> inImgs1_1; | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImg2 The second input image to process.
 | ||||
|         /// @param inImg3 The third input image to process, next step up the resolution.
 | ||||
|         /// @param optImg An optional additional input from the previous pass.
 | ||||
|         /// @param genc Amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|  | @ -44,17 +45,19 @@ namespace LSFG::Shaderchains { | |||
|             std::array<Core::Image, 4> inImgs1_2, | ||||
|             Core::Image inImg2, | ||||
|             Core::Image inImg3, | ||||
|             std::optional<Core::Image> optImg); | ||||
|             std::optional<Core::Image> optImg, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param fc The frame count, used to select the input images.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the first set of output images
 | ||||
|         [[nodiscard]] const auto& getOutImages1() const { return this->outImgs1; } | ||||
|  | @ -72,8 +75,8 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         Core::ShaderModule shaderModule; | ||||
|         Core::Pipeline pipeline; | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::vector<std::array<Core::DescriptorSet, 3>> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 4> inImgs1_0; | ||||
|         std::array<Core::Image, 4> inImgs1_1; | ||||
|  |  | |||
|  | @ -34,7 +34,8 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImg3 The first related input texture
 | ||||
|         /// @param inImg4 The second related input texture
 | ||||
|         /// @param inImg5 The third related input texture
 | ||||
|         /// @param outFd File descriptor for the output image.
 | ||||
|         /// @param outFds File descriptors for the output images.
 | ||||
|         /// @param genc The amount of frames to generaten.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|  | @ -44,20 +45,22 @@ namespace LSFG::Shaderchains { | |||
|             Core::Image inImg3, | ||||
|             Core::Image inImg4, | ||||
|             Core::Image inImg5, | ||||
|             int outFd); | ||||
|             const std::vector<int>& outFds, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param fc The frame count, used to select the input images.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output image
 | ||||
|         [[nodiscard]] const auto& getOutImage() const { return this->outImg; } | ||||
|         [[nodiscard]] const auto& getOutImage(size_t pass) const { return this->outImgs.at(pass); } | ||||
| 
 | ||||
|         /// Trivially copyable, moveable and destructible
 | ||||
|         Merge(const Merge&) noexcept = default; | ||||
|  | @ -68,8 +71,8 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         Core::ShaderModule shaderModule; | ||||
|         Core::Pipeline pipeline; | ||||
|         std::array<Core::DescriptorSet, 2> descriptorSets; // one for each input combination
 | ||||
|         Core::Buffer buffer; | ||||
|         std::vector<std::array<Core::DescriptorSet, 2>> nDescriptorSets; // per combo
 | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         Core::Image inImg1; | ||||
|         Core::Image inImg2; | ||||
|  | @ -77,7 +80,7 @@ namespace LSFG::Shaderchains { | |||
|         Core::Image inImg4; | ||||
|         Core::Image inImg5; | ||||
| 
 | ||||
|         Core::Image outImg; | ||||
|         std::vector<Core::Image> outImgs; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -32,22 +32,25 @@ namespace LSFG::Shaderchains { | |||
|         /// @param inImgs1 The first set of input images to process.
 | ||||
|         /// @param inImg2 The second type image to process.
 | ||||
|         /// @param inImg3 The third type image to process.
 | ||||
|         /// @param genc The amount of frames to generate.
 | ||||
|         ///
 | ||||
|         /// @throws LSFG::vulkan_error if resource creation fails.
 | ||||
|         ///
 | ||||
|         Zeta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|             std::array<Core::Image, 3> inImgs1, | ||||
|             Core::Image inImg2, | ||||
|             Core::Image inImg3); | ||||
|             Core::Image inImg3, | ||||
|             size_t genc); | ||||
| 
 | ||||
|         ///
 | ||||
|         /// Dispatch the shaderchain.
 | ||||
|         ///
 | ||||
|         /// @param buf The command buffer to use for dispatching.
 | ||||
|         /// @param pass The pass number.
 | ||||
|         ///
 | ||||
|         /// @throws std::logic_error if the command buffer is not recording.
 | ||||
|         ///
 | ||||
|         void Dispatch(const Core::CommandBuffer& buf); | ||||
|         void Dispatch(const Core::CommandBuffer& buf, uint64_t pass); | ||||
| 
 | ||||
|         /// Get the output image.
 | ||||
|         [[nodiscard]] const auto& getOutImage() const { return this->outImg; } | ||||
|  | @ -61,8 +64,9 @@ namespace LSFG::Shaderchains { | |||
|     private: | ||||
|         std::array<Core::ShaderModule, 4> shaderModules; | ||||
|         std::array<Core::Pipeline, 4> pipelines; | ||||
|         std::array<Core::DescriptorSet, 4> descriptorSets; | ||||
|         Core::Buffer buffer; | ||||
|         std::array<Core::DescriptorSet, 3> descriptorSets; | ||||
|         std::vector<Core::DescriptorSet> nDescriptorSets; | ||||
|         std::vector<Core::Buffer> buffers; | ||||
| 
 | ||||
|         std::array<Core::Image, 3> inImgs1; | ||||
|         Core::Image inImg2; | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| 
 | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <vulkan/vulkan_core.h> | ||||
| 
 | ||||
| namespace LSFG { | ||||
|  | @ -21,23 +22,24 @@ namespace LSFG { | |||
|     /// @param height Height of the input images.
 | ||||
|     /// @param in0 File descriptor for the first input image.
 | ||||
|     /// @param in1 File descriptor for the second input image.
 | ||||
|     /// @param out File descriptor for the output image.
 | ||||
|     /// @param outN File descriptor for each output image. This defines the LSFG level.
 | ||||
|     /// @return A unique identifier for the created context.
 | ||||
|     ///
 | ||||
|     /// @throws LSFG::vulkan_error if the context cannot be created.
 | ||||
|     ///
 | ||||
|     int32_t createContext(uint32_t width, uint32_t height, int in0, int in1, int out); | ||||
|     int32_t createContext(uint32_t width, uint32_t height, int in0, int in1, | ||||
|         const std::vector<int>& outN); | ||||
| 
 | ||||
|     ///
 | ||||
|     /// Present a context.
 | ||||
|     ///
 | ||||
|     /// @param id Unique identifier of the context to present.
 | ||||
|     /// @param inSem Semaphore to wait on before starting the generation.
 | ||||
|     /// @param outSem Semaphore to signal when the generation is complete.
 | ||||
|     /// @param outSem Semaphores to signal once each output image is ready.
 | ||||
|     ///
 | ||||
|     /// @throws LSFG::vulkan_error if the context cannot be presented.
 | ||||
|     ///
 | ||||
|     void presentContext(int32_t id, int inSem, int outSem); | ||||
|     void presentContext(int32_t id, int inSem, const std::vector<int>& outSem); | ||||
| 
 | ||||
|     ///
 | ||||
|     /// Delete an LSFG context.
 | ||||
|  |  | |||
|  | @ -8,7 +8,8 @@ | |||
| 
 | ||||
| using namespace LSFG; | ||||
| 
 | ||||
| Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, int out) { | ||||
| Context::Context(const Core::Device& device, uint32_t width, uint32_t height, int in0, int in1, | ||||
|         const std::vector<int>& outN) { | ||||
|     // import images
 | ||||
|     this->inImg_0 = Core::Image(device, { width, height }, | ||||
|         VK_FORMAT_R8G8B8A8_UNORM, | ||||
|  | @ -25,16 +26,24 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in | |||
|     this->descPool = Core::DescriptorPool(device); | ||||
|     this->cmdPool = Core::CommandPool(device); | ||||
| 
 | ||||
|     // prepare vectors
 | ||||
|     for (size_t i = 0; i < 8; i++) | ||||
|         this->internalSemaphores.at(i).resize(outN.size()); | ||||
|     for (size_t i = 0; i < outN.size(); i++) { | ||||
|         this->outSemaphores.emplace_back(); | ||||
|         this->cmdBuffers2.emplace_back(); | ||||
|     } | ||||
| 
 | ||||
|     // create shader chains
 | ||||
|     this->downsampleChain = Shaderchains::Downsample(device, this->descPool, | ||||
|         this->inImg_0, this->inImg_1); | ||||
|         this->inImg_0, this->inImg_1, outN.size()); | ||||
|     for (size_t i = 0; i < 7; i++) | ||||
|         this->alphaChains.at(i) = Shaderchains::Alpha(device, this->descPool, | ||||
|             this->downsampleChain.getOutImages().at(i)); | ||||
|     this->betaChain = Shaderchains::Beta(device, this->descPool, | ||||
|         this->alphaChains.at(0).getOutImages0(), | ||||
|         this->alphaChains.at(0).getOutImages1(), | ||||
|         this->alphaChains.at(0).getOutImages2()); | ||||
|         this->alphaChains.at(0).getOutImages2(), outN.size()); | ||||
|     for (size_t i = 0; i < 7; i++) { | ||||
|         if (i < 4) { | ||||
|             this->gammaChains.at(i) = Shaderchains::Gamma(device, this->descPool, | ||||
|  | @ -46,7 +55,8 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in | |||
|                        : std::optional{this->gammaChains.at(i - 1).getOutImage2()}, | ||||
|                 i == 0 ? std::nullopt | ||||
|                        : std::optional{this->gammaChains.at(i - 1).getOutImage1()}, | ||||
|                 this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent() | ||||
|                 this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent(), | ||||
|                 outN.size() | ||||
|             ); | ||||
|         } else { | ||||
|             this->magicChains.at(i - 4) = Shaderchains::Magic(device, this->descPool, | ||||
|  | @ -57,31 +67,36 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in | |||
|                        : this->extractChains.at(i - 5).getOutImage(), | ||||
|                 i == 4 ? this->gammaChains.at(i - 1).getOutImage1() | ||||
|                        : this->zetaChains.at(i - 5).getOutImage(), | ||||
|                 i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()} | ||||
|                 i == 4 ? std::nullopt : std::optional{this->epsilonChains.at(i - 5).getOutImage()}, | ||||
|                 outN.size() | ||||
|             ); | ||||
|             this->deltaChains.at(i - 4) = Shaderchains::Delta(device, this->descPool, | ||||
|                 this->magicChains.at(i - 4).getOutImages1(), | ||||
|                 i == 4 ? std::nullopt | ||||
|                        : std::optional{this->deltaChains.at(i - 5).getOutImage()} | ||||
|                        : std::optional{this->deltaChains.at(i - 5).getOutImage()}, | ||||
|                        outN.size() | ||||
|             ); | ||||
|             this->epsilonChains.at(i - 4) = Shaderchains::Epsilon(device, this->descPool, | ||||
|                 this->magicChains.at(i - 4).getOutImages2(), | ||||
|                 this->betaChain.getOutImages().at(6 - i), | ||||
|                 i == 4 ? std::nullopt | ||||
|                        : std::optional{this->epsilonChains.at(i - 5).getOutImage()} | ||||
|                        : std::optional{this->epsilonChains.at(i - 5).getOutImage()}, | ||||
|                        outN.size() | ||||
|             ); | ||||
|             this->zetaChains.at(i - 4) = Shaderchains::Zeta(device, this->descPool, | ||||
|                 this->magicChains.at(i - 4).getOutImages3(), | ||||
|                 i == 4 ? this->gammaChains.at(i - 1).getOutImage1() | ||||
|                        : this->zetaChains.at(i - 5).getOutImage(), | ||||
|                 this->betaChain.getOutImages().at(6 - i) | ||||
|                 this->betaChain.getOutImages().at(6 - i), | ||||
|                 outN.size() | ||||
|             ); | ||||
|             if (i >= 6) | ||||
|                 continue; // no extract for i >= 6
 | ||||
|             this->extractChains.at(i - 4) = Shaderchains::Extract(device, this->descPool, | ||||
|                 this->zetaChains.at(i - 4).getOutImage(), | ||||
|                 this->epsilonChains.at(i - 4).getOutImage(), | ||||
|                 this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent() | ||||
|                 this->alphaChains.at(6 - i - 1).getOutImages0().at(0).getExtent(), | ||||
|                 outN.size() | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | @ -91,41 +106,61 @@ Context::Context(const Core::Device& device, uint32_t width, uint32_t height, in | |||
|         this->zetaChains.at(2).getOutImage(), | ||||
|         this->epsilonChains.at(2).getOutImage(), | ||||
|         this->deltaChains.at(2).getOutImage(), | ||||
|         out | ||||
|         outN, | ||||
|         outN.size() | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| void Context::present(const Core::Device& device, int inSem, int outSem) { | ||||
| void Context::present(const Core::Device& device, int inSem, | ||||
|         const std::vector<int>& outSem) { | ||||
|     auto& inSemaphore = this->inSemaphores.at(this->fc % 8); | ||||
|     inSemaphore = Core::Semaphore(device, inSem); | ||||
|     auto& outSemaphore = this->outSemaphores.at(this->fc % 8); | ||||
|     outSemaphore = Core::Semaphore(device, outSem); | ||||
|     auto& internalSemaphores = this->internalSemaphores.at(this->fc % 8); | ||||
|     for (size_t i = 0; i < outSem.size(); i++) | ||||
|         internalSemaphores.at(i) = Core::Semaphore(device); | ||||
| 
 | ||||
|     auto& cmdBuffer = this->cmdBuffers.at(this->fc % 8); | ||||
|     cmdBuffer = Core::CommandBuffer(device, this->cmdPool); | ||||
|     cmdBuffer.begin(); | ||||
|     auto& cmdBuffer1 = this->cmdBuffers1.at(this->fc % 8); | ||||
|     cmdBuffer1 = Core::CommandBuffer(device, this->cmdPool); | ||||
|     cmdBuffer1.begin(); | ||||
| 
 | ||||
|     this->downsampleChain.Dispatch(cmdBuffer, fc); | ||||
|     this->downsampleChain.Dispatch(cmdBuffer1, fc); | ||||
|     for (size_t i = 0; i < 7; i++) | ||||
|         this->alphaChains.at(6 - i).Dispatch(cmdBuffer, fc); | ||||
|     this->betaChain.Dispatch(cmdBuffer, fc); | ||||
|     for (size_t i = 0; i < 4; i++) | ||||
|         this->gammaChains.at(i).Dispatch(cmdBuffer, fc); | ||||
|     for (size_t i = 0; i < 3; i++) { | ||||
|         this->magicChains.at(i).Dispatch(cmdBuffer, fc); | ||||
|         this->deltaChains.at(i).Dispatch(cmdBuffer); | ||||
|         this->epsilonChains.at(i).Dispatch(cmdBuffer); | ||||
|         this->zetaChains.at(i).Dispatch(cmdBuffer); | ||||
|         if (i < 2) | ||||
|             this->extractChains.at(i).Dispatch(cmdBuffer); | ||||
|     } | ||||
|     this->mergeChain.Dispatch(cmdBuffer, fc); | ||||
|         this->alphaChains.at(6 - i).Dispatch(cmdBuffer1, fc); | ||||
| 
 | ||||
|     cmdBuffer.end(); | ||||
|     cmdBuffer1.end(); | ||||
| 
 | ||||
|     cmdBuffer.submit(device.getComputeQueue(), std::nullopt, | ||||
|     cmdBuffer1.submit(device.getComputeQueue(), std::nullopt, | ||||
|         { inSemaphore }, std::nullopt, | ||||
|         { outSemaphore }, std::nullopt); | ||||
|         internalSemaphores, std::nullopt); | ||||
| 
 | ||||
| 
 | ||||
|     for (size_t pass = 0; pass < outSem.size(); pass++) { | ||||
|         auto& outSemaphore = this->outSemaphores.at(pass).at(this->fc % 8); | ||||
|         outSemaphore = Core::Semaphore(device, outSem.at(pass)); | ||||
| 
 | ||||
|         auto& cmdBuffer2 = this->cmdBuffers2.at(pass).at(this->fc % 8); | ||||
|         cmdBuffer2 = Core::CommandBuffer(device, this->cmdPool); | ||||
|         cmdBuffer2.begin(); | ||||
| 
 | ||||
|         this->betaChain.Dispatch(cmdBuffer2, fc, pass); | ||||
|         for (size_t i = 0; i < 4; i++) | ||||
|             this->gammaChains.at(i).Dispatch(cmdBuffer2, fc, pass); | ||||
|         for (size_t i = 0; i < 3; i++) { | ||||
|             this->magicChains.at(i).Dispatch(cmdBuffer2, fc, pass); | ||||
|             this->deltaChains.at(i).Dispatch(cmdBuffer2, pass); | ||||
|             this->epsilonChains.at(i).Dispatch(cmdBuffer2, pass); | ||||
|             this->zetaChains.at(i).Dispatch(cmdBuffer2, pass); | ||||
|             if (i < 2) | ||||
|                 this->extractChains.at(i).Dispatch(cmdBuffer2, pass); | ||||
|         } | ||||
|         this->mergeChain.Dispatch(cmdBuffer2, fc, pass); | ||||
| 
 | ||||
|         cmdBuffer2.end(); | ||||
| 
 | ||||
|         cmdBuffer2.submit(device.getComputeQueue(), std::nullopt, | ||||
|             { internalSemaphores.at(pass) }, std::nullopt, | ||||
|             { outSemaphore }, std::nullopt); | ||||
|     } | ||||
| 
 | ||||
|     fc++; | ||||
| } | ||||
|  |  | |||
|  | @ -28,16 +28,17 @@ void LSFG::initialize() { | |||
|     std::srand(static_cast<uint32_t>(std::time(nullptr))); | ||||
| } | ||||
| 
 | ||||
| int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1, int out) { | ||||
| int32_t LSFG::createContext(uint32_t width, uint32_t height, int in0, int in1, | ||||
|         const std::vector<int>& outN) { | ||||
|     if (!instance.has_value() || !device.has_value()) | ||||
|         throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized"); | ||||
| 
 | ||||
|     auto id = std::rand(); | ||||
|     contexts.emplace(id, Context(*device, width, height, in0, in1, out)); | ||||
|     contexts.emplace(id, Context(*device, width, height, in0, in1, outN)); | ||||
|     return id; | ||||
| } | ||||
| 
 | ||||
| void LSFG::presentContext(int32_t id, int inSem, int outSem) { | ||||
| void LSFG::presentContext(int32_t id, int inSem, const std::vector<int>& outSem) { | ||||
|     if (!instance.has_value() || !device.has_value()) | ||||
|         throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "LSFG not initialized"); | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,8 @@ using namespace LSFG::Shaderchains; | |||
| Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         std::array<Core::Image, 4> inImgs_0, | ||||
|         std::array<Core::Image, 4> inImgs_1, | ||||
|         std::array<Core::Image, 4> inImgs_2) | ||||
|         std::array<Core::Image, 4> inImgs_2, | ||||
|         size_t genc) | ||||
|         : inImgs_0(std::move(inImgs_0)), | ||||
|           inImgs_1(std::move(inImgs_1)), | ||||
|           inImgs_2(std::move(inImgs_2)) { | ||||
|  | @ -36,14 +37,21 @@ Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     for (size_t i = 0; i < 5; i++) { | ||||
|         this->pipelines.at(i) = Core::Pipeline(device, | ||||
|             this->shaderModules.at(i)); | ||||
|         if (i == 0) continue; // first shader has special logic
 | ||||
|         if (i == 0 || i == 4) continue; // first shader has special logic
 | ||||
|         this->descriptorSets.at(i - 1) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(i)); | ||||
|     } | ||||
|     for (size_t i = 0; i < 3; i++) | ||||
|         this->specialDescriptorSets.at(i) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(0)); | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->nDescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(4)); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     const auto extent = this->inImgs_0.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -104,15 +112,17 @@ Beta::Beta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(3).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | ||||
| void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) { | ||||
|     const auto extent = this->tempImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -170,6 +180,6 @@ void Beta::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(4).bind(buf); | ||||
|     this->descriptorSets.at(3).bind(buf, this->pipelines.at(4)); | ||||
|     this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(4)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,8 @@ using namespace LSFG::Shaderchains; | |||
| 
 | ||||
| Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         std::array<Core::Image, 2> inImgs, | ||||
|         std::optional<Core::Image> optImg) | ||||
|         std::optional<Core::Image> optImg, | ||||
|         size_t genc) | ||||
|         : inImgs(std::move(inImgs)), | ||||
|           optImg(std::move(optImg)) { | ||||
|     this->shaderModules = {{ | ||||
|  | @ -30,13 +31,19 @@ Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     for (size_t i = 0; i < 4; i++) { | ||||
|         this->pipelines.at(i) = Core::Pipeline(device, | ||||
|             this->shaderModules.at(i)); | ||||
|         if (i == 3) continue; | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(i)); | ||||
|     } | ||||
| 
 | ||||
|     Globals::FgBuffer data = Globals::fgBuffer; | ||||
|     data.firstIterS = !this->optImg.has_value(); | ||||
|     this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->nDescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(3)); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         data.firstIterS = !this->optImg.has_value(); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     const auto extent = this->inImgs.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -74,17 +81,19 @@ Delta::Delta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(3).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Delta::Dispatch(const Core::CommandBuffer& buf) { | ||||
| void Delta::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) { | ||||
|     const auto extent = this->tempImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -128,6 +137,6 @@ void Delta::Dispatch(const Core::CommandBuffer& buf) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(3).bind(buf); | ||||
|     this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); | ||||
|     this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,8 @@ | |||
| using namespace LSFG::Shaderchains; | ||||
| 
 | ||||
| Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         Core::Image inImg_0, Core::Image inImg_1) | ||||
|         Core::Image inImg_0, Core::Image inImg_1, | ||||
|         size_t genc) | ||||
|         : inImg_0(std::move(inImg_0)), | ||||
|           inImg_1(std::move(inImg_1)) { | ||||
|     this->shaderModule = Core::ShaderModule(device, "rsc/shaders/downsample.spv", | ||||
|  | @ -15,7 +16,10 @@ Downsample::Downsample(const Core::Device& device, const Core::DescriptorPool& p | |||
|     this->pipeline = Core::Pipeline(device, this->shaderModule); | ||||
|     for (size_t i = 0; i < 2; i++) | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
| 
 | ||||
|     auto data = Globals::fgBuffer; | ||||
|     data.timestamp = 1.0F / static_cast<float>(genc + 1); | ||||
|     this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
| 
 | ||||
|     auto extent = this->inImg_0.getExtent(); | ||||
|     for (size_t i = 0; i < 7; i++) | ||||
|  |  | |||
|  | @ -6,7 +6,8 @@ using namespace LSFG::Shaderchains; | |||
| Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         std::array<Core::Image, 3> inImgs1, | ||||
|         Core::Image inImg2, | ||||
|         std::optional<Core::Image> optImg) | ||||
|         std::optional<Core::Image> optImg, | ||||
|         size_t genc) | ||||
|         : inImgs1(std::move(inImgs1)), | ||||
|           inImg2(std::move(inImg2)), | ||||
|           optImg(std::move(optImg)) { | ||||
|  | @ -32,10 +33,18 @@ Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     for (size_t i = 0; i < 4; i++) { | ||||
|         this->pipelines.at(i) = Core::Pipeline(device, | ||||
|             this->shaderModules.at(i)); | ||||
|         if (i == 3) continue; | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(i)); | ||||
|     } | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->nDescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(3)); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     const auto extent = this->inImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -73,18 +82,20 @@ Epsilon::Epsilon(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(3).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Epsilon::Dispatch(const Core::CommandBuffer& buf) { | ||||
| void Epsilon::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) { | ||||
|     const auto extent = this->tempImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -129,6 +140,6 @@ void Epsilon::Dispatch(const Core::CommandBuffer& buf) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(3).bind(buf); | ||||
|     this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); | ||||
|     this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -6,7 +6,8 @@ using namespace LSFG::Shaderchains; | |||
| Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         Core::Image inImg1, | ||||
|         Core::Image inImg2, | ||||
|         VkExtent2D outExtent) | ||||
|         VkExtent2D outExtent, | ||||
|         size_t genc) | ||||
|         : inImg1(std::move(inImg1)), | ||||
|           inImg2(std::move(inImg2)) { | ||||
|     this->shaderModule = Core::ShaderModule(device, "rsc/shaders/extract.spv", | ||||
|  | @ -15,8 +16,14 @@ Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|           { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, | ||||
|           { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); | ||||
|     this->pipeline = Core::Pipeline(device, this->shaderModule); | ||||
|     this->descriptorSet = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->nDescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModule); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     this->whiteImg = Core::Image(device, | ||||
|         outExtent, | ||||
|  | @ -30,21 +37,23 @@ Extract::Extract(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | ||||
|         VK_IMAGE_ASPECT_COLOR_BIT); | ||||
| 
 | ||||
|     this->descriptorSet.update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|     } | ||||
| 
 | ||||
|     // clear white image
 | ||||
|     Utils::clearImage(device, this->whiteImg, true); | ||||
| } | ||||
| 
 | ||||
| void Extract::Dispatch(const Core::CommandBuffer& buf) { | ||||
| void Extract::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) { | ||||
|     auto extent = this->whiteImg.getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -59,6 +68,6 @@ void Extract::Dispatch(const Core::CommandBuffer& buf) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipeline.bind(buf); | ||||
|     this->descriptorSet.bind(buf, this->pipeline); | ||||
|     this->nDescriptorSets.at(pass).bind(buf, this->pipeline); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -10,7 +10,8 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         Core::Image inImg2, | ||||
|         std::optional<Core::Image> optImg1, // NOLINT
 | ||||
|         std::optional<Core::Image> optImg2, | ||||
|         VkExtent2D outExtent) | ||||
|         VkExtent2D outExtent, | ||||
|         size_t genc) | ||||
|         : inImgs1_0(std::move(inImgs1_0)), | ||||
|           inImgs1_1(std::move(inImgs1_1)), | ||||
|           inImgs1_2(std::move(inImgs1_2)), | ||||
|  | @ -48,17 +49,28 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     for (size_t i = 0; i < 6; i++) { | ||||
|         this->pipelines.at(i) = Core::Pipeline(device, | ||||
|             this->shaderModules.at(i)); | ||||
|         if (i == 0) continue; // first shader has special logic
 | ||||
|         if (i == 0 || i >= 4) continue; // first shader has special logic
 | ||||
|         this->descriptorSets.at(i - 1) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(i)); | ||||
|     } | ||||
|     for (size_t i = 0; i < 3; i++) | ||||
|         this->specialDescriptorSets.at(i) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(0)); | ||||
| 
 | ||||
|     Globals::FgBuffer data = Globals::fgBuffer; | ||||
|     data.firstIter = !optImg1.has_value(); | ||||
|     this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->n1DescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(4)); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->n2DescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(5)); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nSpecialDescriptorSets.emplace_back(); | ||||
|         for (size_t j = 0; j < 3; j++) | ||||
|             this->nSpecialDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool, | ||||
|                 this->shaderModules.at(0)); | ||||
|     } | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         data.firstIter = !optImg1.has_value(); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     const auto extent = this->inImgs1_0.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -107,18 +119,20 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|             nextImgs1 = &this->inImgs1_2; | ||||
|             prevImgs1 = &this->inImgs1_1; | ||||
|         } | ||||
|         this->specialDescriptorSets.at(fc).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0)) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1)) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(2)) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|             .build(); | ||||
|         for (size_t i = 0; i < genc; i++) { | ||||
|             this->nSpecialDescriptorSets.at(i).at(fc).update(device) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(0)) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(1)) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1.at(2)) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|                 .build(); | ||||
|         } | ||||
|     } | ||||
|     this->descriptorSets.at(0).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|  | @ -137,23 +151,25 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs2) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(3).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(4).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->outImg1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->n1DescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|         this->n2DescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->whiteImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->outImg1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|             .build(); | ||||
|     } | ||||
| 
 | ||||
|     // clear white image and optImg1 if needed
 | ||||
|     Utils::clearImage(device, this->whiteImg, true); | ||||
|  | @ -161,7 +177,7 @@ Gamma::Gamma(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         Utils::clearImage(device, this->optImg1); | ||||
| } | ||||
| 
 | ||||
| void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | ||||
| void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) { | ||||
|     const auto extent = this->tempImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -188,7 +204,7 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(0).bind(buf); | ||||
|     this->specialDescriptorSets.at(fc % 3).bind(buf, this->pipelines.at(0)); | ||||
|     this->nSpecialDescriptorSets.at(pass).at(fc % 3).bind(buf, this->pipelines.at(0)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| 
 | ||||
|     // second pass
 | ||||
|  | @ -232,7 +248,7 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(4).bind(buf); | ||||
|     this->descriptorSets.at(3).bind(buf, this->pipelines.at(4)); | ||||
|     this->n1DescriptorSets.at(pass).bind(buf, this->pipelines.at(4)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| 
 | ||||
|     // sixth pass
 | ||||
|  | @ -246,6 +262,6 @@ void Gamma::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(5).bind(buf); | ||||
|     this->descriptorSets.at(4).bind(buf, this->pipelines.at(5)); | ||||
|     this->n2DescriptorSets.at(pass).bind(buf, this->pipelines.at(5)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,8 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     std::array<Core::Image, 4> inImgs1_2, | ||||
|         Core::Image inImg2, | ||||
|         Core::Image inImg3, | ||||
|         std::optional<Core::Image> optImg) | ||||
|         std::optional<Core::Image> optImg, | ||||
|         size_t genc) | ||||
|         : inImgs1_0(std::move(inImgs1_0)), | ||||
|           inImgs1_1(std::move(inImgs1_1)), | ||||
|           inImgs1_2(std::move(inImgs1_2)), | ||||
|  | @ -21,12 +22,17 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|           { 3+3+2,   VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, | ||||
|           { 1,       VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); | ||||
|     this->pipeline = Core::Pipeline(device, this->shaderModule); | ||||
|     for (size_t i = 0; i < 3; i++) | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
| 
 | ||||
|     Globals::FgBuffer data = Globals::fgBuffer; | ||||
|     data.firstIterS = !this->optImg.has_value(); | ||||
|     this->buffer = Core::Buffer(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.emplace_back(); | ||||
|         for (size_t j = 0; j < 3; j++) | ||||
|             this->nDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
|     } | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         data.firstIterS = !this->optImg.has_value(); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     auto extent = this->inImgs1_0.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -59,23 +65,25 @@ Magic::Magic(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|             nextImgs1 = &this->inImgs1_2; | ||||
|             prevImgs1 = &this->inImgs1_1; | ||||
|         } | ||||
|         this->descriptorSets.at(fc).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs3) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|             .build(); | ||||
|         for (size_t i = 0; i < genc; i++) { | ||||
|             this->nDescriptorSets.at(i).at(fc).update(device) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *prevImgs1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, *nextImgs1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->optImg) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs3) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs2) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|                 .build(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | ||||
| void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) { | ||||
|     auto extent = this->inImgs1_0.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -103,6 +111,6 @@ void Magic::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipeline.bind(buf); | ||||
|     this->descriptorSets.at(fc % 3).bind(buf, this->pipeline); | ||||
|     this->nDescriptorSets.at(pass).at(fc % 3).bind(buf, this->pipeline); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,8 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         Core::Image inImg3, | ||||
|         Core::Image inImg4, | ||||
|         Core::Image inImg5, | ||||
|         int outFd) | ||||
|         const std::vector<int>& outFds, | ||||
|         size_t genc) | ||||
|         : inImg1(std::move(inImg1)), | ||||
|           inImg2(std::move(inImg2)), | ||||
|           inImg3(std::move(inImg3)), | ||||
|  | @ -21,35 +22,45 @@ Merge::Merge(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|           { 1, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE }, | ||||
|           { 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER } }); | ||||
|     this->pipeline = Core::Pipeline(device, this->shaderModule); | ||||
|     for (size_t i = 0; i < 2; i++) | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.emplace_back(); | ||||
|         for (size_t j = 0; j < 2; j++) | ||||
|             this->nDescriptorSets.at(i).at(j) = Core::DescriptorSet(device, pool, this->shaderModule); | ||||
|     } | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     auto extent = this->inImg1.getExtent(); | ||||
| 
 | ||||
|     this->outImg = Core::Image(device, | ||||
|         extent, | ||||
|         VK_FORMAT_R8G8B8A8_UNORM, | ||||
|         VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | ||||
|         VK_IMAGE_ASPECT_COLOR_BIT, | ||||
|         outFd); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->outImgs.emplace_back(device, | ||||
|             extent, | ||||
|             VK_FORMAT_R8G8B8A8_UNORM, | ||||
|             VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, | ||||
|             VK_IMAGE_ASPECT_COLOR_BIT, | ||||
|             outFds.at(i)); | ||||
| 
 | ||||
|     for (size_t fc = 0; fc < 2; fc++) { | ||||
|         this->descriptorSets.at(fc).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg1 : this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg2 : this->inImg1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg4) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg5) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|             .build(); | ||||
|         for (size_t i = 0; i < genc; i++) { | ||||
|             this->nDescriptorSets.at(i).at(fc).update(device) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg1 : this->inImg2) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, (fc % 2 == 0) ? this->inImg2 : this->inImg1) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg4) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg5) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImgs.at(i)) | ||||
|                 .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i)) | ||||
|                 .build(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | ||||
| void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc, uint64_t pass) { | ||||
|     auto extent = this->inImg1.getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -62,10 +73,10 @@ void Merge::Dispatch(const Core::CommandBuffer& buf, uint64_t fc) { | |||
|         .addW2R(this->inImg3) | ||||
|         .addW2R(this->inImg4) | ||||
|         .addW2R(this->inImg5) | ||||
|         .addR2W(this->outImg) | ||||
|         .addR2W(this->outImgs.at(pass)) | ||||
|         .build(); | ||||
| 
 | ||||
|     this->pipeline.bind(buf); | ||||
|     this->descriptorSets.at(fc % 2).bind(buf, this->pipeline); | ||||
|     this->nDescriptorSets.at(pass).at(fc % 2).bind(buf, this->pipeline); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
|  | @ -6,7 +6,8 @@ using namespace LSFG::Shaderchains; | |||
| Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool, | ||||
|         std::array<Core::Image, 3> inImgs1, | ||||
|         Core::Image inImg2, | ||||
|         Core::Image inImg3) | ||||
|         Core::Image inImg3, | ||||
|         size_t genc) | ||||
|         : inImgs1(std::move(inImgs1)), | ||||
|           inImg2(std::move(inImg2)), | ||||
|           inImg3(std::move(inImg3)) { | ||||
|  | @ -32,10 +33,18 @@ Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|     for (size_t i = 0; i < 4; i++) { | ||||
|         this->pipelines.at(i) = Core::Pipeline(device, | ||||
|             this->shaderModules.at(i)); | ||||
|         if (i == 3) continue; | ||||
|         this->descriptorSets.at(i) = Core::DescriptorSet(device, pool, | ||||
|             this->shaderModules.at(i)); | ||||
|     } | ||||
|     this->buffer = Core::Buffer(device, Globals::fgBuffer, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     for (size_t i = 0; i < genc; i++) | ||||
|         this->nDescriptorSets.emplace_back(device, pool, | ||||
|             this->shaderModules.at(3)); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         auto data = Globals::fgBuffer; | ||||
|         data.timestamp = static_cast<float>(i + 1) / static_cast<float>(genc + 1); | ||||
|         this->buffers.emplace_back(device, data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); | ||||
|     } | ||||
| 
 | ||||
|     const auto extent = this->inImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|  | @ -73,18 +82,20 @@ Zeta::Zeta(const Core::Device& device, const Core::DescriptorPool& pool, | |||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->tempImgs1) | ||||
|         .build(); | ||||
|     this->descriptorSets.at(3).update(device) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|         .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|         .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|         .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffer) | ||||
|         .build(); | ||||
|     for (size_t i = 0; i < genc; i++) { | ||||
|         this->nDescriptorSets.at(i).update(device) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampBorder) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLER, Globals::samplerClampEdge) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->tempImgs1) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg2) | ||||
|             .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, this->inImg3) | ||||
|             .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, this->outImg) | ||||
|             .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, this->buffers.at(i) ) | ||||
|             .build(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Zeta::Dispatch(const Core::CommandBuffer& buf) { | ||||
| void Zeta::Dispatch(const Core::CommandBuffer& buf, uint64_t pass) { | ||||
|     const auto extent = this->tempImgs1.at(0).getExtent(); | ||||
| 
 | ||||
|     // first pass
 | ||||
|  | @ -129,6 +140,6 @@ void Zeta::Dispatch(const Core::CommandBuffer& buf) { | |||
|         .build(); | ||||
| 
 | ||||
|     this->pipelines.at(3).bind(buf); | ||||
|     this->descriptorSets.at(3).bind(buf, this->pipelines.at(3)); | ||||
|     this->nDescriptorSets.at(pass).bind(buf, this->pipelines.at(3)); | ||||
|     buf.dispatch(threadsX, threadsY, 1); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 PancakeTAS
						PancakeTAS