Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1ff6aaa49d6f
Choose a base ref
...
head repository: ngscopeclient/scopehal-apps
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b01f926e8182
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Feb 24, 2020

  1. Copy the full SHA
    b01f926 View commit details
Showing with 94 additions and 81 deletions.
  1. +23 −23 glscopeclient/WaveformArea.cpp
  2. +30 −14 glscopeclient/WaveformArea.h
  3. +2 −2 glscopeclient/WaveformArea_events.cpp
  4. +39 −42 glscopeclient/WaveformArea_rendering.cpp
46 changes: 23 additions & 23 deletions glscopeclient/WaveformArea.cpp
Original file line number Diff line number Diff line change
@@ -73,24 +73,25 @@ WaveformArea::WaveformArea(const WaveformArea* clone)

void WaveformArea::SharedCtorInit()
{
m_frameTime = 0;
m_frameCount = 0;
m_renderTime = 0;
m_prepareTime = 0;
m_downloadTime = 0;
m_cairoTime = 0;
m_texDownloadTime = 0;
m_compositeTime = 0;
m_indexTime = 0;
m_updatingContextMenu = false;
m_selectedChannel = m_channel;
m_dragState = DRAG_NONE;
m_padding = 2;
m_lastFrameStart = -1;
m_persistenceClear = true;
m_geometryDirty = true;
m_firstFrame = false;
m_geometryOK = false;
//performance counters
m_frameTime = 0;
m_frameCount = 0;
m_renderTime = 0;
m_prepareTime = 0;
m_downloadTime = 0;
m_cairoTime = 0;
m_texDownloadTime = 0;
m_compositeTime = 0;
m_indexTime = 0;
m_lastFrameStart = -1;

m_updatingContextMenu = false;
m_selectedChannel = m_channel;
m_dragState = DRAG_NONE;
m_padding = 2;
m_persistenceClear = true;
m_firstFrame = false;
m_waveformRenderData = NULL;

set_has_alpha();

@@ -446,6 +447,8 @@ void WaveformArea::on_realize()
//This means we need to save some configuration (like the current FBO) that GTK doesn't tell us directly
m_firstFrame = true;

m_waveformRenderData = new WaveformRenderData(m_channel);

//Set stuff up for each rendering pass
InitializeWaveformPass();
InitializeColormapPass();
@@ -485,16 +488,13 @@ void WaveformArea::CleanupGLHandles()
m_eyeVBO.Destroy();

//Clean up old textures
m_waveformTextureResolved.Destroy();
m_cairoTexture.Destroy();
m_cairoTextureOver.Destroy();
for(auto& e : m_eyeColorRamp)
e.Destroy();

//Clean up old SSBOs
m_waveformStorageBuffer.Destroy();
m_waveformConfigBuffer.Destroy();
m_waveformIndexBuffer.Destroy();
delete m_waveformRenderData;
m_waveformRenderData = NULL;

//Detach the FBO so we don't destroy it!!
//GTK manages this, and it might be used by more than one waveform area within the application.
44 changes: 30 additions & 14 deletions glscopeclient/WaveformArea.h
Original file line number Diff line number Diff line change
@@ -77,6 +77,32 @@ class Rect : public Gdk::Rectangle
}
};

/**
@rbief GL buffers etc needed to render a single waveform
*/
class WaveformRenderData
{
public:
WaveformRenderData(OscilloscopeChannel* channel)
: m_channel(channel)
, m_geometryOK(false)
{}

//The channel of interest
OscilloscopeChannel* m_channel;

//True if everything is good to render
bool m_geometryOK;

//SSBOs with waveform data
ShaderStorageBuffer m_waveformStorageBuffer;
ShaderStorageBuffer m_waveformConfigBuffer;
ShaderStorageBuffer m_waveformIndexBuffer;

//RGBA32 but only alpha actually used
Texture m_waveformTexture;
};

float sinc(float x, float width);
float blackman(float x, float width);

@@ -97,8 +123,9 @@ class WaveformArea : public Gtk::GLArea
void ClearPersistence()
{ m_persistenceClear = true; }

//TODO: dirtiness needs complete revamp
void SetGeometryDirty()
{ m_geometryDirty = true; }
{ }

WaveformGroup* m_group;

@@ -229,25 +256,16 @@ class WaveformArea : public Gtk::GLArea
//Trace rendering
void RenderTrace();
void InitializeWaveformPass();
size_t m_waveformLength;
std::vector<float> m_traceBuffer;
float m_xoff;
bool PrepareGeometry();

