Skip to content

Commit f9361be

Browse files
committed
Add multi-backend renderer selection & GLFW layer
Introduce selectable renderer backends (auto, vulkan, metal, opengl) in CMake and wire up a GLFW platform abstraction. Adds imiv_platform_glfw (platform_glfw_* APIs) and renderer backend files/headers (including imiv_renderer_backend.h, metal/opengl/vulkan sources) and reorganizes source lists and ImGui backend selection. Refactors imiv_app, imiv_actions, imiv_frame and related headers to use the new platform and renderer abstractions, replaces direct GLFW/ImGui/Vulkan calls with platform_glfw_* and renderer_* helpers, and updates build/link logic for each backend. Also adds imiv_upload_types, tweaks OCIO uniform API (PreviewControls -> RendererPreviewControls), and includes various build checks and messages to ensure correct backend selection and platform requirements (e.g. Metal on Apple). This enables cleaner multi-backend support and isolates GLFW/platform-specific behavior.
1 parent 95104d2 commit f9361be

20 files changed

Lines changed: 2223 additions & 643 deletions

src/imiv/CMakeLists.txt

Lines changed: 161 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,54 @@ option (OIIO_IMIV_ADD_UPLOAD_SMOKE_CTEST
2828
"Add an optional CTest entry that generates/upload-tests the imiv corpus" OFF)
2929
set (OIIO_IMIV_VULKAN_SDK "$ENV{VULKAN_SDK}" CACHE PATH
3030
"Optional Vulkan SDK root path used to locate Vulkan package for imiv")
31+
set (_imiv_default_renderer "vulkan")
32+
if (APPLE)
33+
set (_imiv_default_renderer "metal")
34+
endif ()
35+
set (OIIO_IMIV_RENDERER "auto" CACHE STRING
36+
"Renderer backend for imiv (auto, vulkan, metal, opengl)")
37+
set_property (CACHE OIIO_IMIV_RENDERER PROPERTY STRINGS
38+
auto vulkan metal opengl)
3139

3240
check_is_enabled (imiv imiv_enabled)
3341
if (NOT imiv_enabled)
3442
message (STATUS "Disabling imiv")
3543
return ()
3644
endif ()
3745

