Skip to content

Removed redundant Settings nodes#1403

Closed
Ungeziefi wants to merge 4 commits into
community-shaders:devfrom
Ungeziefi:dev
Closed

Removed redundant Settings nodes#1403
Ungeziefi wants to merge 4 commits into
community-shaders:devfrom
Ungeziefi:dev

Conversation

@Ungeziefi
Copy link
Copy Markdown
Contributor

@Ungeziefi Ungeziefi commented Aug 17, 2025

This makes Dynamic Cubemaps and VL menus consistent with the rest

Summary by CodeRabbit

  • New Features
    • Performance overlay now shows a historical average FPS alongside current FPS.
    • Settings > Shaders shows the last shader cache build duration when available.
  • Refactor
    • Settings UI reorganized: reflections, cubemap creator and VR advanced settings promoted to top-level for quicker access.
    • Volumetric Lighting settings are always visible, removing the collapsible wrapper.
  • Bug Fixes
    • Cubemap export hardened with safer path handling, existence checks, clearer status messages and reliable resource cleanup.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 17, 2025

Warning

Rate limit exceeded

@Ungeziefi has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between b598064 and ff4e440.

📒 Files selected for processing (8)
  • src/Features/DynamicCubemaps.cpp (1 hunks)
  • src/Features/PerformanceOverlay.cpp (1 hunks)
  • src/Features/VolumetricLighting.cpp (1 hunks)
  • src/Menu/SettingsTabRenderer.cpp (2 hunks)
  • src/ShaderCache.cpp (2 hunks)
  • src/ShaderCache.h (2 hunks)
  • src/State.cpp (10 hunks)
  • src/State.h (2 hunks)

Walkthrough

Flattened several ImGui Settings trees (DynamicCubemaps, VolumetricLighting). Dynamic cubemap export flow hardened with explicit filename/path assembly, existence checks, try/catch logging, and deterministic resource cleanup. PerformanceOverlay now displays a historical average FPS alongside smoothed FPS.

Changes

Cohort / File(s) Summary
Dynamic Cubemaps UI and Export Flow
src/Features/DynamicCubemaps.cpp
Promoted SSR, Cubemap Creator, and VR Advanced blocks to top-level nodes. Reworked export: local temp texture & ScratchImage, explicit filename/path via std::format, ensure directory, existence check, try/catch logging on failure, and guaranteed resource release.
Volumetric Lighting UI Structure
src/Features/VolumetricLighting.cpp
Removed outer collapsible “Settings” wrapper; settings render unconditionally. Toggles still call SetupVL(); detailed settings remain gated by Enabled flags.
Performance Overlay Average FPS
src/Features/PerformanceOverlay.cpp
DrawFPS now computes average frame time from history, derives avgFps, and appends “
Shader cache stats API and usage
src/ShaderCache.cpp, src/ShaderCache.h
Added boolean parameter a_elapsedOnly to CompilationSet::GetStatsString and ShaderCache::GetShaderStatsString (defaults false). Logic updated to optionally return elapsed-only time when requested; callers updated accordingly.
Settings UI tweak
src/Menu/SettingsTabRenderer.cpp
Shortened Disk Cache tooltip text and added conditional display of last shader cache build duration using shaderCache->GetShaderStatsString(true, true).

Sequence Diagram(s)

sequenceDiagram
  participant UI as ImGui UI
  participant DCC as DynamicCubemap Creator
  participant FS as Filesystem
  participant DX as DirectX

  UI->>DCC: Click Export
  DCC->>DCC: Build filename (RxxxGxxxBxxxAxxx.dds)
  DCC->>FS: Ensure directory exists
  DCC->>FS: Check file existence
  alt File exists
    DCC->>UI: Log "skip (exists)"
  else
    DCC->>DX: Create temp texture & capture to ScratchImage
    DX-->>DCC: Image data
    DCC->>FS: Save DDS
    DCC->>UI: Log "written"
  end
  DCC->>DX: Release image/texture
  note over DCC: try/catch logs failures
Loading
sequenceDiagram
  participant PO as PerformanceOverlay::DrawFPS
  participant Hist as FrameTimeHistory
  participant UI as ImGui

  PO->>Hist: GetData()
  Hist-->>PO: frame times
  PO->>PO: Compute avgFrameTime, avgFps
  PO->>UI: Print "FPS: smoothFps (ms) | Avg: avgFps"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • davo0411
  • alandtse
  • jiayev

Poem

I hopped through settings, pruned a tree,
Saved cubemaps neatly, tidy as can be.
I counted frames both new and old,
Averaged tales the numbers told.
A rabbit logs, a format sings — export complete with tiny springs. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link
Copy Markdown

Using provided base ref: 2a9e819
Using base ref: 2a9e819
Base commit date: 2025-08-16T00:16:27-07:00 (Saturday, August 16, 2025 12:16 AM)
No actionable suggestions for changed features.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/Features/PerformanceOverlay.cpp (1)

