Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
22c7340
Build: full optimization + LTO for Dist config
claude Jul 2, 2026
73319a3
SceneRenderer: reuse push-constant scratch in RT_DrawStaticMesh
claude Jul 2, 2026
2de5852
SceneRenderer: capture MeshDrawParams instead of TransformMapData per…
claude Jul 2, 2026
14ce49f
SceneRenderer: single-copy captures in the GPUScene upload submit
claude Jul 2, 2026
958c5f5
Scene: reuse SyncRenderScene sync-item scratch across frames
claude Jul 2, 2026
d8528d4
SceneRenderer: version-gate the per-frame texture/material table copies
claude Jul 2, 2026
5e642c6
Docs: record Phase 2 (submission-path allocations + build config)
claude Jul 2, 2026
a27258e
Build: use linktimeoptimization API instead of removed flags value
claude Jul 2, 2026
434305c
Fix permanent mesh disappearance on quality preset change
claude Jul 2, 2026
eb54dd8
Fix permanent per-frame descriptor set re-Bake after first invalidation
claude Jul 3, 2026
2ba9445
Build the GPUScene debug snapshot only when the debugger panel asks
claude Jul 3, 2026
37a0743
Run PreIntegration only when SSR is enabled
claude Jul 3, 2026
70b2bf2
Skip cluster froxel build and light culling when no local lights exist
claude Jul 3, 2026
bdb2392
Idle the atmosphere UBO rebuild when no atmosphere feature is active
claude Jul 3, 2026
25ca02e
Default directional shadows to 2K cascades
claude Jul 3, 2026
28d127a
Disable GPU timer/statistics queries in Dist builds
claude Jul 3, 2026
0e173bd
Docs: record Phase 3 (rendering audit fixes) and Phase 4 candidates
claude Jul 3, 2026
edb9d1e
Self-heal framebuffers whose baked attachment handles went stale
claude Jul 3, 2026
74a4633
Docs: record the stale wrapped-framebuffer self-heal fix
claude Jul 3, 2026
c066e48
Fix const-propagation compile error in the framebuffer repair sweep
claude Jul 3, 2026
2b06ab1
Bloom and SSR pre-convolution pyramids: RGBA32F -> RGBA16F
claude Jul 3, 2026
1d478b6
Batch resource uploads into one shared command list
claude Jul 3, 2026
51293d6
Docs: record Phase 4 loading/stutter progress and PSO-cache findings
claude Jul 3, 2026
4faa432
Rewrite README to honestly reflect the engine's current state
sheazywi Jul 3, 2026
96150f5
fix: framebuffer attachment type
sheazywi Jul 3, 2026
97d1bf3
Memory HUD: report driver-truth VRAM usage via VK_EXT_memory_budget
claude Jul 3, 2026
f551a74
Mesh CPU memory: drop dead triangle cache, compact vertices in runtime
claude Jul 3, 2026
3f1982c
Skip editor-only render targets in the standalone runtime (~180 MB)
claude Jul 3, 2026
04421b4
Docs: record memory-diet results and the aliasing-coverage verdict
claude Jul 3, 2026
7462019
Trim small always-on per-frame CPU costs
claude Jul 3, 2026
00c8753
Upload only dirty GPUScene rows instead of the full instance array
claude Jul 3, 2026
5c3f504
Bindless texture resolve: retry only pending slots in steady state
claude Jul 3, 2026
ca32315
Rebake only affected descriptor sets on invalidation
claude Jul 3, 2026
6e4706a
Reuse per-pass sorted draw order when the draw-list key set is unchanged
claude Jul 3, 2026
8329179
Docs: record the CPU frame-cost batch (items 9-14)
claude Jul 3, 2026
b4848a1
Grant UAV usage only to compute-written images
claude Jul 4, 2026
624c956
Skip empty editor/transparent passes at the graph level
claude Jul 4, 2026
34f1725
Effect defaults: 2 GTAO denoise passes, temporal SSR/GTAO at High
claude Jul 4, 2026
3a69fc9
Fold the AO composite multiply into the deferred lighting shader
claude Jul 4, 2026
d3e596b
Merge the GBuffer material/object ID targets into one RG32UI attachment
claude Jul 4, 2026
bec0a5a
Docs: record the GPU bandwidth batch and async-compute/VRS designs
claude Jul 4, 2026
303740b
Fix DeferredLighting startup crash from the AO fold
claude Jul 4, 2026
b9af654
Re-bake render/compute pass descriptor sets when their shader reloads
claude Jul 4, 2026
7a6ecfb
Defer pass descriptor rebake on shader reload to the render thread
claude Jul 4, 2026
5178ed1
Diagnostic: log each render-graph pass as it executes on frame 1
claude Jul 4, 2026
326682f
Fix build: move PassDesc.DebugName last so aggregate initializers sti…
claude Jul 4, 2026
2e26181
Diagnostic: bracket GBuffer BeginRenderPass + draw sub-steps
claude Jul 4, 2026
c8551a1
fix: GTAO first-frame crash
sheazywi Jul 4, 2026
da0b97f
Remove TAA: stop creating the resolve pass, buffers, and editor toggle
claude Jul 4, 2026
c9b583c
Remove GBuffer-crash diagnostic instrumentation
claude Jul 4, 2026
d98265c
Remove Sky Atmosphere, Volumetric Clouds, and Atmospheric Fog
claude Jul 4, 2026
e2afc27
Cap Cinematic shadow atlas at 2K (was 8K)
claude Jul 4, 2026
b9f2550
Cache the mip-generation compute pipeline instead of rebuilding it pe…
claude Jul 4, 2026
445f92f
Async compute (1/N): enable the compute queue + cross-queue plumbing
claude Jul 4, 2026
f2c9b4e
Async compute (2/N): cluster light-culling on the compute queue (corr…
claude Jul 4, 2026
7a44db9
Add Async Compute toggle to the renderer panel (experimental)
claude Jul 4, 2026
94e025d
Async compute (3/N): split the graphics submit around the compute wait
claude Jul 5, 2026
ed61d65
Revert "Async compute (3/N): split the graphics submit around the com…
claude Jul 5, 2026
eda6d57
Make the Renderer Debugger pass-timing table sortable
claude Jul 5, 2026
808fbc6
Perf: allow 2 frames in flight and drop the validation layer in Release
claude Jul 5, 2026
3c92d3d
Editor: redesign the ImGui theme (cool graphite + indigo-violet accent)
claude Jul 5, 2026
f88e15b
Merge branch 'dev' into claude/lux-engine-performance-q69zu4
sheazywi Jul 5, 2026
5f376ab
Potential fix for pull request finding
sheazywi Jul 5, 2026
7286271
Potential fix for pull request finding
sheazywi Jul 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions Core/Source/Lux/Asset/AssimpMeshImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,20 +569,6 @@ namespace Lux

ImportAssimpMaterials(m_Path, scene, meshSource);

// ── Triangle cache ────────────────────────────────────────────────────
for (uint32_t i = 0; i < (uint32_t)meshSource->m_Submeshes.size(); i++)
{
const Submesh& sm = meshSource->m_Submeshes[i];
for (uint32_t f = 0; f < sm.IndexCount / 3; f++)
{
const Index& idx = meshSource->m_Indices[sm.BaseIndex / 3 + f];
meshSource->m_TriangleCache[i].emplace_back(
meshSource->m_Vertices[sm.BaseVertex + idx.V1],
meshSource->m_Vertices[sm.BaseVertex + idx.V2],
meshSource->m_Vertices[sm.BaseVertex + idx.V3]);
}
}

// ── GPU buffers ───────────────────────────────────────────────────────
meshSource->m_VertexBuffer = VertexBuffer::Create(
Buffer(meshSource->m_Vertices.data(),
Expand Down
24 changes: 3 additions & 21 deletions Core/Source/Lux/Asset/MeshRuntimeSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,27 +252,9 @@ namespace Lux
if (!meshSource->m_Indices.empty())
meshSource->m_IndexBuffer = IndexBuffer::Create(Buffer(meshSource->m_Indices.data(), (uint32_t)(meshSource->m_Indices.size() * sizeof(Index))));

for (uint32_t i = 0; i < (uint32_t)meshSource->m_Submeshes.size(); i++)
{
const Submesh& submesh = meshSource->m_Submeshes[i];
const uint32_t firstTriangle = submesh.BaseIndex / 3;
const uint32_t triangleCount = submesh.IndexCount / 3;
for (uint32_t triangle = 0; triangle < triangleCount; triangle++)
{
const uint32_t indexOffset = firstTriangle + triangle;
if (indexOffset >= meshSource->m_Indices.size())
break;

const Index& index = meshSource->m_Indices[indexOffset];
const uint32_t v0 = submesh.BaseVertex + index.V1;
const uint32_t v1 = submesh.BaseVertex + index.V2;
const uint32_t v2 = submesh.BaseVertex + index.V3;
if (v0 >= meshSource->m_Vertices.size() || v1 >= meshSource->m_Vertices.size() || v2 >= meshSource->m_Vertices.size())
continue;

meshSource->m_TriangleCache[i].emplace_back(meshSource->m_Vertices[v0], meshSource->m_Vertices[v1], meshSource->m_Vertices[v2]);
}
}
// In the standalone runtime, drop the full CPU vertex array now that the
// GPU has it (positions + indices are kept for physics cooking).
meshSource->CompactCPUGeometry();

return meshSource;
}
Expand Down
64 changes: 40 additions & 24 deletions Core/Source/Lux/ImGui/Colors.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,45 @@ namespace Colors
// members of a static "Theme" class and add a quick ImGui window to adjust the colour values
namespace Theme
{
constexpr auto accent = IM_COL32(236, 158, 36, 255);
constexpr auto highlight = IM_COL32(39, 185, 242, 255);
constexpr auto niceBlue = IM_COL32(83, 232, 254, 255);
constexpr auto compliment = IM_COL32(78, 151, 166, 255);
constexpr auto background = IM_COL32(36, 36, 36, 255);
constexpr auto backgroundDark = IM_COL32(26, 26, 26, 255);
constexpr auto titlebar = IM_COL32(21, 21, 21, 255);
constexpr auto titlebarOrange = IM_COL32(186, 66, 30, 255);
constexpr auto titlebarGreen = IM_COL32(18, 88, 30, 255);
constexpr auto titlebarRed = IM_COL32(185, 30, 30, 255);
constexpr auto propertyField = IM_COL32(15, 15, 15, 255);
constexpr auto text = IM_COL32(192, 192, 192, 255);
constexpr auto textBrighter = IM_COL32(210, 210, 210, 255);
constexpr auto textDarker = IM_COL32(128, 128, 128, 255);
constexpr auto textError = IM_COL32(230, 51, 51, 255);
constexpr auto muted = IM_COL32(77, 77, 77, 255);
constexpr auto groupHeader = IM_COL32(47, 47, 47, 255);
constexpr auto selection = IM_COL32(237, 192, 119, 255);
constexpr auto selectionMuted = IM_COL32(237, 201, 142, 23);
constexpr auto backgroundPopup = IM_COL32(50, 50, 50, 255);
constexpr auto validPrefab = IM_COL32(82, 179, 222, 255);
constexpr auto invalidPrefab = IM_COL32(222, 43, 43, 255);
constexpr auto missingMesh = IM_COL32(230, 102, 76, 255);
constexpr auto meshNotSet = IM_COL32(250, 101, 23, 255);
// LuxEngine editor theme: a cool-graphite dark base with a single luminous
// indigo-violet accent ("Lux" = light). The accent is used sparingly — selection,
// active separators, focus, checkmarks — so the UI reads calm and clean rather
// than busy. Deliberately distinct from Hazel's orange/cyan palette.

// Signature accent + its cooler/brighter relatives.
constexpr auto accent = IM_COL32(124, 131, 248, 255); // #7C83F8 indigo-violet
constexpr auto highlight = IM_COL32(139, 156, 255, 255); // brighter periwinkle
constexpr auto niceBlue = IM_COL32(150, 165, 255, 255);
constexpr auto compliment = IM_COL32(116, 126, 168, 255);

// Neutral graphite surfaces (a faint cool/blue tint reads more premium than flat gray).
constexpr auto background = IM_COL32(30, 31, 37, 255);
constexpr auto backgroundDark = IM_COL32(21, 22, 27, 255);
constexpr auto titlebar = IM_COL32(17, 18, 22, 255);
constexpr auto propertyField = IM_COL32(13, 14, 17, 255);
constexpr auto groupHeader = IM_COL32(38, 40, 48, 255);
constexpr auto backgroundPopup = IM_COL32(40, 42, 50, 255);

// Play/pause/stop and status titlebars (kept semantic, just refined).
constexpr auto titlebarOrange = IM_COL32(197, 121, 45, 255);
constexpr auto titlebarGreen = IM_COL32(46, 121, 78, 255);
constexpr auto titlebarRed = IM_COL32(192, 64, 64, 255);

// Text: slightly cool whites with clear hierarchy.
constexpr auto text = IM_COL32(199, 202, 213, 255);
constexpr auto textBrighter = IM_COL32(226, 228, 238, 255);
constexpr auto textDarker = IM_COL32(118, 122, 138, 255);
constexpr auto textError = IM_COL32(232, 84, 84, 255);
constexpr auto muted = IM_COL32(70, 73, 86, 255);

// Selection derives from the accent so highlighted rows/text stay on-brand.
constexpr auto selection = IM_COL32(124, 131, 248, 255);
constexpr auto selectionMuted = IM_COL32(124, 131, 248, 38);

// Asset-status semantic colours.
constexpr auto validPrefab = IM_COL32(124, 156, 232, 255);
constexpr auto invalidPrefab = IM_COL32(222, 64, 64, 255);
constexpr auto missingMesh = IM_COL32(226, 112, 86, 255);
constexpr auto meshNotSet = IM_COL32(232, 146, 60, 255);
}
}
53 changes: 36 additions & 17 deletions Core/Source/Lux/ImGui/ImGuiLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ namespace Lux {
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.15f, 0.15f, 0.15f, style.Colors[ImGuiCol_WindowBg].w);
// Docked/window backgrounds sit a touch above the titlebar; use the theme's
// graphite surface (not a flat gray) so it stays cohesive with the palette.
{
ImVec4 windowBg = ImGui::ColorConvertU32ToFloat4(Colors::Theme::background);
windowBg.w = style.Colors[ImGuiCol_WindowBg].w;
style.Colors[ImGuiCol_WindowBg] = windowBg;
}

ImGui_ImplGlfw_InitForVulkan((GLFWwindow*)Application::Get().GetWindow().GetNativeWindow(), true);

Expand Down Expand Up @@ -348,10 +354,10 @@ namespace Lux {
colors[ImGuiCol_FrameBgHovered] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::propertyField);
colors[ImGuiCol_FrameBgActive] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::propertyField);

