Skip to content

Add TheNoise-based upscalers - #3327

Merged
bitgamma merged 6 commits into
mainfrom
bitgamma/thenoise-v0.4.0
Aug 25, 2026
Merged

Add TheNoise-based upscalers#3327
bitgamma merged 6 commits into
mainfrom
bitgamma/thenoise-v0.4.0

Conversation

@bitgamma

@bitgamma bitgamma commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

Adds the ability to upscale images using TheNoise + adds additional upscaling models. Since the upscaling endpoint was hardcoded for sdcpp, a few changes were needed to sdcpp backend to move backend-specific code away from server.cpp.

Additionally I removed "experimental" from the backend's name and added the "rocm" bin variant to users can keep track of specific forks or "latest" like the other backends.

Scope

  • This PR addresses one clear issue or change.
  • I reviewed the full diff myself before submitting.
  • I removed unrelated local changes.
  • I kept refactoring separate unless it is required for this change.

Testing

  • Code builds without errors locally.
  • I tested this change locally.
  • I described the testing performed below.

In image generation, select one of the upscaler models from this PR (-TheNoise suffix). Also tried the pre-existing models and both paths still work.

Documentation

  • Documentation is affected and has been updated.

Breaking Changes

  • This PR does not introduce breaking changes.

AI-assisted contribution

Please select one:

  • I used AI tools for this PR.

If AI tools were used:

  • I verified that I understand the changes.
  • I checked for hallucinated APIs, unrelated changes, and incorrect assumptions.

@bitgamma bitgamma changed the title Add TheNoise-based upscaler options Add TheNoise-based upscalers Aug 24, 2026

@ramkrishna2910 ramkrishna2910 left a comment

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.

The refactor here is the right call and I'd like to land it — moving the binary-path resolution, backend selection, and CLI shelling out of server.cpp and into each backend is exactly where that code belongs, and the net −112 lines in server.cpp is a real improvement. I checked that the sd-cpp path survives the move intact: SDServer::upscale_via_cli preserves the full selection chain (explicit sd-cpp_backend config → SystemInfo::get_supported_backends auto-detect → cpu fallback), so the "silently falls back to CPU" hazard the old inline comment warned about is still guarded. It also now resolves the ROCm channel, which the inline version in server.cpp did not — a latent fix that came along for free.

The five new models are well-formed: recipe: "thenoise" resolves against backend_versions.json, and the upscaling + image labels are right.

Two things I'd like addressed before this merges, both small.

1. upscale_factor is a new request field on a documented endpoint, and it isn't documented.

POST /v1/images/upscale has a full entry in docs/api/openai.md (request table, examples in three languages). This PR adds upscale_factor to that request body with no corresponding documentation — I grepped, there are zero references to it anywhere under docs/. We're trying to hold the line that every endpoint and its parameters are documented, so this needs a row in that table.

2. upscale_factor is silently ignored by sd-cpp, which makes the docs harder to write honestly.

SDServer::upscale_via_cli takes the parameter as double /* upscale_factor */ and never uses it — only TheNoiseServer honors it. So the same field on the same endpoint either works or is silently discarded depending on which recipe the selected model happens to use, with nothing in the response indicating which happened.

Please either wire it through to sd-cli, or reject it with a clear 400 when the target recipe can't honor it. Silently dropping a caller-supplied parameter is the one option I'd rather avoid. Whichever you pick, the doc row from point 1 should say so explicitly.