395-401: Avg FPS calculation works but should exclude zero/uninitialized samples to avoid misleading low averages

The history buffer is pre-sized; early frames will include zeros. Averaging zeros yields "Avg: 0.0" or an artificially low Avg FPS until the buffer is warmed up. Excluding non-positive samples makes the metric more representative immediately.

Apply this diff to compute the average over valid samples only:

-        float avgFrameTime = std::accumulate(this->state.frameTimeHistory.GetData().begin(),
-                                 this->state.frameTimeHistory.GetData().end(), 0.0f) /
-                             this->state.frameTimeHistory.GetData().size();
-        float avgFps = avgFrameTime > 0.0f ? 1000.0f / avgFrameTime : 0.0f;
+        const auto& data = this->state.frameTimeHistory.GetData();
+        size_t validCount = std::count_if(data.begin(), data.end(), [](float ft) { return ft > 0.0f; });
+        float sum = 0.0f;
+        for (float ft : data) {
+            if (ft > 0.0f) sum += ft;
+        }
+        float avgFrameTime = validCount > 0 ? (sum / static_cast<float>(validCount)) : 0.0f;
+        float avgFps = (avgFrameTime > 0.0f) ? (1000.0f / avgFrameTime) : 0.0f;
src/Features/DynamicCubemaps.cpp (1)

64-88: Zero-initialize D3D11_SUBRESOURCE_DATA to avoid undefined fields

While you set the essential fields, value-initializing the array prevents garbage in unused members and is cheap.

Apply this small change:

-                D3D11_SUBRESOURCE_DATA subresourceData[6];
+                D3D11_SUBRESOURCE_DATA subresourceData[6] = {};
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2a9e819 and 98c45f2.

📒 Files selected for processing (3)
  • src/Features/DynamicCubemaps.cpp (1 hunks)
  • src/Features/PerformanceOverlay.cpp (1 hunks)
  • src/Features/VolumetricLighting.cpp (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build plugin and addons
🔇 Additional comments (3)
src/Features/VolumetricLighting.cpp (1)

24-35: Good UI flattening; toggles still call SetupVL() immediately

Removing the outer Settings wrapper and exposing the two toggles directly aligns with the PR objective and preserves behavior.

src/Features/DynamicCubemaps.cpp (2)

28-41: SSR section flattening looks correct

Promoting “Screen Space Reflections” to a top-level TreeNode with its own Tooltip/VR note maintains behavior and meets the PR goal.


122-128: VR advanced settings moved to a top-level section—looks good

The VR settings are now self-contained under their own node with both visible and hidden settings, matching the flattened UI intent.

Comment on lines +90 to 117
ID3D11Texture2D* tempTexture;
DirectX::ScratchImage image;

if (std::filesystem::create_directories(defaultDynamicCubeMapSavePath)) {
logger::info("Missing DynamicCubeMap Creator directory created: {}", defaultDynamicCubeMapSavePath);
}
try {
DX::ThrowIfFailed(device->CreateTexture2D(&texDesc, subresourceData, &tempTexture));
DX::ThrowIfFailed(CaptureTexture(device, context, tempTexture, image));

std::filesystem::path DynamicCubeMapSavePath = defaultDynamicCubeMapSavePath;
std::filesystem::path filename(std::format("R{:03d}G{:03d}B{:03d}A{:03d}.dds", colorPixel.r, colorPixel.g, colorPixel.b, colorPixel.a));
DynamicCubeMapSavePath /= filename;
if (std::filesystem::create_directories(defaultDynamicCubeMapSavePath)) {
logger::info("Missing DynamicCubeMap Creator directory created: {}", defaultDynamicCubeMapSavePath);
}

if (std::filesystem::exists(DynamicCubeMapSavePath)) {
logger::info("DynamicCubeMap Creator file for {} already exists, skipping.", filename.string());
} else {
DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DirectX::DDS_FLAGS::DDS_FLAGS_NONE, DynamicCubeMapSavePath.c_str()));
logger::info("DynamicCubeMap Creator file for {} written", filename.string());
}
std::filesystem::path DynamicCubeMapSavePath = defaultDynamicCubeMapSavePath;
std::filesystem::path filename(std::format("R{:03d}G{:03d}B{:03d}A{:03d}.dds", colorPixel.r, colorPixel.g, colorPixel.b, colorPixel.a));
DynamicCubeMapSavePath /= filename;

} catch (const std::exception& e) {
logger::error("Failed in DynamicCubeMap Creator file: {} {}", defaultDynamicCubeMapSavePath, e.what());
if (std::filesystem::exists(DynamicCubeMapSavePath)) {
logger::info("DynamicCubeMap Creator file for {} already exists, skipping.", filename.string());
} else {
DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DirectX::DDS_FLAGS::DDS_FLAGS_NONE, DynamicCubeMapSavePath.c_str()));
logger::info("DynamicCubeMap Creator file for {} written", filename.string());
}