// Tabs
// Tabs (accent-tinted so the active tab reads as "selected" on-brand)
colors[ImGuiCol_Tab] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::titlebar);
colors[ImGuiCol_TabHovered] = ImColor(255, 225, 135, 30);
colors[ImGuiCol_TabActive] = ImColor(255, 225, 135, 60);
colors[ImGuiCol_TabHovered] = ImColor(124, 131, 248, 45);
colors[ImGuiCol_TabActive] = ImColor(124, 131, 248, 90);
colors[ImGuiCol_TabUnfocused] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::titlebar);
colors[ImGuiCol_TabUnfocusedActive] = colors[ImGuiCol_TabHovered];

Expand All @@ -371,23 +377,21 @@ namespace Lux {
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.0f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.0f);

// Check Mark
colors[ImGuiCol_CheckMark] = ImColor(200, 200, 200, 255);
// Check Mark (accent so ticks pop cleanly against the deep frame bg)
colors[ImGuiCol_CheckMark] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::accent);

// Slider
colors[ImGuiCol_SliderGrab] = ImVec4(0.51f, 0.51f, 0.51f, 0.7f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.66f, 0.66f, 0.66f, 1.0f);
// Slider (neutral grab, accent when actively dragged)
colors[ImGuiCol_SliderGrab] = ImVec4(0.42f, 0.44f, 0.52f, 0.9f);
colors[ImGuiCol_SliderGrabActive] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::accent);

