载入中...
搜索中...
未找到
Graphics.h
浏览该文件的文档.
1#pragma once
2#include <array>
3#include <atomic>
4#include <cstdint>
5#include <glm/glm.hpp>
6#include <memory>
7#include <optional>
8#include <unordered_map>
9#include <vector>
10#include "graphics/Batcher.h"
12#include "graphics/Graphics.h"
13#include "graphics/Light.h"
14#include "graphics/Mesh.h"
15#include "graphics/Shader.h"
16#include "graphics/Shadow.h"
17#include "graphics/Texture.h"
18#include "vkbuilder.hpp"
19#include "vkbuilder/framegraph.hpp"
20
21namespace eve::graphics::vulkan {
22
23class OffscreenCanvas;
24
26 glm::vec2 pos;
27 glm::vec4 color;
28
29 static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding) {
30 vk::VertexInputBindingDescription b{};
31 b.binding = binding;
32 b.stride = sizeof(ColorVertex);
33 b.inputRate = vk::VertexInputRate::eVertex;
34 return b;
35 }
36 static std::vector<vk::VertexInputAttributeDescription> getAttributeDescription(uint32_t binding) {
37 return {
38 {0, binding, vk::Format::eR32G32Sfloat, offsetof(ColorVertex, pos)},
39 {1, binding, vk::Format::eR32G32B32A32Sfloat, offsetof(ColorVertex, color)},
40 };
41 }
42};
43
45 glm::vec2 pos;
46 glm::vec4 color;
47 glm::vec2 uv;
48
49 static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding) {
50 vk::VertexInputBindingDescription b{};
51 b.binding = binding;
52 b.stride = sizeof(TexturedVertex);
53 b.inputRate = vk::VertexInputRate::eVertex;
54 return b;
55 }
56 static std::vector<vk::VertexInputAttributeDescription> getAttributeDescription(uint32_t binding) {
57 return {
58 {0, binding, vk::Format::eR32G32Sfloat, offsetof(TexturedVertex, pos)},
59 {1, binding, vk::Format::eR32G32B32A32Sfloat, offsetof(TexturedVertex, color)},
60 {2, binding, vk::Format::eR32G32Sfloat, offsetof(TexturedVertex, uv)},
61 };
62 }
63};
64
65struct MeshVertex {
66 glm::vec3 pos;
67 glm::vec3 normal;
68 glm::vec2 uv;
69
70 static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding) {
71 vk::VertexInputBindingDescription b{};
72 b.binding = binding;
73 b.stride = sizeof(MeshVertex);
74 b.inputRate = vk::VertexInputRate::eVertex;
75 return b;
76 }
77 static std::vector<vk::VertexInputAttributeDescription> getAttributeDescription(uint32_t binding) {
78 return {
79 {0, binding, vk::Format::eR32G32B32Sfloat, offsetof(MeshVertex, pos)},
80 {1, binding, vk::Format::eR32G32B32Sfloat, offsetof(MeshVertex, normal)},
81 {2, binding, vk::Format::eR32G32Sfloat, offsetof(MeshVertex, uv)},
82 };
83 }
84};
85
86struct Mesh3DUBO {
87 // Layout prefix matches legacy custom Mesh3D shaders (toon etc.).
88 glm::mat4 mvp{1.f};
89 glm::mat4 model{1.f};
90 glm::vec4 lightDir{0.4f, 1.f, 0.3f, 0.f}; // xyz = primary dir; w = lightCount
91 glm::vec4 lightColor{1.f, 1.f, 1.f, 0.f}; // rgb = primary color; w = envIntensity (IBL)
92 glm::vec4 tint{1.f, 1.f, 1.f, 1.f};
93 glm::vec4 cameraPos{0.f, 0.f, 3.f, 0.45f}; // xyz = eye; w = roughness
94 glm::vec4 ambient{0.12f, 0.12f, 0.14f, 0.f}; // rgb = ambient; w = metallic
96 // Appended: custom shaders that only read the prefix stay valid (buffer may be larger).
97 glm::vec4 texBomb{4.f, 0.f, 1.f, 0.f}; // x=cellScale, y=strength (0=off), z=rotAmount
98 glm::vec4 parallax{0.f, 8.f, 32.f, 0.f}; // x=scale (0=off), y=minLayers, z=maxLayers
99 glm::mat4 view{1.f}; // camera view (CSM / view-space depth)
100 glm::vec4 clipInfo{0.1f, 100.f, 0.f, 0.f}; // x=near, y=far (linear depth in scene color A)
101 // Dynamic cloud shadows on ground. cloud.x=strength (0=off), y=world cell size,
102 // z=time, w=unused; cloudWind.xy=wind velocity (world/s), z=coverage, w=detail.
103 glm::vec4 cloud{0.f, 1.5f, 0.f, 0.f};
104 glm::vec4 cloudWind{4.f, 0.f, 0.55f, 0.5f};
105};
106
108 glm::mat4 mvp{1.f};
109 glm::mat4 model{1.f};
110 glm::mat4 view{1.f};
111 glm::vec4 lightDir{0.4f, 1.f, 0.3f, 0.f};
112 glm::vec4 lightColor{1.f, 1.f, 1.f, 0.f}; // rgb = primary; w = envIntensity
113 glm::vec4 tint{1.f, 1.f, 1.f, 1.f};
114 glm::vec4 cameraPos{0.f, 0.f, 3.f, 0.45f};
115 glm::vec4 ambient{0.12f, 0.12f, 0.14f, 0.f};
116 glm::vec4 gridInfo{16.f, 9.f, 24.f, 0.f};
117 glm::vec4 clipInfo{0.1f, 100.f, 1.f, 1.f};
118 glm::vec4 texBomb{4.f, 0.f, 1.f, 0.f}; // x=cellScale, y=strength (0=off), z=rotAmount
119 glm::vec4 parallax{0.f, 8.f, 32.f, 0.f}; // x=scale (0=off), y=minLayers, z=maxLayers
120};
121
123 vkb::TextureImage2D image;
124 vkb::TextureImageCube cubeImage;
125 bool isCube = false;
126 vk::Sampler sampler;
127 vkb::BoundSet descriptorSet;
128 vk::ImageView viewOverride{};
129 int width = 0;
130 int height = 0;
131 uint32_t mipLevels = 1;
133
134 vk::ImageView imageView() const {
135 if (viewOverride) return viewOverride;
136 return isCube ? cubeImage.imageView() : image.imageView();
137 }
138};
139
140struct GpuMesh {
145 static constexpr size_t kDynamicVertexCopies = 3;
146 vkb::HostVertexBuffer vertices;
147 vkb::GenericBuffer indices;
148 std::array<vkb::HostVertexBuffer, kDynamicVertexCopies> dynVertices;
149 std::array<vkb::GenericBuffer, kDynamicVertexCopies> dynIndices;
152 std::vector<uint32_t> cpuIndices;
154 uint64_t dynamicWriteCount = 0;
155 bool dynamic = false;
156 uint32_t indexCount = 0;
157 vk::IndexType indexType = vk::IndexType::eUint32;
158};
159
160struct GpuShader {
161 vk::Pipeline swapchainPipeline;
162 vk::Pipeline offscreenPipeline;
163 vk::Pipeline mesh3dPipeline;
164 vk::Pipeline mesh3dXrayPipeline;
165 vk::PipelineLayout pipelineLayout;
166 bool isMesh3D = false;
167 bool isHair3D = false;
168 Shader *owner = nullptr;
169};
170
171class Graphics final : public eve::graphics::Graphics {
172public:
173 ~Graphics() override;
174
175 std::string getBackendName() const override;
176
177 void initWithWindow(void *nativeWindow) override;
178 void present() override;
179 void requestSurfaceRecreate() override { surfaceNeedsRecreate = true; }
180 void onNativeWindowDestroyed() override;
181 void setScreenReadbackEnabled(bool enabled) override {
183 ensurePresentCaptureHook();
184 }
185 void setVSync(bool enabled) override {
186 if (vsyncEnabled == enabled) return;
188 markSwapchainDirty();
189 }
190 void setMsaaSamples(int samples) override {
191 const int raw = samples > 1 ? samples : 0;
192 if (raw == msaaSamples) return;
194 }
195 int getMsaaSamples() const override { return msaaSamples; }
196 void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override;
197 void drawSolidRect(float x, float y, float w, float h, const Color &color,
198 BlendMode blend = BlendMode::Alpha) override;
199 void drawSolidRectRotated(float cx, float cy, float w, float h, float degrees,
200 const Color &color,
201 BlendMode blend = BlendMode::Alpha) override;
202 void pushValidationScope() override {}
203 void popValidationScope() override {}
204 Texture *newTexture(int width, int height, const uint8_t *rgba, bool repeatU = false,
205 bool repeatV = false) override;
206 Texture *newTexture(int width, int height, const uint8_t *rgba,
207 const TextureCreateInfo &info) override;
208 Texture *newCubemap(int faceSize, const uint8_t *rgbaFaces) override;
209 Texture *newCubemap(int faceSize, const uint8_t *rgbaFaces,
210 const TextureCreateInfo &info) override;
211 Texture *newTexture(image::ImageData *data) override;
212 Texture *newTexture(image::ImageData *data, const TextureCreateInfo &info) override;
213 void setTextureSampler(Texture *texture, const TextureSampler &sampler) override;
214 float getMaxAnisotropy() const override;
215 Texture *newTextureFromFile(const std::string &filename) override;
216 bool reloadTextureFromFile(const std::string &filename) override;
217 bool releaseTexture(Texture *texture) override;
219 void drawTexturedRect(Texture *texture, float x, float y, float w, float h, const Color &color) override;
220 void drawTexturedRectShader(Texture *texture, Shader *shader, float x, float y, float w, float h,
221 const Color &color) override;
222 void drawTexturedRectUV(Texture *texture, float x, float y, float w, float h, float u0, float v0,
223 float u1, float v1, const Color &color) override;
224 void drawTexturedRectShaderUV(Texture *texture, Shader *shader, float x, float y, float w,
225 float h, float u0, float v0, float u1, float v1,
226 const Color &color, bool rotatedUV = false,
227 BlendMode blend = BlendMode::Alpha) override;
228 void drawTexturedRectShaderUVRotated(Texture *texture, Shader *shader, float cx, float cy,
229 float w, float h, float degrees, float u0, float v0,
230 float u1, float v1, const Color &color,
231 bool rotatedUV = false,
232 BlendMode blend = BlendMode::Alpha) override;
234 float w, float h, const Color &tint) override;
235 void drawTexturedRectLitUV(Texture *albedo, Texture *normal, float x, float y, float w, float h,
236 float u0, float v0, float u1, float v1, const Color &color) override;
237 void setLighting2D(const Lighting2DUBO &ubo) override;
238 Shader *newShaderFromSpv(const std::vector<uint32_t> &vertSpv,
239 const std::vector<uint32_t> &fragSpv) override;
240 Shader *newShaderFromSpvFile(const std::string &vertPath, const std::string &fragPath) override;
241 Shader *newShader(const std::string &vertGlsl, const std::string &fragGlsl) override;
242 Shader *newMeshShaderFromSpv(const std::vector<uint32_t> &vertSpv,
243 const std::vector<uint32_t> &fragSpv) override;
244 Shader *newMeshShaderFromWgsl(const std::string &vertWgsl,
245 const std::string &fragWgsl) override;
246 Shader *newMeshShader(const std::string &vertGlsl, const std::string &fragGlsl) override;
247 Shader *newHairShaderFromSpv(const std::vector<uint32_t> &vertSpv,
248 const std::vector<uint32_t> &fragSpv) override;
249 bool releaseShader(Shader *shader) override;
250 Mesh *newMeshFromAssimp(const ::aiMesh &mesh) override;
251 Mesh *newMeshFromAssimp(const ::aiMesh &mesh, const aiMatrix4x4 &worldTransform) override;
252 Mesh *newMeshFromArrays(const float *posXYZ, const float *nrmXYZ, const float *uvST,
253 int vertexCount, const uint32_t *indices, int indexCount) override;
254 bool bakeMeshMorph(Mesh *mesh) override;
255 bool updateMeshVertices(Mesh *mesh, const float *posXYZ, const float *nrmXYZ, const float *uvST,
256 int vertexCount, const uint32_t *indices, int indexCount) override;
257 Mesh *newMeshSphere(int slices = 32, int stacks = 16) override;
258 Mesh *newMeshCylinder(int slices = 32, int stacks = 1, bool caps = true) override;
259 bool releaseMesh(Mesh *mesh) override;
260 void begin3DFrame() override;
261 void begin3DFrameToCanvas(Canvas *canvas) override;
262 void end3DFrameToCanvas() override;
263 void setMesh3DViewProj(const glm::mat4 &viewProj) override;
264 void setMesh3DView(const glm::mat4 &view) override;
265 void setMesh3DClip(float nearZ, float farZ) override;
266 Texture *getSceneColorTexture() override;
268 const std::vector<eve::graphics::Graphics::EntityIdDraw> &draws, const glm::mat4 &viewProj,
269 int width, int height) override;
270 image::ImageData *readGBufferToImageData(const std::string &name) override;
271 void drawMesh(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint) override;
272 void drawMeshShader(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint,
273 Shader *shader) override;
274 void drawVoxelFaceInstances(const uint32_t *packed, int count, float originX, float originY,
275 float originZ, const std::string &faceDir, Texture *atlas,
276 int tilesPerRow = 16, const uint32_t *ao = nullptr) override;
277 void setMesh3DNormalTexture(Texture *normal) override;
278 void setMesh3DHeightTexture(Texture *height) override;
279 void setMesh3DSceneDepth(Texture *depth) override;
280 void setMesh3DMaterial(float metallic, float roughness) override;
281 void setMesh3DTexCellBomb(float cellScale, float strength, float rotAmount = 1.f) override;
282 void setMesh3DParallax(float scale, float minLayers = 8.f, float maxLayers = 32.f) override;
283 void setMesh3DLighting(const Lighting3DPack &pack) override;
284 void setCloudShadows(float strength, float worldCell, float time, float windSpeed, float windAngle, float coverage,
285 float detail) override;
286 void setMesh3DClusteredLighting(const ClusteredLightingUpload &upload) override;
287 void setMesh3DClusteredActive(bool active) override;
288 void setMesh3DLight(const glm::vec3 &dir, const glm::vec3 &color) override;
289 void setMesh3DCameraPos(const glm::vec3 &eye) override;
290 void setMesh3DEnv(Texture *cube, float intensity) override;
291 void setMesh3DShadows(const ShadowUpload &upload) override;
292 void setMesh3DShadowReceive(bool receive) override;
293 void beginShadowPass(int cascadeIndex) override;
294 void drawMeshShadow(Mesh *mesh, const glm::mat4 &lightMVP) override;
295 void drawMeshShadowAlpha(Mesh *mesh, const glm::mat4 &lightMVP, Texture *albedo = nullptr) override;
296 void endShadowPass() override;
297
298 void beginGBufferPass(int width, int height) override;
299 void drawMeshGBuffer(Mesh *mesh, const glm::mat4 &mvp, const glm::mat4 &model, float nearZ,
300 float farZ, Texture *albedo = nullptr, float tintR = 1.f, float tintG = 1.f,
301 float tintB = 1.f) override;
302 void drawMeshGBufferAlpha(Mesh *mesh, const glm::mat4 &mvp, const glm::mat4 &model, float nearZ,
303 float farZ, Texture *albedo = nullptr, float tintR = 1.f,
304 float tintG = 1.f, float tintB = 1.f) override;
305 void endGBufferPass() override;
306
307 Canvas *newCanvas(int width, int height) override;
308 void setCanvas(Canvas *canvas) override;
309 bool isCanvasActive() const override;
310 Canvas *getCanvas() const override;
311
312 Texture *getTexture() override;
313 image::ImageData *newImageData() override;
314
315 void draw(eve::graphics::Graphics *gfx, const glm::mat4 &matrix) const override;
316 void draw(Canvas *C, const glm::mat4 &matrix) const override;
317 void clear(std::optional<Color> color, std::optional<int> stencil, std::optional<double> depth) override;
318 Color getPixel(int x, int y) override;
319
320 vkb::Device &getDevice() { return device; }
321 vk::CommandPool getUploadPool() const { return uploadPool; }
322 vk::DescriptorSetLayout getTexSetLayout() const { return texSetLayout; }
323 vk::DescriptorPool getDescriptorPool() const { return descriptorPool; }
324 const vkb::BuiltRenderPass &getOffscreenRenderPass() const { return offscreenRenderPass; }
325 const vkb::BuiltRenderPass &getOffscreen3DRenderPass() { return offscreen3DRenderPass; }
326 vk::Format getDepthFormat() const { return depthFormat; }
327 vk::RenderPass getSwapchainRenderPass() const { return renderpass; }
328 vk::RenderPass getUiMsaaRenderPass() const { return uiRenderPass; }
330 vk::SampleCountFlagBits getUiMsaaSamples() const { return uiColorSamples; }
333 createUiColorResources(int(swapchain.extent.width), int(swapchain.extent.height));
334 }
335 vkb::Instance &getInstance() { return inst; }
336 vkb::Swapchain &getSwapchain() { return swapchain; }
337 void *getSdlWindow() const { return sdlWindow; }
338 uint32_t getSwapchainImageCount() const { return swapchain.image_count; }
339
340 friend class OffscreenCanvas;
341
342 struct LitBatch {
343 Texture *albedo = nullptr;
344 Texture *normal = nullptr;
346 };
347
348private:
349 struct Mesh3dFrameSlots;
350 struct Mesh3dClusteredFrameSlots;
351 void createSwapchainAndPipeline();
352 void createTexturedPipeline();
353 void createLit2DPipeline();
354 void createMesh3DPipeline();
355 void createMesh3DClusteredPipeline();
356 void createVoxelRectPipeline();
357 vk::Pipeline buildVoxelRectPipeline(const vkb::BuiltRenderPass &rp,
358 vk::SampleCountFlagBits samples);
359 void destroyVoxelRectResources();
360 void ensureVoxelUnitQuad();
361 vkb::BoundSet voxelRectSetFor(GpuTexture *gpuTex);
362 void createShadowResources();
363 void destroyShadowResources();
364 void createGBufferResources(int width, int height);
365 void destroyGBufferResources();
366 void createSceneColorResources(int width, int height);
367 void destroySceneColorResources();
368 void createUiColorResources(int width, int height);
369 void destroyUiColorTargets();
370 void destroyUiColorResources();
371 void queueUiResolve();
373 bool renderUiOverlayPass();
375 void recordDeferredFrameGraph();
376 void dropPendingOffscreenPasses();
378 bool beginSwapchainRenderPass();
380 void beginSwapchainColorPass();
381 bool beginSceneColorRenderPass();
382 void endSceneColorRenderPass();
383 void ensureOffscreen3DResources();
384 void destroyOffscreen3DResources();
385 void queueSceneColorResolve();
386 void ensureClusteredBuffers(size_t lightsBytes, size_t tableBytes, size_t indicesBytes);
387 void uploadClusteredLighting(const ClusteredLightingUpload &upload);
388 void ensureMesh3dStrides();
389 void ensureMesh3dRing(Mesh3dFrameSlots &fslots);
390 void ensureMesh3dClusteredRing(Mesh3dClusteredFrameSlots &fslots);
391 vkb::BoundSet mesh3dClusteredSetFor(GpuTexture *gpuTex, GpuTexture *normalTex, GpuTexture *envTex,
392 GpuTexture *heightTex, Mesh3dClusteredFrameSlots &fslots);
393 void ensureOffscreenPipelines();
394 void ensureShaderOffscreenPipeline(Shader *shader);
395 vk::Pipeline createTexturedStylePipeline(const std::vector<uint32_t> &vert, const std::vector<uint32_t> &frag,
396 const vkb::BuiltRenderPass &rp, vk::PipelineLayout layout,
398 vk::Pipeline createMesh3DStylePipeline(const std::vector<uint32_t> &vert, const std::vector<uint32_t> &frag,
399 vk::PipelineLayout layout, const vkb::BuiltRenderPass &rp,
400 vk::SampleCountFlagBits samples);
402 vk::Pipeline createMesh3DXrayPipeline(const std::vector<uint32_t> &vert,
403 const std::vector<uint32_t> &frag,
404 vk::PipelineLayout layout,
405 const vkb::BuiltRenderPass &rp,
406 vk::SampleCountFlagBits samples);
407 vk::Pipeline createMesh3DHairPipeline(const std::vector<uint32_t> &vert,
408 const std::vector<uint32_t> &frag,
409 vk::PipelineLayout layout,
410 const vkb::BuiltRenderPass &rp,
411 vk::SampleCountFlagBits samples);
413 void ensureScenePassPipelines(const vkb::BuiltRenderPass &target,
414 vk::SampleCountFlagBits samples);
416 int clampMsaaSamples(int requested) const;
418 const vkb::BuiltRenderPass &activeScenePass() const {
419 return sceneColorRenderPass ? sceneColorRenderPass : renderpass;
420 }
422 vk::SampleCountFlagBits activeSceneSamples() const {
423 return sceneColorRenderPass ? sceneColorSamples : vk::SampleCountFlagBits::e1;
424 }
425 void destroySwapchainResources();
426 void flushBatch();
427 void flushToSwapchain();
428 void flushToOffscreen(OffscreenCanvas *canvas);
429 void abortOpen3DFrame();
430 void noteSolidOverlay();
431 void noteTexturedOverlay(Texture *tex);
432 void noteLitOverlay();
433 void clear2DBatches();
434 void drawLitBatches(vk::CommandBuffer cb, int viewW, int viewH, vk::Pipeline pipeline,
435 std::vector<LitBatch> &batches, std::vector<vkb::HostVertexBuffer> &texBufs,
436 size_t &texBufIndex, bool offscreen);
437 vkb::BoundSet lit2dSetFor(GpuTexture *albedo, GpuTexture *normal, bool offscreen);
438 vkb::BoundSet post2SetFor(GpuTexture *color, GpuTexture *depth);
439 void ensureFlatNormalTexture();
441 void ensureReadbackSlots();
443 bool recordSwapchainReadback(vk::CommandBuffer cb);
445 void syncReadbackCpu();
447 void destroyReadbackResources();
448 void ensurePresentCaptureHook();
449 vkb::BoundSet mesh3dSetFor(GpuTexture *gpuTex, GpuTexture *normalTex, GpuTexture *envTex, GpuTexture *heightTex,
450 GpuTexture *depthTex, Mesh3dFrameSlots &fslots);
451 void ensureDefaultEnvCubemap();
452 void ensureFlatNormalTexture3D();
453 void ensureFlatHeightTexture3D();
454 vk::Sampler createVkSampler(const TextureSampler &sampler, uint32_t mipLevels) const;
455 void writeCombinedImageDescriptor(GpuTexture *gpu);
457 bool rebuildSwapchainIfNeeded();
459 bool beginPresentCommandBuffer();
460
461 bool initialized = false;
462 bool hasPresentedFrame = false;
463 float maxSamplerAnisotropy = 1.f;
464 std::vector<uint8_t> lastFrameRgba;
465 // Persistent host-visible staging buffers for swapchain readback. The copy
466 // is recorded into the present command buffer (no extra submit / no
467 // per-frame GPU wait), and each present frame slot owns one slot so a
468 // staging buffer is only reused after that slot's fence has signaled.
469 struct ScreenReadbackSlot {
470 vkb::GenericBuffer staging;
471 void *mapped = nullptr;
472 };
473 std::vector<ScreenReadbackSlot> screenReadbackSlots;
474 size_t screenReadbackBytes = 0;
475 size_t readbackWriteSlot = 0;
476 bool readbackReady = false; // at least one copy submitted
477 bool readbackCpuSynced = false; // newest copy already converted to lastFrameRgba
478 bool readbackBgra = false; // swapchain format of the newest captured frame
479 Canvas *activeCanvas = nullptr;
480 bool swapchainDirty = false;
481 void markSwapchainDirty() override { swapchainDirty = true; }
482 // Set from the SDL event-watch thread on Android foreground; consumed on
483 // the render thread inside flushToSwapchain().
484 std::atomic<bool> surfaceNeedsRecreate{false};
485 void recreateSurfaceForResume();
486 // False while the native window is mid-(re)creation / rotation (Android),
487 // when touching the swapchain or presenting would crash the GPU driver.
488 bool isRenderSurfaceReady() const;
489 // Returns true only once the drawable size has been non-zero and identical
490 // across consecutive frames, i.e. the surface has settled after a
491 // rotation/resume and is safe to (re)build a swapchain against.
492 bool isRenderSurfaceStable();
493 int pendingSurfaceW = 0;
494 int pendingSurfaceH = 0;
495 int surfaceStableFrames = 0;
496 void *sdlWindow = nullptr;
497 vk::SurfaceKHR surface;
498
499 vkb::Instance inst;
500 vkb::Device device;
501 vkb::Swapchain swapchain;
502 vkb::BuiltRenderPass renderpass;
503
504 vk::Pipeline pipeline;
505 vk::PipelineLayout pipelineLayout;
506 vk::Pipeline solidAlphaPipeline; // alpha-blended solid (BlendMode::Alpha)
507 vk::Pipeline additiveSolidPipeline; // additive solid (BlendMode::Additive)
508
509 vk::DescriptorSetLayout texSetLayout;
510 vk::UniqueDescriptorSetLayout texSetLayoutUnique;
511 vk::DescriptorPool descriptorPool;
512 vk::Pipeline texPipeline;
513 vk::Pipeline additiveTexPipeline;
514 vk::Pipeline opaqueTexPipeline;
515 vk::PipelineLayout texPipelineLayout;
516 vk::PipelineLayout shaderPipelineLayout; // tex set + push constants
517 vk::CommandPool uploadPool;
518
519 vkb::BuiltRenderPass offscreenRenderPass;
520 vk::Pipeline offscreenSolidPipeline;
521 vk::Pipeline offscreenSolidAlphaPipeline;
522 vk::Pipeline offscreenAdditiveSolidPipeline;
523 vk::Pipeline offscreenTexPipeline;
524 vk::Pipeline offscreenAdditiveTexPipeline;
525 vk::Pipeline offscreenOpaqueTexPipeline;
526
527 vk::DescriptorSetLayout mesh3dSetLayout;
528 vk::UniqueDescriptorSetLayout mesh3dSetLayoutUnique;
529 vk::PipelineLayout mesh3dPipelineLayout;
530 vk::PipelineLayout mesh3dShaderPipelineLayout; // + push constants for custom mesh shaders
531 vk::Pipeline mesh3dPipeline;
532 // One UBO (+ per-texture descriptor sets) per draw in the current 3D frame.
533 // Avoids vkUpdateDescriptorSets on a set already bound in a recording /
534 // executable command buffer (which invalidates the CB).
535 struct Mesh3dSetKey {
536 GpuTexture *albedo = nullptr;
537 GpuTexture *normal = nullptr;
538 GpuTexture *env = nullptr;
539 GpuTexture *height = nullptr;
540 GpuTexture *depth = nullptr;
541 bool operator==(const Mesh3dSetKey &o) const {
542 return albedo == o.albedo && normal == o.normal && env == o.env && height == o.height &&
543 depth == o.depth;
544 }
545 };
546 struct Mesh3dSetKeyHash {
547 size_t operator()(const Mesh3dSetKey &k) const {
548 return std::hash<GpuTexture *>()(k.albedo) ^ (std::hash<GpuTexture *>()(k.normal) << 1) ^
549 (std::hash<GpuTexture *>()(k.env) << 2) ^ (std::hash<GpuTexture *>()(k.height) << 3) ^
550 (std::hash<GpuTexture *>()(k.depth) << 4);
551 }
552 };
553 // Per-frame-slot UBO rings, keyed by Present::frames_in_flight so a frame
554 // never overwrites a UBO that an in-flight frame is still reading.
555 // Per-draw data is written at dynamic offsets into the ring and the same
556 // descriptor set (cached per texture combination) is re-bound with a new
557 // offset, so descriptor-pool usage is bounded by texture count instead of
558 // growing with draw count.
559 struct Mesh3dFrameSlots {
560 vkb::GenericBuffer uboRing; // capacity * mesh3dUboStride bytes
561 vkb::GenericBuffer shadowRing; // capacity * shadowUboStride bytes
562 size_t capacity = 0; // per-draw slot count the rings hold
563 size_t drawIndex = 0;
564 size_t lastDrawCount = 0;
565 std::unordered_map<Mesh3dSetKey, vkb::BoundSet, Mesh3dSetKeyHash> sets;
566 };
567 std::vector<Mesh3dFrameSlots> mesh3dFrameSlots;
568 Texture *whiteTexture = nullptr;
569 Texture *flatNormalTexture3D = nullptr;
570 Texture *flatHeightTexture3D = nullptr;
571 Texture *defaultEnvCubemap = nullptr;
572 Texture *mesh3dNormalTexture = nullptr;
573 Texture *mesh3dHeightTexture = nullptr;
574 Texture *mesh3dEnvTexture = nullptr;
575 Texture *mesh3dSceneDepthTexture = nullptr;
576 float mesh3dEnvIntensity = 0.f;
577 float mesh3dMetallic = 0.f;
578 float mesh3dRoughness = 0.45f;
579 float mesh3dTexBombScale = 4.f;
580 float mesh3dTexBombStrength = 0.f;
581 float mesh3dTexBombRot = 1.f;
582 float mesh3dParallaxScale = 0.f;
583 float mesh3dParallaxMinLayers = 8.f;
584 float mesh3dParallaxMaxLayers = 32.f;
585 Lighting3DPack mesh3dLighting{};
586 ShadowUpload mesh3dShadows{};
587 bool mesh3dShadowReceive = true;
588
589 // Clustered forward (separate set layout / pipeline; default PBR only).
590 bool mesh3dClusteredActive = false;
591 ClusteredLightingUpload mesh3dClustered{};
592 vk::DescriptorSetLayout mesh3dClusteredSetLayout;
593 vk::UniqueDescriptorSetLayout mesh3dClusteredSetLayoutUnique;
594 vk::PipelineLayout mesh3dClusteredPipelineLayout;
595 vk::Pipeline mesh3dClusteredPipeline;
596 // Per-frame clustered storage (lights / cluster table / light indices),
597 // multi-buffered so an in-flight frame's forward pass never reads storage
598 // that the next frame is overwriting.
599 struct ClusteredStorage {
600 vkb::GenericBuffer lightsBuf;
601 vkb::GenericBuffer tableBuf;
602 vkb::GenericBuffer indicesBuf;
603 size_t lightsCap = 0;
604 size_t tableCap = 0;
605 size_t indicesCap = 0;
606 };
607 std::vector<ClusteredStorage> clusteredStorages; // per swapchain frame slot
608 struct Mesh3dClusteredFrameSlots {
609 vkb::GenericBuffer uboRing; // capacity * mesh3dClusteredUboStride bytes
610 vkb::GenericBuffer shadowRing; // capacity * shadowUboStride bytes
611 size_t capacity = 0;
612 size_t drawIndex = 0;
613 size_t lastDrawCount = 0;
614 std::unordered_map<Mesh3dSetKey, vkb::BoundSet, Mesh3dSetKeyHash> sets;
615 };
616 std::vector<Mesh3dClusteredFrameSlots> mesh3dClusteredFrameSlots;
617
619 uint32_t mesh3dUboStride = 0;
620 uint32_t shadowUboStride = 0;
621 uint32_t mesh3dClusteredUboStride = 0;
623 vk::Pipeline lastMesh3dPipeline = nullptr;
624 vk::Pipeline lastMesh3dClusteredPipeline = nullptr;
625
626 // Ping-pong copies so frame N+1 can write while frame N still samples.
627 static constexpr uint32_t kAsyncResourceCopies = 2;
628
629 // CSM shadow map (3 cascade layers), one array per in-flight slot.
630 struct ShadowMapSlot {
631 vkb::DepthArrayImage image;
632 vk::Framebuffer framebuffers[ShadowConfig::kCascades]{};
633 };
634 std::vector<ShadowMapSlot> shadowMaps;
635 vkb::DepthSampler shadowSampler{};
636 vkb::BuiltRenderPass shadowRenderPass{};
637 vk::PipelineLayout shadowPipelineLayout{};
638 vk::Pipeline shadowPipeline{};
639 vk::PipelineLayout shadowAlphaPipelineLayout{};
640 vk::Pipeline shadowAlphaPipeline{};
641 int shadowPassCascade = -1;
642 struct ShadowDraw {
643 Mesh *mesh = nullptr;
644 glm::mat4 mvp{1.f};
645 Texture *albedo = nullptr;
646 bool alphaTest = false; // use the alpha-cutout shadow pipeline
647 };
648 std::vector<ShadowDraw> shadowPassDraws;
649 std::vector<ShadowDraw> shadowCascadeDraws[ShadowConfig::kCascades];
650 uint32_t shadowPendingMask = 0;
651 ShadowMapSlot &currentShadowMap();
652 vk::ImageView currentShadowArrayView();
653
654 // Screen-space G-buffer (normal / linear-depth / albedo + HW depth).
655 struct GBufferPush {
656 glm::mat4 mvp{1.f};
657 glm::vec4 modelR0{1.f, 0.f, 0.f, 0.f};
658 glm::vec4 modelR1{0.f, 1.f, 0.f, 0.f};
659 glm::vec4 modelR2{0.f, 0.f, 1.f, 0.f};
660 glm::vec4 clip{0.1f, 100.f, 0.f, 0.f};
661 };
662 static_assert(sizeof(GBufferPush) == 128, "GBuffer push constants must be 128 bytes");
663 struct GBufferDraw {
664 Mesh *mesh = nullptr;
665 Texture *albedo = nullptr;
666 GBufferPush push{};
667 bool alphaTest = false; // use the alpha-cutout gbuffer pipeline
668 };
669 struct GBufferSlot {
670 vkb::ColorTarget normal;
671 vkb::ColorTarget depthColor;
672 vkb::ColorTarget albedo;
673 vkb::DepthTarget depth;
674 vk::Framebuffer framebuffer{};
675 GpuTexture normalGpu{};
676 GpuTexture depthColorGpu{};
677 GpuTexture albedoGpu{};
678 GpuTexture depthGpu{};
679 Texture normalTex{};
680 Texture depthColorTex{};
681 Texture albedoTex{};
682 Texture depthTex{};
683 };
684 int gbufferWidth = 0;
685 int gbufferHeight = 0;
686 std::vector<GBufferSlot> gbufferSlots;
687 vkb::BuiltRenderPass gbufferRenderPass{};
688 vk::PipelineLayout gbufferPipelineLayout{};
689 vk::Pipeline gbufferPipeline{};
690 vk::Pipeline gbufferAlphaPipeline{};
691 bool gbufferPassActive = false;
692 bool gbufferPending = false;
693 std::vector<GBufferDraw> gbufferPassDraws;
694 GBufferSlot *currentGBufferSlot();
695 // One FrameGraph per in-flight slot for the deferred passes: the 3 CSM
696 // shadow cascades + the G-buffer fill are declarative passes in one layer,
697 // recorded concurrently on JobSystem workers. Each graph's command buffer
698 // is only reused two frames later — by then the present slot fence (waited
699 // in Present::begin) guarantees the previous graph submit has completed
700 // (same queue, submitted before the present command buffer). The graphs
701 // import the engine-owned shadow array + ColorTarget images; the engine
702 // keeps ownership so readback / entity-ID rendering / postFX wrappers keep
703 // working unchanged.
704 std::array<std::unique_ptr<vkb::FrameGraph>, kAsyncResourceCopies> deferredFrameGraphs_;
705 vkb::FrameGraph *currentDeferredFrameGraph();
707 bool deferredGraphRecorded_ = false;
708 size_t deferredGraphRecordedSlot_ = 0;
710 void buildDeferredFrameGraphs();
712 void recordShadowCascadePass(vkb::FrameGraphPassContext &ctx, int cascade);
714 void recordGBufferPassDraws(vkb::FrameGraphPassContext &ctx);
715
716 struct SceneColorSlot {
717 vkb::ColorTarget msaaColor;
718 vkb::ColorTarget color;
719 vkb::DepthTarget depth;
720 vk::Framebuffer framebuffer{};
721 GpuTexture colorGpu{};
722 Texture colorTex{};
723 };
724 int sceneColorWidth = 0;
725 int sceneColorHeight = 0;
726 vk::Format sceneColorFormat = vk::Format::eUndefined;
727 vk::SampleCountFlagBits sceneColorSamples = vk::SampleCountFlagBits::e1;
728 std::vector<SceneColorSlot> sceneColorSlots;
729 vkb::BuiltRenderPass sceneColorRenderPass{};
730 bool sceneColorPassOpen = false;
731 vk::RenderPass scenePassPipelineTarget = vk::RenderPass{};
732 vk::SampleCountFlagBits scenePassPipelineSamples = vk::SampleCountFlagBits::e1;
733 int appliedMsaa = -1;
734 SceneColorSlot *currentSceneColorSlot();
735
736 // Offscreen 3D render-to-canvas (color + D32 depth) used for planar
737 // reflection / render targets. Rendered on a dedicated command buffer and
738 // submitted directly to the graphics queue (no swapchain / present).
739 vkb::BuiltRenderPass offscreen3DRenderPass{};
740 vk::Pipeline offscreen3DMeshPipeline = nullptr;
741 vk::CommandPool offscreen3DPool = nullptr;
742 vk::CommandBuffer offscreen3DCB = nullptr;
743 vk::Fence offscreen3DFence = nullptr;
744 bool offscreen3DPassOpen = false;
745 OffscreenCanvas *offscreen3DCanvas = nullptr;
746
747 // Dedicated 4x-MSAA color target for the UI overlay (ImGui), resolved to a
748 // single-sample texture that is composited as the top-most fullscreen quad.
749 struct UiColorSlot {
750 vkb::ColorTarget msaaColor;
751 vkb::ColorTarget color;
752 vk::Framebuffer framebuffer{};
753 GpuTexture colorGpu{};
754 Texture colorTex{};
755 };
756 int uiColorWidth = 0;
757 int uiColorHeight = 0;
758 vk::Format uiColorFormat = vk::Format::eUndefined;
759 vk::SampleCountFlagBits uiColorSamples = vk::SampleCountFlagBits::e1;
760 std::vector<UiColorSlot> uiColorSlots;
761 vkb::BuiltRenderPass uiRenderPass{};
762 UiColorSlot *currentUiColorSlot();
763
764 vkb::Present presentModel;
765 vkb::RecordingCmd presentRecording;
766 vkb::InRenderPass swapchainPass;
767 vkb::DepthStencilImage depthImage;
768 vk::Format depthFormat = vk::Format::eD32Sfloat;
769
770 struct SolidBatch {
772 Batcher batch;
773 };
774 std::vector<SolidBatch> solidBatches;
775 struct TexturedBatch {
776 Texture *texture = nullptr;
777 Texture *depth = nullptr;
778 Shader *shader = nullptr;
780 Batcher batch;
781 };
782 std::vector<TexturedBatch> texturedBatches;
783
784 std::vector<LitBatch> litBatches;
785
786 enum class OverlayKind : uint8_t { Solid, Textured, Lit };
787 struct OverlaySpan {
788 OverlayKind kind = OverlayKind::Solid;
789 uint32_t index = 0;
790 uint32_t vertBegin = 0;
791 uint32_t vertCount = 0;
792 };
793 std::vector<OverlaySpan> overlaySpans;
794 std::vector<OverlaySpan> engine3DSpans;
795 std::optional<TexturedBatch> pendingSceneResolve;
796 std::optional<TexturedBatch> pendingUiResolve;
797 bool sceneColorComposited = false;
798
799 // Persistent host-visible vertex buffers for 2D batching, reused across
800 // frames. GenericBuffer now owns the Vulkan handles.
801 struct Frame2DBuffers {
802 std::vector<vkb::HostVertexBuffer> solidBufs;
803 std::vector<vkb::HostVertexBuffer> texBufs;
804 };
805 std::vector<Frame2DBuffers> frame2dBuffers; // per swapchain frame slot
806 Frame2DBuffers offscreenBuffers; // synchronous offscreen path
807
808 vk::DescriptorSetLayout lit2dSetLayout;
809 vk::UniqueDescriptorSetLayout lit2dSetLayoutUnique;
810 vk::PipelineLayout lit2dPipelineLayout;
811 vk::Pipeline lit2dPipeline;
812 vk::Pipeline offscreenLitPipeline;
813 std::vector<vkb::GenericBuffer> lighting2dUboSlots; // per swapchain frame slot
814 vkb::GenericBuffer offscreenLighting2dUbo; // synchronous offscreen path
815 Lighting2DUBO lighting2dFrame{};
816 struct LitSetKey {
817 GpuTexture *albedo = nullptr;
818 GpuTexture *normal = nullptr;
819 bool operator==(const LitSetKey &o) const {
820 return albedo == o.albedo && normal == o.normal;
821 }
822 };
823 struct LitSetKeyHash {
824 size_t operator()(const LitSetKey &k) const {
825 return std::hash<void *>()(k.albedo) ^ (std::hash<void *>()(k.normal) << 1);
826 }
827 };
828 std::vector<std::unordered_map<LitSetKey, vkb::BoundSet, LitSetKeyHash>> lit2dSets;
829 std::unordered_map<LitSetKey, vkb::BoundSet, LitSetKeyHash> offscreenLit2dSets;
830 std::unordered_map<LitSetKey, vkb::BoundSet, LitSetKeyHash> post2Sets;
831 Texture *flatNormalTexture = nullptr;
832
833 Color clearColor{0.1f, 0.1f, 0.12f, 1.0f};
834 bool hasPendingClear = true;
835
836 std::vector<std::unique_ptr<Texture>> ownedTextures;
837 std::vector<std::unique_ptr<GpuTexture>> ownedGpuTextures;
839 std::unordered_map<std::string, Texture *> texturesByPath;
840 std::vector<std::unique_ptr<Mesh>> ownedMeshes;
841 std::vector<std::unique_ptr<GpuMesh>> ownedGpuMeshes;
842 std::vector<std::unique_ptr<Shader>> ownedShaders;
843 std::vector<std::unique_ptr<GpuShader>> ownedGpuShaders;
844 std::vector<std::unique_ptr<eve::graphics::Canvas>> ownedCanvases;
845
846 bool swapchainPassOpen = false;
847 bool flushingSwapchain_ = false;
848 Mesh3DUBO mesh3dFrameUbo{};
849
850 // Instanced voxel face rectangles (packed uint32 instances).
851 struct VoxelRectPC {
852 glm::mat4 viewProj{1.f};
853 glm::vec4 chunkOrigin{0.f}; // xyz = origin, w = faceDir
854 glm::vec4 atlasInfo{16.f, 0.f, 0.f, 0.f};
855 glm::vec4 tint{1.f};
856 };
857 vk::DescriptorSetLayout voxelRectSetLayout{};
858 vk::UniqueDescriptorSetLayout voxelRectSetLayoutUnique;
859 vk::PipelineLayout voxelRectPipelineLayout{};
860 vk::Pipeline voxelRectPipeline{};
861 vkb::GenericBuffer voxelUnitQuadVerts;
862 vkb::GenericBuffer voxelUnitQuadIndices;
863 bool voxelUnitQuadReady = false;
864 std::unordered_map<GpuTexture *, vkb::BoundSet> voxelRectSets;
865 // Grow-only instance buffer pool (reset index each begin3DFrame), per
866 // swapchain frame slot for async safety.
867 struct VoxelInstanceSlot {
868 vkb::GenericBuffer buffer;
869 size_t capacityBytes = 0;
870 vkb::GenericBuffer aoBuffer;
871 size_t aoCapacityBytes = 0;
872 };
873 struct VoxelInstanceFrame {
874 std::vector<VoxelInstanceSlot> slots;
875 size_t drawIndex = 0;
876 };
877 std::vector<VoxelInstanceFrame> voxelInstanceFrames; // per swapchain frame slot
878
879 Frame2DBuffers &currentFrame2DBuffers();
880 Mesh3dFrameSlots &currentMesh3dFrameSlots();
881 Mesh3dClusteredFrameSlots &currentMesh3dClusteredFrameSlots();
882 vkb::GenericBuffer &currentLighting2dUbo();
883 std::unordered_map<LitSetKey, vkb::BoundSet, LitSetKeyHash> &currentLit2dSets();
884 ClusteredStorage &currentClusteredStorage();
885 VoxelInstanceFrame &currentVoxelInstanceFrame();
886 uint32_t frameSlotCount() const;
887 size_t currentFrameSlot() const;
888 vk::CommandBuffer &currentPresentCb();
889 vkb::FrameSlot frameToken() const;
891 void waitForSharedGpuResources();
892 void invalidateTextureBindings();
893};
894
895} // namespace eve::graphics::vulkan
bool active
Definition CardTypes.cpp:34
float cx
Definition CardTypes.cpp:31
float cy
Definition CardTypes.cpp:32
float degrees
Definition CardTypes.cpp:33
Tok kind
std::string layout
vk::ShaderModule vert
vk::ShaderModule frag
int y
Definition Grass.cpp:135
float height
Definition Grass.cpp:235
int x
Definition Grass.cpp:135
int h
int w
float depth
uint32_t b
float roughness
Texture * normal
Texture * albedo
float metallic
glm::vec3 eye
Mesh * mesh
glm::mat4 viewProj
Shader * shader
glm::mat4 view
glm::mat4 model
const char * name
Definition RockMesh.cpp:21
bool repeatV
bool repeatU
bool enabled
image::ImageData::Colorf color
std::string image
float scale
Definition TreeMesh.cpp:122
V3 dir
Definition TreeMesh.cpp:121
Accumulates solid / textured quads in logical (Y-down) coordinates. Used by RenderSystem; not a publi...
Definition Batcher.h:22
virtual void setVSync(bool enabled)
Prefer uncapped present (IMMEDIATE/MAILBOX) when false, vsync (MAILBOX/FIFO) when true....
Definition Graphics.h:604
virtual void setMsaaSamples(int samples)
Hardware MSAA sample count for the 3D scene color pass (0 disables, then 2/4/8 are used when the devi...
Definition Graphics.h:612
virtual void setScreenReadbackEnabled(bool enabled)
When true, each present copies the swapchain to a CPU buffer for getPixel/newImageData....
Definition Graphics.h:591
GPU mesh handle (+ optional CPU morph targets).
Definition Mesh.h:18
Custom GPU program.
Definition Shader.h:30
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:17
void drawMeshGBuffer(Mesh *mesh, const glm::mat4 &mvp, const glm::mat4 &model, float nearZ, float farZ, Texture *albedo=nullptr, float tintR=1.f, float tintG=1.f, float tintB=1.f) override
void beginShadowPass(int cascadeIndex) override
Depth-only shadow pass for one cascade layer (0..2). Draws are recorded into the next begin3DFrame co...
float getMaxAnisotropy() const override
Device max supported anisotropy (1 if unsupported). Valid after initWithWindow.
void drawTexturedRectUV(Texture *texture, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color) override
Draw a textured sub-rect (atlas / tile UVs). texture may be null → solid.
void begin3DFrame() override
Begin a 3D frame: shadow/gbuffer (if pending) then a sampleable scene color pass (color+depth)....
Shader * newShaderFromSpvFile(const std::string &vertPath, const std::string &fragPath) override
Load SPIR-V from files via Filesystem (empty vertPath → default textured vert).
bool releaseMesh(Mesh *mesh) override
Eagerly releases a mesh created by this Graphics.
void setMesh3DParallax(float scale, float minLayers=8.f, float maxLayers=32.f) override
Parallax occlusion mapping for the next default mesh draw. scale: UV displacement strength (0=off)....
void onNativeWindowDestroyed() override
Called by the Window module when the native window backing the render surface is destroyed (window cl...
Definition Graphics.cpp:272
void setCloudShadows(float strength, float worldCell, float time, float windSpeed, float windAngle, float coverage, float detail) override
Dynamic cloud shadows cast on the ground by the default PBR mesh path. strength 0 disables (no change...
void draw(eve::graphics::Graphics *gfx, const glm::mat4 &matrix) const override
Draws the object with the specified transformation matrix.
Definition Graphics.cpp:577
vkb::Instance & getInstance()
Definition Graphics.h:335
Mesh * newMeshSphere(int slices=32, int stacks=16) override
Procedural UV sphere (radius 1, Y-up). Owned by Graphics. slices = longitude divisions,...
void drawVoxelFaceInstances(const uint32_t *packed, int count, float originX, float originY, float originZ, const std::string &faceDir, Texture *atlas, int tilesPerRow=16, const uint32_t *ao=nullptr) override
Instanced voxel face rectangles (32-bit packed instances). ao: optional per-instance ambient-occlusio...
Texture * getTexture() override
Sampleable color buffer; screen Canvas returns nullptr.
void setLighting2D(const Lighting2DUBO &ubo) override
Upload per-frame / per-canvas 2D lighting constants for subsequent lit draws.
Canvas * getCanvas() const override
image::ImageData * renderEntityIdMask(const std::vector< eve::graphics::Graphics::EntityIdDraw > &draws, const glm::mat4 &viewProj, int width, int height) override
int getMsaaSamples() const override
Definition Graphics.h:195
void pushValidationScope() override
Backend hooks so the platform-independent render3D() can wrap its work in a GPU validation error scop...
Definition Graphics.h:202
void setMesh3DShadowReceive(bool receive) override
Per-draw: when false, shadow sampling is forced off for the next mesh draw.
bool bakeMeshMorph(Mesh *mesh) override
If mesh morph weights are dirty, bake blended positions and upload to the GPU VBO....
void setMesh3DLighting(const Lighting3DPack &pack) override
Per-frame ambient + up to 8 lights packed into Mesh3DUBO.
Color getPixel(int x, int y) override
void setMesh3DEnv(Texture *cube, float intensity) override
Specular IBL environment for subsequent default mesh draws. cube must be from newCubemap (or nullptr ...
uint32_t getSwapchainImageCount() const
Definition Graphics.h:338
const vkb::BuiltRenderPass & getOffscreen3DRenderPass()
Definition Graphics.h:325
Texture * getSceneColorTexture() override
Sampleable 3D color target for the current frame (RGB = lit, A = linear depth). Valid after begin3DFr...
Definition Graphics.cpp:410
Shader * newShader(const std::string &vertGlsl, const std::string &fragGlsl) override
Compile GLSL source with glslc (must be on PATH). Empty vertGlsl → default textured vert....
void setMsaaSamples(int samples) override
Hardware MSAA sample count for the 3D scene color pass (0 disables, then 2/4/8 are used when the devi...
Definition Graphics.h:190
std::string getBackendName() const override
Renderer backend id used by sibling modules (e.g. Gpgpu).
Definition Graphics.cpp:56
bool isCanvasActive() const override
bool reloadTextureFromFile(const std::string &filename) override
Reload a path-cached texture from disk in place (pointer stable). False if unbound.
vk::CommandPool getUploadPool() const
Definition Graphics.h:321
void initWithWindow(void *nativeWindow) override
Bind to an existing native window (SDL_Window*) and create Vulkan device/swapchain....
Definition Graphics.cpp:139
Shader * newMeshShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv) override
Create a Mesh3D custom shader (MeshVertex + Frame UBO + albedo). Empty vert → default mesh3d....
void drawTexturedRectShaderUV(Texture *texture, Shader *shader, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color, bool rotatedUV=false, BlendMode blend=BlendMode::Alpha) override
UV draw with an explicit Shader (nullptr = default textured pipeline).
vk::RenderPass getUiMsaaRenderPass() const
Definition Graphics.h:328
Mesh * newMeshCylinder(int slices=32, int stacks=1, bool caps=true) override
Procedural Y-up cylinder (radius 1, height 2 centered at origin). slices = longitude divisions; stack...
void setMesh3DTexCellBomb(float cellScale, float strength, float rotAmount=1.f) override
Texture cell bombing for the next default mesh draw (breaks tiling). cellScale: cells per UV unit (ty...
void setScreenReadbackEnabled(bool enabled) override
When true, each present copies the swapchain to a CPU buffer for getPixel/newImageData....
Definition Graphics.h:181
Canvas * newCanvas(int width, int height) override
Create an offscreen render target (sampleable). Owned by Graphics.
void drawMeshShadow(Mesh *mesh, const glm::mat4 &lightMVP) override
Mesh * newMeshFromArrays(const float *posXYZ, const float *nrmXYZ, const float *uvST, int vertexCount, const uint32_t *indices, int indexCount) override
Upload a triangle mesh from packed CPU arrays. Owned by Graphics. posXYZ required (vertexCount*3)....
void setViewportSize(int width, int height, int pixelwidth, int pixelheight) override
Sets the current graphics display viewport dimensions.
void setMesh3DCameraPos(const glm::vec3 &eye) override
Camera eye used by mesh shaders that need view/rim (stored in Mesh3DUBO).
bool replaceTexturePixels(Texture *tex, image::ImageData *data)
Shader * newMeshShader(const std::string &vertGlsl, const std::string &fragGlsl) override
void begin3DFrameToCanvas(Canvas *canvas) override
Open a 3D render pass targeting an offscreen Canvas (color + depth) at the canvas size....
Mesh * newMeshFromAssimp(const ::aiMesh &mesh) override
void setMesh3DViewProj(const glm::mat4 &viewProj) override
image::ImageData * readGBufferToImageData(const std::string &name) override
Read a G-buffer attachment back to CPU as RGBA8. name is one of "depth" (RGBA8 linear depth),...
const vkb::BuiltRenderPass & getOffscreenRenderPass() const
Definition Graphics.h:324
void drawMeshShader(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint, Shader *shader) override
Draw mesh with an explicit Mesh3D Shader (nullptr = default PBR pipeline).
vk::DescriptorSetLayout getTexSetLayout() const
Definition Graphics.h:322
void setMesh3DShadows(const ShadowUpload &upload) override
Upload CSM constants for subsequent default mesh draws (active=false disables).
void drawTexturedRect(Texture *texture, float x, float y, float w, float h, const Color &color) override
void beginGBufferPass(int width, int height) override
Depth/normal(/albedo) fill pass for mid/post effects. One-shot submit (like shadow); call before begi...
void setTextureSampler(Texture *texture, const TextureSampler &sampler) override
Recreate the sampler for an existing texture (keeps image / mip chain). No-op when texture is null or...
void drawTexturedRectShaderUVRotated(Texture *texture, Shader *shader, float cx, float cy, float w, float h, float degrees, float u0, float v0, float u1, float v1, const Color &color, bool rotatedUV=false, BlendMode blend=BlendMode::Alpha) override
UV draw rotated degrees clockwise (screen Y-down) around the rect center. texture may be null → solid...
bool updateMeshVertices(Mesh *mesh, const float *posXYZ, const float *nrmXYZ, const float *uvST, int vertexCount, const uint32_t *indices, int indexCount) override
In-place update of a mesh's vertex/index data (CPU -> host-visible VBO). Mirrors bakeMeshMorph: the u...
void setMesh3DLight(const glm::vec3 &dir, const glm::vec3 &color) override
Directional light for subsequent drawMesh calls (world-space direction toward surface).
void setMesh3DHeightTexture(Texture *height) override
Optional height map for parallax (R channel; nullptr = flat / off).
vk::RenderPass getSwapchainRenderPass() const
Definition Graphics.h:327
void popValidationScope() override
Definition Graphics.h:203
void drawMesh(Mesh *mesh, const glm::mat4 &model, Texture *texture, const Color &tint) override
Draw one mesh with model matrix. Requires begin3DFrame() (or an open swapchain pass).
image::ImageData * newImageData() override
void drawMeshGBufferAlpha(Mesh *mesh, const glm::mat4 &mvp, const glm::mat4 &model, float nearZ, float farZ, Texture *albedo=nullptr, float tintR=1.f, float tintG=1.f, float tintB=1.f) override
GBuffer fill with alpha-cutout discard (card/billboard geometry such as sprite-stack slices): same ou...
vkb::Swapchain & getSwapchain()
Definition Graphics.h:336
void drawTexturedRectShader(Texture *texture, Shader *shader, float x, float y, float w, float h, const Color &color) override
Draw with an explicit Shader (nullptr = default textured pipeline).
void ensureUiColorResources()
Create the UI MSAA render pass (once) and its color targets for ImGui init.
Definition Graphics.h:332
void drawTexturedRectLitUV(Texture *albedo, Texture *normal, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color) override
Lit 2D draw (albedo + normal map). Uses Lighting2DUBO from setLighting2D. normal may be null → treate...
Texture * newCubemap(int faceSize, const uint8_t *rgbaFaces) override
Create an RGBA8 cubemap from 6 faces packed as +X,-X,+Y,-Y,+Z,-Z (each faceSize×faceSize,...
void drawTexturedRectShaderDepth(Texture *color, Texture *depth, Shader *shader, float x, float y, float w, float h, const Color &tint) override
Fullscreen/post draw sampling color at binding 0 and depth at binding 1 (hardware D32,...
Shader * newShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv) override
Create a custom 2D shader from SPIR-V words (vert + frag). Owned by Graphics. Vertex stage may be emp...
void drawSolidRectRotated(float cx, float cy, float w, float h, float degrees, const Color &color, BlendMode blend=BlendMode::Alpha) override
Rotated solid quad degrees clockwise (screen Y-down) around (cx, cy).
Texture * newTextureFromFile(const std::string &filename) override
void setVSync(bool enabled) override
Prefer uncapped present (IMMEDIATE/MAILBOX) when false, vsync (MAILBOX/FIFO) when true....
Definition Graphics.h:185
void setMesh3DView(const glm::mat4 &view) override
Camera view matrix for subsequent drawMesh (view-space depth / CSM select).
void setMesh3DClusteredActive(bool active) override
Cheap per-draw toggle for the already-uploaded clustered light table. Unlike setMesh3DClusteredLighti...
void drawMeshShadowAlpha(Mesh *mesh, const glm::mat4 &lightMVP, Texture *albedo=nullptr) override
Shadow pass draw with alpha-cutout discard (card/billboard geometry such as sprite-stack slices): tra...
bool releaseTexture(Texture *texture) override
Eagerly releases a texture created by this Graphics.
void setMesh3DNormalTexture(Texture *normal) override
Optional normal map for the next drawMesh / drawMeshShader (nullptr = flat).
vk::Format getDepthFormat() const
Definition Graphics.h:326
Shader * newMeshShaderFromWgsl(const std::string &vertWgsl, const std::string &fragWgsl) override
Create a Mesh3D custom shader from WGSL source (WebGPU backend). The WGSL must declare the engine's F...
void requestSurfaceRecreate() override
Request recreation of the platform render surface on the next frame (Android background/foreground de...
Definition Graphics.h:179
void setMesh3DClip(float nearZ, float farZ) override
Near/far used to pack linear depth into scene color A (SSGI).
Shader * newHairShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv) override
Hair/fur card shader (alpha blend + Kajiya-Kay). Empty vert → mesh3d_hair.vert. Owned by Graphics.
Texture * newTexture(int width, int height, const uint8_t *rgba, bool repeatU=false, bool repeatV=false) override
vk::DescriptorPool getDescriptorPool() const
Definition Graphics.h:323
void setMesh3DSceneDepth(Texture *depth) override
Optional scene hardware depth (G-buffer hwDepth, Vulkan NDC z) bound to mesh3d shader binding 7....
bool releaseShader(Shader *shader) override
Eagerly releases a shader created by this Graphics.
void setMesh3DClusteredLighting(const ClusteredLightingUpload &upload) override
Enable clustered forward path for subsequent default mesh draws (SSBO light lists)....
void setMesh3DMaterial(float metallic, float roughness) override
Metallic (0..1) and roughness (0..1) for the next default mesh draw.
void clear(std::optional< Color > color, std::optional< int > stencil, std::optional< double > depth) override
vk::SampleCountFlagBits getUiMsaaSamples() const
Sample count the UI MSAA pass runs with (matches getUiMsaaRenderPass).
Definition Graphics.h:330
void drawSolidRect(float x, float y, float w, float h, const Color &color, BlendMode blend=BlendMode::Alpha) override
Internal immediate-mode helper used by RenderSystem / Batcher.
Represents raw pixel data.
Definition ImageData.h:26
glm::vec4 Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
BlendMode
2D quad blend mode (drawn in draw order within a layer).
Definition BlendMode.h:6
CPU-built clustered lighting upload for one frame/camera. Point lights are clustered; directional lig...
GPU light packing for mesh3d / PBR (std140-friendly).
Definition Light.h:85
static constexpr int kMaxLights
Definition Light.h:91
static constexpr int kCascades
Definition Shadow.h:8
Options for Graphics::newTexture / newCubemap. When generateMipmaps is true and sampler....
Sampler state for a Texture (filter, wrap, mip LOD, anisotropy). Defaults match historical engine beh...
static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding)
Definition Graphics.h:29
static std::vector< vk::VertexInputAttributeDescription > getAttributeDescription(uint32_t binding)
Definition Graphics.h:36
vkb::HostVertexBuffer vertices
Definition Graphics.h:146
static constexpr size_t kDynamicVertexCopies
Ring copies for per-frame updated meshes (skin/morph/sprite stack). Writing the next copy never races...
Definition Graphics.h:145
uint64_t dynamicWriteCount
Number of dynamic updates; ring slot = count % kDynamicVertexCopies.
Definition Graphics.h:154
std::array< vkb::GenericBuffer, kDynamicVertexCopies > dynIndices
Definition Graphics.h:149
vkb::GenericBuffer indices
Definition Graphics.h:147
std::array< vkb::HostVertexBuffer, kDynamicVertexCopies > dynVertices
Definition Graphics.h:148
std::vector< uint32_t > cpuIndices
CPU index copy for dynamic meshes (also normalizes 16-bit static indices to 32-bit ring buffers).
Definition Graphics.h:152
vk::PipelineLayout pipelineLayout
Definition Graphics.h:165
vkb::TextureImage2D image
Definition Graphics.h:123
vk::ImageView imageView() const
Definition Graphics.h:134
vkb::TextureImageCube cubeImage
Definition Graphics.h:124
Light3DGpu lights[Lighting3DPack::kMaxLights]
Definition Graphics.h:95
static std::vector< vk::VertexInputAttributeDescription > getAttributeDescription(uint32_t binding)
Definition Graphics.h:77
static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding)
Definition Graphics.h:70
static std::vector< vk::VertexInputAttributeDescription > getAttributeDescription(uint32_t binding)
Definition Graphics.h:56
static vk::VertexInputBindingDescription getBindingDescription(uint32_t binding)
Definition Graphics.h:49