diff --git a/game/graphics/opengl_renderer/background/Shrub.cpp b/game/graphics/opengl_renderer/background/Shrub.cpp index 6e169374bf..d3c4165813 100644 --- a/game/graphics/opengl_renderer/background/Shrub.cpp +++ b/game/graphics/opengl_renderer/background/Shrub.cpp @@ -93,6 +93,8 @@ void Shrub::update_load(const Loader::LevelData* loader_data) { m_trees[l_tree].draws = &tree.static_draws; m_trees[l_tree].colors = &tree.time_of_day_colors; m_trees[l_tree].tod_cache = swizzle_time_of_day(tree.time_of_day_colors); + m_trees[l_tree].indices_debug = tree.indices.data(); + m_trees[l_tree].index_count = tree.indices.size(); glBindBuffer(GL_ARRAY_BUFFER, m_trees[l_tree].vertex_buffer); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); @@ -271,9 +273,13 @@ void Shrub::render_tree(int idx, tree.perf.draws++; tree.perf.verts += draw_size; - DrawCall::multi_draw_elements( + // DrawCall::multi_draw_elements( + // GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, + // &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.indices_debug); switch (double_draw.kind) { case DoubleDrawKind::NONE: @@ -288,9 +294,10 @@ void Shrub::render_tree(int idx, glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::SHRUB].id(), "alpha_max"), double_draw.aref_second); glDepthMask(GL_FALSE); - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.indices_debug); break; default: ASSERT(false); diff --git a/game/graphics/opengl_renderer/background/Shrub.h b/game/graphics/opengl_renderer/background/Shrub.h index d330fbb76b..1506ef0e9a 100644 --- a/game/graphics/opengl_renderer/background/Shrub.h +++ b/game/graphics/opengl_renderer/background/Shrub.h @@ -33,10 +33,12 @@ class Shrub : public BucketRenderer { GLuint time_of_day_texture; GLuint vao; u32 vert_count; + u32 index_count; const std::vector* draws = nullptr; const std::vector* instance_info = nullptr; const std::vector* colors = nullptr; SwizzledTimeOfDay tod_cache; + const u32* indices_debug = nullptr; struct { u32 verts = 0; diff --git a/game/graphics/opengl_renderer/background/Tfrag3.cpp b/game/graphics/opengl_renderer/background/Tfrag3.cpp index 99e868f633..63f9a13320 100644 --- a/game/graphics/opengl_renderer/background/Tfrag3.cpp +++ b/game/graphics/opengl_renderer/background/Tfrag3.cpp @@ -77,6 +77,8 @@ void Tfrag3::update_load(const std::vector& tree_kind tree_cache.colors = &tree.colors; tree_cache.vis = &tree.bvh; tree_cache.tod_cache = swizzle_time_of_day(tree.colors); + tree_cache.index_count = tree.unpacked.indices.size(); + tree_cache.indices_debug = tree.unpacked.indices.data(); vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size()); glBindBuffer(GL_ARRAY_BUFFER, tree_cache.vertex_buffer); // glBufferData(GL_ARRAY_BUFFER, verts * sizeof(tfrag3::PreloadedVertex), @@ -225,9 +227,10 @@ void Tfrag3::render_tree(int geom, prof.add_draw_call(); - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.indices_debug); switch (double_draw.kind) { case DoubleDrawKind::NONE: @@ -240,9 +243,10 @@ void Tfrag3::render_tree(int geom, glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"), double_draw.aref_second); glDepthMask(GL_FALSE); - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.indices_debug); break; default: ASSERT(false); diff --git a/game/graphics/opengl_renderer/background/Tfrag3.h b/game/graphics/opengl_renderer/background/Tfrag3.h index e79aad3301..fd475105a7 100644 --- a/game/graphics/opengl_renderer/background/Tfrag3.h +++ b/game/graphics/opengl_renderer/background/Tfrag3.h @@ -63,6 +63,8 @@ class Tfrag3 { GLuint time_of_day_texture; GLuint vao; u32 vert_count = 0; + u32 index_count = 0; + const u32* indices_debug; const std::vector* draws = nullptr; const std::vector* colors = nullptr; const tfrag3::BVH* vis = nullptr; diff --git a/game/graphics/opengl_renderer/background/Tie3.cpp b/game/graphics/opengl_renderer/background/Tie3.cpp index 957dfe2b2f..cf392827d7 100644 --- a/game/graphics/opengl_renderer/background/Tie3.cpp +++ b/game/graphics/opengl_renderer/background/Tie3.cpp @@ -56,6 +56,8 @@ void Tie3::update_load(const Loader::LevelData* loader_data) { lod_tree[l_tree].vis = &tree.bvh; lod_tree[l_tree].instance_info = &tree.wind_instance_info; lod_tree[l_tree].wind_draws = &tree.instanced_wind_draws; + lod_tree[l_tree].index_count = tree.unpacked.indices.size(); + lod_tree[l_tree].index_debug = tree.unpacked.indices.data(); vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size()); lod_tree[l_tree].tod_cache = swizzle_time_of_day(tree.colors); glBindBuffer(GL_ARRAY_BUFFER, lod_tree[l_tree].vertex_buffer); @@ -589,9 +591,10 @@ void Tie3::render_tree(int idx, tree.perf.draws++; tree.perf.verts += draw_size; - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.index_debug); switch (double_draw.kind) { case DoubleDrawKind::NONE: @@ -606,9 +609,10 @@ void Tie3::render_tree(int idx, glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"), double_draw.aref_second); glDepthMask(GL_FALSE); - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.index_debug); break; default: ASSERT(false); @@ -628,9 +632,10 @@ void Tie3::render_tree(int idx, settings.fog.x()); glDisable(GL_BLEND); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - DrawCall::multi_draw_elements( + DrawCall::multi_draw_elements_verify( GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first], GL_UNSIGNED_INT, - &m_cache.multidraw_index_offset_buffer[indices.first], indices.second); + &m_cache.multidraw_index_offset_buffer[indices.first], indices.second, tree.index_count, + tree.vert_count, tree.index_debug); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); prof.add_draw_call(); prof.add_tri(draw_size); diff --git a/game/graphics/opengl_renderer/background/Tie3.h b/game/graphics/opengl_renderer/background/Tie3.h index ede3d5ec68..e9ef97bda2 100644 --- a/game/graphics/opengl_renderer/background/Tie3.h +++ b/game/graphics/opengl_renderer/background/Tie3.h @@ -54,6 +54,8 @@ class Tie3 : public BucketRenderer { GLuint time_of_day_texture; GLuint vao; u32 vert_count; + u32 index_count; + const u32* index_debug; const std::vector* draws = nullptr; const std::vector* wind_draws = nullptr; const std::vector* instance_info = nullptr; diff --git a/game/graphics/opengl_renderer/opengl_utils.cpp b/game/graphics/opengl_renderer/opengl_utils.cpp index 842b5d4bfd..f4b3d002bf 100644 --- a/game/graphics/opengl_renderer/opengl_utils.cpp +++ b/game/graphics/opengl_renderer/opengl_utils.cpp @@ -166,7 +166,48 @@ void multi_draw_elements(u32 kind, for (u32 i = 0; i < draw_count; i++) { ASSERT(counts[i] > 0); } - glMultiDrawElements(kind, counts, index_kind, index_offsets, draw_count); + // glMultiDrawElements(kind, counts, index_kind, index_offsets, draw_count); + for (u32 i = 0; i < draw_count; i++) { + glDrawElements(kind, counts[i], index_kind, index_offsets[i]); + } +} + +void multi_draw_elements_verify(u32 kind, + GLsizei* counts, + u32 index_kind, + void** index_offsets, + u32 draw_count, + u32 idx_buffer_len, + u32 vert_buffer_len, + const u32* idx_buffer_data) { + ASSERT(draw_count > 0); // should have at least 1 draw + + for (u32 draw_idx = 0; draw_idx < draw_count; draw_idx++) { + u64 offset = (u64)(index_offsets[draw_idx]); + s64 count = counts[draw_idx]; + ASSERT(count >= 0); + ASSERT((offset % 4) == 0); // should be aligned + offset /= 4; + ASSERT(offset < idx_buffer_len); + ASSERT(offset + count <= idx_buffer_len); + + for (int idx = 0; idx < count; idx++) { + u32 val = idx_buffer_data[offset + idx]; + if (val == UINT32_MAX) { + + } else if (val >= vert_buffer_len) { + fmt::print("Verify index failed in multi_draw_elements_verify\n"); + fmt::print(" draw {} / {}\n", draw_idx, draw_count); + fmt::print(" indices: {} to {}\n", offset, offset + count); + fmt::print(" index {} of draw ({} in buffer)\n", idx, offset + idx); + fmt::print(" index value: {}\n", idx_buffer_data[offset + idx]); + fmt::print(" vertex buffer length: {}\n", vert_buffer_len); + ASSERT(false); + } + } + } + + multi_draw_elements(kind, counts, index_kind, index_offsets, draw_count); } } // namespace DrawCall \ No newline at end of file diff --git a/game/graphics/opengl_renderer/opengl_utils.h b/game/graphics/opengl_renderer/opengl_utils.h index 71028fed08..eafba192a4 100644 --- a/game/graphics/opengl_renderer/opengl_utils.h +++ b/game/graphics/opengl_renderer/opengl_utils.h @@ -65,4 +65,12 @@ void multi_draw_elements(u32 kind, u32 index_kind, void** index_offsets, u32 draw_count); +void multi_draw_elements_verify(u32 kind, + GLsizei* counts, + u32 index_kind, + void** index_offsets, + u32 draw_count, + u32 idx_buffer_len, + u32 vert_buffer_len, + const u32* idx_buffer_data); } // namespace DrawCall \ No newline at end of file