// Text
colors[ImGuiCol_Text] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::text);
colors[ImGuiCol_TextDisabled] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::textDarker);

// Checkbox
colors[ImGuiCol_CheckMark] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::text);

// Separator
// Separator (subtle by default, accent when active/hovered)
colors[ImGuiCol_Separator] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::backgroundDark);
colors[ImGuiCol_SeparatorActive] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::highlight);
colors[ImGuiCol_SeparatorHovered] = ImColor(39, 185, 242, 150);
colors[ImGuiCol_SeparatorActive] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::accent);
colors[ImGuiCol_SeparatorHovered] = ImColor(124, 131, 248, 150);

// Window Background
colors[ImGuiCol_WindowBg] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::titlebar);
Expand All @@ -402,10 +406,25 @@ namespace Lux {
// Menubar
colors[ImGuiCol_MenuBarBg] = ImVec4{ 0.0f, 0.0f, 0.0f, 0.0f };

// Accent-driven interaction feedback (text selection, drag/drop, keyboard nav)
colors[ImGuiCol_TextSelectedBg] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::selectionMuted);
colors[ImGuiCol_DragDropTarget] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::accent);
colors[ImGuiCol_NavHighlight] = ImGui::ColorConvertU32ToFloat4(Colors::Theme::accent);

//========================================================
/// Style
style.FrameRounding = 2.5f;
/// Style — softer, rounder, cleaner than the default. Rounding is applied to the
/// widgets that read as "controls" (frames, grabs, tabs, scrollbars, popups);
/// spacing/padding are left alone so the panels' hand-tuned cursor offsets still line up.
style.FrameRounding = 4.0f;
style.FrameBorderSize = 1.0f;
style.GrabRounding = 4.0f;
style.GrabMinSize = 7.0f;
style.TabRounding = 4.0f;
style.ScrollbarRounding = 9.0f;
style.ScrollbarSize = 13.0f;
style.PopupRounding = 6.0f;
style.ChildRounding = 6.0f;
style.PopupBorderSize = 1.0f;
style.IndentSpacing = 11.0f;
}

