@@ -438,11 +438,82 @@ bool Session::LoadWaveformData(int version, const string& dataDir)
438438 }
439439 }
440440
441+ // Third pass: history and refresh filters
442+ double hstart = GetTime ();
443+ double cdt = 0 ;
444+ bool converted = false ;
445+ for (auto point : m_history.m_history )
446+ {
447+ point->LoadHistoryToSession (*this );
448+
449+ double cstart = GetTime ();
450+ if (ConvertLegacyUniformWaveforms ())
451+ converted = true ;
452+ cdt += GetTime () - cstart;
453+
454+ RefreshAllFilters ();
455+ }
456+ double hdt = GetTime () - hstart;
457+ LogTrace (" History replay took %.3f ms\n " , hdt * 1000 );
458+ if (converted)
459+ LogTrace (" Legacy waveform conversion took %.3f ms\n " , cdt * 1000 );
460+
441461 m_history.SetMaxToCurrentDepth ();
442462
443463 return true ;
444464}
445465
466+ /* *
467+ @brief Check for any legacy waveforms stored in sparsev1 format that are actually uniform
468+ */
469+ bool Session::ConvertLegacyUniformWaveforms ()
470+ {
471+ bool converted = false ;
472+
473+ for (auto scope : m_oscilloscopes)
474+ {
475+ for (size_t i=0 ; i < scope->GetChannelCount (); i++)
476+ {
477+ auto oc = scope->GetOscilloscopeChannel (i);
478+ if (!oc)
479+ continue ;
480+
481+ for (size_t j=0 ; j<oc->GetStreamCount (); j++)
482+ {
483+ auto data = oc->GetData (j);
484+ if (!data)
485+ continue ;
486+
487+ auto sacap = dynamic_cast <SparseAnalogWaveform*>(data);
488+
489+ // Quickly check if the waveform is dense packed, even if it was stored as sparse.
490+ // Since we know samples must be monotonic and non-overlapping, we don't have to check every single one!
491+ if (sacap)
492+ {
493+ int64_t nlast = sacap->size () - 1 ;
494+ if ( (sacap->m_offsets [0 ] == 0 ) &&
495+ (sacap->m_offsets [nlast] == nlast) &&
496+ (sacap->m_durations [nlast] == 1 ) )
497+ {
498+ LogDebug (" Found legacy uniform waveform stored on disk as sparse, converting to uniform\n " );
499+
500+ // Waveform was actually uniform, so convert it
501+ auto cap = new UniformAnalogWaveform (*sacap);
502+ oc->SetData (cap, j);
503+
504+ // Update history
505+ m_history.Retcon (scope, i, j, cap);
506+
507+ converted = true ;
508+ }
509+ }
510+ }
511+ }
512+ }
513+
514+ return converted;
515+ }
516+
446517/* *
447518 @brief Loads waveform data for filters that need to be preserved
448519 */
@@ -520,7 +591,7 @@ bool Session::LoadWaveformDataForFilters(
520591
521592 // Actually load the waveform
522593 string fname = datdir + " /stream" + to_string (i) + " .bin" ;
523- DoLoadWaveformDataForStream (f, i , fmt, fname);
594+ DoLoadWaveformDataForStream (cap , fmt, fname);
524595 }
525596 }
526597
@@ -538,6 +609,7 @@ bool Session::LoadWaveformDataForScope(
538609{
539610 LogTrace (" Loading waveform data for scope \" %s\"\n " , scope->m_nickname .c_str ());
540611 LogIndenter li;
612+ double start = GetTime ();
541613
542614 TimePoint time (0 , 0 );
543615 TimePoint newest (0 , 0 );
@@ -563,7 +635,16 @@ bool Session::LoadWaveformDataForScope(
563635 chan->SetData (nullptr , j);
564636 }
565637
566- // Load the data for each waveform
638+ // Save info for each waveform so we know where to load it from
639+ struct WaveformLoadInfo
640+ {
641+ WaveformBase* wfm;
642+ string format;
643+ string fname;
644+ };
645+ vector<WaveformLoadInfo> waveformsToLoad;
646+
647+ // First pass: Load metadata and allocate waveforms etc
567648 for (auto it : wavenode)
568649 {
569650 // Top level metadata
@@ -706,32 +787,49 @@ bool Session::LoadWaveformDataForScope(
706787 nstream);
707788 }
708789
709- DoLoadWaveformDataForStream (
710- scope->GetOscilloscopeChannel (nchan),
711- nstream,
712- formats[i],
713- tmp);
790+ // Figure out what needs to be loaded
791+ WaveformLoadInfo info;
792+ info.wfm = scope->GetOscilloscopeChannel (nchan)->GetData (nstream);
793+ info.format = formats[i];
794+ info.fname = tmp;
795+ waveformsToLoad.push_back (info);
714796 }
715797
798+ // TODO: merge history in multi scope sessions?
716799 vector<shared_ptr<Oscilloscope>> temp;
717800 temp.push_back (scope);
718801 m_history.AddHistory (temp, false , pinned, label);
802+ }
719803
720- // TODO: this is not good for multiscope
721- // TODO: handle eye patterns (need to know window size for it to work right)
722- RefreshAllFilters ();
804+ // Second pass: Actually load the waveform data in parallel
805+ #pragma omp parallel for
806+ for (size_t i=0 ; i<waveformsToLoad.size (); i++)
807+ {
808+ auto info = waveformsToLoad[i];
809+ DoLoadWaveformDataForStream (info.wfm , info.format , info.fname );
723810 }
811+
812+ // Copy it all to the GPU in one go
813+ // For now, use the global transfer queue for this
814+ {
815+ std::lock_guard<std::mutex> lock (g_vkTransferMutex);
816+ g_vkTransferCommandBuffer->begin ({});
817+
818+ for (size_t i=0 ; i<waveformsToLoad.size (); i++)
819+ waveformsToLoad[i].wfm ->PrepareForGpuAccessNonblocking (*g_vkTransferCommandBuffer);
820+
821+ g_vkTransferCommandBuffer->end ();
822+ g_vkTransferQueue->SubmitAndBlock (*g_vkTransferCommandBuffer);
823+ }
824+
825+ double dt = GetTime () - start;
826+ LogTrace (" Scope data loaded in %.3f ms\n " , dt * 1000 );
827+
724828 return true ;
725829}
726830
727- void Session::DoLoadWaveformDataForStream (
728- OscilloscopeChannel* chan,
729- int stream,
730- string format,
731- string fname
732- )
831+ void Session::DoLoadWaveformDataForStream (WaveformBase* cap, string format, string fname)
733832{
734- auto cap = chan->GetData (stream);
735833 auto sacap = dynamic_cast <SparseAnalogWaveform*>(cap);
736834 auto uacap = dynamic_cast <UniformAnalogWaveform*>(cap);
737835 auto sdcap = dynamic_cast <SparseDigitalWaveform*>(cap);
@@ -837,21 +935,6 @@ void Session::DoLoadWaveformDataForStream(
837935 ccap->m_durations [j] = stime[1 ];
838936 }
839937 }
840-
841- // Quickly check if the waveform is dense packed, even if it was stored as sparse.
842- // Since we know samples must be monotonic and non-overlapping, we don't have to check every single one!
843- int64_t nlast = nsamples - 1 ;
844- if (sacap)
845- {
846- if ( (sacap->m_offsets [0 ] == 0 ) &&
847- (sacap->m_offsets [nlast] == nlast) &&
848- (sacap->m_durations [nlast] == 1 ) )
849- {
850- // Waveform was actually uniform, so convert it
851- cap = new UniformAnalogWaveform (*sacap);
852- chan->SetData (cap, stream);
853- }
854- }
855938 }
856939
857940 // Dense packed
@@ -880,7 +963,6 @@ void Session::DoLoadWaveformDataForStream(
880963 }
881964
882965 cap->MarkModifiedFromCpu ();
883- cap->PrepareForGpuAccess ();
884966
885967 #ifdef _WIN32
886968 delete[] buf;
0 commit comments