Skip to content

Commit 4b6571b

Browse files
committed
Refactor renderer bootstrap and test utilities
Introduce centralized cleanup lambdas in imiv_app.cpp to simplify failure paths and unify renderer window/device cleanup. Factor OCIO texture blueprint construction in imiv_ocio.cpp into a reusable append_texture_blueprint helper. In Metal renderer (imiv_renderer_metal.mm) add a render_preview lambda to consolidate OCIO vs non-OCIO preview rendering and reduce duplicated calls. Refactor multiple test/utility Python scripts to reuse a new imiv_test_utils module: move many common helpers (path discovery, env loading, command builders, timing/logging, program resolution, defaults) into imiv_test_utils and update imiv_backend_verify.py, imiv_ocio_config_source_regression.py, imiv_ocio_missing_fallback_regression.py, imiv_ux_actions_regression.py, and others to import and use those utilities. Replace ad-hoc subprocess/run helpers with shared run_timed_logged_process, run_capture_output, script_command, generic_smoke_runner_command, and standardized error handling via fail(). Overall this cleans up error/cleanup handling in C++ code and consolidates Python test tooling to reduce duplication and improve maintainability. Signed-off-by: Vlad <shaamaan@gmail.com>
1 parent c0a9461 commit 4b6571b

8 files changed

Lines changed: 469 additions & 705 deletions

src/imiv/imiv_app.cpp

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -429,37 +429,36 @@ run(const AppConfig& config)
429429
renderer_state.verbose_logging = verbose_logging;
430430
renderer_state.verbose_validation_output = verbose_validation_output;
431431
renderer_state.log_imgui_texture_updates = log_imgui_texture_updates;
432-
ImVector<const char*> instance_extensions;
433-
if (active_backend == BackendKind::Vulkan)
434-
platform_glfw_collect_vulkan_instance_extensions(instance_extensions);
435-
436-
if (!renderer_setup_instance(renderer_state, instance_extensions,
437-
startup_error)) {
432+
const auto fail_bootstrap = [&](bool destroy_surface, bool cleanup_window,
433+
bool shutdown_platform_imgui) {
438434
print(stderr, "imiv: {}\n", startup_error);
435+
if (shutdown_platform_imgui)
436+
platform_glfw_imgui_shutdown();
437+
if (cleanup_window)
438+
renderer_cleanup_window(renderer_state);
439+
if (destroy_surface)
440+
renderer_destroy_surface(renderer_state);
439441
renderer_cleanup(renderer_state);
440442
ImGui::DestroyContext();
441443
platform_glfw_destroy_window(window);
442444
platform_glfw_terminate();
443445
return EXIT_FAILURE;
446+
};
447+
ImVector<const char*> instance_extensions;
448+
if (active_backend == BackendKind::Vulkan)
449+
platform_glfw_collect_vulkan_instance_extensions(instance_extensions);
450+
451+
if (!renderer_setup_instance(renderer_state, instance_extensions,
452+
startup_error)) {
453+
return fail_bootstrap(false, false, false);
444454
}
445455

446456
if (!renderer_create_surface(renderer_state, window, startup_error)) {
447-
print(stderr, "imiv: {}\n", startup_error);
448-
renderer_cleanup(renderer_state);
449-
ImGui::DestroyContext();
450-
platform_glfw_destroy_window(window);
451-
platform_glfw_terminate();
452-
return EXIT_FAILURE;
457+
return fail_bootstrap(false, false, false);
453458
}
454459

455460
if (!renderer_setup_device(renderer_state, startup_error)) {
456-
print(stderr, "imiv: {}\n", startup_error);
457-
renderer_destroy_surface(renderer_state);
458-
renderer_cleanup(renderer_state);
459-
ImGui::DestroyContext();
460-
platform_glfw_destroy_window(window);
461-
platform_glfw_terminate();
462-
return EXIT_FAILURE;
461+
return fail_bootstrap(true, false, false);
463462
}
464463

465464
int framebuffer_width = 0;
@@ -468,13 +467,7 @@ run(const AppConfig& config)
468467
framebuffer_height);
469468
if (!renderer_setup_window(renderer_state, framebuffer_width,
470469
framebuffer_height, startup_error)) {
471-
print(stderr, "imiv: {}\n", startup_error);
472-
renderer_cleanup_window(renderer_state);
473-
renderer_cleanup(renderer_state);
474-
ImGui::DestroyContext();
475-
platform_glfw_destroy_window(window);
476-
platform_glfw_terminate();
477-
return EXIT_FAILURE;
470+
return fail_bootstrap(false, true, false);
478471
}
479472