image.Release();
tempTexture->Release();
} catch (const std::exception& e) {
logger::error("Failed in DynamicCubeMap Creator file: {} {}", defaultDynamicCubeMapSavePath, e.what());
}

image.Release();
tempTexture->Release();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential null/garbage dereference on cleanup when exceptions occur

  • tempTexture is uninitialized and released unconditionally after the try/catch. If CreateTexture2D throws before assignment, tempTexture is indeterminate and dereferencing it is UB.
  • Prefer RAII (ComPtr) or at least initialize to nullptr and null-check before Release().

Minimal safe fix:

-                ID3D11Texture2D* tempTexture;
+                ID3D11Texture2D* tempTexture = nullptr;
                 DirectX::ScratchImage image;
@@
-                image.Release();
-                tempTexture->Release();
+                image.Release();
+                if (tempTexture) {
+                    tempTexture->Release();
+                    tempTexture = nullptr;
+                }

Optional: Switch to Microsoft::WRL::ComPtr to make cleanup exception-safe automatically.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ID3D11Texture2D* tempTexture;
DirectX::ScratchImage image;
if (std::filesystem::create_directories(defaultDynamicCubeMapSavePath)) {
logger::info("Missing DynamicCubeMap Creator directory created: {}", defaultDynamicCubeMapSavePath);
}
try {
DX::ThrowIfFailed(device->CreateTexture2D(&texDesc, subresourceData, &tempTexture));
DX::ThrowIfFailed(CaptureTexture(device, context, tempTexture, image));
std::filesystem::path DynamicCubeMapSavePath = defaultDynamicCubeMapSavePath;
std::filesystem::path filename(std::format("R{:03d}G{:03d}B{:03d}A{:03d}.dds", colorPixel.r, colorPixel.g, colorPixel.b, colorPixel.a));
DynamicCubeMapSavePath /= filename;
if (std::filesystem::create_directories(defaultDynamicCubeMapSavePath)) {
logger::info("Missing DynamicCubeMap Creator directory created: {}", defaultDynamicCubeMapSavePath);
}
if (std::filesystem::exists(DynamicCubeMapSavePath)) {
logger::info("DynamicCubeMap Creator file for {} already exists, skipping.", filename.string());
} else {
DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DirectX::DDS_FLAGS::DDS_FLAGS_NONE, DynamicCubeMapSavePath.c_str()));
logger::info("DynamicCubeMap Creator file for {} written", filename.string());
}
std::filesystem::path DynamicCubeMapSavePath = defaultDynamicCubeMapSavePath;
std::filesystem::path filename(std::format("R{:03d}G{:03d}B{:03d}A{:03d}.dds", colorPixel.r, colorPixel.g, colorPixel.b, colorPixel.a));
DynamicCubeMapSavePath /= filename;
} catch (const std::exception& e) {
logger::error("Failed in DynamicCubeMap Creator file: {} {}", defaultDynamicCubeMapSavePath, e.what());
if (std::filesystem::exists(DynamicCubeMapSavePath)) {
logger::info("DynamicCubeMap Creator file for {} already exists, skipping.", filename.string());
} else {
DX::ThrowIfFailed(SaveToDDSFile(image.GetImages(), image.GetImageCount(), image.GetMetadata(), DirectX::DDS_FLAGS::DDS_FLAGS_NONE, DynamicCubeMapSavePath.c_str()));
logger::info("DynamicCubeMap Creator file for {} written", filename.string());
}
image.Release();
tempTexture->Release();
} catch (const std::exception& e) {
logger::error("Failed in DynamicCubeMap Creator file: {} {}", defaultDynamicCubeMapSavePath, e.what());
}
image.Release();
tempTexture->Release();
}
// Ensure tempTexture is always initialized
ID3D11Texture2D* tempTexture = nullptr;
DirectX::ScratchImage image;
try {
DX::ThrowIfFailed(device->CreateTexture2D(&texDesc, subresourceData, &tempTexture));
DX::ThrowIfFailed(CaptureTexture(device, context, tempTexture, image));
if (std::filesystem::create_directories(defaultDynamicCubeMapSavePath)) {
logger::info("Missing DynamicCubeMap Creator directory created: {}", defaultDynamicCubeMapSavePath);
}
std::filesystem::path DynamicCubeMapSavePath = defaultDynamicCubeMapSavePath;
std::filesystem::path filename(std::format(
"R{:03d}G{:03d}B{:03d}A{:03d}.dds",
colorPixel.r, colorPixel.g, colorPixel.b, colorPixel.a));
DynamicCubeMapSavePath /= filename;
if (std::filesystem::exists(DynamicCubeMapSavePath)) {
logger::info(
"DynamicCubeMap Creator file for {} already exists, skipping.",
filename.string());
} else {
DX::ThrowIfFailed(SaveToDDSFile(
image.GetImages(), image.GetImageCount(),
image.GetMetadata(), DirectX::DDS_FLAGS::DDS_FLAGS_NONE,
DynamicCubeMapSavePath.c_str()));
logger::info(
"DynamicCubeMap Creator file for {} written",
filename.string());
}
} catch (const std::exception& e) {
logger::error(
"Failed in DynamicCubeMap Creator file: {} {}",
defaultDynamicCubeMapSavePath, e.what());
}
image.Release();
if (tempTexture) {
tempTexture->Release();
tempTexture = nullptr;
}
}
🤖 Prompt for AI Agents
In src/Features/DynamicCubemaps.cpp around lines 90-118, tempTexture is declared
uninitialized and unconditionally released after the try/catch which can cause
undefined behavior if CreateTexture2D throws; fix by making tempTexture
initialized to nullptr and only calling Release() when it's non-null, or better
replace the raw pointer with Microsoft::WRL::ComPtr<ID3D11Texture2D> (or a
similar RAII wrapper) so the texture is released automatically even if an
exception is thrown; ensure the image.Release() and texture cleanup happen
safely in all control paths (if keeping raw pointer, null-check before Release
and set to nullptr after release).

