@@ -80,10 +80,6 @@ DisplayedChannel::DisplayedChannel(StreamDescriptor stream, Session& session)
8080 m_rasterizedWaveform.SetCpuAccessHint (AcceleratorBuffer<float >::HINT_LIKELY);
8181 m_rasterizedWaveform.SetGpuAccessHint (AcceleratorBuffer<float >::HINT_LIKELY);
8282
83- // Use pinned memory for index buffer since it should only be read once
84- m_indexBuffer.SetCpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_LIKELY);
85- m_indexBuffer.SetGpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_UNLIKELY);
86-
8783 // Create tone map pipeline depending on waveform type
8884 switch (m_stream.GetType ())
8985 {
@@ -111,6 +107,23 @@ DisplayedChannel::DisplayedChannel(StreamDescriptor stream, Session& session)
111107 m_toneMapPipe = make_shared<ComputePipeline>(
112108 " shaders/WaveformToneMap.spv" , 1 , sizeof (WaveformToneMapArgs), 1 );
113109 }
110+
111+ // If we have native int64 support we can do the index search for sparse waveforms on the GPU
112+ if (g_hasShaderInt64)
113+ {
114+ m_indexSearchComputePipeline = make_shared<ComputePipeline>(
115+ " shaders/IndexSearch.spv" , 2 , sizeof (IndexSearchConstants));
116+
117+ // Use GPU local memory for index buffer
118+ m_indexBuffer.SetCpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_LIKELY);
119+ m_indexBuffer.SetGpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_LIKELY);
120+ }
121+ else
122+ {
123+ // Use pinned memory for index buffer since it should only be read once
124+ m_indexBuffer.SetCpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_LIKELY);
125+ m_indexBuffer.SetGpuAccessHint (AcceleratorBuffer<uint32_t >::HINT_UNLIKELY);
126+ }
114127}
115128
116129DisplayedChannel::~DisplayedChannel ()
@@ -1339,7 +1352,6 @@ ImVec2 WaveformArea::ClosestPointOnLineSegment(ImVec2 lineA, ImVec2 lineB, ImVec
13391352void WaveformArea::RenderSpectrumPeaks (ImDrawList* list, shared_ptr<DisplayedChannel> channel)
13401353{
13411354 auto stream = channel->GetStream ();
1342- auto data = stream.GetData ();
13431355 auto & peaks = dynamic_cast <PeakDetectionFilter*>(stream.m_channel )->GetPeaks ();
13441356
13451357 // TODO: add a preference for peak circle color and size?
@@ -2107,38 +2119,72 @@ void WaveformArea::RasterizeAnalogOrDigitalWaveform(
21072119 }
21082120
21092121 // Bind input buffers
2110- if (uadata)
2111- comp->BindBufferNonblocking (1 , uadata->m_samples , cmdbuf);
2112- if (uddata)
2113- comp->BindBufferNonblocking (1 , uddata->m_samples , cmdbuf);
21142122 if (sdata)
21152123 {
2124+ // Calculate indexes for X axis
2125+ auto & ibuf = channel->GetIndexBuffer ();
2126+
2127+ // FIXME: what still depends on m_offsets CPU side??
2128+ // If we don't copy this, nothing is drawn
2129+ sdata->m_offsets .PrepareForCpuAccessNonblocking (cmdbuf);
2130+
2131+ // If we have native int64, do this on the GPU
2132+ if (g_hasShaderInt64)
2133+ {
2134+ IndexSearchConstants cfg;
2135+ cfg.len = data->size ();
2136+ cfg.w = w;
2137+ cfg.xscale = xscale;
2138+ cfg.offset_samples = offset_samples;
2139+
2140+ const uint32_t threadsPerBlock = 64 ;
2141+ const uint32_t numBlocks = (w | (threadsPerBlock - 1 )) / threadsPerBlock;
2142+
2143+ auto ipipe = channel->GetIndexSearchPipeline ();
2144+ ipipe->BindBufferNonblocking (0 , sdata->m_offsets , cmdbuf);
2145+ ipipe->BindBufferNonblocking (1 , ibuf, cmdbuf, true );
2146+ ipipe->Dispatch (cmdbuf, cfg, numBlocks);
2147+ ipipe->AddComputeMemoryBarrier (cmdbuf);
2148+ ibuf.MarkModifiedFromGpu ();
2149+ }
2150+
2151+ // otherwise CPU fallback
2152+ else
2153+ {
2154+ ibuf.PrepareForCpuAccess ();
2155+ sdata->m_offsets .PrepareForCpuAccess ();
2156+ for (size_t i=0 ; i<w; i++)
2157+ {
2158+ int64_t target = floor (i / xscale) + offset_samples;
2159+ ibuf[i] = BinarySearchForGequal (
2160+ sdata->m_offsets .GetCpuPointer (),
2161+ data->size (),
2162+ target);
2163+
2164+ if (i < 16 )
2165+ LogDebug (" ibuf[%zu] = %d\n " , i, ibuf[i]);
2166+ }
2167+ ibuf.MarkModifiedFromCpu ();
2168+ }
2169+
2170+ // Bind the buffers
21162171 if (sadata)
21172172 comp->BindBufferNonblocking (1 , sadata->m_samples , cmdbuf);
21182173 if (sddata)
21192174 comp->BindBufferNonblocking (1 , sddata->m_samples , cmdbuf);
21202175
21212176 // Map offsets and, if requested, durations
21222177 comp->BindBufferNonblocking (2 , sdata->m_offsets , cmdbuf);
2178+ comp->BindBufferNonblocking (3 , ibuf, cmdbuf);
21232179 if (channel->ShouldMapDurations ())
21242180 comp->BindBufferNonblocking (4 , sdata->m_durations , cmdbuf);
2125-
2126- // Calculate indexes for X axis
2127- auto & ibuf = channel->GetIndexBuffer ();
2128- ibuf.PrepareForCpuAccess ();
2129- sdata->m_offsets .PrepareForCpuAccess ();
2130- for (size_t i=0 ; i<w; i++)
2131- {
2132- int64_t target = floor (i / xscale) + offset_samples;
2133- ibuf[i] = BinarySearchForGequal (
2134- sdata->m_offsets .GetCpuPointer (),
2135- data->size (),
2136- target);
2137- }
2138- ibuf.MarkModifiedFromCpu ();
2139- comp->BindBufferNonblocking (3 , ibuf, cmdbuf);
21402181 }
21412182
2183+ if (uadata)
2184+ comp->BindBufferNonblocking (1 , uadata->m_samples , cmdbuf);
2185+ if (uddata)
2186+ comp->BindBufferNonblocking (1 , uddata->m_samples , cmdbuf);
2187+
21422188 // Bind output texture and bail if there's nothing there
21432189 auto & imgOut = channel->GetRasterizedWaveform ();
21442190 if (imgOut.empty ())
0 commit comments