46+
string (TOLOWER "${OIIO_IMIV_RENDERER}" _imiv_renderer_request)
47+
if (_imiv_renderer_request STREQUAL ""
48+
OR _imiv_renderer_request STREQUAL "auto")
49+
set (_imiv_selected_renderer "${_imiv_default_renderer}")
50+
elseif (_imiv_renderer_request STREQUAL "vulkan"
51+
OR _imiv_renderer_request STREQUAL "metal"
52+
OR _imiv_renderer_request STREQUAL "opengl")
53+
set (_imiv_selected_renderer "${_imiv_renderer_request}")
54+
else ()
55+
message (FATAL_ERROR
56+
"imiv: unsupported OIIO_IMIV_RENDERER='${OIIO_IMIV_RENDERER}' "
57+
"(expected auto, vulkan, metal, or opengl)")
58+
endif ()
59+
60+
if (_imiv_selected_renderer STREQUAL "metal" AND NOT APPLE)
61+
message (FATAL_ERROR
62+
"imiv: OIIO_IMIV_RENDERER=metal requires APPLE")
63+
endif ()
64+
65+
set (_imiv_renderer_is_vulkan OFF)
66+
set (_imiv_renderer_is_metal OFF)
67+
set (_imiv_renderer_is_opengl OFF)
68+
if (_imiv_selected_renderer STREQUAL "vulkan")
69+
set (_imiv_renderer_is_vulkan ON)
70+
elseif (_imiv_selected_renderer STREQUAL "metal")
71+
set (_imiv_renderer_is_metal ON)
72+
elseif (_imiv_selected_renderer STREQUAL "opengl")
73+
set (_imiv_renderer_is_opengl ON)
74+
endif ()
75+
76+
message (STATUS
77+
"imiv: selected renderer backend = glfw+${_imiv_selected_renderer}")
78+
3879
set (_imiv_imgui_required_files
3980
"${OIIO_IMIV_IMGUI_ROOT}/imgui.h"
4081
"${OIIO_IMIV_IMGUI_ROOT}/imgui.cpp"
@@ -43,10 +84,25 @@ set (_imiv_imgui_required_files
4384
"${OIIO_IMIV_IMGUI_ROOT}/imgui_widgets.cpp"
4485
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_glfw.h"
4586
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_glfw.cpp")
46-
if (NOT APPLE)
87+
set (_imiv_imgui_renderer_sources)
88+
if (_imiv_renderer_is_vulkan)
4789
list (APPEND _imiv_imgui_required_files
4890
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_vulkan.h"
4991
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_vulkan.cpp")
92+
list (APPEND _imiv_imgui_renderer_sources
93+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_vulkan.cpp")
94+
elseif (_imiv_renderer_is_metal)
95+
list (APPEND _imiv_imgui_required_files
96+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_metal.h"
97+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_metal.mm")
98+
list (APPEND _imiv_imgui_renderer_sources
99+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_metal.mm")
100+
elseif (_imiv_renderer_is_opengl)
101+
list (APPEND _imiv_imgui_required_files
102+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_opengl3.h"
103+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_opengl3.cpp")
104+
list (APPEND _imiv_imgui_renderer_sources
105+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_opengl3.cpp")
50106
endif ()
51107
set (_imiv_imgui_found ON)
52108
foreach (_imiv_required_file ${_imiv_imgui_required_files})
@@ -67,12 +123,10 @@ if (NOT _imiv_imgui_found)
67123
endif ()
68124
record_build_dependency (ImGui FOUND)
69125

70-
set (_imiv_core_sources
126+
set (_imiv_shared_sources
71127
imiv_actions.cpp
72128
imiv_app.cpp
73129
imiv_aux_windows.cpp
74-
imiv_capture.cpp
75-
imiv_drag_drop.cpp
76130
imiv_file_dialog.cpp
77131
imiv_frame.cpp
78132
imiv_image_view.cpp
@@ -83,22 +137,51 @@ set (_imiv_core_sources
83137
imiv_renderer.cpp
84138
imiv_shader_compile.cpp
85139
imiv_style.cpp
140+
imiv_upload_types.cpp
86141
imiv_ui.cpp
87142
imiv_viewer.cpp
143+
imiv_main.cpp)
144+
145+
set (_imiv_test_engine_integration_sources
146+
imiv_test_engine.cpp)
147+
148+
set (_imiv_platform_glfw_sources
149+
imiv_drag_drop.cpp
150+
imiv_platform_glfw.cpp)
151+
if (APPLE)
152+
list (APPEND _imiv_platform_glfw_sources
153+
external/dnd_glfw/dnd_glfw_macos.mm)
154+
endif ()
155+
156+
set (_imiv_renderer_vulkan_sources
157+
imiv_renderer_vulkan.cpp
158+
imiv_capture.cpp
88159
imiv_vulkan_setup.cpp
89160
imiv_vulkan_ocio.cpp
90161
imiv_vulkan_preview.cpp
91162
imiv_vulkan_runtime.cpp
92163
imiv_vulkan_texture.cpp
93-
imiv_vulkan_window.cpp
94-
imiv_test_engine.cpp
95-
imiv_main.cpp)
96-
97-
if (APPLE)
98-
list (APPEND _imiv_core_sources
99-
external/dnd_glfw/dnd_glfw_macos.mm)
164+
imiv_vulkan_window.cpp)
165+
166+
set (_imiv_renderer_metal_sources
167+
imiv_renderer_metal.mm)
168+
set (_imiv_renderer_opengl_sources
169+
imiv_renderer_opengl.cpp)
170+
set (_imiv_renderer_selected_sources)
171+
if (_imiv_renderer_is_vulkan)
172+
set (_imiv_renderer_selected_sources ${_imiv_renderer_vulkan_sources})
173+
elseif (_imiv_renderer_is_metal)
174+
set (_imiv_renderer_selected_sources ${_imiv_renderer_metal_sources})
175+
elseif (_imiv_renderer_is_opengl)
176+
set (_imiv_renderer_selected_sources ${_imiv_renderer_opengl_sources})
100177
endif ()
101178

179+
set (_imiv_core_sources
180+
${_imiv_shared_sources}
181+
${_imiv_test_engine_integration_sources}
182+
${_imiv_platform_glfw_sources}
183+
${_imiv_renderer_selected_sources})
184+
102185
set (_imiv_shader_src "${CMAKE_CURRENT_SOURCE_DIR}/shaders/imiv_upload_to_rgba.comp")
103186
set (_imiv_preview_vert_src "${CMAKE_CURRENT_SOURCE_DIR}/shaders/imiv_preview.vert")
104187
set (_imiv_preview_frag_src "${CMAKE_CURRENT_SOURCE_DIR}/shaders/imiv_preview.frag")
@@ -110,7 +193,7 @@ set (_imiv_preview_vert_spv "${CMAKE_CURRENT_BINARY_DIR}/imiv_preview.vert.spv")
110193
set (_imiv_preview_frag_spv "${CMAKE_CURRENT_BINARY_DIR}/imiv_preview.frag.spv")
111194
set (_imiv_shader_outputs)
112195

113-
if (NOT APPLE)
196+
if (_imiv_renderer_is_vulkan)
114197
find_program (OIIO_IMIV_GLSLC_EXECUTABLE
115198
NAMES glslc
116199
HINTS
@@ -204,11 +287,8 @@ set (_imiv_imgui_sources
204287
"${OIIO_IMIV_IMGUI_ROOT}/imgui_draw.cpp"
205288
"${OIIO_IMIV_IMGUI_ROOT}/imgui_tables.cpp"
206289
"${OIIO_IMIV_IMGUI_ROOT}/imgui_widgets.cpp"
207-
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_glfw.cpp")
208-
if (NOT APPLE)
209-
list (APPEND _imiv_imgui_sources
210-
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_vulkan.cpp")
211-
endif ()
290+
"${OIIO_IMIV_IMGUI_ROOT}/backends/imgui_impl_glfw.cpp"
291+
${_imiv_imgui_renderer_sources})
212292

213293
set (_imiv_test_engine_sources)
214294
set (_imiv_test_engine_dir "")
@@ -260,16 +340,16 @@ set (_imiv_link_libs
260340
OpenImageIO
261341
$<TARGET_NAME_IF_EXISTS:OpenColorIO::OpenColorIO>
262342
$<TARGET_NAME_IF_EXISTS:OpenColorIO::OpenColorIOHeaders>)
263-
if (NOT APPLE)
264-
find_package (glfw3 CONFIG QUIET)
265-
if (TARGET glfw)
266-
list (APPEND _imiv_link_libs glfw)
267-
else ()
268-
message (STATUS
269-
"\n\n WARNING: glfw not found -- 'imiv' will not be built!\n")
270-
return ()
271-
endif ()
343+
find_package (glfw3 CONFIG QUIET)
344+
if (TARGET glfw)
345+
list (APPEND _imiv_link_libs glfw)
346+
else ()
347+
message (STATUS
348+
"\n\n WARNING: glfw not found -- 'imiv' will not be built!\n")
349+
return ()
350+
endif ()
272351

352+
if (_imiv_renderer_is_vulkan)
273353
find_package (Vulkan QUIET)
274354
if (Vulkan_FOUND)
275355
record_build_dependency (Vulkan FOUND VERSION "${Vulkan_VERSION}")
@@ -513,12 +593,48 @@ if (NOT APPLE)
513593
GLSLANG_RUNTIME NOTFOUND
514594
NOT_FOUND_EXPLANATION "${_imiv_runtime_glslang_explanation}")
515595
endif ()
516-
else ()
596+
elseif (_imiv_renderer_is_metal)
517597
set (_imiv_has_runtime_glslang OFF)
518598
record_build_dependency (
519599
GLSLANG_RUNTIME NOTFOUND
520600
NOT_FOUND_EXPLANATION
521601
"(runtime shader compilation disabled on Metal backend)")
602+
find_library (OIIO_IMIV_COCOA_FRAMEWORK Cocoa)
603+
find_library (OIIO_IMIV_METAL_FRAMEWORK Metal)
604+
find_library (OIIO_IMIV_QUARTZCORE_FRAMEWORK QuartzCore)
605+
if (NOT OIIO_IMIV_COCOA_FRAMEWORK
606+
OR NOT OIIO_IMIV_METAL_FRAMEWORK
607+
OR NOT OIIO_IMIV_QUARTZCORE_FRAMEWORK)
608+
message (STATUS
609+
"\n\n WARNING: Metal frameworks not found -- 'imiv' will not be built!\n")
610+
return ()
611+
endif ()
612+
list (APPEND _imiv_link_libs
613+
${OIIO_IMIV_COCOA_FRAMEWORK}
614+
${OIIO_IMIV_METAL_FRAMEWORK}
615+
${OIIO_IMIV_QUARTZCORE_FRAMEWORK})
616+
elseif (_imiv_renderer_is_opengl)
617+
set (_imiv_has_runtime_glslang OFF)
618+
record_build_dependency (
619+
GLSLANG_RUNTIME NOTFOUND
620+
NOT_FOUND_EXPLANATION
621+
"(runtime shader compilation disabled on OpenGL backend)")
622+
find_package (OpenGL QUIET)
623+
if (TARGET OpenGL::GL)
624+
list (APPEND _imiv_link_libs OpenGL::GL)
625+
elseif (TARGET OpenGL::OpenGL)
626+
list (APPEND _imiv_link_libs OpenGL::OpenGL)
627+
else ()
628+
message (STATUS
629+
"\n\n WARNING: OpenGL not found -- 'imiv' will not be built!\n")
630+
return ()
631+
endif ()
632+
else ()
633+
set (_imiv_has_runtime_glslang OFF)
634+
record_build_dependency (
635+
GLSLANG_RUNTIME NOTFOUND
636+
NOT_FOUND_EXPLANATION
637+
"(runtime shader compilation disabled on selected backend)")
522638
endif ()
523639

524640
if (MSVC)
@@ -546,8 +662,17 @@ fancy_add_executable (
546662
source_group ("imgui" FILES ${_imiv_imgui_sources})
547663
source_group ("imgui_te" FILES
548664
${_imiv_test_engine_sources}
549-
"${CMAKE_CURRENT_SOURCE_DIR}/imiv_test_engine.cpp"
665+
${_imiv_test_engine_integration_sources}
550666
"${CMAKE_CURRENT_SOURCE_DIR}/imiv_test_engine.h")
667+
source_group ("imiv\\shared" FILES ${_imiv_shared_sources})
668+
source_group ("imiv\\platform\\glfw" FILES ${_imiv_platform_glfw_sources})
669+
source_group ("imiv\\renderer\\vulkan" FILES ${_imiv_renderer_vulkan_sources})
670+
if (_imiv_renderer_metal_sources)
671+
source_group ("imiv\\renderer\\metal" FILES ${_imiv_renderer_metal_sources})
672+
endif ()
673+
if (_imiv_renderer_opengl_sources)
674+
source_group ("imiv\\renderer\\opengl" FILES ${_imiv_renderer_opengl_sources})
675+
endif ()
551676

552677
if (TARGET imiv)
553678
target_compile_definitions (imiv PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
@@ -558,15 +683,16 @@ if (TARGET imiv)
558683
else ()
559684
target_compile_definitions (imiv PRIVATE IMIV_HAS_COMPUTE_UPLOAD_SHADERS=0)
560685
endif ()
561-
if (APPLE)
562-
target_compile_definitions (imiv PRIVATE IMIV_BACKEND_METAL_GLFW=1)
563-
find_library (OIIO_IMIV_COCOA_FRAMEWORK Cocoa)
564-
if (OIIO_IMIV_COCOA_FRAMEWORK)
565-
target_link_libraries (imiv PRIVATE ${OIIO_IMIV_COCOA_FRAMEWORK})
566-
endif ()
567-
else ()
686+
if (_imiv_renderer_is_vulkan)
568687
target_compile_definitions (imiv PRIVATE IMIV_BACKEND_VULKAN_GLFW=1
569688
$<$<CONFIG:Debug>:IMIV_VULKAN_VALIDATION=1>)
689+
elseif (_imiv_renderer_is_metal)
690+
target_compile_definitions (imiv PRIVATE IMIV_BACKEND_METAL_GLFW=1)
691+
elseif (_imiv_renderer_is_opengl)
692+
target_compile_definitions (imiv PRIVATE IMIV_BACKEND_OPENGL_GLFW=1)
693+
if (APPLE)
694+
target_compile_definitions (imiv PRIVATE GL_SILENCE_DEPRECATION)
695+
endif ()
570696
endif ()
571697
if (_imiv_has_runtime_glslang)
572698
target_compile_definitions (imiv PRIVATE IMIV_HAS_GLSLANG_RUNTIME=1)

src/imiv/imiv_actions.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
#include <system_error>
1717
#include <vector>
1818

19-
#if defined(IMIV_BACKEND_VULKAN_GLFW)
19+
#if defined(IMIV_BACKEND_VULKAN_GLFW) || defined(IMIV_BACKEND_METAL_GLFW) \
20+
|| defined(IMIV_BACKEND_OPENGL_GLFW)
2021
# define GLFW_INCLUDE_NONE
2122
# include <GLFW/glfw3.h>
2223
#endif
@@ -32,7 +33,6 @@ using namespace OIIO;
3233

3334
namespace Imiv {
3435

35-
#if defined(IMIV_BACKEND_VULKAN_GLFW)
3636
namespace {
3737

3838
void clear_loaded_image_state(ViewerState& viewer)
@@ -98,11 +98,11 @@ namespace {
9898

9999
std::tm local_tm = {};
100100
const std::time_t now = std::time(nullptr);
101-
# if defined(_WIN32)
101+
#if defined(_WIN32)
102102
localtime_s(&local_tm, &now);
103-
# else
103+
#else
104104
localtime_r(&now, &local_tm);
105-
# endif
105+
#endif
106106

107107
char timestamp[64] = {};
108108
if (std::strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S",
@@ -123,7 +123,6 @@ namespace {
123123
}
124124

125125
} // namespace
126-
#endif
127126

128127
bool
129128
read_env_value(const char* name, std::string& out_value)
@@ -399,7 +398,6 @@ save_as_dialog_action(ViewerState& viewer)
399398
}
400399
}
401400

402-
#if defined(IMIV_BACKEND_VULKAN_GLFW)
403401
void
404402
set_full_screen_mode(GLFWwindow* window, ViewerState& viewer, bool enable,
405403
std::string& error_message)
@@ -679,9 +677,9 @@ close_current_image_action(RendererState& vk_state, ViewerState& viewer,
679677
{
680678
const std::string closing_path = viewer.image.path;
681679
const int closing_index = viewer.current_path_index;
682-
# if defined(IMIV_BACKEND_VULKAN_GLFW)
680+
#if defined(IMIV_BACKEND_VULKAN_GLFW)
683681
quiesce_viewer_texture_lifetime(vk_state, viewer.texture);
684-
# endif
682+
#endif
685683
renderer_destroy_texture(vk_state, viewer.texture);
686684
remove_loaded_image_path(viewer, closing_path);
687685
if (!viewer.loaded_image_paths.empty()) {
@@ -847,8 +845,12 @@ capture_main_viewport_screenshot_action(RendererState& vk_state,
847845
out_path.clear();
848846
viewer.last_error.clear();
849847

850-
const int width = std::max(0, vk_state.window_data.Width);
851-
const int height = std::max(0, vk_state.window_data.Height);
848+
int width = std::max(0, vk_state.framebuffer_width);
849+
int height = std::max(0, vk_state.framebuffer_height);
850+
#if defined(IMIV_BACKEND_VULKAN_GLFW)
851+
width = std::max(width, vk_state.window_data.Width);
852+
height = std::max(height, vk_state.window_data.Height);
853+
#endif
852854
if (width <= 0 || height <= 0) {
853855
viewer.last_error = "screenshot failed: main viewport size is invalid";
854856
return false;
@@ -898,6 +900,4 @@ capture_main_viewport_screenshot_action(RendererState& vk_state,
898900
return true;
899901
}
900902

901-
#endif
902-
903903
} // namespace Imiv

0 commit comments

Comments
 (0)