dlss xyz grid

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2026-09-10 10:50:52 +02:00
parent df163f3f35
commit b0c21c5448
9 changed files with 87 additions and 30 deletions
+1
View File
@@ -50,6 +50,7 @@ Plus inevitable bug-fixes...
dlls 5 caused quite a stir, but combined with generative ai it becomes a nice tool
- available as part of image/video generate workflows via *extras -> dlss*
or as a standalone *processing* workflow
or via xyz grid
- *note*: requires nvidia rtx gpu, windows platform and compatible gpu drivers
but...it can be used from wsl2: unpack required package on windows host and you can access it from the wsl2 environment
- *install*: requires [DLSS 5 Visual Enhancer](https://github.com/Merserk/dlss5-visual-enhancer/releases/tag/v7.0)
+1
View File
@@ -80,6 +80,7 @@ def image_grid(imgs: list, batch_size=1, rows: int | None = None, cols: int | No
for i, img in enumerate(params.imgs):
if img is not None:
grid.paste(img, box=(i % params.cols * w, i // params.cols * h))
grid.is_grid = True # flag image as grid
return grid
except Exception as e:
log.error(f'Grid: images={imgs} {e}')
+2 -1
View File
@@ -352,7 +352,7 @@ def process_samples(p: StableDiffusionProcessing, samples):
method = p.color_correction_method if p.color_correction_method is not None else getattr(shared.opts, 'color_correction_method', 'histogram')
image = apply_color_correction(p.color_corrections[i], image, method=method)
if p.scripts is not None and isinstance(p.scripts, scripts_manager.ScriptRunner):
if p.scripts is not None and isinstance(p.scripts, scripts_manager.ScriptRunner) and not getattr(p, 'is_grid', False):
pp = scripts_manager.PostprocessImageArgs(image)
p.scripts.postprocess_image(p, pp)
if pp.image is not None:
@@ -364,6 +364,7 @@ def process_samples(p: StableDiffusionProcessing, samples):
image = pp.image[-1]
else:
image = pp.image
grading_params = processing_grading.GradingParams(
brightness=getattr(p, 'grading_brightness', 0.0),
contrast=getattr(p, 'grading_contrast', 0.0),
+73 -24
View File
@@ -7,8 +7,12 @@ from modules import shared, devices, processing, timer, errors, scripts_manager,
from scripts.dlss import controller_cli as c
registered = False
debug = os.environ.get('SD_DLSS_DEBUG', None) is not None
FPS_CHOICES = ['23.976', '25', '29.97', '30', '50', '59.94', '60', '90', '119.88', '120', '144', '165', '180', '240', '360', '480']
NR_STYLES = ['None', 'Default', 'Natural', 'Cinematic']
NR_MODELS = ['None','Default', 'J', 'K', 'L', 'M']
NR_PRESETS = ['Default', 'Preset #1', 'Preset #2', 'Preset #3']
def create_ui(parent):
@@ -25,24 +29,25 @@ def create_ui(parent):
with gr.Accordion('DLSS NeuralRender', open=False, elem_id='dlss_nn'):
with gr.Row():
nr_enabled = gr.Checkbox(label='NR enable', value=False, elem_id='dlss_nr_enabled')
nr_append = gr.Checkbox(label='Append result', value=True, elem_id='dlss_nr_append')
nr_append = gr.Checkbox(label='NR append result', value=True, elem_id='dlss_nr_append')
with gr.Row():
nr_style = gr.Dropdown(label='NR style', choices=NR_STYLES, value='Default', elem_id='dlss_nr_style')
nr_preset = gr.Dropdown(label='NR preset', choices=NR_PRESETS, value='Default', elem_id='dlss_nr_preset')
nr_model_preset = gr.Dropdown(label='NR model', choices=NR_MODELS, value='Default', elem_id='dlss_nr_model_preset')
with gr.Row():
nr_style = gr.Dropdown(label='NR style', choices=['Default', 'Natural', 'Cinematic'], value='Default', elem_id='dlss_nr_style')
nr_intensity = gr.Slider(label='NR intensity', minimum=0.0, maximum=2.0, step=0.05, value=1.0, elem_id='dlss_nr_intensity')
nr_upscaling_factor = gr.Dropdown(label='NR upscaling factor', choices=["1.0", "1.5", "1.724", "2.0", "3.0"], value="1.0", elem_id='dlss_nr_upscaling_factor')
with gr.Row():
nr_preset = gr.Dropdown(label='NR preset', choices=['Default', 'Preset #1', 'Preset #2', 'Preset #3'], value='Default', elem_id='dlss_nr_preset')
nr_model_preset = gr.Dropdown(label='NR model', choices=['Default', 'J', 'K', 'L', 'M'], value='Default', elem_id='dlss_nr_model_preset')
with gr.Row():
nr_local_tone = gr.Slider(label='NR tone strength', minimum=0.0, maximum=2.0, step=0.05, value=1.0, elem_id='dlss_nr_local_tone')
with gr.Row():
nr_local_structure = gr.Slider(label='NR local structure', minimum=0.0, maximum=2.0, step=0.05, value=1.0, elem_id='dlss_nr_local_structure')
nr_skin_structure = gr.Slider(label='NR skin structure', minimum=-1.0, maximum=2.0, step=0.05, value=-1.0, elem_id='dlss_nr_skin_structure')
nr_automatic_mask = gr.Checkbox(label='Automatic mask', value=False, elem_id='dlss_nr_automatic_mask')
with gr.Row():
nr_upscaling_factor = gr.Dropdown(label='NR upscaling factor', choices=["1.0", "1.5", "1.724", "2.0", "3.0"], value="1.0", elem_id='dlss_nr_upscaling_factor')
nr_automatic_mask = gr.Checkbox(label='NR automatic mask', value=False, elem_id='dlss_nr_automatic_mask')
with gr.Accordion('DLSS SuperSample', open=False, elem_id='dlss_ss'):
with gr.Row():
ss_enabled = gr.Checkbox(label='SR enable', value=False, elem_id='dlss_ss_enabled')
ss_append = gr.Checkbox(label='Append result', value=True, elem_id='dlss_ss_append')
ss_enabled = gr.Checkbox(label='SS enable', value=False, elem_id='dlss_ss_enabled')
ss_append = gr.Checkbox(label='SS append result', value=True, elem_id='dlss_ss_append')
with gr.Row():
ss_vsr_quality = gr.Dropdown(label='SS VSR quality', choices=["1: Low", "2: Medium", "3: High", "4: Ultra"], value="4: Ultra", type='value', elem_id='dlss_ss_vsr_quality')
with gr.Row():
@@ -252,24 +257,30 @@ def dlss(p: processing.StableDiffusionProcessing | None, pp: processing.Processe
if debug:
log.trace(f'DLSS: path="{pkg_path}" args={args} kwargs={kwargs}')
update = 'none'
if hasattr(pp, 'images') and pp.images is not None and len(pp.images) > 0:
update = 'images'
inputs = pp.images
elif hasattr(pp, 'image') and pp.image is not None:
update = 'image'
inputs = [pp.image]
else:
return None
# cast to appropriate types
nr_intensity = float(nr_intensity)
nr_local_tone = float(nr_local_tone)
nr_local_structure = float(nr_local_structure)
nr_skin_structure = float(nr_skin_structure)
nr_upscaling_factor = float(nr_upscaling_factor)
ss_width = int(ss_width)
ss_height = int(ss_height)
ss_scale_factor = float(ss_scale_factor)
fg_source_fps = str(fg_source_fps)
fg_target_fps = str(fg_target_fps)
nr_style = str(getattr(p, 'nr_style', nr_style))
nr_preset = str(getattr(p, 'nr_preset', nr_preset))
nr_model_preset = str(getattr(p, 'nr_model_preset', nr_model_preset))
nr_intensity = float(getattr(p, 'nr_intensity', nr_intensity))
nr_local_tone = float(getattr(p, 'nr_local_tone', nr_local_tone))
nr_local_structure = float(getattr(p, 'nr_local_structure', nr_local_structure))
nr_skin_structure = float(getattr(p, 'nr_skin_structure', nr_skin_structure))
nr_upscaling_factor = float(getattr(p, 'nr_upscaling_factor', nr_upscaling_factor))
ss_width = int(getattr(p, 'ss_width', ss_width))
ss_height = int(getattr(p, 'ss_height', ss_height))
ss_scale_factor = float(getattr(p, 'ss_scale_factor', ss_scale_factor))
fg_source_fps = str(getattr(p, 'fg_source_fps', fg_source_fps))
fg_target_fps = str(getattr(p, 'fg_target_fps', fg_target_fps))
images = []
originals = []
@@ -291,6 +302,8 @@ def dlss(p: processing.StableDiffusionProcessing | None, pp: processing.Processe
current_images = output
t.ts('supersample', t0)
if nr_style == 'None' or nr_model_preset == 'None':
nr_enabled = False
if nr_enabled:
t0 = time.time()
if p:
@@ -320,13 +333,19 @@ def dlss(p: processing.StableDiffusionProcessing | None, pp: processing.Processe
t.ts('framegen', t0)
log.debug(f'DLSS: frames={len(images)} {t.summary(min_time=0)}')
pp.images = images
if update == 'images':
pp.images = images
elif update == 'image' and len(images) > 0:
pp.image = images[-1]
pp.originals = originals
return pp
class DLSSScript(scripts_manager.Script):
video_capable = scripts_manager.AlwaysVisible
def __init__(self):
super().__init__()
self.video_capable = scripts_manager.AlwaysVisible
self.register()
def title(self):
return 'nVidia DLSS'
@@ -339,11 +358,41 @@ class DLSSScript(scripts_manager.Script):
def ui(self, _is_img2img):
return create_ui(self.parent)
def register(self): # register xyz grid elements
global registered # pylint: disable=global-statement
if registered:
return
registered = True
def apply_field(field):
def fun(p, x, xs): # pylint: disable=unused-argument
setattr(p, field, x)
self.run(p)
return fun
import sys
xyz_classes = [v for k, v in sys.modules.items() if 'xyz_grid_classes' in k]
if xyz_classes and len(xyz_classes) > 0:
xyz_classes = xyz_classes[0]
options = [
xyz_classes.AxisOption("[DLSS] NR style", str, apply_field("nr_style"), choices=lambda: NR_STYLES),
xyz_classes.AxisOption("[DLSS] NR preset", str, apply_field("nr_preset"), choices=lambda: NR_PRESETS),
xyz_classes.AxisOption("[DLSS] NR model", str, apply_field("nr_model_preset"), choices=lambda: NR_MODELS),
xyz_classes.AxisOption("[DLSS] NR intensity", float, apply_field("nr_intensity")),
xyz_classes.AxisOption("[DLSS] NR local tone", float, apply_field("nr_local_tone")),
xyz_classes.AxisOption("[DLSS] NR local structure", float, apply_field("nr_local_structure")),
xyz_classes.AxisOption("[DLSS] NR skin structure", float, apply_field("nr_skin_structure")),
]
for option in options:
if option not in xyz_classes.axis_options:
xyz_classes.axis_options.append(option)
def postprocess_image(self, p: processing.StableDiffusionProcessing, pp: scripts_manager.PostprocessImageArgs, *args, **kwargs):
# postprocess_image is intended to modify single image in-place so not suited for dlss
pass
if p.xyz:
pp = dlss(p, pp, *args, **kwargs)
def postprocess(self, p: processing.StableDiffusionProcessing, pp: processing.Processed, *args, **kwargs): # pylint: disable=arguments-differ,unused-argument
if p.xyz: # do not postprocessing when running in xyz mode
return
_pp = dlss(p, pp, *args, **kwargs)
# postprocess triggers after initial images have already been saved
if _pp is not None and hasattr(_pp, 'images') and _pp.images is not None:
+2
View File
@@ -117,6 +117,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
continue
if (not no_grid or include_sub_grids) and images.check_grid_size(to_process):
grid = images.image_grid(to_process, rows=len(ys))
p.is_grid = True
if draw_legend:
grid = images.draw_grid_annotations(grid, w, h, x_texts, y_texts, margin_size, title=z_texts[i])
processed_result.images.insert(i, grid)
@@ -124,6 +125,7 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend
processed_result.all_seeds.insert(i, processed_result.all_seeds[idx0])
processed_result.infotexts.insert(i, processed_result.infotexts[idx0])
if len(zs) > 1 and not no_grid and images.check_grid_size(processed_result.images[:len(zs)]): # create grid-of-grids
p.is_grid = True
grid = images.image_grid(processed_result.images[:len(zs)], rows=1)
processed_result.images.insert(0, grid)
processed_result.all_prompts.insert(0, processed_result.all_prompts[0])
+2
View File
@@ -387,6 +387,7 @@ class XYZGridScript(scripts_manager.Script):
pc.extra_generation_params["Fixed Y Values"] = ", ".join([str(y) for y in ys])
info = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(xs)}x{len(ys)}')
grid_infotext.append(info)
if ix == 0 and iy == 0 and iz == 0 and len(zs) > 1: # create main grid info text
pc.extra_generation_params = copy(pc.extra_generation_params)
if z_opt.label != 'Nothing':
@@ -396,6 +397,7 @@ class XYZGridScript(scripts_manager.Script):
pc.extra_generation_params["Fixed Z Values"] = ", ".join([str(z) for z in zs])
info = processing.create_infotext(pc, pc.all_prompts, pc.all_seeds, pc.all_subseeds, grid=f'{len(zs)}x{len(xs)}x{len(ys)}')
grid_infotext.insert(0, info)
t1 = time.time()
return processed, t1-t0
+3 -3
View File
@@ -16144,9 +16144,6 @@ async function waitForOpts() {
const t0 = performance.now();
let t1 = performance.now();
while (true) {
if (t1 - t0 > 15e3) {
log("waitForOpts delayed", t1 - t0);
}
if (t1 - t0 > 6e4) {
log("waitForOpts timeout");
break;
@@ -16159,6 +16156,9 @@ async function waitForOpts() {
break;
}
}
if (t1 - t0 > 15e3) {
log("waitForOpts delayed", Math.round(t1 - t0));
}
await sleep(100);
t1 = performance.now();
}
+2 -2
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -325,6 +325,7 @@ class SimpleProgressBar {
}
update(loaded, max) {
// log('galleryUpdate', { loaded, max });
this.#progress.style.width = `${Math.floor((loaded / max) * 100)}%`;
this.#text.textContent = `${loaded}/${max}`;
if (!this.#visible) {