diff --git a/.gitignore b/.gitignore index bdb6a0c..b7995ca 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -``` -# Compiled and binary files +```cpp +# Compiled and build artifacts *.o *.obj *.exe @@ -7,27 +7,24 @@ *.so *.a *.out +build/ +dist/ # Dependencies -node_modules/ venv/ .venv/ +node_modules/ __pycache__/ .mypy_cache/ .pytest_cache/ target/ .gradle/ -# Build artifacts -build/ -dist/ - -# Editor/IDE files +# Editors .vscode/ .idea/ *.swp *.swo -*.tmp # System files .DS_Store @@ -36,8 +33,9 @@ Thumbs.db .env.local *.env.* -# Logs +# Logs and temp files *.log +*.tmp # Coverage coverage/ diff --git a/FarmEngine/src/rendering/graph/RenderGraph.cpp b/FarmEngine/src/rendering/graph/RenderGraph.cpp index f8412e2..f34175e 100644 --- a/FarmEngine/src/rendering/graph/RenderGraph.cpp +++ b/FarmEngine/src/rendering/graph/RenderGraph.cpp @@ -116,7 +116,8 @@ RenderGraphBuilder& RenderGraphBuilder::addDependency(uint32_t from, uint32_t to VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage, VkAccessFlags srcAccess, - VkAccessFlags dstAccess) { + VkAccessFlags dstAccess, + VkDependencyFlags dependencyFlags) { PassDependency dep; dep.from = from; dep.to = to; @@ -124,6 +125,7 @@ RenderGraphBuilder& RenderGraphBuilder::addDependency(uint32_t from, uint32_t to dep.dstStageMask = dstStage; dep.srcAccessMask = srcAccess; dep.dstAccessMask = dstAccess; + dep.dependencyFlags = dependencyFlags; explicitDependencies.push_back(dep); return *this; } @@ -136,7 +138,8 @@ RenderGraphBuilder& RenderGraphBuilder::addResourceDependency(uint32_t from, uin VkAccessFlags dstAccess, VkImageLayout oldLayout, VkImageLayout newLayout, - VkImageAspectFlags aspectMask) { + VkImageAspectFlags aspectMask, + VkDependencyFlags dependencyFlags) { PassDependency dep; dep.from = from; dep.to = to; @@ -148,6 +151,7 @@ RenderGraphBuilder& RenderGraphBuilder::addResourceDependency(uint32_t from, uin dep.oldLayout = oldLayout; dep.newLayout = newLayout; dep.aspectMask = aspectMask; + dep.dependencyFlags = dependencyFlags; explicitDependencies.push_back(dep); return *this; } @@ -268,6 +272,7 @@ void RenderGraph::compile(RenderGraphBuilder&& builder) { pendingBarrier.oldLayout = dep.oldLayout; pendingBarrier.newLayout = dep.newLayout; pendingBarrier.aspectMask = dep.aspectMask; + pendingBarrier.dependencyFlags = dep.dependencyFlags; compiledPasses[dep.to].pendingResourceBarriers.push_back(pendingBarrier); } else { @@ -279,7 +284,7 @@ void RenderGraph::compile(RenderGraphBuilder&& builder) { passDep.dstStageMask = dep.dstStageMask; passDep.srcAccessMask = dep.srcAccessMask; passDep.dstAccessMask = dep.dstAccessMask; - passDep.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + passDep.dependencyFlags = dep.dependencyFlags; compiledPasses[dep.to].passLevelDependencies.push_back(passDep); } @@ -374,8 +379,8 @@ void RenderGraph::recordBarriers(VkCommandBuffer cmd, const CompiledPass& pass, VkPipelineStageFlags combinedSrcStage = 0; VkPipelineStageFlags combinedDstStage = 0; - // Combine dependency flags from all pass-level dependencies - VkDependencyFlags combinedDependencyFlags = 0; + // Combine dependency flags from all pass-level dependencies (for memory barriers only) + VkDependencyFlags combinedMemoryDependencyFlags = 0; // Process pass-level dependencies (emit as VkMemoryBarrier) std::vector memoryBarriers; @@ -388,11 +393,13 @@ void RenderGraph::recordBarriers(VkCommandBuffer cmd, const CompiledPass& pass, combinedSrcStage |= dep.srcStageMask; combinedDstStage |= dep.dstStageMask; - combinedDependencyFlags |= dep.dependencyFlags; + combinedMemoryDependencyFlags |= dep.dependencyFlags; } // Process resource-specific barriers (resolve image at runtime) + // Collect dependency flags from resource barriers separately std::vector imageBarriers; + VkDependencyFlags combinedImageDependencyFlags = 0; for (const auto& pending : pass.pendingResourceBarriers) { VkImage image = registry.getImage(pending.resourceName); const ResourceHandle* res = registry.getResource(pending.resourceName); @@ -421,19 +428,50 @@ void RenderGraph::recordBarriers(VkCommandBuffer cmd, const CompiledPass& pass, combinedSrcStage |= pending.srcStageMask; combinedDstStage |= pending.dstStageMask; + combinedImageDependencyFlags |= pending.dependencyFlags; } - // Emit barriers if any exist - if (!memoryBarriers.empty() || !imageBarriers.empty()) { - // Use combined stage masks, or fallback to ALL_COMMANDS if no stages were specified - VkPipelineStageFlags srcStage = combinedSrcStage != 0 ? combinedSrcStage : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkPipelineStageFlags dstStage = combinedDstStage != 0 ? combinedDstStage : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + // Emit barriers - use separate calls when dependency flags differ to avoid + // unintentionally applying flags (like VK_DEPENDENCY_BY_REGION_BIT) to all barrier types + const bool hasMemoryBarriers = !memoryBarriers.empty(); + const bool hasImageBarriers = !imageBarriers.empty(); + const bool flagsDiffer = combinedMemoryDependencyFlags != combinedImageDependencyFlags; + + // Use combined stage masks, or fallback to ALL_COMMANDS if no stages were specified + VkPipelineStageFlags srcStage = combinedSrcStage != 0 ? combinedSrcStage : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStage = combinedDstStage != 0 ? combinedDstStage : VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + + if (hasMemoryBarriers && hasImageBarriers && flagsDiffer) { + // Emit separate barrier calls to keep dependency flags isolated + vkCmdPipelineBarrier( + cmd, + srcStage, + dstStage, + combinedMemoryDependencyFlags, + static_cast(memoryBarriers.size()), + memoryBarriers.data(), + 0, nullptr, + 0, nullptr + ); vkCmdPipelineBarrier( cmd, srcStage, dstStage, - combinedDependencyFlags, + combinedImageDependencyFlags, + 0, nullptr, + 0, nullptr, + static_cast(imageBarriers.size()), + imageBarriers.data() + ); + } else if (hasMemoryBarriers || hasImageBarriers) { + // Same flags or only one type of barrier - can combine in single call + VkDependencyFlags finalFlags = !memoryBarriers.empty() ? combinedMemoryDependencyFlags : combinedImageDependencyFlags; + vkCmdPipelineBarrier( + cmd, + srcStage, + dstStage, + finalFlags, static_cast(memoryBarriers.size()), memoryBarriers.data(), 0, nullptr, diff --git a/FarmEngine/src/rendering/graph/RenderGraph.h b/FarmEngine/src/rendering/graph/RenderGraph.h index c16423f..ba19d36 100644 --- a/FarmEngine/src/rendering/graph/RenderGraph.h +++ b/FarmEngine/src/rendering/graph/RenderGraph.h @@ -65,6 +65,7 @@ struct PassDependency { VkImageLayout oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout newLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + VkDependencyFlags dependencyFlags = 0; }; class RenderPass { @@ -109,7 +110,8 @@ class RenderGraphBuilder { // in sequential order. Attempting to add a dependency where from >= to will throw an error. RenderGraphBuilder& addDependency(uint32_t from, uint32_t to, VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage, - VkAccessFlags srcAccess, VkAccessFlags dstAccess); + VkAccessFlags srcAccess, VkAccessFlags dstAccess, + VkDependencyFlags dependencyFlags = 0); // Definir dependencias específicas de recursos (para barreras de imagen) // Note: The 'from' pass index must be less than the 'to' pass index, as passes execute @@ -119,7 +121,8 @@ class RenderGraphBuilder { VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage, VkAccessFlags srcAccess, VkAccessFlags dstAccess, VkImageLayout oldLayout, VkImageLayout newLayout, - VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT); + VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + VkDependencyFlags dependencyFlags = 0); private: friend class RenderGraph; @@ -172,6 +175,7 @@ class RenderGraph { VkImageLayout oldLayout; VkImageLayout newLayout; VkImageAspectFlags aspectMask; + VkDependencyFlags dependencyFlags = 0; }; // Pass-level execution dependency info - emitted as VkMemoryBarrier at execution time