Skip to content

Update from task a6ea5542-24e3-4e5b-ad34-e79b70444f85#30

Open
tronpis wants to merge 2 commits into
rendergraph-dependency-issues-4b345from
vulkan-barrier-semantics-adjustment-44f85
Open

Update from task a6ea5542-24e3-4e5b-ad34-e79b70444f85#30
tronpis wants to merge 2 commits into
rendergraph-dependency-issues-4b345from
vulkan-barrier-semantics-adjustment-44f85

Conversation

@tronpis
Copy link
Copy Markdown
Owner

@tronpis tronpis commented Apr 2, 2026

This PR was created by qwen-chat coder for task a6ea5542-24e3-4e5b-ad34-e79b70444f85.

- Extended RenderGraphBuilder::addDependency and addResourceDependency with optional VkDependencyFlags parameter
- Modified RenderGraph::compile to default PassLevelDependency::dependencyFlags to 0 instead of VK_DEPENDENCY_BY_REGION_BIT
- Updated RenderGraph::recordBarriers to emit separate vkCmdPipelineBarrier calls when memory and image barriers have different dependency flags
- Added dependencyFlags field to PassDependency, PendingResourceBarrier and PassLevelDependency structs
- Fixed barrier emission logic to prevent BY_REGION flag from incorrectly applying to all barrier types in same call

This change provides explicit control over dependency flags while maintaining safe defaults and ensuring correct synchronization behavior for different resource types.
@qodo-code-review
Copy link
Copy Markdown

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Fix VK_DEPENDENCY_BY_REGION_BIT overuse in RenderGraph barriers

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Fixed VK_DEPENDENCY_BY_REGION_BIT overuse by adding explicit VkDependencyFlags parameter to
  dependency methods
• Modified barrier emission logic to use separate vkCmdPipelineBarrier calls when memory and image
  barriers have different dependency flags
• Changed PassLevelDependency default dependencyFlags from VK_DEPENDENCY_BY_REGION_BIT to 0 for
  safer defaults
• Added dependencyFlags field to PassDependency, PendingResourceBarrier, and PassLevelDependency
  structs
Diagram
flowchart LR
  A["addDependency<br/>addResourceDependency"] -->|"add dependencyFlags<br/>parameter"| B["PassDependency struct"]
  B -->|"propagate flags"| C["PendingResourceBarrier<br/>PassLevelDependency"]
  C -->|"separate barriers<br/>if flags differ"| D["vkCmdPipelineBarrier calls"]
  E["Default: 0<br/>not BY_REGION_BIT"] -->|"safer defaults"| D
Loading

Grey Divider

File Changes

1. FarmEngine/src/rendering/graph/RenderGraph.h ✨ Enhancement +6/-2

Add dependencyFlags parameter to dependency methods

• Added VkDependencyFlags dependencyFlags = 0 field to PassDependency struct
• Added VkDependencyFlags dependencyFlags = 0 field to PendingResourceBarrier struct
• Extended addDependency() method signature with optional VkDependencyFlags dependencyFlags = 0
 parameter
• Extended addResourceDependency() method signature with optional `VkDependencyFlags
 dependencyFlags = 0` parameter

FarmEngine/src/rendering/graph/RenderGraph.h


2. FarmEngine/src/rendering/graph/RenderGraph.cpp 🐞 Bug fix +50/-12

Implement separate barrier calls for different dependency flags

• Updated addDependency() to accept and store dependencyFlags parameter in PassDependency
• Updated addResourceDependency() to accept and store dependencyFlags parameter in
 PassDependency
• Changed PassLevelDependency::dependencyFlags default from VK_DEPENDENCY_BY_REGION_BIT to
 dep.dependencyFlags (0 by default)
• Refactored recordBarriers() to track separate dependency flags for memory and image barriers
• Implemented logic to emit separate vkCmdPipelineBarrier calls when memory and image barrier
 flags differ
• Added fallback to combined call when flags are identical or only one barrier type exists

FarmEngine/src/rendering/graph/RenderGraph.cpp


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 2, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Per-dependency flags lost 🐞 Bug ≡ Correctness
Description
RenderGraph::recordBarriers bitwise-ORs dependencyFlags across all memory barriers and across all
image barriers, then applies the combined value to a single vkCmdPipelineBarrier call. This makes it
impossible to use different VkDependencyFlags for different dependencies of the same barrier type
because a flag set by one dependency is applied to all barriers in that batch.
Code