//New trace rendering path
void PrepareGeometry(WaveformRenderData* wdata);
Program m_waveformComputeProgram;
std::vector<uint32_t> m_indexBuffer;
ShaderStorageBuffer m_waveformStorageBuffer;
ShaderStorageBuffer m_waveformConfigBuffer;
ShaderStorageBuffer m_waveformIndexBuffer;
WaveformRenderData* m_waveformRenderData;

//Color correction
void RenderTraceColorCorrection();
void InitializeColormapPass();
VertexArray m_colormapVAO;
VertexBuffer m_colormapVBO;
Program m_colormapProgram;
Texture m_waveformTextureResolved;

//Persistence
void RenderPersistenceOverlay();
@@ -356,9 +374,7 @@ class WaveformArea : public Gtk::GLArea
DRAG_CURSOR
} m_dragState;

bool m_geometryDirty;
bool m_firstFrame;
bool m_geometryOK;
};

#endif
4 changes: 2 additions & 2 deletions glscopeclient/WaveformArea_events.cpp
Original file line number Diff line number Diff line change
@@ -71,8 +71,8 @@ void WaveformArea::on_resize(int width, int height)
LogNotice("resize 2, err = %x\n", err);

//Allocate waveform texture
m_waveformTextureResolved.Bind();
m_waveformTextureResolved.SetData(width, height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA32F);
m_waveformRenderData->m_waveformTexture.Bind();
m_waveformRenderData->m_waveformTexture.SetData(width, height, NULL, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA32F);
ResetTextureFiltering();

SetGeometryDirty();
81 changes: 39 additions & 42 deletions glscopeclient/WaveformArea_rendering.cpp
Original file line number Diff line number Diff line change
@@ -50,46 +50,44 @@ using namespace glm;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rendering

bool WaveformArea::PrepareGeometry()
void WaveformArea::PrepareGeometry(WaveformRenderData* wdata)
{
//Look up some configuration and update the X axis offset
auto pdat = dynamic_cast<AnalogCapture*>(m_channel->GetData());
if(!pdat)
return false;
AnalogCapture& data = *pdat;
m_xoff = (pdat->m_triggerPhase - m_group->m_xAxisOffset) * m_group->m_pixelsPerXUnit;
size_t count = data.size();
if(count == 0)
return false;

//Early out if nothing has changed.
//glBufferData() and tesselation are expensive, only do them if changing LOD or new waveform data
//if(!m_geometryDirty)
// return true;

double start = GetTime();

//TODO: support digital channels
auto channel = wdata->m_channel;
auto pdat = dynamic_cast<AnalogCapture*>(channel->GetData());
if(!pdat || (pdat->size() == 0))
{
wdata->m_geometryOK = false;
return;
}

size_t count = pdat->size();
double xscale = pdat->m_timescale * m_group->m_pixelsPerXUnit;
float xoff = (pdat->m_triggerPhase - m_group->m_xAxisOffset) * m_group->m_pixelsPerXUnit;

bool fft = IsFFT();

//Calculate X/Y coordinate of each sample point
//TODO: some of this can probably move to GPU too?
m_traceBuffer.resize(count*2);
m_indexBuffer.resize(m_width);
m_waveformLength = count;
double offset = m_channel->GetOffset();
vector<float> traceBuffer;
vector<uint32_t> indexBuffer;
traceBuffer.resize(count*2);
indexBuffer.resize(m_width);
double offset = channel->GetOffset();
#pragma omp parallel for num_threads(8)
for(size_t j=0; j<count; j++)
{
m_traceBuffer[j*2] = data.GetSampleStart(j) * xscale + m_xoff;
traceBuffer[j*2] = pdat->GetSampleStart(j) * xscale + xoff;

float y;
if(fft)
y = DbToYPosition(-70 - (20 * log10(data[j]))); //TODO: don't hard code plot limits
y = DbToYPosition(-70 - (20 * log10((*pdat)[j]))); //TODO: don't hard code plot limits
else
y = (m_pixelsPerVolt * (data[j] + offset)) + m_height/2;
y = (m_pixelsPerVolt * ((*pdat)[j] + offset)) + m_height/2;

m_traceBuffer[j*2 + 1] = y;
traceBuffer[j*2 + 1] = y;
}

double dt = GetTime() - start;
@@ -104,17 +102,17 @@ bool WaveformArea::PrepareGeometry()
for(int j=0; j<m_width; j++)
{
//Default to drawing nothing
m_indexBuffer[j] = count;
indexBuffer[j] = count;

//Move forward until we find a sample that starts in the current column
for(; nsample < count-1; nsample ++)
{
//If the next sample ends after the start of the current pixel. stop
float end = m_traceBuffer[(nsample+1)*2];
float end = traceBuffer[(nsample+1)*2];
if(end >= j)
{
//Start the current column at this sample
m_indexBuffer[j] = nsample;
indexBuffer[j] = nsample;
break;
}
}
@@ -125,27 +123,26 @@ bool WaveformArea::PrepareGeometry()
start = GetTime();

//Download it
m_waveformStorageBuffer.Bind();
glBufferData(GL_SHADER_STORAGE_BUFFER, m_traceBuffer.size()*sizeof(float), &m_traceBuffer[0], GL_STREAM_DRAW);
wdata->m_waveformStorageBuffer.Bind();
glBufferData(GL_SHADER_STORAGE_BUFFER, traceBuffer.size()*sizeof(float), &traceBuffer[0], GL_STREAM_DRAW);

//Config stuff
uint32_t config[4];
config[0] = m_height; //windowHeight
config[1] = m_plotRight; //windowWidth
config[2] = count; //depth
config[3] = m_parent->GetTraceAlpha() * 256; //alpha
m_waveformConfigBuffer.Bind();
wdata->m_waveformConfigBuffer.Bind();
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(config), config, GL_STREAM_DRAW);

//Indexing
m_waveformIndexBuffer.Bind();
glBufferData(GL_SHADER_STORAGE_BUFFER, m_indexBuffer.size()*sizeof(uint32_t), &m_indexBuffer[0], GL_STREAM_DRAW);
wdata->m_waveformIndexBuffer.Bind();
glBufferData(GL_SHADER_STORAGE_BUFFER, indexBuffer.size()*sizeof(uint32_t), &indexBuffer[0], GL_STREAM_DRAW);

dt = GetTime() - start;
m_downloadTime += dt;

m_geometryDirty = false;
return true;
wdata->m_geometryOK = true;
}

