Skip to content

Commit b2f17e5

Browse files
committed
Add native texture upload & fix Vulkan capture
Vulkan: account for ImGui viewport scaling and clamp capture region before calling the swapchain capture helper so screen captures map correctly to window pixels. Metal: implement a native source upload path using a compute pipeline. Add a Metal compute shader to decode multiple host pixel formats (u8/u16/u32/f16/f32/f64) with arbitrary row pitch and channel counts, create/upload helpers (create_upload_pipeline, upload_source_texture, prepare_source_upload), and switch source textures to private storage with compute-based initialization. Handles double->float conversion and validates stride/size limits. OpenGL: add missing GL format/type constants and support native uploads via GL_UNPACK_ROW_LENGTH with a SourceTextureUploadDesc. New logic selects matching internal formats/types when possible, falls back to RGBA32F conversion for unsupported types or misaligned stride, and allocates preview textures separately. Also handle 2-channel inputs in preview shaders and minor API/refactor changes.
1 parent ffaebd4 commit b2f17e5

3 files changed

Lines changed: 547 additions & 95 deletions

File tree

src/imiv/imiv_capture.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "imiv_types.h"
66

7+
#include <cmath>
78
#include <cstdio>
89
#include <cstring>
910
#include <string>
@@ -413,11 +414,51 @@ bool
413414
imiv_vulkan_screen_capture(ImGuiID viewport_id, int x, int y, int w, int h,
414415
unsigned int* pixels, void* user_data)
415416
{
416-
(void)viewport_id;
417417
VulkanState* vk_state = reinterpret_cast<VulkanState*>(user_data);
418418
if (vk_state == nullptr)
419419
return false;
420-
return capture_swapchain_region_rgba8(*vk_state, x, y, w, h, pixels);
420+
421+
int capture_x = x;
422+
int capture_y = y;
423+
int capture_w = w;
424+
int capture_h = h;
425+
ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id);
426+
if (viewport != nullptr && vk_state->window_data.Width > 0
427+
&& vk_state->window_data.Height > 0 && viewport->Size.x > 0.0f
428+
&& viewport->Size.y > 0.0f) {
429+
const double scale_x = static_cast<double>(vk_state->window_data.Width)
430+
/ static_cast<double>(viewport->Size.x);
431+
const double scale_y = static_cast<double>(vk_state->window_data.Height)
432+
/ static_cast<double>(viewport->Size.y);
433+
capture_x = static_cast<int>(std::lround(
434+
(static_cast<double>(x) - static_cast<double>(viewport->Pos.x))
435+
* scale_x));
436+
capture_y = static_cast<int>(std::lround(
437+
(static_cast<double>(y) - static_cast<double>(viewport->Pos.y))
438+
* scale_y));
439+
capture_w = std::max(1, static_cast<int>(std::lround(
440+
static_cast<double>(w) * scale_x)));
441+
capture_h = std::max(1, static_cast<int>(std::lround(
442+
static_cast<double>(h) * scale_y)));
443+
}
444+
445+
if (capture_x < 0) {
446+
capture_w += capture_x;
447+
capture_x = 0;
448+
}
449+
if (capture_y < 0) {
450+
capture_h += capture_y;
451+
capture_y = 0;
452+
}
453+
if (capture_x < vk_state->window_data.Width
454+
&& capture_y < vk_state->window_data.Height) {
455+
capture_w = std::min(capture_w, vk_state->window_data.Width - capture_x);
456+
capture_h = std::min(capture_h,
457+
vk_state->window_data.Height - capture_y);
458+
}
459+
460+
return capture_swapchain_region_rgba8(*vk_state, capture_x, capture_y,
461+
capture_w, capture_h, pixels);
421462
}
422463

423464
#endif

0 commit comments

Comments
 (0)