Created
April 25, 2020 12:15
-
-
Save thedmd/e384a83c0fe9e82ec0f69c869510ad44 to your computer and use it in GitHub Desktop.
ImDrawListSplitter::Merge - corrupted data in buffer (64k+ vertices) with 16-bits indices #3129
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static bool randomize = false; | |
static int vtx_count = 64790; | |
static int map[100000 / 4]; | |
static int rev_map[100000 / 4]; | |
# include <random> | |
ImDrawList* ShowBackendCheckerWindow(bool* p_open, int* p_vertex_delta) | |
{ | |
ImDrawList* draw_list = nullptr; | |
int dummy_vertex_delta = 0; | |
int& vertex_delta = p_vertex_delta ? *p_vertex_delta : dummy_vertex_delta; | |
vertex_delta = 0; | |
if (!ImGui::Begin("Dear ImGui Backend Checker##1", p_open)) | |
{ | |
ImGui::End(); | |
return draw_list; | |
} | |
ImGuiIO& io = ImGui::GetIO(); | |
ImGui::Text("Dear ImGui %s Backend Checker", ImGui::GetVersion()); | |
ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL"); | |
ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL"); | |
ImGui::Separator(); | |
if (ImGui::TreeNodeEx("0001: Renderer: Large Mesh Support", ImGuiTreeNodeFlags_DefaultOpen)) | |
{ | |
draw_list = ImGui::GetWindowDrawList(); | |
{ | |
auto* draw_list = ImGui::GetWindowDrawList(); | |
int start_vertex_count = draw_list->VtxBuffer.Size; | |
ImDrawListSplitter splitter; | |
splitter.Split(draw_list, 100000 / 4); | |
ImVec2 p = ImGui::GetCursorScreenPos(); | |
for (int n = 0; n < vtx_count / 4; n++) | |
{ | |
splitter.SetCurrentChannel(draw_list, map[n]); | |
float off_x = (float)(n % 100) * 3.0f; | |
float off_y = (float)(n % 100) * 1.0f; | |
ImU32 col = IM_COL32(((n * 17) & 255), ((n * 59) & 255), ((n * 83) & 255), 255); | |
draw_list->AddRectFilled(ImVec2(p.x + off_x, p.y + off_y), ImVec2(p.x + off_x + 50, p.y + off_y + 50), col); | |
} | |
splitter.Merge(draw_list); | |
int end_vertex_count = draw_list->VtxBuffer.Size; | |
vertex_delta = end_vertex_count - start_vertex_count; | |
ImGui::Dummy(ImVec2(300 + 50, 100 + 50)); | |
ImGui::Text("VtxBuffer.Size = %d", draw_list->VtxBuffer.Size); | |
} | |
ImGui::TreePop(); | |
} | |
ImGui::End(); | |
return draw_list; | |
} | |
ImDrawList* ShowBackendCheckerWindow_NoSplitter(bool* p_open, int* p_vertex_delta) | |
{ | |
ImDrawList* draw_list = nullptr; | |
int dummy_vertex_delta = 0; | |
int& vertex_delta = p_vertex_delta ? *p_vertex_delta : dummy_vertex_delta; | |
vertex_delta = 0; | |
if (!ImGui::Begin("Dear ImGui Backend Checker##2", p_open)) | |
{ | |
ImGui::End(); | |
return draw_list; | |
} | |
ImGuiIO& io = ImGui::GetIO(); | |
ImGui::Text("Dear ImGui %s Backend Checker", ImGui::GetVersion()); | |
ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL"); | |
ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL"); | |
ImGui::Separator(); | |
if (ImGui::TreeNodeEx("0001: Renderer: Large Mesh Support", ImGuiTreeNodeFlags_DefaultOpen)) | |
{ | |
draw_list = ImGui::GetWindowDrawList(); | |
{ | |
auto* draw_list = ImGui::GetWindowDrawList(); | |
int start_vertex_count = draw_list->VtxBuffer.Size; | |
ImVec2 p = ImGui::GetCursorScreenPos(); | |
for (int i = 0; i < vtx_count / 4; i++) | |
{ | |
int n = randomize ? rev_map[i] : i; | |
float off_x = (float)(n % 100) * 3.0f; | |
float off_y = (float)(n % 100) * 1.0f; | |
ImU32 col = IM_COL32(((n * 17) & 255), ((n * 59) & 255), ((n * 83) & 255), 255); | |
draw_list->AddRectFilled(ImVec2(p.x + off_x, p.y + off_y), ImVec2(p.x + off_x + 50, p.y + off_y + 50), col); | |
} | |
int end_vertex_count = draw_list->VtxBuffer.Size; | |
vertex_delta = end_vertex_count - start_vertex_count; | |
ImGui::Dummy(ImVec2(300 + 50, 100 + 50)); | |
ImGui::Text("VtxBuffer.Size = %d", draw_list->VtxBuffer.Size); | |
} | |
ImGui::TreePop(); | |
} | |
ImGui::End(); | |
return draw_list; | |
} | |
void TestSplitterBug() | |
{ | |
auto& io = ImGui::GetIO(); | |
ImGui::SliderInt("VtxCount##1", &vtx_count, 0, 100000); | |
if (ImGui::Button("-10", ImVec2(50.0f, 0.0f))) | |
vtx_count -= 10; | |
ImGui::SameLine(); | |
if (ImGui::Button("-1", ImVec2(50.0f, 0.0f))) | |
vtx_count -= 1; | |
ImGui::SameLine(); | |
if (ImGui::Button("+1", ImVec2(50.0f, 0.0f))) | |
vtx_count += 1; | |
ImGui::SameLine(); | |
if (ImGui::Button("+10", ImVec2(50.0f, 0.0f))) | |
vtx_count += 10; | |
vtx_count = ImMax(ImMin(vtx_count, 100000), 0); | |
ImGui::SameLine(); | |
if (ImGui::Button("Copy", ImVec2(50.0f, 0.0f))) | |
{ | |
char buffer[64]; | |
_itoa_s(vtx_count, buffer, 10); | |
ImGui::SetClipboardText(buffer); | |
} | |
ImGui::SameLine(); | |
ImGui::Checkbox("Randomize", &randomize); | |
for (int n = 0; n < vtx_count / 4; n++) | |
map[n] = n; | |
if (randomize) | |
{ | |
std::srand(13); | |
std::random_shuffle(&map[0], &map[vtx_count / 4], [](auto n) { return std::rand() % n; }); | |
for (int i = 0; i < vtx_count / 4; ++i) | |
rev_map[map[i]] = i; | |
} | |
ImGui::Spacing(); | |
ImGui::Spacing(); | |
ImGui::Spacing(); | |
int vertex_delta_a = 0; | |
int vertex_delta_b = 0; | |
ImGui::SetNextWindowPos(ImVec2(700, 100)); | |
auto draw_list_a = ShowBackendCheckerWindow(nullptr, &vertex_delta_a); | |
ImGui::SetNextWindowPos(ImVec2(1200, 100)); | |
auto draw_list_b = ShowBackendCheckerWindow_NoSplitter(nullptr, &vertex_delta_b); | |
if (!draw_list_a || !draw_list_b) | |
return; | |
ImGui::Spacing(); | |
ImGui::Spacing(); | |
ImGui::Spacing(); | |
const int table_width = 600.0f; | |
ImGui::PushItemWidth(table_width); | |
auto work_rect_max_x = ImGui::GetCurrentWindow()->WorkRect.Max.x; | |
ImGui::GetCurrentWindow()->WorkRect.Max.x = table_width; | |
ImGui::GetCurrentWindow()->Size.x -= work_rect_max_x - table_width; | |
ImGui::Columns(3); | |
ImGui::NextColumn(); | |
ImGui::Text("Splitter"); | |
ImGui::NextColumn(); | |
ImGui::Text("No Splitter"); | |
ImGui::Separator(); ImGui::NextColumn(); | |
ImGui::Text("VtxCount"); | |
ImGui::NextColumn(); | |
ImGui::Text("%d", draw_list_a->VtxBuffer.Size); | |
ImGui::Text("%d (delta)", vertex_delta_a); | |
ImGui::NextColumn(); | |
ImGui::Text("%d", draw_list_b->VtxBuffer.Size); | |
ImGui::Text("%d (delta)", vertex_delta_b); | |
ImGui::Separator(); ImGui::NextColumn(); | |
ImGui::Text("Commands"); | |
ImGui::NextColumn(); | |
ImGui::Text("%d", draw_list_a->CmdBuffer.Size); | |
ImGui::NextColumn(); | |
ImGui::Text("%d", draw_list_b->CmdBuffer.Size); | |
ImGui::Separator(); ImGui::NextColumn(); | |
auto max_cmd_buffers = ImMax(draw_list_a->CmdBuffer.Size, draw_list_b->CmdBuffer.Size); | |
for (int i = 0; i < max_cmd_buffers; ++i) | |
{ | |
ImGui::Text("Command Buffer %d", i); | |
ImGui::NextColumn(); | |
if (i < draw_list_a->CmdBuffer.Size) | |
{ | |
auto& cmd_buffer = draw_list_a->CmdBuffer[i]; | |
ImGui::Text("ElemCount %d", cmd_buffer.ElemCount); | |
ImGui::Text("VtxOffset %d", cmd_buffer.VtxOffset); | |
} | |
ImGui::NextColumn(); | |
if (i < draw_list_b->CmdBuffer.Size) | |
{ | |
auto& cmd_buffer = draw_list_b->CmdBuffer[i]; | |
ImGui::Text("ElemCount %d", cmd_buffer.ElemCount); | |
ImGui::Text("VtxOffset %d", cmd_buffer.VtxOffset); | |
} | |
ImGui::Separator(); ImGui::NextColumn(); | |
} | |
ImGui::GetCurrentWindow()->WorkRect.Max.x = work_rect_max_x; | |
ImGui::GetCurrentWindow()->Size.x += work_rect_max_x - table_width; | |
ImGui::Columns(); | |
ImGui::PopItemWidth(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment