MayaFlux 1.0.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 1060 of file BackendWindowHandler.cpp.

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

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