toggle for old format

This commit is contained in:
water
2022-04-03 13:56:45 -04:00
parent 4310bb1419
commit 2e31c9f09b
10 changed files with 347 additions and 114 deletions
@@ -42,6 +42,7 @@ struct SharedRenderState {
bool use_generic2 = true;
math::Vector<u8, 4> fog_color;
float fog_intensity = 1.f;
bool no_multidraw = false;
void reset();
bool has_camera_planes = false;
@@ -366,6 +366,7 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
void OpenGLRenderer::draw_renderer_selection_window() {
ImGui::Begin("Renderer Debug");
ImGui::Checkbox("Use old single-draw", &m_render_state.no_multidraw);
ImGui::SliderFloat("Fog Adjust", &m_render_state.fog_intensity, 0, 10);
ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu);
ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling);
@@ -70,6 +70,7 @@ void Shrub::update_load(const Loader::LevelData* loader_data) {
size_t max_draws = 0;
size_t time_of_day_count = 0;
size_t max_num_grps = 0;
size_t max_inds = 0;
for (u32 l_tree = 0; l_tree < lev_data->shrub_trees.size(); l_tree++) {
size_t num_grps = 0;
@@ -84,6 +85,7 @@ void Shrub::update_load(const Loader::LevelData* loader_data) {
max_num_grps = std::max(max_num_grps, num_grps);
time_of_day_count = std::max(tree.time_of_day_colors.size(), time_of_day_count);
max_inds = std::max(tree.indices.size(), max_inds);
u32 verts = tree.unpacked.vertices.size();
glGenVertexArrays(1, &m_trees[l_tree].vao);
glBindVertexArray(m_trees[l_tree].vao);
@@ -91,6 +93,7 @@ void Shrub::update_load(const Loader::LevelData* loader_data) {
m_trees[l_tree].vert_count = verts;
m_trees[l_tree].draws = &tree.static_draws;
m_trees[l_tree].colors = &tree.time_of_day_colors;
m_trees[l_tree].index_data = tree.indices.data();
m_trees[l_tree].tod_cache = swizzle_time_of_day(tree.time_of_day_colors);
glBindBuffer(GL_ARRAY_BUFFER, m_trees[l_tree].vertex_buffer);
glEnableVertexAttribArray(0);
@@ -129,6 +132,7 @@ void Shrub::update_load(const Loader::LevelData* loader_data) {
(void*)offsetof(tfrag3::ShrubGpuVertex, color_index) // offset (0)
);
glGenBuffers(1, &m_trees[l_tree].single_draw_index_buffer);
glGenBuffers(1, &m_trees[l_tree].index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_trees[l_tree].index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, tree.indices.size() * sizeof(u32), tree.indices.data(),
@@ -148,6 +152,8 @@ void Shrub::update_load(const Loader::LevelData* loader_data) {
m_cache.multidraw_offset_per_stripdraw.resize(max_draws);
m_cache.multidraw_count_buffer.resize(max_num_grps);
m_cache.multidraw_index_offset_buffer.resize(max_num_grps);
m_cache.draw_idx_temp.resize(max_draws);
m_cache.index_temp.resize(max_inds);
ASSERT(time_of_day_count <= TIME_OF_DAY_COLOR_COUNT);
}
@@ -185,6 +191,7 @@ void Shrub::discard_tree_cache() {
glBindTexture(GL_TEXTURE_1D, tree.time_of_day_texture);
glDeleteTextures(1, &tree.time_of_day_texture);
glDeleteBuffers(1, &tree.index_buffer);
glDeleteBuffers(1, &tree.single_draw_index_buffer);
glDeleteVertexArrays(1, &tree.vao);
}
@@ -206,7 +213,6 @@ void Shrub::render_tree(int idx,
Timer tree_timer;
auto& tree = m_trees.at(idx);
tree.perf.draws = 0;
tree.perf.verts = 0;
tree.perf.wind_draws = 0;
if (!m_has_level) {
return;
@@ -230,7 +236,8 @@ void Shrub::render_tree(int idx,
glBindVertexArray(tree.vao);
glBindBuffer(GL_ARRAY_BUFFER, tree.vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tree.index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
render_state->no_multidraw ? tree.single_draw_index_buffer : tree.index_buffer);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(UINT32_MAX);
@@ -240,9 +247,16 @@ void Shrub::render_tree(int idx,
tree.perf.cull_time.add(0);
Timer index_timer;
make_all_visible_multidraws(m_cache.multidraw_offset_per_stripdraw.data(),
m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws);
if (render_state->no_multidraw) {
u32 idx_buffer_size = make_all_visible_index_list(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, tree.index_data);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size * sizeof(u32), m_cache.index_temp.data(),
GL_STREAM_DRAW);
} else {
make_all_visible_multidraws(m_cache.multidraw_offset_per_stripdraw.data(),
m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws);
}
tree.perf.index_time.add(index_timer.getSeconds());
@@ -250,10 +264,17 @@ void Shrub::render_tree(int idx,
for (size_t draw_idx = 0; draw_idx < tree.draws->size(); draw_idx++) {
const auto& draw = tree.draws->operator[](draw_idx);
const auto& indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& multidraw_indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& singledraw_indices = m_cache.draw_idx_temp[draw_idx];
if (indices.second == 0) {
continue;
if (render_state->no_multidraw) {
if (singledraw_indices.second == 0) {
continue;
}
} else {
if (multidraw_indices.second == 0) {
continue;
}
}
if ((int)draw.tree_tex_id != last_texture) {
@@ -262,34 +283,42 @@ void Shrub::render_tree(int idx,
}
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::SHRUB);
int draw_size = indices.second - indices.first;
prof.add_draw_call();
prof.add_tri(draw.num_triangles);
tree.perf.draws++;
tree.perf.verts += draw_size;
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(GL_TRIANGLE_STRIP,
&m_cache.multidraw_count_buffer[multidraw_indices.first], GL_UNSIGNED_INT,
&m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
switch (double_draw.kind) {
case DoubleDrawKind::NONE:
break;
case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE:
tree.perf.draws++;
tree.perf.verts += draw_size;
prof.add_draw_call();
prof.add_tri(draw_size);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::SHRUB].id(), "alpha_min"),
-10.f);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::SHRUB].id(), "alpha_max"),
double_draw.aref_second);
glDepthMask(GL_FALSE);
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(
GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[multidraw_indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
break;
default:
ASSERT(false);
@@ -30,16 +30,17 @@ class Shrub : public BucketRenderer {
struct Tree {
GLuint vertex_buffer;
GLuint index_buffer;
GLuint single_draw_index_buffer;
GLuint time_of_day_texture;
GLuint vao;
u32 vert_count;
const std::vector<tfrag3::ShrubDraw>* draws = nullptr;
const std::vector<tfrag3::TieWindInstance>* instance_info = nullptr;
const std::vector<tfrag3::TimeOfDayColor>* colors = nullptr;
const u32* index_data = nullptr;
SwizzledTimeOfDay tod_cache;
struct {
u32 verts = 0;
u32 draws = 0;
u32 wind_draws = 0;
Filtered<float> cull_time;
@@ -62,6 +63,8 @@ class Shrub : public BucketRenderer {
bool m_has_level = false;
struct Cache {
std::vector<std::pair<int, int>> draw_idx_temp;
std::vector<u32> index_temp;
std::vector<std::pair<int, int>> multidraw_offset_per_stripdraw;
std::vector<GLsizei> multidraw_count_buffer;
std::vector<void*> multidraw_index_offset_buffer;
@@ -50,6 +50,7 @@ void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kind
size_t vis_temp_len = 0;
size_t max_draws = 0;
size_t max_num_grps = 0;
size_t max_inds = 0;
for (int geom = 0; geom < GEOM_MAX; ++geom) {
for (size_t tree_idx = 0; tree_idx < lev_data->tfrag_trees[geom].size(); tree_idx++) {
@@ -65,7 +66,7 @@ void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kind
num_grps += draw.vis_groups.size();
}
max_num_grps = std::max(max_num_grps, num_grps);
max_inds = std::max(tree.unpacked.indices.size(), max_inds);
time_of_day_count = std::max(tree.colors.size(), time_of_day_count);
u32 verts = tree.packed_vertices.vertices.size();
glGenVertexArrays(1, &tree_cache.vao);
@@ -76,6 +77,7 @@ void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kind
tree_cache.draws = &tree.draws; // todo - should we just copy this?
tree_cache.colors = &tree.colors;
tree_cache.vis = &tree.bvh;
tree_cache.index_data = tree.unpacked.indices.data();
tree_cache.tod_cache = swizzle_time_of_day(tree.colors);
vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size());
glBindBuffer(GL_ARRAY_BUFFER, tree_cache.vertex_buffer);
@@ -108,7 +110,7 @@ void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kind
sizeof(tfrag3::PreloadedVertex), // stride
(void*)offsetof(tfrag3::PreloadedVertex, color_index) // offset (0)
);
glGenBuffers(1, &tree_cache.single_draw_index_buffer);
glGenBuffers(1, &tree_cache.index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tree_cache.index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, tree.unpacked.indices.size() * sizeof(u32),
@@ -129,7 +131,8 @@ void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kind
m_cache.multidraw_offset_per_stripdraw.resize(max_draws);
m_cache.multidraw_count_buffer.resize(max_num_grps);
m_cache.multidraw_index_offset_buffer.resize(max_num_grps);
m_cache.draw_idx_temp.resize(max_draws);
m_cache.index_temp.resize(max_inds);
ASSERT(time_of_day_count <= TIME_OF_DAY_COLOR_COUNT);
}
@@ -191,7 +194,8 @@ void Tfrag3::render_tree(int geom,
glBindVertexArray(tree.vao);
glBindBuffer(GL_ARRAY_BUFFER, tree.vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tree.index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
render_state->no_multidraw ? tree.single_draw_index_buffer : tree.index_buffer);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(UINT32_MAX);
@@ -199,18 +203,34 @@ void Tfrag3::render_tree(int geom,
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, settings.occlusion_culling,
m_cache.vis_temp.data());
u32 total_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
u32 total_tris;
if (render_state->no_multidraw) {
u32 idx_buffer_size = make_index_list_from_vis_string(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, m_cache.vis_temp,
tree.index_data, &total_tris);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size * sizeof(u32), m_cache.index_temp.data(),
GL_STREAM_DRAW);
} else {
total_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
}
prof.add_tri(total_tris);
for (size_t draw_idx = 0; draw_idx < tree.draws->size(); draw_idx++) {
const auto& draw = tree.draws->operator[](draw_idx);
const auto& indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& multidraw_indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& singledraw_indices = m_cache.draw_idx_temp[draw_idx];
if (indices.second == 0) {
continue;
if (render_state->no_multidraw) {
if (singledraw_indices.second == 0) {
continue;
}
} else {
if (multidraw_indices.second == 0) {
continue;
}
}
ASSERT(m_textures);
@@ -218,31 +238,37 @@ void Tfrag3::render_tree(int geom,
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::TFRAG3);
tree.tris_this_frame += draw.num_triangles;
tree.draws_this_frame++;
int draw_size = 0;
for (int i = 0; i < indices.second; i++) {
draw_size += m_cache.multidraw_count_buffer[indices.first + i];
}
prof.add_draw_call();
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(GL_TRIANGLE_STRIP,
&m_cache.multidraw_count_buffer[multidraw_indices.first], GL_UNSIGNED_INT,
&m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
switch (double_draw.kind) {
case DoubleDrawKind::NONE:
break;
case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE:
prof.add_draw_call();
prof.add_tri(draw_size);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_min"),
-10.f);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
double_draw.aref_second);
glDepthMask(GL_FALSE);
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(
GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[multidraw_indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
break;
default:
ASSERT(false);
@@ -344,7 +370,7 @@ void Tfrag3::discard_tree_cache() {
if (tree.kind != tfrag3::TFragmentTreeKind::INVALID) {
glBindTexture(GL_TEXTURE_1D, tree.time_of_day_texture);
glDeleteTextures(1, &tree.time_of_day_texture);
// glDeleteBuffers(1, &tree.vertex_buffer);
glDeleteBuffers(1, &tree.single_draw_index_buffer);
glDeleteBuffers(1, &tree.index_buffer);
glDeleteVertexArrays(1, &tree.vao);
}
@@ -60,12 +60,14 @@ class Tfrag3 {
tfrag3::TFragmentTreeKind kind;
GLuint vertex_buffer = -1;
GLuint index_buffer = -1;
GLuint time_of_day_texture;
GLuint vao;
GLuint single_draw_index_buffer = -1;
GLuint time_of_day_texture = -1;
GLuint vao = -1;
u32 vert_count = 0;
const std::vector<tfrag3::StripDraw>* draws = nullptr;
const std::vector<tfrag3::TimeOfDayColor>* colors = nullptr;
const tfrag3::BVH* vis = nullptr;
const u32* index_data = nullptr;
SwizzledTimeOfDay tod_cache;
void reset_stats() {
@@ -83,6 +85,8 @@ class Tfrag3 {
struct Cache {
std::vector<u8> vis_temp;
std::vector<std::pair<int, int>> draw_idx_temp;
std::vector<u32> index_temp;
std::vector<std::pair<int, int>> multidraw_offset_per_stripdraw;
std::vector<GLsizei> multidraw_count_buffer;
std::vector<void*> multidraw_index_offset_buffer;
@@ -28,6 +28,7 @@ void Tie3::update_load(const Loader::LevelData* loader_data) {
size_t max_num_grps = 0;
u16 max_wind_idx = 0;
size_t time_of_day_count = 0;
size_t max_inds = 0;
for (u32 l_geo = 0; l_geo < tfrag3::TIE_GEOS; l_geo++) {
for (u32 l_tree = 0; l_tree < lev_data->tie_trees[l_geo].size(); l_tree++) {
size_t wind_idx_buffer_len = 0;
@@ -45,6 +46,7 @@ void Tie3::update_load(const Loader::LevelData* loader_data) {
max_wind_idx = std::max(max_wind_idx, inst.wind_idx);
}
time_of_day_count = std::max(tree.colors.size(), time_of_day_count);
max_inds = std::max(tree.unpacked.indices.size(), max_inds);
u32 verts = tree.packed_vertices.color_indices.size();
auto& lod_tree = m_trees.at(l_geo);
glGenVertexArrays(1, &lod_tree[l_tree].vao);
@@ -54,6 +56,7 @@ void Tie3::update_load(const Loader::LevelData* loader_data) {
lod_tree[l_tree].draws = &tree.static_draws;
lod_tree[l_tree].colors = &tree.colors;
lod_tree[l_tree].vis = &tree.bvh;
lod_tree[l_tree].index_data = tree.unpacked.indices.data();
lod_tree[l_tree].instance_info = &tree.wind_instance_info;
lod_tree[l_tree].wind_draws = &tree.instanced_wind_draws;
vis_temp_len = std::max(vis_temp_len, tree.bvh.vis_nodes.size());
@@ -86,6 +89,7 @@ void Tie3::update_load(const Loader::LevelData* loader_data) {
(void*)offsetof(tfrag3::PreloadedVertex, color_index) // offset (0)
);
glGenBuffers(1, &lod_tree[l_tree].single_draw_index_buffer);
glGenBuffers(1, &lod_tree[l_tree].index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lod_tree[l_tree].index_buffer);
// todo: move to loader, this will probably be quite slow.
@@ -121,6 +125,8 @@ void Tie3::update_load(const Loader::LevelData* loader_data) {
m_cache.multidraw_count_buffer.resize(max_num_grps);
m_cache.multidraw_index_offset_buffer.resize(max_num_grps);
m_wind_vectors.resize(4 * max_wind_idx + 4); // 4x u32's per wind.
m_cache.draw_idx_temp.resize(max_draws);
m_cache.index_temp.resize(max_inds);
ASSERT(time_of_day_count <= TIME_OF_DAY_COLOR_COUNT);
}
@@ -273,6 +279,7 @@ void Tie3::discard_tree_cache() {
glBindTexture(GL_TEXTURE_1D, tree.time_of_day_texture);
glDeleteTextures(1, &tree.time_of_day_texture);
glDeleteBuffers(1, &tree.index_buffer);
glDeleteBuffers(1, &tree.single_draw_index_buffer);
glDeleteVertexArrays(1, &tree.vao);
}
@@ -465,7 +472,6 @@ void Tie3::render_tree_wind(int idx,
tree.perf.draws++;
tree.perf.wind_draws++;
tree.perf.verts += grp.num;
glDrawElements(GL_TRIANGLE_STRIP, grp.num, GL_UNSIGNED_INT,
(void*)((off + tree.wind_vertex_index_offsets.at(draw_idx)) * sizeof(u32)));
@@ -477,7 +483,6 @@ void Tie3::render_tree_wind(int idx,
case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE:
tree.perf.draws++;
tree.perf.wind_draws++;
tree.perf.verts += grp.num;
prof.add_draw_call();
prof.add_tri(grp.num);
glUniform1f(
@@ -502,15 +507,18 @@ void Tie3::render_tree(int idx,
const TfragRenderSettings& settings,
SharedRenderState* render_state,
ScopedProfilerNode& prof) {
// reset perf
Timer tree_timer;
auto& tree = m_trees.at(geom).at(idx);
tree.perf.draws = 0;
tree.perf.verts = 0;
tree.perf.wind_draws = 0;
// don't render if we haven't loaded
if (!m_has_level) {
return;
}
// update time of day
if (m_color_result.size() < tree.colors->size()) {
m_color_result.resize(tree.colors->size());
}
@@ -529,11 +537,13 @@ void Tie3::render_tree(int idx,
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, tree.colors->size(), GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,
m_color_result.data());
// setup OpenGL shader
first_tfrag_draw_setup(settings, render_state, ShaderId::TFRAG3);
glBindVertexArray(tree.vao);
glBindBuffer(GL_ARRAY_BUFFER, tree.vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tree.index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
render_state->no_multidraw ? tree.single_draw_index_buffer : tree.index_buffer);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(UINT32_MAX);
@@ -541,25 +551,49 @@ void Tie3::render_tree(int idx,
int last_texture = -1;
u32 num_tris;
if (m_debug_all_visible) {
tree.perf.cull_time.add(0);
Timer index_timer;
num_tris = make_all_visible_multidraws(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws);
tree.perf.index_time.add(index_timer.getSeconds());
} else {
if (!m_debug_all_visible) {
// need culling data
Timer cull_timer;
cull_check_all_slow(settings.planes, tree.vis->vis_nodes, settings.occlusion_culling,
m_cache.vis_temp.data());
tree.perf.cull_time.add(cull_timer.getSeconds());
} else {
// no culling.
tree.perf.cull_time.add(0);
}
u32 num_tris;
if (render_state->no_multidraw) {
Timer index_timer;
num_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
u32 idx_buffer_size;
if (m_debug_all_visible) {
idx_buffer_size =
make_all_visible_index_list(m_cache.draw_idx_temp.data(), m_cache.index_temp.data(),
*tree.draws, tree.index_data, &num_tris);
} else {
idx_buffer_size = make_index_list_from_vis_string(
m_cache.draw_idx_temp.data(), m_cache.index_temp.data(), *tree.draws, m_cache.vis_temp,
tree.index_data, &num_tris);
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size * sizeof(u32), m_cache.index_temp.data(),
GL_STREAM_DRAW);
tree.perf.index_time.add(index_timer.getSeconds());
} else {
if (m_debug_all_visible) {
Timer index_timer;
num_tris = make_all_visible_multidraws(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws);
tree.perf.index_time.add(index_timer.getSeconds());
} else {
Timer index_timer;
num_tris = make_multidraws_from_vis_string(
m_cache.multidraw_offset_per_stripdraw.data(), m_cache.multidraw_count_buffer.data(),
m_cache.multidraw_index_offset_buffer.data(), *tree.draws, m_cache.vis_temp);
tree.perf.index_time.add(index_timer.getSeconds());
}
}
Timer draw_timer;
@@ -567,10 +601,17 @@ void Tie3::render_tree(int idx,
for (size_t draw_idx = 0; draw_idx < tree.draws->size(); draw_idx++) {
const auto& draw = tree.draws->operator[](draw_idx);
const auto& indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& multidraw_indices = m_cache.multidraw_offset_per_stripdraw[draw_idx];
const auto& singledraw_indices = m_cache.draw_idx_temp[draw_idx];
if (indices.second == 0) {
continue;
if (render_state->no_multidraw) {
if (singledraw_indices.second == 0) {
continue;
}
} else {
if (multidraw_indices.second == 0) {
continue;
}
}
if ((int)draw.tree_tex_id != last_texture) {
@@ -579,42 +620,47 @@ void Tie3::render_tree(int idx,
}
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::TFRAG3);
int draw_size = 0;
for (int i = 0; i < indices.second; i++) {
draw_size += m_cache.multidraw_count_buffer[indices.first + i];
}
prof.add_draw_call();
tree.perf.draws++;
tree.perf.verts += draw_size;
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(GL_TRIANGLE_STRIP,
&m_cache.multidraw_count_buffer[multidraw_indices.first], GL_UNSIGNED_INT,
&m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
switch (double_draw.kind) {
case DoubleDrawKind::NONE:
break;
case DoubleDrawKind::AFAIL_NO_DEPTH_WRITE:
tree.perf.draws++;
tree.perf.verts += draw_size;
prof.add_draw_call();
prof.add_tri(draw_size);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_min"),
-10.f);
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "alpha_max"),
double_draw.aref_second);
glDepthMask(GL_FALSE);
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
if (render_state->no_multidraw) {
glDrawElements(GL_TRIANGLE_STRIP, singledraw_indices.second, GL_UNSIGNED_INT,
(void*)(singledraw_indices.first * sizeof(u32)));
} else {
glMultiDrawElements(
GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[multidraw_indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
}
break;
default:
ASSERT(false);
}
if (m_debug_wireframe) {
if (m_debug_wireframe && !render_state->no_multidraw) {
render_state->shaders[ShaderId::TFRAG3_NO_TEX].activate();
glUniformMatrix4fv(
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "camera"), 1,
@@ -628,12 +674,12 @@ void Tie3::render_tree(int idx,
settings.fog.x());
glDisable(GL_BLEND);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glMultiDrawElements(GL_TRIANGLE_STRIP, &m_cache.multidraw_count_buffer[indices.first],
GL_UNSIGNED_INT, &m_cache.multidraw_index_offset_buffer[indices.first],
indices.second);
glMultiDrawElements(GL_TRIANGLE_STRIP,
&m_cache.multidraw_count_buffer[multidraw_indices.first], GL_UNSIGNED_INT,
&m_cache.multidraw_index_offset_buffer[multidraw_indices.first],
multidraw_indices.second);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
prof.add_draw_call();
prof.add_tri(draw_size);
render_state->shaders[ShaderId::TFRAG3].activate();
}
}
@@ -665,7 +711,7 @@ void Tie3::draw_debug_window() {
auto& perf = m_trees[lod()][i].perf;
ImGui::Text("Tree: %d", i);
ImGui::Text("time of days: %d", (int)m_trees[lod()][i].colors->size());
ImGui::Text("draw: %d, verts: %d", perf.draws, perf.verts);
ImGui::Text("draw: %d", perf.draws);
ImGui::Text("wind draw: %d", perf.wind_draws);
ImGui::Text("total: %.2f", perf.tree_time.get());
ImGui::Text("cull: %.2f index: %.2f tod: %.2f setup: %.2f draw: %.2f",
@@ -51,6 +51,7 @@ class Tie3 : public BucketRenderer {
struct Tree {
GLuint vertex_buffer;
GLuint index_buffer;
GLuint single_draw_index_buffer;
GLuint time_of_day_texture;
GLuint vao;
u32 vert_count;
@@ -59,6 +60,7 @@ class Tie3 : public BucketRenderer {
const std::vector<tfrag3::TieWindInstance>* instance_info = nullptr;
const std::vector<tfrag3::TimeOfDayColor>* colors = nullptr;
const tfrag3::BVH* vis = nullptr;
const u32* index_data = nullptr;
SwizzledTimeOfDay tod_cache;
std::vector<std::array<math::Vector4f, 4>> wind_matrix_cache;
@@ -68,7 +70,6 @@ class Tie3 : public BucketRenderer {
std::vector<u32> wind_vertex_index_offsets;
struct {
u32 verts = 0;
u32 draws = 0;
u32 wind_draws = 0;
Filtered<float> cull_time;
@@ -86,6 +87,8 @@ class Tie3 : public BucketRenderer {
u64 m_load_id = -1;
struct Cache {
std::vector<std::pair<int, int>> draw_idx_temp;
std::vector<u32> index_temp;
std::vector<u8> vis_temp;
std::vector<std::pair<int, int>> multidraw_offset_per_stripdraw;
std::vector<GLsizei> multidraw_count_buffer;
@@ -501,36 +501,6 @@ void make_all_visible_multidraws(std::pair<int, int>* draw_ptrs_out,
}
}
u32 make_multidraws_from_vis_string(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data) {
u64 md_idx = 0;
u32 num_tris = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
u64 iidx = draw.unpacked.idx_of_first_idx_in_full_buffer;
std::pair<int, int> ds;
ds.first = md_idx;
ds.second = 0;
for (auto& grp : draw.vis_groups) {
if (grp.vis_idx_in_pc_bvh == 0xffffffff || vis_data[grp.vis_idx_in_pc_bvh]) {
// visible!
// let's use a multidraw
counts_out[md_idx] = grp.num_inds;
index_offsets_out[md_idx] = (void*)(iidx * sizeof(u32));
ds.second++;
md_idx++;
num_tris += grp.num_tris;
}
iidx += grp.num_inds;
}
draw_ptrs_out[i] = ds;
}
return num_tris;
}
u32 make_all_visible_multidraws(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
@@ -557,3 +527,135 @@ u32 make_all_visible_multidraws(std::pair<int, int>* draw_ptrs_out,
}
return num_tris;
}
u32 make_all_visible_index_list(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::ShrubDraw>& draws,
const u32* idx_in) {
int idx_buffer_ptr = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
std::pair<int, int> ds;
ds.first = idx_buffer_ptr;
memcpy(&idx_out[idx_buffer_ptr], idx_in + draw.first_index_index,
draw.num_indices * sizeof(u32));
idx_buffer_ptr += draw.num_indices;
ds.second = idx_buffer_ptr - ds.first;
group_out[i] = ds;
}
return idx_buffer_ptr;
}
u32 make_multidraws_from_vis_string(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data) {
u64 md_idx = 0;
u32 num_tris = 0;
u32 sanity_check = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
u64 iidx = draw.unpacked.idx_of_first_idx_in_full_buffer;
ASSERT(sanity_check == iidx);
std::pair<int, int> ds;
ds.first = md_idx;
ds.second = 0;
for (auto& grp : draw.vis_groups) {
sanity_check += grp.num_inds;
if (grp.vis_idx_in_pc_bvh == 0xffffffff || vis_data[grp.vis_idx_in_pc_bvh]) {
// visible!
// let's use a multidraw
counts_out[md_idx] = grp.num_inds;
index_offsets_out[md_idx] = (void*)(iidx * sizeof(u32));
ds.second++;
md_idx++;
num_tris += grp.num_tris;
}
iidx += grp.num_inds;
}
draw_ptrs_out[i] = ds;
}
return num_tris;
}
u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const u32* idx_in,
u32* num_tris_out) {
int idx_buffer_ptr = 0;
u32 num_tris = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
int vtx_idx = 0;
std::pair<int, int> ds;
ds.first = idx_buffer_ptr;
bool building_run = false;
int run_start_out = 0;
int run_start_in = 0;
for (auto& grp : draw.vis_groups) {
bool vis = grp.vis_idx_in_pc_bvh == 0xffffffff || vis_data[grp.vis_idx_in_pc_bvh];
if (vis) {
num_tris += grp.num_tris;
}
if (building_run) {
if (vis) {
idx_buffer_ptr += grp.num_inds;
} else {
building_run = false;
memcpy(&idx_out[run_start_out],
idx_in + draw.unpacked.idx_of_first_idx_in_full_buffer + run_start_in,
(idx_buffer_ptr - run_start_out) * sizeof(u32));
}
} else {
if (vis) {
building_run = true;
run_start_out = idx_buffer_ptr;
run_start_in = vtx_idx;
idx_buffer_ptr += grp.num_inds;
}
}
vtx_idx += grp.num_inds;
}
if (building_run) {
memcpy(&idx_out[run_start_out],
idx_in + draw.unpacked.idx_of_first_idx_in_full_buffer + run_start_in,
(idx_buffer_ptr - run_start_out) * sizeof(u32));
}
ds.second = idx_buffer_ptr - ds.first;
group_out[i] = ds;
}
*num_tris_out = num_tris;
return idx_buffer_ptr;
}
u32 make_all_visible_index_list(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const u32* idx_in,
u32* num_tris_out) {
int idx_buffer_ptr = 0;
u32 num_tris = 0;
for (size_t i = 0; i < draws.size(); i++) {
const auto& draw = draws[i];
std::pair<int, int> ds;
ds.first = idx_buffer_ptr;
u32 num_inds = 0;
for (auto& grp : draw.vis_groups) {
num_inds += grp.num_inds;
num_tris += grp.num_tris;
}
memcpy(&idx_out[idx_buffer_ptr], idx_in + draw.unpacked.idx_of_first_idx_in_full_buffer,
num_inds * sizeof(u32));
idx_buffer_ptr += num_inds;
ds.second = idx_buffer_ptr - ds.first;
group_out[i] = ds;
}
*num_tris_out = num_tris;
return idx_buffer_ptr;
}
@@ -74,4 +74,22 @@ u32 make_multidraws_from_vis_string(std::pair<int, int>* draw_ptrs_out,
GLsizei* counts_out,
void** index_offsets_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data);
const std::vector<u8>& vis_data);
u32 make_all_visible_index_list(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const u32* idx_in,
u32* num_tris_out);
u32 make_index_list_from_vis_string(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::StripDraw>& draws,
const std::vector<u8>& vis_data,
const u32* idx_in,
u32* num_tris_out);
u32 make_all_visible_index_list(std::pair<int, int>* group_out,
u32* idx_out,
const std::vector<tfrag3::ShrubDraw>& draws,
const u32* idx_in);