480473
ImGuiIO& io = ImGui::GetIO();
@@ -494,14 +487,7 @@ run(const AppConfig& config)
494487
}
495488
platform_glfw_imgui_init(window, active_backend);
496489
if (!renderer_imgui_init(renderer_state, startup_error)) {
497-
print(stderr, "imiv: {}\n", startup_error);
498-
platform_glfw_imgui_shutdown();
499-
renderer_cleanup_window(renderer_state);
500-
renderer_cleanup(renderer_state);
501-
ImGui::DestroyContext();
502-
platform_glfw_destroy_window(window);
503-
platform_glfw_terminate();
504-
return EXIT_FAILURE;
490+
return fail_bootstrap(false, true, true);
505491
}
506492

507493
const bool platform_has_viewports
@@ -822,21 +808,21 @@ run(const AppConfig& config)
822808
#endif
823809
FileDialog::set_native_dialog_scope_hook(nullptr, nullptr);
824810
uninstall_drag_drop(window);
825-
if (active_backend == BackendKind::OpenGL) {
811+
const auto cleanup_renderer_backend = [&] {
826812
renderer_cleanup_window(renderer_state);
827813
renderer_cleanup(renderer_state);
828-
}
814+
};
815+
if (active_backend == BackendKind::OpenGL)
816+
cleanup_renderer_backend();
829817
renderer_imgui_shutdown(renderer_state);
830818
platform_glfw_imgui_shutdown();
831819
ImGui::DestroyContext();
832820
#if defined(IMGUI_ENABLE_TEST_ENGINE)
833821
test_engine_destroy(test_engine_runtime);
834822
#endif
835823

836-
if (active_backend != BackendKind::OpenGL) {
837-
renderer_cleanup_window(renderer_state);
838-
renderer_cleanup(renderer_state);
839-
}
824+
if (active_backend != BackendKind::OpenGL)
825+
cleanup_renderer_backend();
840826
platform_glfw_destroy_window(window);
841827
platform_glfw_terminate();
842828
return EXIT_SUCCESS;

src/imiv/imiv_ocio.cpp

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,27 @@ namespace {
328328
blueprint.textures.clear();
329329
blueprint.textures.reserve(num_textures
330330
+ shader_desc->getNum3DTextures());
331+
const auto append_texture_blueprint =
332+
[&](const char* texture_name, const char* sampler_name,
333+
uint32_t shader_binding, uint32_t width, uint32_t height,
334+
uint32_t depth, OcioTextureChannel channel,
335+
OcioTextureDimensions dimensions,
336+
OcioInterpolation interpolation, const float* values,
337+
size_t texel_count) {
338+
OcioTextureBlueprint texture;
339+
texture.texture_name = texture_name ? texture_name : "";
340+
texture.sampler_name = sampler_name ? sampler_name : "";
341+
texture.shader_binding = shader_binding;
342+
texture.width = width;
343+
texture.height = height;
344+
texture.depth = depth;
345+
texture.channel = channel;
346+
texture.dimensions = dimensions;
347+
texture.interpolation = interpolation;
348+
if (values && texel_count != 0)
349+
texture.values.assign(values, values + texel_count);
350+
blueprint.textures.push_back(std::move(texture));
351+
};
331352
for (unsigned idx = 0; idx < num_textures; ++idx) {
332353
const char* texture_name = nullptr;
333354
const char* sampler_name = nullptr;
@@ -342,31 +363,17 @@ namespace {
342363
height, channel, dimensions, interpolation);
343364
const float* values = nullptr;
344365
shader_desc->getTextureValues(idx, values);
345-
346-
OcioTextureBlueprint texture;
347-
if (texture_name)
348-
texture.texture_name = texture_name;
349-
if (sampler_name)
350-
texture.sampler_name = sampler_name;
351-
texture.shader_binding = shader_desc->getTextureShaderBindingIndex(
352-
idx);
353-
texture.width = width;
354-
texture.height = height;
355-
texture.depth = 1;
356-
texture.channel = map_ocio_texture_channel(channel);
357-
texture.dimensions = map_ocio_texture_dimensions(dimensions,
358-
height);
359-
texture.interpolation = map_ocio_interpolation(interpolation);
360-
if (values) {
361-
const size_t texel_count
362-
= static_cast<size_t>(width) * static_cast<size_t>(height)
363-
* static_cast<size_t>(
364-
channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL
365-
? 1
366-
: 3);
367-
texture.values.assign(values, values + texel_count);
368-
}
369-
blueprint.textures.push_back(std::move(texture));
366+
const size_t texel_count
367+
= static_cast<size_t>(width) * static_cast<size_t>(height)
368+
* static_cast<size_t>(
369+
channel == OCIO::GpuShaderDesc::TEXTURE_RED_CHANNEL ? 1
370+
: 3);
371+
append_texture_blueprint(
372+
texture_name, sampler_name,
373+
shader_desc->getTextureShaderBindingIndex(idx), width, height,
374+
1, map_ocio_texture_channel(channel),
375+
map_ocio_texture_dimensions(dimensions, height),
376+
map_ocio_interpolation(interpolation), values, texel_count);
370377
}
371378

372379
const unsigned num_textures_3d = shader_desc->getNum3DTextures();
@@ -379,27 +386,15 @@ namespace {
379386
interpolation);
380387
const float* values = nullptr;
381388
shader_desc->get3DTextureValues(idx, values);
382-
383-
OcioTextureBlueprint texture;
384-
if (texture_name)
385-
texture.texture_name = texture_name;
386-
if (sampler_name)
387-
texture.sampler_name = sampler_name;
388-
texture.shader_binding
389-
= shader_desc->get3DTextureShaderBindingIndex(idx);
390-
texture.width = edge_len;
391-
texture.height = edge_len;
392-
texture.depth = edge_len;
393-
texture.channel = OcioTextureChannel::RGB;
394-
texture.dimensions = OcioTextureDimensions::Tex3D;
395-
texture.interpolation = map_ocio_interpolation(interpolation);
396-
if (values) {
397-
const size_t texel_count = static_cast<size_t>(edge_len)
398-
* static_cast<size_t>(edge_len)
399-
* static_cast<size_t>(edge_len) * 3u;
400-
texture.values.assign(values, values + texel_count);
401-
}
402-
blueprint.textures.push_back(std::move(texture));
389+
const size_t texel_count = static_cast<size_t>(edge_len)
390+
* static_cast<size_t>(edge_len)
391+
* static_cast<size_t>(edge_len) * 3u;
392+
append_texture_blueprint(
393+
texture_name, sampler_name,
394+
shader_desc->get3DTextureShaderBindingIndex(idx), edge_len,
395+
edge_len, edge_len, OcioTextureChannel::RGB,
396+
OcioTextureDimensions::Tex3D,
397+
map_ocio_interpolation(interpolation), values, texel_count);
403398
}
404399

