1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-23 02:38:53 -05:00

[backends] make heatmap use ImPool, add ShowBackendMetrics, misc cleanup

This commit is contained in:
Evan Pezent 2021-07-03 11:10:35 -07:00
parent 4371c2d200
commit aa1918ff16
3 changed files with 63 additions and 63 deletions

View File

@ -37,11 +37,13 @@ namespace Backend {
#ifdef IMPLOT_BACKEND_ENABLED #ifdef IMPLOT_BACKEND_ENABLED
void* CreateContext(); void* CreateContext();
void DestroyContext(); void DestroyContext();
void ShowBackendMetrics();
void BustPlotCache(); void BustPlotCache();
void BustItemCache(); void BustItemCache();
#else #else
inline void* CreateContext() { return nullptr; } inline void* CreateContext() { return nullptr; }
inline void DestroyContext() {} inline void DestroyContext() {}
inline void ShowBackendMetrics() {}
inline void BustPlotCache() {} inline void BustPlotCache() {}
inline void BustItemCache() {} inline void BustItemCache() {}
#endif #endif

View File

@ -37,7 +37,6 @@ namespace Backend {
struct HeatmapShader struct HeatmapShader
{ {
GLuint ID = 0; ///< Shader ID for the heatmap shader GLuint ID = 0; ///< Shader ID for the heatmap shader
GLuint AttribLocationProjection = 0; ///< Attribute location for the projection matrix uniform GLuint AttribLocationProjection = 0; ///< Attribute location for the projection matrix uniform
GLuint AttribLocationMinValue = 0; ///< Attribute location for the minimum value uniform GLuint AttribLocationMinValue = 0; ///< Attribute location for the minimum value uniform
GLuint AttribLocationMaxValue = 0; ///< Attribute location for the maximum value uniform GLuint AttribLocationMaxValue = 0; ///< Attribute location for the maximum value uniform
@ -48,6 +47,7 @@ struct HeatmapShader
struct HeatmapData struct HeatmapData
{ {
ImGuiID ID;
HeatmapShader* ShaderProgram; ///< Shader to be used by this heatmap (either ShaderInt or ShaderFloat) HeatmapShader* ShaderProgram; ///< Shader to be used by this heatmap (either ShaderInt or ShaderFloat)
GLuint HeatmapTexID; ///< Texture ID of the heatmap 2D texture GLuint HeatmapTexID; ///< Texture ID of the heatmap 2D texture
GLuint ColormapTexID; ///< Texture ID of the colormap 1D texture GLuint ColormapTexID; ///< Texture ID of the colormap 1D texture
@ -57,6 +57,14 @@ struct HeatmapData
float MaxValue; ///< Maximum value of the colormap float MaxValue; ///< Maximum value of the colormap
bool AxisLogX; ///< Whether the X axis is logarithmic or not bool AxisLogX; ///< Whether the X axis is logarithmic or not
bool AxisLogY; ///< Whether the Y axis is logarithmic or not bool AxisLogY; ///< Whether the Y axis is logarithmic or not
HeatmapData() {
glGenTextures(1, &HeatmapTexID);
glBindTexture(GL_TEXTURE_2D, HeatmapTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
}; };
struct ContextData struct ContextData
@ -67,9 +75,8 @@ struct ContextData
GLuint AttribLocationImGuiProjection = 0; ///< Attribute location for the projection matrix uniform (ImGui default shader) GLuint AttribLocationImGuiProjection = 0; ///< Attribute location for the projection matrix uniform (ImGui default shader)
GLuint ImGuiShader = 0; ///< Shader ID of ImGui's default shader GLuint ImGuiShader = 0; ///< Shader ID of ImGui's default shader
ImVector<HeatmapData> HeatmapDataList; ///< Array of heatmap data ImPool<HeatmapData> Heatmaps; ///< Array of heatmap data
ImVector<GLuint> ColormapIDs; ///< Texture IDs of the colormap textures ImVector<GLuint> ColormapIDs; ///< Texture IDs of the colormap textures
ImGuiStorage ItemIDs; ///< PlotID <-> Heatmap array index table
ImVector<float> temp1; ///< Temporary data ImVector<float> temp1; ///< Temporary data
ImVector<ImS32> temp2; ///< Temporary data ImVector<ImS32> temp2; ///< Temporary data
@ -78,24 +85,21 @@ struct ContextData
void* CreateContext() void* CreateContext()
{ {
return new ContextData; return IM_NEW(ContextData)();
} }
void DestroyContext() void DestroyContext()
{ {
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData* Context = ((ContextData*)GImPlot->backendCtx);
// free OpenGL resources
for(const HeatmapData& data : Context.HeatmapDataList) for(int i = 0; i < Context->Heatmaps.GetBufSize(); ++i)
glDeleteTextures(1, &data.HeatmapTexID); glDeleteTextures(1, &Context->Heatmaps.GetByIndex(i)->HeatmapTexID);
for(GLuint texID : Context->ColormapIDs)
for(GLuint texID : Context.ColormapIDs)
glDeleteTextures(1, &texID); glDeleteTextures(1, &texID);
glDeleteProgram(Context->ShaderInt.ID);
glDeleteProgram(Context.ShaderInt.ID); glDeleteProgram(Context->ShaderFloat.ID);
glDeleteProgram(Context.ShaderFloat.ID); Context->Heatmaps.Clear();
IM_DELETE(Context);
Context.HeatmapDataList.clear();
Context.ItemIDs.Clear();
} }
#define HEATMAP_VERTEX_SHADER_CODE \ #define HEATMAP_VERTEX_SHADER_CODE \
@ -214,8 +218,7 @@ static void RenderCallback(const ImDrawList*, const ImDrawCmd* cmd)
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData& Context = *((ContextData*)GImPlot->backendCtx);
int itemID = (int)(intptr_t)cmd->UserCallbackData; int itemID = (int)(intptr_t)cmd->UserCallbackData;
int plotIdx = Context.ItemIDs.GetInt(itemID, -1); HeatmapData& data = *Context.Heatmaps.GetByKey(itemID);
HeatmapData& data = Context.HeatmapDataList[plotIdx];
// Get projection matrix of current shader // Get projection matrix of current shader
float OrthoProjection[4][4]; float OrthoProjection[4][4];
@ -239,7 +242,6 @@ static void ResetState(const ImDrawList*, const ImDrawCmd*)
{ {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData& Context = *((ContextData*)GImPlot->backendCtx);
glUseProgram(Context.ImGuiShader); glUseProgram(Context.ImGuiShader);
} }
@ -248,12 +250,10 @@ static void SetTextureData(int itemID, const void* data, GLsizei rows, GLsizei c
{ {
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData& Context = *((ContextData*)GImPlot->backendCtx);
int idx = Context.ItemIDs.GetInt(itemID, -1); HeatmapData& hm = *Context.Heatmaps.GetByKey(itemID);
GLuint texID = Context.HeatmapDataList[idx].HeatmapTexID; hm.ShaderProgram = (type == GL_FLOAT ? &Context.ShaderFloat : &Context.ShaderInt);
Context.HeatmapDataList[idx].ShaderProgram = (type == GL_FLOAT ? &Context.ShaderFloat : &Context.ShaderInt);
// Set heatmap data glBindTexture(GL_TEXTURE_2D, hm.HeatmapTexID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, cols, rows, 0, format, type, data); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, cols, rows, 0, format, type, data);
} }
@ -273,18 +273,6 @@ void AddColormap(const ImU32* keys, int count, bool qual)
Context.ColormapIDs.push_back(textureID); Context.ColormapIDs.push_back(textureID);
} }
static GLuint CreateHeatmapTexture()
{
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
return textureID;
}
void SetHeatmapData(int itemID, const ImS8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8I, GL_RED_INTEGER, GL_BYTE); } void SetHeatmapData(int itemID, const ImS8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8I, GL_RED_INTEGER, GL_BYTE); }
void SetHeatmapData(int itemID, const ImU8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE); } void SetHeatmapData(int itemID, const ImU8* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE); }
void SetHeatmapData(int itemID, const ImS16* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R16I, GL_RED_INTEGER, GL_SHORT); } void SetHeatmapData(int itemID, const ImS16* values, int rows, int cols) { SetTextureData(itemID, values, rows, cols, GL_R16I, GL_RED_INTEGER, GL_SHORT); }
@ -335,9 +323,7 @@ void SetHeatmapData(int itemID, const ImU64* values, int rows, int cols)
void SetAxisLog(int itemID, bool x_is_log, bool y_is_log, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max) void SetAxisLog(int itemID, bool x_is_log, bool y_is_log, const ImPlotPoint& bounds_min, const ImPlotPoint& bounds_max)
{ {
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData& Context = *((ContextData*)GImPlot->backendCtx);
int idx = Context.ItemIDs.GetInt(itemID, -1); HeatmapData& data = *Context.Heatmaps.GetByKey(itemID);
HeatmapData& data = Context.HeatmapDataList[idx];
data.AxisLogX = x_is_log; data.AxisLogX = x_is_log;
data.AxisLogY = y_is_log; data.AxisLogY = y_is_log;
data.MinBounds = bounds_min; data.MinBounds = bounds_min;
@ -347,42 +333,48 @@ void SetAxisLog(int itemID, bool x_is_log, bool y_is_log, const ImPlotPoint& bou
void RenderHeatmap(int itemID, ImDrawList& DrawList, const ImVec2& bounds_min, const ImVec2& bounds_max, float scale_min, float scale_max, ImPlotColormap colormap, bool reverse_y) void RenderHeatmap(int itemID, ImDrawList& DrawList, const ImVec2& bounds_min, const ImVec2& bounds_max, float scale_min, float scale_max, ImPlotColormap colormap, bool reverse_y)
{ {
ContextData& Context = *((ContextData*)GImPlot->backendCtx); ContextData& Context = *((ContextData*)GImPlot->backendCtx);
int idx = Context.ItemIDs.GetInt(itemID, Context.HeatmapDataList.Size); HeatmapData& data = *Context.Heatmaps.GetOrAddByKey(itemID);
data.ID = itemID;
if(idx == Context.HeatmapDataList.Size)
{
// New entry
Context.ItemIDs.SetInt(itemID, Context.HeatmapDataList.Size);
Context.HeatmapDataList.push_back(HeatmapData());
Context.HeatmapDataList[idx].HeatmapTexID = CreateHeatmapTexture();
}
HeatmapData& data = Context.HeatmapDataList[idx];
data.ColormapTexID = Context.ColormapIDs[colormap]; data.ColormapTexID = Context.ColormapIDs[colormap];
data.MinValue = scale_min; data.MinValue = scale_min;
data.MaxValue = scale_max; data.MaxValue = scale_max;
if(Context.ShaderInt.ID == 0 || Context.ShaderFloat.ID == 0) if(Context.ShaderInt.ID == 0 || Context.ShaderFloat.ID == 0)
DrawList.AddCallback(CreateHeatmapShader, nullptr); DrawList.AddCallback(CreateHeatmapShader, nullptr);
DrawList.AddCallback(RenderCallback, (void*)(intptr_t)itemID); DrawList.AddCallback(RenderCallback, (void*)(intptr_t)itemID);
DrawList.PrimReserve(6, 4); DrawList.PrimReserve(6, 4);
DrawList.PrimRectUV(bounds_min, bounds_max, ImVec2(0.0f, reverse_y ? 1.0f : 0.0f), ImVec2(1.0f, reverse_y ? 0.0f : 1.0f), 0); DrawList.PrimRectUV(bounds_min, bounds_max, ImVec2(0.0f, reverse_y ? 1.0f : 0.0f), ImVec2(1.0f, reverse_y ? 0.0f : 1.0f), 0);
DrawList.AddCallback(ResetState, nullptr); DrawList.AddCallback(ResetState, nullptr);
} }
void BustPlotCache() void BustPlotCache() {
{ BustItemCache();
ContextData& Context = *((ContextData*)GImPlot->backendCtx);
for(const HeatmapData& data : Context.HeatmapDataList)
glDeleteTextures(1, &data.HeatmapTexID);
Context.HeatmapDataList.clear();
Context.ItemIDs.Clear();
} }
void BustItemCache() {} void BustItemCache() {
ContextData* Context = ((ContextData*)GImPlot->backendCtx);
for(int i = 0; i < Context->Heatmaps.GetBufSize(); ++i)
glDeleteTextures(1, &Context->Heatmaps.GetByIndex(i)->HeatmapTexID);
Context->Heatmaps.Clear();
}
void ShowBackendMetrics() {
ContextData* Context = ((ContextData*)GImPlot->backendCtx);
// heatmaps
int n_heatmaps = Context->Heatmaps.GetBufSize();
if (ImGui::TreeNode("Heatmaps","Heatmaps (%d)",n_heatmaps)) {
for (int i = 0; i < n_heatmaps; ++i) {
HeatmapData& data = *Context->Heatmaps.GetByIndex(i);
ImGui::PushID(i);
if (ImGui::TreeNode("Item","Item [0x%08X]", data.ID)) {
ImGui::BulletText("HeatmapTexID: %u", data.HeatmapTexID);
ImGui::BulletText("ColormapTexID: %u", data.ColormapTexID);
ImGui::TreePop();
}
ImGui::PopID();
}
ImGui::TreePop();
} }
} }
} // namespace Backend
} // namespace ImPlot

View File

@ -4067,6 +4067,12 @@ void ShowMetricsWindow(bool* p_popen) {
} }
ImGui::TreePop(); ImGui::TreePop();
} }
#ifdef IMPLOT_BACKEND_ENABLED
if (ImGui::TreeNode("Backend")) {
ImPlot::Backend::ShowBackendMetrics();
ImGui::TreePop();
}
#endif
ImGui::End(); ImGui::End();
} }