FarmEngine/src/rendering/graph/RenderGraph.cpp[R382-386]

+    // Combine dependency flags from all pass-level dependencies (for memory barriers only)
+    VkDependencyFlags combinedMemoryDependencyFlags = 0;
    
    // Process pass-level dependencies (emit as VkMemoryBarrier)
    std::vector<VkMemoryBarrier> memoryBarriers;
Evidence
The builder API now allows specifying dependencyFlags per dependency, but recordBarriers collapses
those per-dependency values into a single OR-combined mask per barrier type and uses that one mask
for the entire batch call, which necessarily applies flags beyond the dependency that requested
them.

FarmEngine/src/rendering/graph/RenderGraph.h[108-125]
FarmEngine/src/rendering/graph/RenderGraph.cpp[382-397]
FarmEngine/src/rendering/graph/RenderGraph.cpp[401-432]
FarmEngine/src/rendering/graph/RenderGraph.cpp[467-480]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`RenderGraph::recordBarriers()` currently merges `VkDependencyFlags` via bitwise-OR across all memory barriers and across all image barriers, then uses that single value for a batched `vkCmdPipelineBarrier()` call. Since `vkCmdPipelineBarrier()` takes one `dependencyFlags` value per call, this causes any flag requested by one dependency to be applied to all barriers in that batch, defeating the intent of the new per-dependency `dependencyFlags` API.

### Issue Context
The builder now accepts `dependencyFlags` per dependency, so the runtime barrier emission should respect heterogeneous flags.

### Fix Focus Areas
- FarmEngine/src/rendering/graph/RenderGraph.cpp[377-482]

### Suggested approach
1. Group barriers by `VkDependencyFlags` value (at least within each barrier type):
  - Build `std::unordered_map<VkDependencyFlags, Group>` where `Group` contains:
    - `std::vector<VkMemoryBarrier> memoryBarriers`
    - `std::vector<VkImageMemoryBarrier> imageBarriers`
    - `VkPipelineStageFlags srcStages`, `dstStages`
2. For each pass-level dependency, append to `groups[dep.dependencyFlags].memoryBarriers` and OR its stage masks into that group's stage masks.
3. For each pending resource barrier, append to `groups[pending.dependencyFlags].imageBarriers` and OR its stage masks into that group's stage masks.
4. Iterate groups and emit **one `vkCmdPipelineBarrier()` per flags value**, using that group’s stage masks (with the existing ALL_COMMANDS fallback per group).

This preserves per-dependency flag semantics while still batching where possible.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

2. Default flags behavior changed 🐞 Bug ⚙ Maintainability
Description
Existing addDependency() call sites that omit the new dependencyFlags parameter now pass 0, and
compile() propagates that value instead of forcing VK_DEPENDENCY_BY_REGION_BIT. This changes the
dependencyFlags used for pass-level barriers (and no longer incidentally applies BY_REGION to image
barriers via a shared call), so downstream code may need to explicitly pass the desired flags.
Code

FarmEngine/src/rendering/graph/RenderGraph.cpp[R284-288]

            passDep.dstStageMask = dep.dstStageMask;
            passDep.srcAccessMask = dep.srcAccessMask;
            passDep.dstAccessMask = dep.dstAccessMask;
-            passDep.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
+            passDep.dependencyFlags = dep.dependencyFlags;
            
Evidence
The API introduces a new parameter with a default of 0, and existing usage (ExampleUsage) does not
provide it, so the propagated flags become 0. compile() now forwards dep.dependencyFlags into
passDep.dependencyFlags, making this behavioral change effective at runtime.

FarmEngine/src/rendering/graph/RenderGraph.h[108-115]
FarmEngine/src/rendering/graph/ExampleUsage.h[105-113]
FarmEngine/src/rendering/graph/RenderGraph.cpp[279-289]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`addDependency(..., VkDependencyFlags dependencyFlags = 0)` introduces a new default that changes behavior for existing call sites: pass-level dependencies now use `dependencyFlags=0` unless explicitly provided (previously `VK_DEPENDENCY_BY_REGION_BIT` was forced during compilation).

### Issue Context
This may be intentional, but it’s a breaking behavioral change for any existing code that relied on the old implicit `VK_DEPENDENCY_BY_REGION_BIT` behavior.

### Fix Focus Areas
- FarmEngine/src/rendering/graph/RenderGraph.h[108-115]
- FarmEngine/src/rendering/graph/ExampleUsage.h[105-113]
- FarmEngine/src/rendering/graph/RenderGraph.cpp[279-289]