Expand Down
12 changes: 7 additions & 5 deletions Core/Source/Lux/Physics/JoltPhysics/JoltShapes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ namespace Lux {

static void AppendSubmeshTriangles(const MeshSource& meshSource, const Submesh& submesh, const glm::vec3& scale, JPH::TriangleList& triangles)
{
const auto& vertices = meshSource.GetVertices();
// Position accessors work whether the mesh kept its full CPU vertex
// array (editor) or was compacted to positions-only (runtime).
const size_t vertexCount = meshSource.GetVertexCount();
const auto& indices = meshSource.GetIndices();
const uint32_t firstTriangle = submesh.BaseIndex / 3;
const uint32_t triangleCount = submesh.IndexCount / 3;
Expand All @@ -64,12 +66,12 @@ namespace Lux {
const uint32_t i0 = submesh.BaseVertex + index.V1;
const uint32_t i1 = submesh.BaseVertex + index.V2;
const uint32_t i2 = submesh.BaseVertex + index.V3;
if (i0 >= vertices.size() || i1 >= vertices.size() || i2 >= vertices.size())
if (i0 >= vertexCount || i1 >= vertexCount || i2 >= vertexCount)
continue;

const glm::vec3 p0 = glm::vec3(submesh.Transform * glm::vec4(vertices[i0].Position, 1.0f)) * scale;
const glm::vec3 p1 = glm::vec3(submesh.Transform * glm::vec4(vertices[i1].Position, 1.0f)) * scale;
const glm::vec3 p2 = glm::vec3(submesh.Transform * glm::vec4(vertices[i2].Position, 1.0f)) * scale;
const glm::vec3 p0 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i0), 1.0f)) * scale;
const glm::vec3 p1 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i1), 1.0f)) * scale;
const glm::vec3 p2 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i2), 1.0f)) * scale;
triangles.emplace_back(JoltUtils::ToJoltVector(p0), JoltUtils::ToJoltVector(p1), JoltUtils::ToJoltVector(p2));
}
}
Expand Down
14 changes: 8 additions & 6 deletions Core/Source/Lux/Physics/PhysicsScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,11 @@ namespace Lux {

static void AppendMeshTrianglesFromSubmesh(const MeshSource& meshSource, const Submesh& submesh, const glm::vec3& scale, JPH::TriangleList& triangles)
{
const auto& vertices = meshSource.GetVertices();
// Position accessors work whether the mesh kept its full CPU vertex
// array (editor) or was compacted to positions-only (runtime).
const size_t vertexCount = meshSource.GetVertexCount();
const auto& indices = meshSource.GetIndices();
if (vertices.empty() || indices.empty())
if (vertexCount == 0 || indices.empty())
return;

const uint32_t firstTriangle = submesh.BaseIndex / 3;
Expand All @@ -369,12 +371,12 @@ namespace Lux {
const uint32_t i0 = submesh.BaseVertex + index.V1;
const uint32_t i1 = submesh.BaseVertex + index.V2;
const uint32_t i2 = submesh.BaseVertex + index.V3;
if (i0 >= vertices.size() || i1 >= vertices.size() || i2 >= vertices.size())
if (i0 >= vertexCount || i1 >= vertexCount || i2 >= vertexCount)
continue;

const glm::vec3 p0 = glm::vec3(submesh.Transform * glm::vec4(vertices[i0].Position, 1.0f)) * scale;
const glm::vec3 p1 = glm::vec3(submesh.Transform * glm::vec4(vertices[i1].Position, 1.0f)) * scale;
const glm::vec3 p2 = glm::vec3(submesh.Transform * glm::vec4(vertices[i2].Position, 1.0f)) * scale;
const glm::vec3 p0 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i0), 1.0f)) * scale;
const glm::vec3 p1 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i1), 1.0f)) * scale;
const glm::vec3 p2 = glm::vec3(submesh.Transform * glm::vec4(meshSource.GetVertexPosition(i2), 1.0f)) * scale;

triangles.push_back(JPH::Triangle(ToJoltVector(p0), ToJoltVector(p1), ToJoltVector(p2)));
}
Expand Down
Loading
Loading