void WaveformArea::ResetTextureFiltering()
@@ -200,8 +197,8 @@ bool WaveformArea::on_render(const Glib::RefPtr<Gdk::GLContext>& /*context*/)
//Download the waveform to the GPU and kick off the compute shader for rendering it
if(IsAnalog())
{
m_geometryOK = PrepareGeometry();
if(m_geometryOK)
PrepareGeometry(m_waveformRenderData);
if(m_waveformRenderData->m_geometryOK)
RenderTrace();
}

@@ -218,7 +215,7 @@ bool WaveformArea::on_render(const Glib::RefPtr<Gdk::GLContext>& /*context*/)
RenderEye();
else if(IsWaterfall())
RenderWaterfall();
else if(m_geometryOK)
else if(m_waveformRenderData->m_geometryOK)
RenderTraceColorCorrection();
glDisable(GL_SCISSOR_TEST);
RenderCairoOverlays();
@@ -333,10 +330,10 @@ void WaveformArea::RenderTrace()
int numGroups = numCols / localSize;

m_waveformComputeProgram.Bind();
m_waveformComputeProgram.SetImageUniform(m_waveformTextureResolved, "outputTex");
m_waveformStorageBuffer.BindBase(1);
m_waveformConfigBuffer.BindBase(2);
m_waveformIndexBuffer.BindBase(3);
m_waveformComputeProgram.SetImageUniform(m_waveformRenderData->m_waveformTexture, "outputTex");
m_waveformRenderData->m_waveformStorageBuffer.BindBase(1);
m_waveformRenderData->m_waveformConfigBuffer.BindBase(2);
m_waveformRenderData->m_waveformIndexBuffer.BindBase(3);
m_waveformComputeProgram.DispatchCompute(numGroups, 1, 1);
}

@@ -407,7 +404,7 @@ void WaveformArea::RenderTraceColorCorrection()
//Draw the offscreen buffer to the onscreen buffer
//as a textured quad. Apply color correction as we do this.
Gdk::Color color(m_channel->m_displaycolor);
m_colormapProgram.SetUniform(m_waveformTextureResolved, "fbtex");
m_colormapProgram.SetUniform(m_waveformRenderData->m_waveformTexture, "fbtex");
m_colormapProgram.SetUniform(color.get_red_p(), "r");
m_colormapProgram.SetUniform(color.get_green_p(), "g");
m_colormapProgram.SetUniform(color.get_blue_p(), "b");