Smaller notes, none blocking:

  • std::to_string(double) is locale-sensitive. In TheNoiseServer::upscale_via_cli the factor is formatted with std::to_string, which follows LC_NUMERIC — under a comma-decimal locale that emits 2,5 and hands --upscale-factor 2,5 to the CLI. It also always emits six decimals. Nothing in src/cpp/ calls setlocale today so this is latent rather than live, but it's the same trap #3169 hit with std::stod, and #3100 already reaches for std::locale::classic() for exactly this reason. An ostringstream with std::locale::classic() would make it robust.
  • No upper bound on the factor. inf passes the > 0.0 guard and becomes --upscale-factor inf; a large finite value gets passed straight through to a subprocess that will try to allocate the result. A sanity ceiling on a public endpoint seems worth it. (NaN is already excluded, since NaN > 0.0 is false.)
  • The dispatch stayed behind. handle_image_upscale now does if (recipe == "thenoise") ... else if (recipe == "sd-cpp"). That's a hardcoded recipe switch in server.cpp — the same shape of backend-specific knowledge the rest of this PR is removing. A capability interface alongside the others in server_capabilities.h would finish the job. Not for this PR, but worth an issue.
  • The "rocm" variant is hardcoded in TheNoiseServer::upscale_via_cli. That matches reality today (it's the only variant in backend_versions.json), but it will silently keep selecting rocm if a vulkan or cuda variant is ever added. A comment noting the ROCm-only assumption would save the next reader the lookup.

Coordination note: this overlaps with #2842, which adds model-level auto-upscale on the generation endpoints. The two conflict in server.cpp, and I think this one should land first — #2842's do_upscale currently dispatches on the upscaling label alone and then hardcodes sd-cli, so the five recipe: "thenoise" upscalers this PR adds (all suggested: true) would pass its check and then be handed to the wrong binary. The recipe dispatch you added here is the fix; once this is in, #2842 can route through it. I've flagged that on the other PR.

@bitgamma

bitgamma commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

@ramkrishna2910 thanks for your review! I agree on all points.

I decided to go ahead and remove the newly introduced upscale_factor altogether. Since both sdcpp and thenoise can reliably determine the scaling factor from the model, its only use was to apply a downscale after the upscale (for example, get 3.75x instead of 4x) so it is hard to document, inconsistent across backends and easy to do in any image editing program if needed. Now both backends behave the same. In a follow up I might introduce a generic way to pass custom args to either backend, but not in scope for now

Regarding the dispatch, I will do a followup PR.

Regarding the hardcoded rocm variant, I added a comment so that it doesn't go unnoticed if new variants are added.

@ramkrishna2910 ramkrishna2910 left a comment

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.

Approving. Both blocking items are resolved, and I built and ran this locally before signing off.

Removing upscale_factor outright was the better call than either option I offered — a parameter that one backend honors and the other silently discards is worse than no parameter, and dropping it means there's nothing to document inconsistently. The ROCm-only comment on the hardcoded variant is exactly what I was after.

Local verification at d4eb776f2, Windows / Visual Studio 2026 (vs18 preset, Release):

Step Result
lemond build clean
cpp-ci-tests build (~55 binaries) clean
ctest -L cpp-ci 55/55 passed, 0 failed (58.8s)
Server start + /api/v1/health OK

The only compiler warnings were two pre-existing NOMINMAX redefinitions in files this PR doesn't touch.

Two runtime checks worth recording, since they exercise the refactor rather than just compiling it:

  • POST /v1/images/upscale with a llamacpp model returns {"message":"Upscale is not supported by recipe: llamacpp","type":"invalid_request_error"} — that's the new else branch, confirmed live.
  • An sd-cpp model reaches binary resolution under bin/sd-cpp/vulkan, which means the selection chain you moved out of server.cpp (explicit sd-cpp_backendSystemInfo::get_supported_backendscpu) still resolves correctly at runtime. That was my main worry about the move and it holds.

What I could not verify: the TheNoise path itself never executes on my machine. None of the 12 thenoise models appear in /v1/models?show_all=true — including the seven that already exist on main — because the backend is ROCm-only and backend-availability filtering drops them. So TheNoiseServer::upscale_via_cli is covered by your testing and by review, not by mine. Flagging it so the gap is on the record rather than implied away.

One observation, not a blocker and not caused by this PR: handle_image_upscale doesn't enforce the upscaling label. I passed SD-Turbo — a generation model labelled image — and it was accepted as an upscaler and handed to sd-cli. I checked main and the guard isn't there either, so this is pre-existing. Worth knowing because #2842's do_upscale does check the label, so once both land the same bad input is rejected on the auto path and accepted on the direct endpoint. That belongs with the capability-interface cleanup rather than here — I'll open an issue.

Merge order: please land this before #2842. Its do_upscale dispatches on the upscaling label alone and then hardcodes sd-cli, so the five recipe: "thenoise" upscalers you're adding (all suggested: true) would pass its check and be handed to the wrong binary. The recipe dispatch you built here is the fix, and I've asked that PR to route through it.

Thanks for turning this around quickly.

@bitgamma
bitgamma added this pull request to the merge queue Aug 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 25, 2026
@bitgamma
bitgamma added this pull request to the merge queue Aug 25, 2026
@jeremyfowers

Copy link
Copy Markdown
Member

Not ready for review yet

To-dos

  • Update the /v1/images/upscale section in docs/api/openai.md to describe the recipe-based dispatch (sd-cpp vs thenoise), remove the sd-cli-only phrasing, and add the five new TheNoise upscaler models to the available models list.
  • Add a regression test to test/server_thenoise.py that sends a request to /images/upscale with a TheNoise model and verifies a valid upscaled image is returned.
Explanation

Description vs. the diff: accurate

The PR body accurately describes adding TheNoise upscaling, the sdcpp refactor away from server.cpp, the removal of 'experimental' from the backend name, and the addition of the rocm bin variant; the diff matches all claims.

Checked: The PR body claims upscaling for TheNoise, the sdcpp refactor, removal of 'experimental', and the rocm bin variant; all are confirmed in the diff (thenoise_server.cpp adds upscale_via_cli, server.cpp dispatches by recipe, thenoise.h changes the display name and bin_variants, server_models.json adds five model entries).

Focus: focused

All changes serve a single goal — enabling TheNoise-based upscaling. The server.cpp refactor, the sdcpp backend restructuring, the thenoise backend extension, the version bump, and the new model entries are all necessary for this one feature.

Checked: The diff touches server.cpp (refactoring the upscale endpoint), thenoise_server.cpp (new upscale_via_cli), sdcpp_server.cpp (receiving the refactored upscale logic), thenoise.h (display name and bin variant), backend_versions.json (version bump), server_models.json (new models), and related docs — all serving the single goal of TheNoise upscaling.

Alignment: none found

Checked: reviewed contribute.md and philosophy.md; the change is a contained extension of the existing /upscale surface with no new endpoints or commands.

Documentation: gaps

  • Update the /v1/images/upscale section in docs/api/openai.md to describe the recipe-based dispatch (sd-cpp vs thenoise), remove the sd-cli-only phrasing, and add the five new TheNoise upscaler models to the available models list.
    • Gap: The /v1/images/upscale API reference still describes the old sd-cli-only path and only lists RealESRGAN models, while this PR adds recipe-based dispatch that routes TheNoise upscalers through the same endpoint.
    • Why: documentation.md: 'A feature isn't shipped until users can find, understand, and act on it without asking for help. Documentation for a new or changed feature belongs in the same PR as the code.'

Testing: gaps

  • Add a regression test to test/server_thenoise.py that sends a request to /images/upscale with a TheNoise model and verifies a valid upscaled image is returned.
    • Gap: The TheNoise upscale path is not exercised by any test. test/server_thenoise.py only covers /images/generations; no test calls /images/upscale with a thenoise model or exercises TheNoiseServer::upscale_via_cli.
    • Why: testing.md: 'New endpoints, commands, and backends need at least one test that exercises them, in the same PR as the code.'

Breaking changes: none found

Checked: no user-facing surfaces are removed or renamed; the SDServer::upscale_via_cli signature change is internal code structure.

Review suggestion

Attention level: Routine — needs any 1 reviewer.

Already reviewed by: ramkrishna2910.

Explanation

Why this rung

A contained fix or extension. The diff is a contained fix or extension under code structure — it adds upscaling support to the existing thenoise backend and refactors the upscaling endpoint in server.cpp to dispatch by recipe. This is one-reviewer per the table.

Reviewer search

Checked: ramkrishna2910 (code-author on server_models.json/sdcpp_server backend registration), superm1 (ROCm maintainer), bconsolvo (original sd-cpp upscaling author); thenoise is bitgamma's area but the author is excluded.

[AI-assisted review] Automated pre-review from repo-manager — flags for the human reviewer, not a replacement for one. Reviewed at head d4eb776; regenerate with repo-manager review-pr 3327.

@jeremyfowers

Copy link
Copy Markdown
Member

will make an issue for the above since its coming in late

Merged via the queue into main with commit 5b41bee Aug 25, 2026
81 checks passed
@bitgamma
bitgamma deleted the bitgamma/thenoise-v0.4.0 branch August 25, 2026 19:02
fl0rianr pushed a commit that referenced this pull request Aug 26, 2026
* update thenoise version

* add support for thenoise in the upscaler endpoint

* bump version and better model names

* update documentation

* remove upscale_factor

* notice about backend selection
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.

3 participants