VEX Engine
Retro looking game engine made in vulkan mostly because i wanted to understand it better.
Loading...
Searching...
No Matches
VulkanBoundsChecking.hpp
Go to the documentation of this file.
1
6
7#pragma once
8
9#include <cstdint>
10#include <vector>
11#include <SDL3/SDL.h>
12#include <cassert>
13
14namespace vex {
15
21 inline bool validateVectorBounds(uint32_t index, size_t size, const char* name) {
22 if (index >= size) {
23 log(LogLevel::ERROR,
24 "VulkanBoundsChecking: %s index out of bounds (index: %u, size: %zu)",
25 name, index, size);
26 return false;
27 }
28 return true;
29 }
30
36 inline bool validateVectorBounds(size_t index, size_t size, const char* name) {
37 if (index >= size) {
38 log(LogLevel::ERROR,
39 "VulkanBoundsChecking: %s index out of bounds (index: %zu, size: %zu)",
40 name, index, size);
41 return false;
42 }
43 return true;
44 }
45
50 inline bool validateFrameIndex(uint32_t frameIndex, uint32_t maxFrames) {
51 if (frameIndex >= maxFrames) {
52 log(LogLevel::ERROR,
53 "VulkanBoundsChecking: Frame index %u exceeds MAX_FRAMES_IN_FLIGHT (%u)",
54 frameIndex, maxFrames);
55 return false;
56 }
57 return true;
58 }
59
64 inline bool validateImageIndex(uint32_t imageIndex, size_t imageCount) {
65 if (imageIndex >= imageCount) {
66 log(LogLevel::ERROR,
67 "VulkanBoundsChecking: Image index %u exceeds swapchain image count (%zu)",
68 imageIndex, imageCount);
69 return false;
70 }
71 return true;
72 }
73
81 template<typename T>
82 inline T safeVectorAccess(const std::vector<T>& vec, size_t index, const char* name, T defaultValue) {
83 if (index >= vec.size()) {
84 log(LogLevel::ERROR,
85 "VulkanBoundsChecking: Safe access to %s failed (index: %zu, size: %zu)",
86 name, index, vec.size());
87 return defaultValue;
88 }
89 return vec[index];
90 }
91
98 template<typename T>
99 inline T* safeVectorAccessPtr(std::vector<T>& vec, size_t index, const char* name) {
100 if (index >= vec.size()) {
101 log(LogLevel::ERROR,
102 "VulkanBoundsChecking: Safe pointer access to %s failed (index: %zu, size: %zu)",
103 name, index, vec.size());
104 return nullptr;
105 }
106 return &vec[index];
107 }
108
114 template<typename T>
115 inline bool validateVectorSize(const std::vector<T>& vec, size_t expectedSize, const char* name) {
116 if (vec.size() != expectedSize) {
117 log(LogLevel::ERROR,
118 "VulkanBoundsChecking: %s size mismatch (expected: %zu, actual: %zu)",
119 name, expectedSize, vec.size());
120 return false;
121 }
122 return true;
123 }
124
130 template<typename T>
131 inline bool validateVectorMinSize(const std::vector<T>& vec, size_t minSize, const char* name) {
132 if (vec.size() < minSize) {
133 log(LogLevel::ERROR,
134 "VulkanBoundsChecking: %s size too small (minimum: %zu, actual: %zu)",
135 name, minSize, vec.size());
136 return false;
137 }
138 return true;
139 }
140
145 size_t size1, const char* name1,
146 size_t size2, const char* name2,
147 size_t size3, const char* name3) {
148
149 bool valid = true;
150
151 if (size1 != size2) {
152 log(LogLevel::WARNING,
153 "VulkanBoundsChecking: %s size (%zu) != %s size (%zu)",
154 name1, size1, name2, size2);
155 valid = false;
156 }
157
158 if (size1 != size3) {
159 log(LogLevel::WARNING,
160 "VulkanBoundsChecking: %s size (%zu) != %s size (%zu)",
161 name1, size1, name3, size3);
162 valid = false;
163 }
164
165 return valid;
166 }
167
173 template<typename T>
174 inline bool validateNonNullHandles(const std::vector<T>& vec, const char* name) {
175 for (size_t i = 0; i < vec.size(); ++i) {
176 if (vec[i] == nullptr || vec[i] == VK_NULL_HANDLE) {
177 log(LogLevel::ERROR,
178 "VulkanBoundsChecking: %s contains null/invalid handle at index %zu",
179 name, i);
180 return false;
181 }
182 }
183 return true;
184 }
185
195 size_t imageAvailSize,
196 size_t renderFinishedSize,
197 size_t fencesSize,
198 size_t poolsSize,
199 size_t buffersSize,
200 uint32_t expectedSize) {
201
202 assert(imageAvailSize == expectedSize &&
203 "imageAvailableSemaphores size mismatch with MAX_FRAMES_IN_FLIGHT");
204 assert(renderFinishedSize == expectedSize &&
205 "renderFinishedSemaphores size mismatch with MAX_FRAMES_IN_FLIGHT");
206 assert(fencesSize == expectedSize &&
207 "inFlightFences size mismatch with MAX_FRAMES_IN_FLIGHT");
208 assert(poolsSize == expectedSize &&
209 "commandPools size mismatch with MAX_FRAMES_IN_FLIGHT");
210 assert(buffersSize == expectedSize &&
211 "commandBuffers size mismatch with MAX_FRAMES_IN_FLIGHT");
212 }
213
216 #define VEX_CHECK_FRAME_INDEX(index, maxFrames, funcName) \
217 do { \
218 if (!vex::validateFrameIndex(index, maxFrames)) { \
219 log(LogLevel::ERROR, "%s: Aborting due to invalid frame index", funcName); \
220 return; \
221 } \
222 } while(0)
223
226 #define VEX_CHECK_FRAME_INDEX_BOOL(index, maxFrames, funcName) \
227 do { \
228 if (!vex::validateFrameIndex(index, maxFrames)) { \
229 log(LogLevel::ERROR, "%s: Aborting due to invalid frame index", funcName); \
230 return false; \
231 } \
232 } while(0)
233
236 #define VEX_CHECK_IMAGE_INDEX(index, imageCount, funcName) \
237 do { \
238 if (!vex::validateImageIndex(index, imageCount)) { \
239 log(LogLevel::ERROR, "%s: Aborting due to invalid image index", funcName); \
240 return; \
241 } \
242 } while(0)
243
246 #define VEX_CHECK_BOUNDS(index, size, name) \
247 do { \
248 if (!vex::validateVectorBounds(index, size, name)) { \
249 log(LogLevel::ERROR, "Bounds check failed for %s", name); \
250 return; \
251 } \
252 } while(0)
253
256 #define VEX_CHECK_BOUNDS_BOOL(index, size, name) \
257 do { \
258 if (!vex::validateVectorBounds(index, size, name)) { \
259 log(LogLevel::ERROR, "Bounds check failed for %s", name); \
260 return false; \
261 } \
262 } while(0)
263
264} // namespace vex
265```
266
267Now let me create a documentation file explaining the bounds checking system:
bool validateVectorSize(const std::vector< T > &vec, size_t expectedSize, const char *name)
Validates that a vector is properly sized.
T safeVectorAccess(const std::vector< T > &vec, size_t index, const char *name, T defaultValue)
Safely accesses a vector element with bounds checking.
void assertSyncObjectConsistency(size_t imageAvailSize, size_t renderFinishedSize, size_t fencesSize, size_t poolsSize, size_t buffersSize, uint32_t expectedSize)
Asserts that all frame-dependent sync object vectors are properly sized.
T * safeVectorAccessPtr(std::vector< T > &vec, size_t index, const char *name)
Safely accesses a vector element with bounds checking (mutable version).
bool validateFrameIndex(uint32_t frameIndex, uint32_t maxFrames)
Validates that a frame index is valid.
bool validateVectorMinSize(const std::vector< T > &vec, size_t minSize, const char *name)
Validates that a vector has minimum required size.
bool validateImageIndex(uint32_t imageIndex, size_t imageCount)
Validates that an image index is valid.
bool validateNonNullHandles(const std::vector< T > &vec, const char *name)
Validates that all pointers in a vector are non-null.
void VEX_EXPORT log(const char *fmt,...)
Logs a formatted message.
bool validateFrameVectorConsistency(size_t size1, const char *name1, size_t size2, const char *name2, size_t size3, const char *name3)
Validates that multiple frame-dependent vectors have consistent sizes.
bool validateVectorBounds(uint32_t index, size_t size, const char *name)
Validates that an index is within bounds of a vector.