Skip to content

Commit

Permalink
update stats and previews
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Mandic <[email protected]>
  • Loading branch information
vladmandic committed Nov 26, 2024
1 parent 4468144 commit 14c8414
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 22 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
- improved live preview display and performance
- improved accordion behavior
- auto-size networks height for sidebar
- control: hide preview column by default
- control: optionn to hide input column
- control: add stats
- browser->server logging framework
- Fixes:
- update `diffusers`
Expand Down
2 changes: 1 addition & 1 deletion extensions-builtin/sdnext-modernui
6 changes: 5 additions & 1 deletion javascript/progressBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ function requestProgress(id_task, progressEl, galleryEl, atEnd = null, onProgres
if (!parentGallery) return;
const footers = Array.from(gradioApp().querySelectorAll('.gallery_footer'));
for (const footer of footers) footer.style.display = 'none'; // remove all footers
const galleries = Array.from(gradioApp().querySelectorAll('.gallery_main'));
for (const gallery of galleries) gallery.style.display = 'none'; // remove all footers

livePreview = document.createElement('div');
livePreview.className = 'livePreview';
Expand All @@ -89,7 +91,9 @@ function requestProgress(id_task, progressEl, galleryEl, atEnd = null, onProgres
localStorage.removeItem('task');
setProgress();
const footers = Array.from(gradioApp().querySelectorAll('.gallery_footer'));
for (const footer of footers) footer.style.display = 'flex'; // remove all footers
for (const footer of footers) footer.style.display = 'flex'; // restore all footers
const galleries = Array.from(gradioApp().querySelectorAll('.gallery_main'));
for (const gallery of galleries) gallery.style.display = 'flex'; // remove all galleries
try {
if (parentGallery && livePreview) {
parentGallery.removeChild(livePreview);
Expand Down
7 changes: 2 additions & 5 deletions modules/control/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,14 +717,11 @@ def set_pipe():
shared.log.error(f'Control pipeline failed: type={unit_type} units={len(active_model)} error={e}')
errors.display(e, 'Control')

t_end = time.time()

if len(output_images) == 0:
output_images = None
image_txt = '| Images None'
else:
image_str = [f'{image.width}x{image.height}' for image in output_images]
image_txt = f'| Time {t_end-t_start:.2f}s | Images {len(output_images)} | Size {" ".join(image_str)}'
image_txt = ''
p.init_images = output_images # may be used for hires

if video_type != 'None' and isinstance(output_images, list):
Expand All @@ -738,7 +735,7 @@ def set_pipe():
restore_pipeline()
debug(f'Ready: {image_txt}')

html_txt = f'<p>Ready {image_txt}</p>'
html_txt = f'<p>Ready {image_txt}</p>' if image_txt != '' else ''
if len(info_txt) > 0:
html_txt = html_txt + infotext_to_html(info_txt[0])
if is_generator:
Expand Down
1 change: 1 addition & 0 deletions modules/ui_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ def create_output_panel(tabname, preview=True, prompt=None, height=None):
object_fit='scale-down',
height=height,
elem_id=f"{tabname}_gallery",
elem_classes=["gallery_main"],
)
if prompt is not None:
interrogate_clip_btn, interrogate_booru_btn = ui_sections.create_interrogate_buttons('control')
Expand Down
57 changes: 42 additions & 15 deletions modules/ui_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from modules.control.units import lite # vislearn ControlNet-XS
from modules.control.units import t2iadapter # TencentARC T2I-Adapter
from modules.control.units import reference # reference pipeline
from modules import errors, shared, progress, ui_components, ui_symbols, ui_common, ui_sections, generation_parameters_copypaste, call_queue, scripts, masking, images, processing_vae # pylint: disable=ungrouped-imports
from modules import errors, shared, progress, ui_components, ui_symbols, ui_common, ui_sections, generation_parameters_copypaste, call_queue, scripts, masking, images, processing_vae, timer # pylint: disable=ungrouped-imports
from modules import ui_control_helpers as helpers


Expand All @@ -21,13 +21,36 @@
debug('Trace: CONTROL')


def return_controls(res):
def return_stats(t: float = None):
if t is None:
elapsed_text = ''
else:
elapsed = time.perf_counter() - t
elapsed_m = int(elapsed // 60)
elapsed_s = elapsed % 60
elapsed_text = f"Time: {elapsed_m}m {elapsed_s:.2f}s |" if elapsed_m > 0 else f"Time: {elapsed_s:.2f}s |"
summary = timer.process.summary(min_time=0.1, total=False).replace('=', ' ')
vram_html = ''
if not shared.mem_mon.disabled:
vram = {k: -(v//-(1024*1024)) for k, v in shared.mem_mon.read().items()}
used = round(100 * vram['used'] / (vram['total'] + 0.001))
if vram.get('active_peak', 0) > 0:
vram_html += f"| GPU {max(vram['active_peak'], vram['reserved_peak'])} MB {used}%"
vram_html += f" | retries {vram['retries']} oom {vram['oom']}" if vram.get('retries', 0) > 0 or vram.get('oom', 0) > 0 else ''
return f"<div class='performance'><p>{elapsed_text} {summary} {vram_html}</p></div>"


def return_controls(res, t: float = None):
# return preview, image, video, gallery, text
debug(f'Control received: type={type(res)} {res}')
if t is None:
perf = ''
else:
perf = return_stats(t)
if res is None: # no response
return [None, None, None, None, '']
return [None, None, None, None, '', perf]
elif isinstance(res, str): # error response
return [None, None, None, None, res]
return [None, None, None, None, res, perf]
elif isinstance(res, tuple): # standard response received as tuple via control_run->yield(output_images, process_image, result_txt)
preview_image = res[1] # may be None
output_image = res[0][0] if isinstance(res[0], list) else res[0] # may be image or list of images
Expand All @@ -37,9 +60,9 @@ def return_controls(res):
output_gallery = [res[0]] if res[0] is not None else [] # must return list, but can receive single image
result_txt = res[2] if len(res) > 2 else '' # do we have a message
output_video = res[3] if len(res) > 3 else None # do we have a video filename
return [preview_image, output_image, output_video, output_gallery, result_txt]
return [preview_image, output_image, output_video, output_gallery, result_txt, perf]
else: # unexpected
return [None, None, None, None, f'Control: Unexpected response: {type(res)}']
return [None, None, None, None, f'Control: Unexpected response: {type(res)}', perf]


def get_units(*values):
Expand Down Expand Up @@ -67,17 +90,18 @@ def generate_click(job_id: str, state: str, active_tab: str, *args):
shared.state.begin('Generate')
progress.add_task_to_queue(job_id)
with call_queue.queue_lock:
yield [None, None, None, None, 'Control: starting']
yield [None, None, None, None, 'Control: starting', '']
shared.mem_mon.reset()
progress.start_task(job_id)
try:
t = time.perf_counter()
for results in control_run(state, units, helpers.input_source, helpers.input_init, helpers.input_mask, active_tab, True, *args):
progress.record_results(job_id, results)
yield return_controls(results)
yield return_controls(results, t)
except Exception as e:
shared.log.error(f"Control exception: {e}")
errors.display(e, 'Control')
yield [None, None, None, None, f'Control: Exception: {e}']
yield [None, None, None, None, f'Control: Exception: {e}', '']
progress.finish_task(job_id)
shared.state.end()

Expand Down Expand Up @@ -106,7 +130,8 @@ def create_ui(_blocks: gr.Blocks=None):

with gr.Accordion(open=False, label="Input", elem_id="control_input", elem_classes=["small-accordion"]):
with gr.Row():
show_preview = gr.Checkbox(label="Show preview", value=True, elem_id="control_show_preview")
show_input = gr.Checkbox(label="Show input", value=True, elem_id="control_show_input")
show_preview = gr.Checkbox(label="Show preview", value=False, elem_id="control_show_preview")
with gr.Row():
input_type = gr.Radio(label="Input type", choices=['Control only', 'Init image same as control', 'Separate init image'], value='Control only', type='index', elem_id='control_input_type')
with gr.Row():
Expand Down Expand Up @@ -153,13 +178,13 @@ def create_ui(_blocks: gr.Blocks=None):
override_settings = ui_common.create_override_inputs('control')

with gr.Row(variant='compact', elem_id="control_extra_networks", elem_classes=["extra_networks_root"], visible=False) as extra_networks_ui:
from modules import timer, ui_extra_networks
from modules import ui_extra_networks
extra_networks_ui = ui_extra_networks.create_ui(extra_networks_ui, btn_extra, 'control', skip_indexing=shared.opts.extra_network_skip_indexing)
timer.startup.record('ui-networks')

with gr.Row(elem_id='control-inputs'):
with gr.Column(scale=9, elem_id='control-input-column', visible=True) as _column_input:
gr.HTML('<span id="control-input-button">Control input</p>')
with gr.Column(scale=9, elem_id='control-input-column', visible=True) as column_input:
gr.HTML('<span id="control-input-button">Input</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-input'):
with gr.Tab('Image', id='in-image') as tab_image:
input_mode = gr.Label(value='select', visible=False)
Expand Down Expand Up @@ -190,12 +215,12 @@ def create_ui(_blocks: gr.Blocks=None):
gr.HTML('<span id="control-output-button">Output</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-output') as output_tabs:
with gr.Tab('Gallery', id='out-gallery'):
output_gallery, _output_gen_info, _output_html_info, _output_html_info_formatted, _output_html_log = ui_common.create_output_panel("control", preview=True, prompt=prompt, height=gr_height)
output_gallery, _output_gen_info, _output_html_info, _output_html_info_formatted, output_html_log = ui_common.create_output_panel("control", preview=True, prompt=prompt, height=gr_height)
with gr.Tab('Image', id='out-image'):
output_image = gr.Image(label="Output", show_label=False, type="pil", interactive=False, tool="editor", height=gr_height, elem_id='control_output_image', elem_classes=['control-image'])
with gr.Tab('Video', id='out-video'):
output_video = gr.Video(label="Output", show_label=False, height=gr_height, elem_id='control_output_video', elem_classes=['control-image'])
with gr.Column(scale=9, elem_id='control-preview-column', visible=True) as column_preview:
with gr.Column(scale=9, elem_id='control-preview-column', visible=False) as column_preview:
gr.HTML('<span id="control-preview-button">Preview</p>')
with gr.Tabs(elem_classes=['control-tabs'], elem_id='control-tab-preview'):
with gr.Tab('Preview', id='preview-image') as _tab_preview:
Expand Down Expand Up @@ -498,6 +523,7 @@ def create_ui(_blocks: gr.Blocks=None):
btn_update = gr.Button('Update', interactive=True, visible=False, elem_id='control_update')
btn_update.click(fn=get_units, inputs=controls, outputs=[], show_progress=True, queue=False)

show_input.change(fn=lambda x: gr.update(visible=x), inputs=[show_input], outputs=[column_input])
show_preview.change(fn=lambda x: gr.update(visible=x), inputs=[show_preview], outputs=[column_preview])
input_type.change(fn=lambda x: gr.update(visible=x == 2), inputs=[input_type], outputs=[column_init])
btn_prompt_counter.click(fn=call_queue.wrap_queued_call(ui_common.update_token_counter), inputs=[prompt, steps], outputs=[prompt_counter])
Expand Down Expand Up @@ -550,6 +576,7 @@ def create_ui(_blocks: gr.Blocks=None):
output_video,
output_gallery,
result_txt,
output_html_log,
]
control_dict = dict(
fn=generate_click,
Expand Down

0 comments on commit 14c8414

Please sign in to comment.