Update from task 8f5f5615-9e0f-40cb-8b38-ecc911acf640#20
Conversation
- Fix ECS container type mismatch by changing components to std::vector<std::vector<std::unique_ptr<Component>>>, add entity bounds checks in add/get/removeComponent, fix getComponentTypeIndex to use componentTypeToIndex map with overflow guard - Fix MemoryManager deallocate to find records by pointer, reallocate to copy data using realloc and update tracked size, add ptr field to AllocationHeader - Add Input.h missing includes (unordered_map, array, glm), initialize Input.cpp arrays with correct sizes, add bounds checks in setKeyState/setButtonState - Fix terrain.frag.glsl by adding missing CameraData uniform block, fix MeshRenderer.h duplicate drawCalls member, update Engine.h with FarmEngine namespace alias, clean up .gitignore formatting
There was a problem hiding this comment.
The PR successfully addresses ECS and memory management bugs by adding pointer tracking to the memory manager and refactoring component storage from map-based to vector-based indexing. The changes correctly implement allocation tracking and component access patterns.
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.
There was a problem hiding this comment.
Code Review
This pull request implements a new input system for keyboard, mouse, and gamepad, refactors the ECS to use vector-based component storage, and enhances the MemoryManager to track allocations by pointer. Key feedback includes addressing performance bottlenecks in memory deallocation and ECS component indexing, fixing a logic error in mouse delta calculations that causes lost input, and restoring standard build directories to the .gitignore file.
I am having trouble creating individual review comments. Click here to see my feedback.
FarmEngine/core/memory/MemoryManager.cpp (32-35)
The use of std::find_if on a std::vector for tracking allocations results in std::unordered_map<void*, AllocationHeader> to achieve
FarmEngine/core/memory/MemoryManager.cpp (54-57)
Similar to deallocate, the reallocate function also performs an
FarmEngine/platform/input/Input.cpp (136-147)
The mouse delta calculation in setPosition is flawed because it overwrites the delta value instead of accumulating it. If multiple mouse movement events occur within a single frame, only the last movement's delta is preserved. A more robust approach is to store the current position and calculate the frame-to-frame delta once per frame in processFrame.
void Mouse::setPosition(double x, double y) {
posX = x;
posY = y;
if (motionCallback) {
motionCallback(x, y);
}
}FarmEngine/platform/input/Input.cpp (158-168)
The processFrame method should be responsible for calculating the mouse delta based on the movement since the last frame. The current implementation simply resets the delta to zero, which, combined with the issues in setPosition, leads to incorrect or lost input data.
void Mouse::processFrame() {
// Reset just pressed/released states
std::fill(justPressed.begin(), justPressed.end(), false);
std::fill(justReleased.begin(), justReleased.end(), false);
// Update previous state
previousButtons = currentButtons;
// Calculate delta and update previous position
delta.x = static_cast<float>(posX - prevX);
delta.y = static_cast<float>(posY - prevY);
prevX = posX;
prevY = posY;
}.gitignore (10-12)
The removal of standard build directories like build/ and dist/ from the .gitignore file is likely a regression. These directories are commonly used for build artifacts and should remain ignored to prevent them from being accidentally committed.
FarmEngine/core/ecs/ECS.h (129-144)
Using std::unordered_map with std::type_index in getComponentTypeIndex introduces a performance bottleneck in a hot code path. Since this function is called frequently during component access, the map lookup and RTTI overhead can be significant. Consider using a static variable within a template to assign unique IDs at compile/link time, which would provide
Review Summary by QodoFix critical ECS, memory manager, and input system bugs with proper bounds checking
WalkthroughsDescription• Fix ECS container type mismatch: changed components from map to vector of vectors with proper bounds checking • Fix MemoryManager allocation tracking: added ptr field to AllocationHeader, implemented proper pointer-based deallocation and reallocation • Implement Input system: added complete Input.cpp with keyboard, mouse, gamepad, and input manager implementations with bounds checks • Fix shader and renderer issues: added missing CameraData uniform block in terrain shader, resolved duplicate drawCalls member in MeshRenderer • Add missing includes and namespace alias: updated Input.h with required headers, added FarmEngine namespace alias in Engine.h Diagramflowchart LR
ECS["ECS System<br/>Vector-based components<br/>with bounds checks"]
Memory["MemoryManager<br/>Pointer tracking<br/>in AllocationHeader"]
Input["Input System<br/>Keyboard/Mouse/Gamepad<br/>with array storage"]
Renderer["Renderer Fixes<br/>CameraData uniform<br/>drawCalls deduplication"]
ECS -- "Fixed container type" --> Fix1["Proper entity validation"]
Memory -- "Added ptr field" --> Fix2["Pointer-based lookup"]
Input -- "Implemented" --> Fix3["Bounds-checked arrays"]
Renderer -- "Added uniforms" --> Fix4["Shader compatibility"]
File Changes1. FarmEngine/core/ecs/ECS.cpp
|
Code Review by Qodo
1. Broken namespace alias
|
| // Alias for FarmEngine namespace to maintain backward compatibility | ||
| namespace EngineNS = FarmEngine; | ||
|
|
There was a problem hiding this comment.
1. Broken namespace alias 🐞 Bug ≡ Correctness
FarmEngine/core/Engine.h introduces namespace EngineNS = FarmEngine; inside namespace farm but FarmEngine is not declared at that point, so any translation unit that includes Engine.h first will fail to compile. FarmEngine/core/Engine.cpp includes core/Engine.h as its first include, making this failure immediate for the core target.
Agent Prompt
### Issue description
`Engine.h` defines `namespace EngineNS = FarmEngine;` but `FarmEngine` is not declared in that header before the alias. This breaks compilation when `Engine.h` is the first include in a translation unit (it is in `Engine.cpp`).
### Issue Context
C++ namespace aliases require the target namespace to be declared before the alias.
### Fix Focus Areas
- FarmEngine/core/Engine.h[8-16]
- FarmEngine/core/Engine.cpp[1-9]
### Suggested fix
Choose one of:
1) Add a forward declaration before the alias:
```cpp
namespace FarmEngine {}
namespace farm {
namespace EngineNS = ::FarmEngine;
...
}
```
2) If you intend a global alias (not nested under `farm`), move it outside `namespace farm`:
```cpp
namespace FarmEngine {}
namespace EngineNS = FarmEngine;
namespace farm { ... }
```
Also consider using `::FarmEngine` in the alias to avoid accidental lookup issues.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| layout(binding = 0) uniform CameraData { | ||
| vec3 cameraPosition; | ||
| } cameraData; |
There was a problem hiding this comment.
2. Terrain ubo layout mismatch 🐞 Bug ≡ Correctness
terrain.frag.glsl binds CameraData at binding 0 with only vec3 cameraPosition, but terrain.vert.glsl binding 0 UBO starts with three mat4 fields, so the fragment shader will read incorrect bytes for cameraPosition and compute an invalid view direction. This will produce incorrect lighting/specular results (and is extremely hard to debug because descriptor binding types still appear compatible).
Agent Prompt
### Issue description
The terrain vertex and fragment shaders both use descriptor `binding = 0`, but they declare incompatible UBO layouts. The fragment shader reads `cameraPosition` from offset 0, while the vertex shader’s binding=0 buffer begins with `mat4 model/view/projection`.
### Issue Context
In Vulkan, `binding = 0` refers to the same descriptor binding across shader stages. Even if both are UBOs, differing struct layouts means the fragment stage will interpret the bytes incorrectly.
### Fix Focus Areas
- FarmEngine/assets/shaders/terrain.frag.glsl[11-23]
- FarmEngine/assets/shaders/terrain.vert.glsl[14-20]
- FarmEngine/assets/shaders/terrain.frag.glsl[49-53]
### Suggested fix
Make the fragment shader binding=0 UBO match the vertex shader layout, e.g.:
```glsl
layout(binding = 0) uniform UniformBuffer {
mat4 model;
mat4 view;
mat4 projection;
vec3 cameraPosition;
float time;
} ubo;
// ...
vec3 viewDir = normalize(ubo.cameraPosition - fragPosition);
```
Alternatively, if you truly want a separate camera-only UBO, give it a different binding number and ensure the descriptor set layout and buffer binding are updated accordingly.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| if (entity >= entities.size() || !entities[entity].active) { | ||
| throw std::out_of_range("Invalid or inactive entity ID"); | ||
| } |
There was a problem hiding this comment.
3. Missing stdexcept include 🐞 Bug ≡ Correctness
ECS.h now throws std::out_of_range and std::overflow_error in header-defined templates, but does not include <stdexcept>, causing compilation errors when these templates are instantiated. This is directly introduced by the new validation/overflow checks.
Agent Prompt
### Issue description
`FarmEngine/core/ecs/ECS.h` throws `std::out_of_range` and `std::overflow_error` in template implementations, but the header does not include `<stdexcept>`. This will break compilation when templates are instantiated.
### Issue Context
Because the throwing code is in the header (templates), every translation unit that instantiates these methods needs the proper declarations available via includes.
### Fix Focus Areas
- FarmEngine/core/ecs/ECS.h[1-9]
- FarmEngine/core/ecs/ECS.h[68-74]
- FarmEngine/core/ecs/ECS.h[128-144]
### Suggested fix
Add the missing include near the top:
```cpp
#include <stdexcept>
```
(Keep existing includes as-is.)
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This PR was created by qwen-chat coder for task 8f5f5615-9e0f-40cb-8b38-ecc911acf640.