Comment thread src/Features/DynamicCubemaps.cpp
Comment thread src/Features/VolumetricLighting.cpp
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/ShaderCache.h (2)

263-263: API extension preserves source compatibility

Adding a_elapsedOnly with a default maintains backward compatibility and aligns with the new UI usage. No issues spotted.

Consider documenting that a_elapsedOnly is only meaningful when a_timeOnly is true, so callers don’t assume it affects the full summary mode.


399-399: Consistent two-flag signature for stats string

Signature matches CompilationSet and enables the UI’s concise duration display. Good cohesion between layers.

Same note as above: a brief comment on parameter semantics would help future readers.

src/Menu/SettingsTabRenderer.cpp (1)

52-55: Differentiate “current” vs “last” build and surface ETA while compiling

Showing only the elapsed time is great post-build, but when a build is in progress, including ETA is more helpful. Also, labeling “Current” vs “Last” removes ambiguity.

Apply this diff:

-        if (shaderCache->GetTotalTasks() > 0) {
-            ImGui::Text("Last shader cache build duration: %s",
-                shaderCache->GetShaderStatsString(true, true).c_str());
-        }
+        if (shaderCache->GetTotalTasks() > 0) {
+            const bool compiling = shaderCache->IsCompiling();
+            ImGui::Text("%s shader cache build %s: %s",
+                compiling ? "Current" : "Last",
+                compiling ? "(elapsed/estimated)" : "duration",
+                shaderCache->GetShaderStatsString(true, !compiling).c_str());
+        }

If you prefer to avoid passing c_str() of a temporary to a variadic function, store the returned std::string in a local and then pass c_str(); it’s safe either way with ImGui::Text.

src/ShaderCache.cpp (1)

2617-2640: Time-only mode now supports “elapsed-only” and “elapsed/estimated” — solid UX improvement

The split between a_elapsedOnly returning only elapsed and the default returning elapsed/estimated is sound and matches UI expectations.

Edge-case: when there are no tasks, totalMs is 0 and both branches format to 00:00:00 or 00:00:00/00:00:00, which is fine. If you want to be explicit, you could early-return an empty string in a_timeOnly mode when totalTasks == 0.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 98c45f2 and b598064.

📒 Files selected for processing (3)
  • src/Menu/SettingsTabRenderer.cpp (2 hunks)
  • src/ShaderCache.cpp (2 hunks)
  • src/ShaderCache.h (2 hunks)
🔇 Additional comments (2)
src/Menu/SettingsTabRenderer.cpp (1)

41-41: Tooltip rewording is clearer

The updated text better communicates what happens when disk cache is disabled. Consistent tone with the “Use Custom Shaders” tooltip.

src/ShaderCache.cpp (1)

2060-2063: Forwarding both flags from ShaderCache to CompilationSet is correct

The new overload cleanly propagates a_timeOnly and a_elapsedOnly. Matches the header.

Added an a_elapsedOnly argument to GetStatsString to easily allow the addition of the feature without doing any formatting on the original one to remove the estimated part. Also improved wording for a tooltip.
The user config is now created from the difference between defaults and current settings. finalSettings is built from the default+override+user layering and the user config is automatically removed when identical to default.
This makes Dynamic Cubemaps and VL menus consistent with the rest
@github-actions
Copy link
Copy Markdown

✅ A pre-release build is available for this PR:
Download

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant