mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
Report leaks after static destruction via _CRTDBG_LEAK_CHECK_DF instead of calling _CrtDumpMemoryLeaks() at the end of main(), which incorrectly reported every global container as a memory leak. Also fix the three remaining real leaks which were discovered after all the noise was cleared up: - Mc_point_list was never freed, because its atexit cleanup was only registered by code that no longer runs. But the list was only a temporary array of pointers used while building the collision tree, so remove it and have model_collide_parse_bsp_defpoints() copy the vertices directly into the tree's point list. - model_batch_buffer's Mem_alloc copy was never freed. But the copy is actually not necessary, so remove it and pass Submodel_matrices directly. - Goal_target_names strings were only freed when the next mission was parsed, so the last mission's names leaked at exit. Hold them in SCP_vm_unique_ptr so they are freed with the vector. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
151 lines
2.9 KiB
C++
151 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include "globalincs/pstypes.h"
|
|
#include "graphics/2d.h"
|
|
#include "graphics/util/UniformBuffer.h"
|
|
#include "lighting/lighting.h"
|
|
#include "math/vecmat.h"
|
|
|
|
class model_batch_buffer
|
|
{
|
|
SCP_vector<matrix4> Submodel_matrices;
|
|
|
|
size_t Current_offset = 0;
|
|
|
|
public:
|
|
void reset();
|
|
|
|
size_t get_buffer_offset() const;
|
|
void set_num_models(int n_models);
|
|
void set_model_transform(const matrix4 &transform, int model_id);
|
|
|
|
void submit_buffer_data();
|
|
|
|
void add_matrix(const matrix4 &mat);
|
|
};
|
|
|
|
template <typename Derived, typename DrawEntryT>
|
|
class render_queue {
|
|
protected:
|
|
SCP_vector<DrawEntryT> _elements;
|
|
SCP_vector<int> _keys;
|
|
transform_stack _transforms;
|
|
scene_lights _lights;
|
|
graphics::util::UniformBuffer _dataBuffer;
|
|
vec3d _scale;
|
|
inline static model_batch_buffer _batchBuffer; // shared across instances so we don't need to do the malloc again
|
|
bool _initialized = false;
|
|
|
|
public:
|
|
render_queue()
|
|
{
|
|
_scale.xyz.x = 1.0f;
|
|
_scale.xyz.y = 1.0f;
|
|
_scale.xyz.z = 1.0f;
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
_elements.clear();
|
|
_keys.clear();
|
|
_transforms.clear();
|
|
_scale.xyz.x = 1.0f;
|
|
_scale.xyz.y = 1.0f;
|
|
_scale.xyz.z = 1.0f;
|
|
_initialized = false;
|
|
_batchBuffer.reset();
|
|
}
|
|
|
|
void push_transform(const vec3d* pos, const matrix* orient)
|
|
{
|
|
_transforms.push(pos, orient);
|
|
}
|
|
|
|
void pop_transform()
|
|
{
|
|
_transforms.pop();
|
|
}
|
|
|
|
const matrix4& get_transform() const
|
|
{
|
|
return _transforms.get_transform();
|
|
}
|
|
|
|
void clear_transforms()
|
|
{
|
|
_transforms.clear();
|
|
}
|
|
|
|
void set_scale(const vec3d* s)
|
|
{
|
|
if (s == nullptr) {
|
|
_scale.xyz.x = 1.0f;
|
|
_scale.xyz.y = 1.0f;
|
|
_scale.xyz.z = 1.0f;
|
|
} else {
|
|
_scale = *s;
|
|
}
|
|
}
|
|
|
|
void start_model_batch(int n_models)
|
|
{
|
|
_batchBuffer.set_num_models(n_models);
|
|
}
|
|
|
|
void add_submodel_to_batch(int model_num)
|
|
{
|
|
matrix4 transform = _transforms.get_transform();
|
|
|
|
vm_vec_scale(&transform.vec.rvec, _scale.xyz.x);
|
|
vm_vec_scale(&transform.vec.uvec, _scale.xyz.y);
|
|
vm_vec_scale(&transform.vec.fvec, _scale.xyz.z);
|
|
|
|
transform.a1d[15] = 0.0f;
|
|
|
|
_batchBuffer.set_model_transform(transform, model_num);
|
|
}
|
|
|
|
void init_render(bool sort = true)
|
|
{
|
|
if (sort) {
|
|
self().sort_draws();
|
|
}
|
|
|
|
_batchBuffer.submit_buffer_data();
|
|
|
|
self().build_uniform_buffer();
|
|
|
|
_initialized = true;
|
|
}
|
|
|
|
void render_all()
|
|
{
|
|
Assertion(_initialized, "init_render must be called before any render_all call!");
|
|
|
|
_lights.resetLightState();
|
|
|
|
for (const int& _key : _keys) {
|
|
self().render_buffer(_elements[_key]);
|
|
}
|
|
|
|
gr_alpha_mask_set(0, 1.0f);
|
|
}
|
|
|
|
void push_element(DrawEntryT&& entry)
|
|
{
|
|
_elements.push_back(std::move(entry));
|
|
_keys.push_back(static_cast<int>(_elements.size() - 1));
|
|
}
|
|
|
|
void sort_draws()
|
|
{
|
|
const auto& d = self();
|
|
std::sort(_keys.begin(), _keys.end(),
|
|
[&d](int a, int b) { return d.sort_draw_pair(a, b); });
|
|
}
|
|
|
|
private:
|
|
Derived& self() { return static_cast<Derived&>(*this); }
|
|
const Derived& self() const { return static_cast<const Derived&>(*this); }
|
|
};
|