405400
if (blueprint.display.empty() || blueprint.view.empty()) {

src/imiv/imiv_renderer_metal.mm

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,41 +1863,44 @@ bool metal_update_preview_texture(RendererState& renderer_state,
18631863
return true;
18641864
}
18651865

1866-
bool used_ocio = false;
1866+
bool used_ocio = false;
1867+
const auto render_preview = [&](id<MTLTexture> target_texture,
1868+
id<MTLSamplerState> sampler_state,
1869+
std::string& render_error) {
1870+
return effective_controls.use_ocio != 0
1871+
? render_ocio_preview_texture(
1872+
*renderer_backend, *texture_state, target_texture,
1873+
sampler_state, effective_controls, render_error)
1874+
: render_preview_texture(*renderer_backend,
1875+
*texture_state, target_texture,
1876+
sampler_state,
1877+
effective_controls,
1878+
render_error);
1879+
};
18671880
if (effective_controls.use_ocio != 0) {
18681881
std::string ocio_error;
18691882
if (ensure_ocio_preview_program(*renderer_backend, ui_state, image,
18701883
ocio_error)
1871-
&& render_ocio_preview_texture(
1872-
*renderer_backend, *texture_state,
1873-
texture_state->preview_linear_texture,
1874-
renderer_backend->linear_sampler, effective_controls,
1875-
ocio_error)
1876-
&& render_ocio_preview_texture(
1877-
*renderer_backend, *texture_state,
1878-
texture_state->preview_nearest_texture,
1879-
renderer_backend->nearest_sampler, effective_controls,
1880-
ocio_error)) {
1884+
&& render_preview(texture_state->preview_linear_texture,
1885+
renderer_backend->linear_sampler, ocio_error)
1886+
&& render_preview(texture_state->preview_nearest_texture,
1887+
renderer_backend->nearest_sampler,
1888+
ocio_error)) {
18811889
used_ocio = true;
18821890
} else {
1883-
if (!ocio_error.empty()) {
1891+
if (!ocio_error.empty())
18841892
std::cerr << "imiv: Metal OCIO fallback: " << ocio_error
18851893
<< "\n";
1886-
}
18871894
effective_controls.use_ocio = 0;
18881895
}
18891896
}
18901897

18911898
if (!used_ocio
1892-
&& (!render_preview_texture(*renderer_backend, *texture_state,
1893-
texture_state->preview_linear_texture,
1894-
renderer_backend->linear_sampler,
1895-
effective_controls, error_message)
1896-
|| !render_preview_texture(
1897-
*renderer_backend, *texture_state,
1898-
texture_state->preview_nearest_texture,
1899-
renderer_backend->nearest_sampler, effective_controls,
1900-
error_message))) {
1899+
&& (!render_preview(texture_state->preview_linear_texture,
1900+
renderer_backend->linear_sampler, error_message)
1901+
|| !render_preview(texture_state->preview_nearest_texture,
1902+
renderer_backend->nearest_sampler,
1903+
error_message))) {
19011904
texture.preview_initialized = false;
19021905
return false;
19031906
}

0 commit comments

Comments
 (0)