### Suggested fixes (choose one)
- **If you want backward compatibility:** change the default parameter to `VK_DEPENDENCY_BY_REGION_BIT` (or reintroduce a compile-time default for pass-level deps) and document it.
- **If the change is intentional:** update examples/docs (and any real call sites) to pass `VK_DEPENDENCY_BY_REGION_BIT` (or other flags) explicitly where desired, and add a brief note in code comments/changelog about the new default being 0.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link
Copy Markdown
Contributor

@amazon-q-developer amazon-q-developer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR correctly addresses Vulkan barrier semantics by removing the hardcoded VK_DEPENDENCY_BY_REGION_BIT and allowing proper per-dependency flag control. The implementation properly separates memory and image barrier dependency flags to prevent unintended flag propagation.

Critical Issue Found:

  • Line 469: Logic error in ternary operator could select wrong dependency flags when both barrier types exist

Changes Validated:

  • API signature updates for addDependency and addResourceDependency with optional dependencyFlags parameter
  • Proper propagation of dependency flags through compilation pipeline
  • Separate tracking of memory vs image barrier flags to prevent cross-contamination

Please address the critical finding before merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Comment thread FarmEngine/src/rendering/graph/RenderGraph.cpp Outdated
Co-authored-by: amazon-q-developer[bot] <208079219+amazon-q-developer[bot]@users.noreply.github.com>
Comment on lines +382 to 386
// Combine dependency flags from all pass-level dependencies (for memory barriers only)
VkDependencyFlags combinedMemoryDependencyFlags = 0;

// Process pass-level dependencies (emit as VkMemoryBarrier)
std::vector<VkMemoryBarrier> memoryBarriers;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Per-dependency flags lost 🐞 Bug ≡ Correctness

RenderGraph::recordBarriers bitwise-ORs dependencyFlags across all memory barriers and across all
image barriers, then applies the combined value to a single vkCmdPipelineBarrier call. This makes it
impossible to use different VkDependencyFlags for different dependencies of the same barrier type
because a flag set by one dependency is applied to all barriers in that batch.
Agent Prompt
### Issue description
`RenderGraph::recordBarriers()` currently merges `VkDependencyFlags` via bitwise-OR across all memory barriers and across all image barriers, then uses that single value for a batched `vkCmdPipelineBarrier()` call. Since `vkCmdPipelineBarrier()` takes one `dependencyFlags` value per call, this causes any flag requested by one dependency to be applied to all barriers in that batch, defeating the intent of the new per-dependency `dependencyFlags` API.

### Issue Context
The builder now accepts `dependencyFlags` per dependency, so the runtime barrier emission should respect heterogeneous flags.

### Fix Focus Areas
- FarmEngine/src/rendering/graph/RenderGraph.cpp[377-482]

### Suggested approach
1. Group barriers by `VkDependencyFlags` value (at least within each barrier type):
   - Build `std::unordered_map<VkDependencyFlags, Group>` where `Group` contains:
     - `std::vector<VkMemoryBarrier> memoryBarriers`
     - `std::vector<VkImageMemoryBarrier> imageBarriers`
     - `VkPipelineStageFlags srcStages`, `dstStages`
2. For each pass-level dependency, append to `groups[dep.dependencyFlags].memoryBarriers` and OR its stage masks into that group's stage masks.
3. For each pending resource barrier, append to `groups[pending.dependencyFlags].imageBarriers` and OR its stage masks into that group's stage masks.
4. Iterate groups and emit **one `vkCmdPipelineBarrier()` per flags value**, using that group’s stage masks (with the existing ALL_COMMANDS fallback per group).

This preserves per-dependency flag semantics while still batching where possible.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the project's .gitignore and enhances the Vulkan RenderGraph to support explicit VkDependencyFlags. The RenderGraph now correctly handles cases where memory and image barriers have different dependency flags by splitting them into separate vkCmdPipelineBarrier calls. A syntax error was identified in the .gitignore file where markdown code block markers were incorrectly added to the top of the file.

Comment thread .gitignore
@@ -1,33 +1,30 @@
```
# Compiled and binary files
```cpp
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The .gitignore file contains markdown code block syntax (```cpp). This is invalid for a .gitignore file and should be removed. Git will interpret this line as a literal pattern to match.

# Compiled and build artifacts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants