MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ start_readback_thread()

void MayaFlux::Core::BackendWindowHandler::start_readback_thread ( CaptureState state,
vk::Device  dev 
)
private

Thread function to perform asynchronous readback of captured frames.

Parameters
stateCapture state containing pending readbacks
devVulkan device to use for readback operations

This thread continuously checks for pending capture slots and performs the necessary Vulkan commands to read back the image data into CPU memory. The last captured frame is stored atomically for retrieval by the display service.

Definition at line 1039 of file BackendWindowHandler.cpp.

1040{
1041 state.readback_running.store(true, std::memory_order_release);
1042
1043 state.readback_thread = std::thread([&state, dev]() {
1044 while (state.readback_running.load(std::memory_order_acquire)) {
1045 bool any = false;
1046
1047 for (auto& slot_ptr : state.slots) {
1048 auto& slot = *slot_ptr;
1049
1050 if (!slot.pending.load(std::memory_order_acquire))
1051 continue;
1052
1053 if (dev.getFenceStatus(slot.fence) != vk::Result::eSuccess)
1054 continue;
1055
1056 const size_t nb = static_cast<size_t>(slot.extent.width)
1057 * slot.extent.height * state.bpp;
1058
1059 vk::SubresourceLayout layout = dev.getImageSubresourceLayout(
1060 slot.image, { vk::ImageAspectFlagBits::eColor, 0, 0 });
1061
1062 const auto* mapped = static_cast<const uint8_t*>(
1063 dev.mapMemory(slot.mem, 0, VK_WHOLE_SIZE));
1064 mapped += layout.offset;
1065
1066 auto buf = std::make_shared<std::vector<uint8_t>>(nb);
1067 const uint32_t row_bytes = slot.extent.width * state.bpp;
1068 for (uint32_t y = 0; y < slot.extent.height; ++y) {
1069 std::memcpy(buf->data() + static_cast<size_t>(y * row_bytes),
1070 mapped + y * layout.rowPitch,
1071 row_bytes);
1072 }
1073
1074 dev.unmapMemory(slot.mem);
1075
1076 // ---------------------------------------------------------------
1077 // Store new frame into last_frame (same pattern as InputManager)
1078 // ---------------------------------------------------------------
1079#ifdef MAYAFLUX_PLATFORM_MACOS
1080 auto* raw_frame = new std::vector<uint8_t>(std::move(*buf));
1081 auto* old = state.last_frame.exchange(raw_frame, std::memory_order_acq_rel);
1082 if (old)
1083 state.retire_last_frame(old);
1084#else
1085 state.last_frame.store(buf, std::memory_order_release);
1086#endif
1087
1088// ---------------------------------------------------------------
1089// Read observers and invoke callbacks
1090// ---------------------------------------------------------------
1091#ifdef MAYAFLUX_PLATFORM_MACOS
1092 size_t obs_slot = CaptureState::OBSERVERS_MAX_READERS;
1093 for (size_t i = 0; i < CaptureState::OBSERVERS_MAX_READERS; ++i) {
1094 bool expected = false;
1095 if (state.observers_slot_active[i].compare_exchange_strong(expected, true, std::memory_order_acquire)) {
1096 obs_slot = i;
1097 break;
1098 }
1099 }
1100
1101 if (obs_slot != CaptureState::OBSERVERS_MAX_READERS) {
1102 const CaptureState::ObserverMap* obs_current;
1103 do {
1104 obs_current = state.observers.load(std::memory_order_acquire);
1105 state.observers_hazard_ptrs[obs_slot].store(obs_current, std::memory_order_release);
1106 } while (obs_current != state.observers.load(std::memory_order_acquire));
1107
1108 if (obs_current) {
1109 for (const auto& [id, cb] : *obs_current) {
1110 cb(buf, slot.extent.width, slot.extent.height,
1111 static_cast<uint32_t>(state.format));
1112 }
1113 }
1114
1115 state.observers_hazard_ptrs[obs_slot].store(nullptr, std::memory_order_release);
1116 state.observers_slot_active[obs_slot].store(false, std::memory_order_release);
1117 }
1118#else
1119 auto obs = state.observers.load(std::memory_order_acquire);
1120 if (obs) {
1121 for (const auto& [id, cb] : *obs) {
1122 cb(buf, slot.extent.width, slot.extent.height,
1123 static_cast<uint32_t>(state.format));
1124 }
1125 }
1126#endif
1127
1128 slot.pending.store(false, std::memory_order_release);
1129 any = true;
1130 }
1131
1132 if (!any)
1133 std::this_thread::sleep_for(std::chrono::microseconds(200));
1134 }
1135 });
1136}

References MayaFlux::Core::CaptureState::readback_running, and MayaFlux::Core::CaptureState::readback_thread.