cull: Use more efficient arena allocation for CullableObject
This commit is contained in:
parent
55fa0e9912
commit
6823634f60
|
|
@ -248,16 +248,8 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
|
||||
// Record them without any state or transform.
|
||||
trav->_geoms_pcollector.add_level(2);
|
||||
{
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(debug_lines), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform());
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
{
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(debug_triangles), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform());
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
}
|
||||
trav->get_cull_handler()->record_object(CullableObject(std::move(debug_lines), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()), trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(std::move(debug_triangles), RenderState::make_empty(), trav->get_scene()->get_cs_world_transform()), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -207,11 +207,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|||
PT(Geom) geom = new Geom(point_vdata);
|
||||
geom->add_primitive(points);
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, point_state,
|
||||
xform_data.get_internal_transform(trav));
|
||||
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
geom, point_state, xform_data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
// Draw the normal vector at the surface point.
|
||||
|
|
@ -236,11 +233,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|||
PT(Geom) geom = new Geom(line_vdata);
|
||||
geom->add_primitive(lines);
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, empty_state,
|
||||
xform_data.get_internal_transform(trav));
|
||||
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
geom, empty_state, xform_data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@
|
|||
* This is called as each Geom is discovered by the CullTraverser.
|
||||
*/
|
||||
void BinCullHandler::
|
||||
record_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
_cull_result->add_object(object, traverser);
|
||||
record_object(CullableObject &&object, const CullTraverser *traverser) {
|
||||
_cull_result->add_object(std::move(object), traverser);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class EXPCL_PANDA_CULL BinCullHandler : public CullHandler {
|
|||
public:
|
||||
INLINE BinCullHandler(CullResult *cull_result);
|
||||
|
||||
virtual void record_object(CullableObject *object,
|
||||
virtual void record_object(CullableObject &&object,
|
||||
const CullTraverser *traverser);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -23,18 +23,6 @@
|
|||
|
||||
TypeHandle CullBinBackToFront::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CullBinBackToFront::
|
||||
~CullBinBackToFront() {
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor for passing to the CullBinManager.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ public:
|
|||
INLINE CullBinBackToFront(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
virtual ~CullBinBackToFront();
|
||||
|
||||
static CullBin *make_bin(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
|
|
|
|||
|
|
@ -23,18 +23,6 @@
|
|||
|
||||
TypeHandle CullBinFixed::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CullBinFixed::
|
||||
~CullBinFixed() {
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor for passing to the CullBinManager.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ public:
|
|||
INLINE CullBinFixed(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
virtual ~CullBinFixed();
|
||||
|
||||
static CullBin *make_bin(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
|
|
|
|||
|
|
@ -23,18 +23,6 @@
|
|||
|
||||
TypeHandle CullBinFrontToBack::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CullBinFrontToBack::
|
||||
~CullBinFrontToBack() {
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor for passing to the CullBinManager.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ public:
|
|||
INLINE CullBinFrontToBack(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
virtual ~CullBinFrontToBack();
|
||||
|
||||
static CullBin *make_bin(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
|
|
|
|||
|
|
@ -22,18 +22,6 @@
|
|||
|
||||
TypeHandle CullBinStateSorted::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CullBinStateSorted::
|
||||
~CullBinStateSorted() {
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi)._object;
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor for passing to the CullBinManager.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ public:
|
|||
INLINE CullBinStateSorted(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
virtual ~CullBinStateSorted();
|
||||
|
||||
static CullBin *make_bin(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
|
|
|
|||
|
|
@ -19,18 +19,6 @@
|
|||
|
||||
TypeHandle CullBinUnsorted::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CullBinUnsorted::
|
||||
~CullBinUnsorted() {
|
||||
Objects::iterator oi;
|
||||
for (oi = _objects.begin(); oi != _objects.end(); ++oi) {
|
||||
CullableObject *object = (*oi);
|
||||
delete object;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory constructor for passing to the CullBinManager.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ public:
|
|||
INLINE CullBinUnsorted(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
~CullBinUnsorted();
|
||||
|
||||
static CullBin *make_bin(const std::string &name,
|
||||
GraphicsStateGuardianBase *gsg,
|
||||
|
|
|
|||
|
|
@ -25,17 +25,14 @@
|
|||
* This is called as each Geom is discovered by the CullTraverser.
|
||||
*/
|
||||
void DrawCullHandler::
|
||||
record_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
record_object(CullableObject &&object, const CullTraverser *traverser) {
|
||||
// Munge vertices as needed for the GSG's requirements, and the object's
|
||||
// current state.
|
||||
bool force = !_gsg->get_effective_incomplete_render();
|
||||
Thread *current_thread = traverser->get_current_thread();
|
||||
|
||||
if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
|
||||
if (object.munge_geom(_gsg, _gsg->get_geom_munger(object._state, current_thread), traverser, force)) {
|
||||
// Now we can immediately draw the object.
|
||||
draw(object, _gsg, force, current_thread);
|
||||
draw(&object, _gsg, force, current_thread);
|
||||
}
|
||||
|
||||
// Dispense with the object.
|
||||
delete object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class EXPCL_PANDA_CULL DrawCullHandler : public CullHandler {
|
|||
public:
|
||||
INLINE DrawCullHandler(GraphicsStateGuardianBase *gsg);
|
||||
|
||||
virtual void record_object(CullableObject *object,
|
||||
virtual void record_object(CullableObject &&object,
|
||||
const CullTraverser *traverser);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ get_occlusion_mask() const {
|
|||
*
|
||||
*/
|
||||
INLINE PipeOcclusionCullTraverser::PendingObject::
|
||||
PendingObject(CullableObject *object) :
|
||||
_object(object)
|
||||
PendingObject(CullableObject &&object) :
|
||||
_object(std::move(object))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -217,28 +217,19 @@ end_traverse() {
|
|||
_current_query = nullptr;
|
||||
_next_query = nullptr;
|
||||
|
||||
PendingObjects::iterator oi;
|
||||
for (oi = _pending_objects.begin(); oi != _pending_objects.end(); ++oi) {
|
||||
PendingObject &pobj = (*oi);
|
||||
for (PendingObject &pobj : _pending_objects) {
|
||||
if (pobj._query == nullptr) {
|
||||
_occlusion_untested_pcollector.add_level(1);
|
||||
_true_cull_handler->record_object(pobj._object, this);
|
||||
_true_cull_handler->record_object(std::move(pobj._object), this);
|
||||
} else {
|
||||
int num_fragments = pobj._query->get_num_fragments();
|
||||
if (num_fragments != 0) {
|
||||
_occlusion_passed_pcollector.add_level(1);
|
||||
_true_cull_handler->record_object(pobj._object, this);
|
||||
_true_cull_handler->record_object(std::move(pobj._object), this);
|
||||
} else {
|
||||
_occlusion_failed_pcollector.add_level(1);
|
||||
delete pobj._object;
|
||||
}
|
||||
}
|
||||
|
||||
// The CullableObject has by now either been recorded (which will
|
||||
// eventually delete it) or deleted directly.
|
||||
#ifndef NDEBUG
|
||||
pobj._object = nullptr;
|
||||
#endif // NDEBUG
|
||||
}
|
||||
_pending_objects.clear();
|
||||
CullTraverser::end_traverse();
|
||||
|
|
@ -363,9 +354,9 @@ traverse_below(CullTraverserData &data) {
|
|||
* the end of the scene.
|
||||
*/
|
||||
void PipeOcclusionCullTraverser::
|
||||
record_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
record_object(CullableObject &&object, const CullTraverser *traverser) {
|
||||
nassertv(traverser == this);
|
||||
PendingObject pobj(object);
|
||||
PendingObject pobj(std::move(object));
|
||||
|
||||
Thread *current_thread = get_current_thread();
|
||||
|
||||
|
|
@ -379,13 +370,13 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
// ancestor. Don't perform another one.
|
||||
pobj._query = _current_query;
|
||||
|
||||
} else if (object->_geom->get_nested_vertices(current_thread) < min_occlusion_vertices) {
|
||||
} else if (pobj._object._geom->get_nested_vertices(current_thread) < min_occlusion_vertices) {
|
||||
// This object is too small to bother testing for occlusions.
|
||||
|
||||
} else {
|
||||
// Issue an occlusion test for this object.
|
||||
CPT(BoundingVolume) vol = object->_geom->get_bounds(current_thread);
|
||||
CPT(TransformState) net_transform = _inv_cs_world_transform->compose(object->_internal_transform);
|
||||
CPT(BoundingVolume) vol = pobj._object._geom->get_bounds(current_thread);
|
||||
CPT(TransformState) net_transform = _inv_cs_world_transform->compose(pobj._object._internal_transform);
|
||||
CPT(TransformState) internal_transform;
|
||||
CPT(Geom) geom;
|
||||
if (get_volume_viz(vol, geom, net_transform, internal_transform)) {
|
||||
|
|
@ -394,7 +385,7 @@ record_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
}
|
||||
}
|
||||
|
||||
_pending_objects.push_back(pobj);
|
||||
_pending_objects.push_back(std::move(pobj));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -608,14 +599,13 @@ perform_occlusion_test(const Geom *geom, const TransformState *net_transform,
|
|||
|
||||
gsg->begin_occlusion_query();
|
||||
|
||||
CullableObject *viz =
|
||||
new CullableObject(geom, _solid_test_state, internal_transform);
|
||||
CullableObject viz(geom, _solid_test_state, internal_transform);
|
||||
|
||||
static ConfigVariableBool test_occlude("test-occlude", false);
|
||||
if (test_occlude) {
|
||||
_true_cull_handler->record_object(viz, _internal_trav);
|
||||
_true_cull_handler->record_object(std::move(viz), _internal_trav);
|
||||
} else {
|
||||
_internal_cull_handler->record_object(viz, _internal_trav);
|
||||
_internal_cull_handler->record_object(std::move(viz), _internal_trav);
|
||||
}
|
||||
|
||||
PT(OcclusionQueryContext) query = gsg->end_occlusion_query();
|
||||
|
|
@ -654,13 +644,9 @@ show_results(int num_fragments, const Geom *geom,
|
|||
TransparencyAttrib::make(TransparencyAttrib::M_alpha),
|
||||
ColorAttrib::make_flat(color));
|
||||
|
||||
CullableObject *internal_viz =
|
||||
new CullableObject(geom, state, internal_transform);
|
||||
_internal_cull_handler->record_object(internal_viz, _internal_trav);
|
||||
_internal_cull_handler->record_object(CullableObject(geom, state, internal_transform), _internal_trav);
|
||||
|
||||
// Also render the viz in the main scene.
|
||||
internal_transform = get_scene()->get_cs_world_transform()->compose(net_transform);
|
||||
CullableObject *main_viz =
|
||||
new CullableObject(geom, state, internal_transform);
|
||||
_true_cull_handler->record_object(main_viz, this);
|
||||
_true_cull_handler->record_object(CullableObject(geom, state, internal_transform), this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class GraphicsStateGuardian;
|
|||
* in grutil instead, for lack of any better ideas.
|
||||
*/
|
||||
class EXPCL_PANDA_GRUTIL PipeOcclusionCullTraverser : public CullTraverser,
|
||||
public CullHandler {
|
||||
public CullHandler {
|
||||
PUBLISHED:
|
||||
explicit PipeOcclusionCullTraverser(GraphicsOutput *host);
|
||||
PipeOcclusionCullTraverser(const PipeOcclusionCullTraverser ©) = delete;
|
||||
|
|
@ -59,7 +59,7 @@ protected:
|
|||
virtual bool is_in_view(CullTraverserData &data);
|
||||
virtual void traverse_below(CullTraverserData &data);
|
||||
|
||||
virtual void record_object(CullableObject *object,
|
||||
virtual void record_object(CullableObject &&object,
|
||||
const CullTraverser *traverser);
|
||||
|
||||
private:
|
||||
|
|
@ -110,10 +110,10 @@ private:
|
|||
|
||||
class PendingObject {
|
||||
public:
|
||||
INLINE PendingObject(CullableObject *object);
|
||||
INLINE PendingObject(CullableObject &&object);
|
||||
INLINE ~PendingObject();
|
||||
|
||||
CullableObject *_object;
|
||||
CullableObject _object;
|
||||
PT(OcclusionQueryContext) _query;
|
||||
};
|
||||
typedef pvector<PendingObject> PendingObjects;
|
||||
|
|
|
|||
|
|
@ -544,8 +544,8 @@ void ShaderTerrainMesh::add_for_draw(CullTraverser *trav, CullTraverserData &dat
|
|||
state = state->set_attrib(current_shader_attrib, 10000);
|
||||
|
||||
// Emit chunk
|
||||
CullableObject *object = new CullableObject(_chunk_geom, std::move(state), std::move(modelview_transform));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
_chunk_geom, std::move(state), std::move(modelview_transform)), trav);
|
||||
|
||||
// After rendering, increment the view index
|
||||
++_current_view_index;
|
||||
|
|
|
|||
|
|
@ -329,10 +329,8 @@ render_thread(CullTraverser *trav, CullTraverserData &data,
|
|||
state = state->add_attrib(ColorAttrib::make_vertex());
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -375,10 +373,8 @@ render_tape(CullTraverser *trav, CullTraverserData &data,
|
|||
state = state->add_attrib(ColorAttrib::make_vertex());
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -428,10 +424,8 @@ render_billboard(CullTraverser *trav, CullTraverserData &data,
|
|||
state = state->add_attrib(ColorAttrib::make_vertex());
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -489,10 +483,8 @@ render_tube(CullTraverser *trav, CullTraverserData &data,
|
|||
state = state->add_attrib(ColorAttrib::make_vertex());
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -319,10 +319,8 @@ render_sheet(CullTraverser *trav, CullTraverserData &data,
|
|||
state = state->add_attrib(ColorAttrib::make_vertex());
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(geom, state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), data.get_internal_transform(trav)), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,10 +40,9 @@ CullHandler::
|
|||
* expected to delete it later.
|
||||
*/
|
||||
void CullHandler::
|
||||
record_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
nout << *object->_geom << " " << *object->_internal_transform << " "
|
||||
<< *object->_state << "\n";
|
||||
delete object;
|
||||
record_object(CullableObject &&object, const CullTraverser *traverser) {
|
||||
nout << *object._geom << " " << *object._internal_transform << " "
|
||||
<< *object._state << "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public:
|
|||
CullHandler();
|
||||
virtual ~CullHandler();
|
||||
|
||||
virtual void record_object(CullableObject *object,
|
||||
virtual void record_object(CullableObject &&object,
|
||||
const CullTraverser *traverser);
|
||||
virtual void end_traverse();
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
INLINE CullResult::
|
||||
~CullResult() {
|
||||
delete_page(_page);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -32,6 +33,19 @@ get_bin(int bin_index) {
|
|||
return make_new_bin(bin_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates memory for a new CullableObject that is associated with this
|
||||
* CullResult.
|
||||
*/
|
||||
INLINE CullableObject *CullResult::
|
||||
alloc_object(CullableObject &&object) {
|
||||
AllocationPage *page = _page;
|
||||
if (page->_size >= page->_capacity) {
|
||||
page = new_page();
|
||||
}
|
||||
return new (page->_memory + sizeof(CullableObject) * (page->_size++)) CullableObject(std::move(object));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user configured flash-bin-binname, then update the object's state to
|
||||
* flash all the geometry in the bin.
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ CullResult(GraphicsStateGuardianBase *gsg,
|
|||
_gsg(gsg),
|
||||
_draw_region_pcollector(draw_region_pcollector)
|
||||
{
|
||||
_page = &_first_page;
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
#endif
|
||||
|
|
@ -100,13 +102,13 @@ make_next() const {
|
|||
* the owner of the object pointer, and will eventually delete it.
|
||||
*/
|
||||
void CullResult::
|
||||
add_object(CullableObject *object, const CullTraverser *traverser) {
|
||||
add_object(CullableObject &&object, const CullTraverser *traverser) {
|
||||
static const LColor flash_alpha_color(0.92, 0.96, 0.10, 1.0f);
|
||||
static const LColor flash_binary_color(0.21f, 0.67f, 0.24, 1.0f);
|
||||
static const LColor flash_multisample_color(0.78f, 0.05f, 0.81f, 1.0f);
|
||||
static const LColor flash_dual_color(0.92, 0.01f, 0.01f, 1.0f);
|
||||
|
||||
nassertv(object->_draw_callback != nullptr || object->_geom != nullptr);
|
||||
nassertv(object._draw_callback != nullptr || object._geom != nullptr);
|
||||
|
||||
bool force = !traverser->get_effective_incomplete_render();
|
||||
Thread *current_thread = traverser->get_current_thread();
|
||||
|
|
@ -114,62 +116,60 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
|
||||
// This is probably a good time to check for an auto rescale setting.
|
||||
const RescaleNormalAttrib *rescale;
|
||||
object->_state->get_attrib_def(rescale);
|
||||
object._state->get_attrib_def(rescale);
|
||||
if (rescale->get_mode() == RescaleNormalAttrib::M_auto) {
|
||||
RescaleNormalAttrib::Mode mode;
|
||||
|
||||
if (object->_internal_transform->has_identity_scale()) {
|
||||
if (object._internal_transform->has_identity_scale()) {
|
||||
mode = RescaleNormalAttrib::M_none;
|
||||
} else if (object->_internal_transform->has_uniform_scale()) {
|
||||
} else if (object._internal_transform->has_uniform_scale()) {
|
||||
mode = RescaleNormalAttrib::M_rescale;
|
||||
} else {
|
||||
mode = RescaleNormalAttrib::M_normalize;
|
||||
}
|
||||
|
||||
object->_state = object->_state->compose(get_rescale_normal_state(mode));
|
||||
object._state = object._state->compose(get_rescale_normal_state(mode));
|
||||
}
|
||||
|
||||
// Check for a special wireframe setting.
|
||||
const RenderModeAttrib *rmode;
|
||||
if (object->_state->get_attrib(rmode)) {
|
||||
if (object._state->get_attrib(rmode)) {
|
||||
if (rmode->get_mode() == RenderModeAttrib::M_filled_wireframe) {
|
||||
CullableObject *wireframe_part = new CullableObject(*object);
|
||||
CullableObject wireframe_part(object);
|
||||
const ShaderAttrib *shader = nullptr;
|
||||
object->_state->get_attrib(shader);
|
||||
wireframe_part->_state = get_wireframe_overlay_state(rmode, shader);
|
||||
object._state->get_attrib(shader);
|
||||
wireframe_part._state = get_wireframe_overlay_state(rmode, shader);
|
||||
|
||||
if (wireframe_part->munge_geom
|
||||
(_gsg, _gsg->get_geom_munger(wireframe_part->_state, current_thread),
|
||||
if (wireframe_part.munge_geom
|
||||
(_gsg, _gsg->get_geom_munger(wireframe_part._state, current_thread),
|
||||
traverser, force)) {
|
||||
int wireframe_bin_index = bin_manager->find_bin("fixed");
|
||||
CullBin *bin = get_bin(wireframe_bin_index);
|
||||
nassertv(bin != nullptr);
|
||||
check_flash_bin(wireframe_part->_state, bin_manager, wireframe_bin_index);
|
||||
bin->add_object(wireframe_part, current_thread);
|
||||
} else {
|
||||
delete wireframe_part;
|
||||
check_flash_bin(wireframe_part._state, bin_manager, wireframe_bin_index);
|
||||
bin->add_object(alloc_object(std::move(wireframe_part)), current_thread);
|
||||
}
|
||||
|
||||
object->_state = object->_state->compose(get_wireframe_filled_state());
|
||||
object._state = object._state->compose(get_wireframe_filled_state());
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if there's a special transparency setting.
|
||||
const TransparencyAttrib *trans;
|
||||
if (object->_state->get_attrib(trans)) {
|
||||
if (object._state->get_attrib(trans)) {
|
||||
switch (trans->get_mode()) {
|
||||
case TransparencyAttrib::M_alpha:
|
||||
case TransparencyAttrib::M_premultiplied_alpha:
|
||||
// M_alpha implies an alpha-write test, so we don't waste time writing
|
||||
// 0-valued pixels.
|
||||
object->_state = object->_state->compose(get_alpha_state());
|
||||
check_flash_transparency(object->_state, flash_alpha_color);
|
||||
object._state = object._state->compose(get_alpha_state());
|
||||
check_flash_transparency(object._state, flash_alpha_color);
|
||||
break;
|
||||
|
||||
case TransparencyAttrib::M_binary:
|
||||
// M_binary is implemented by explicitly setting the alpha test.
|
||||
object->_state = object->_state->compose(get_binary_state());
|
||||
check_flash_transparency(object->_state, flash_binary_color);
|
||||
object._state = object._state->compose(get_binary_state());
|
||||
check_flash_transparency(object._state, flash_binary_color);
|
||||
break;
|
||||
|
||||
case TransparencyAttrib::M_multisample:
|
||||
|
|
@ -177,14 +177,14 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
// The multisample modes are implemented using M_binary if the GSG in
|
||||
// use doesn't support multisample.
|
||||
if (!_gsg->get_supports_multisample()) {
|
||||
object->_state = object->_state->compose(get_binary_state());
|
||||
object._state = object._state->compose(get_binary_state());
|
||||
}
|
||||
check_flash_transparency(object->_state, flash_multisample_color);
|
||||
check_flash_transparency(object._state, flash_multisample_color);
|
||||
break;
|
||||
|
||||
case TransparencyAttrib::M_dual:
|
||||
#ifndef NDEBUG
|
||||
check_flash_transparency(object->_state, flash_dual_color);
|
||||
check_flash_transparency(object._state, flash_dual_color);
|
||||
#endif
|
||||
if (!m_dual) {
|
||||
// If m_dual is configured off, it becomes M_alpha.
|
||||
|
|
@ -198,7 +198,7 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
// falls back to M_alpha.
|
||||
{
|
||||
const CullBinAttrib *bin_attrib;
|
||||
if (!object->_state->get_attrib(bin_attrib) ||
|
||||
if (!object._state->get_attrib(bin_attrib) ||
|
||||
bin_attrib->get_bin_name().empty()) {
|
||||
// We make a copy of the object to draw the transparent part; this
|
||||
// gets placed in the transparent bin.
|
||||
|
|
@ -206,28 +206,25 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
if (m_dual_transparent)
|
||||
#endif
|
||||
{
|
||||
CullableObject *transparent_part = new CullableObject(*object);
|
||||
CullableObject transparent_part(object);
|
||||
CPT(RenderState) transparent_state = get_dual_transparent_state();
|
||||
transparent_part->_state = object->_state->compose(transparent_state);
|
||||
if (transparent_part->munge_geom
|
||||
(_gsg, _gsg->get_geom_munger(transparent_part->_state, current_thread),
|
||||
transparent_part._state = object._state->compose(transparent_state);
|
||||
if (transparent_part.munge_geom
|
||||
(_gsg, _gsg->get_geom_munger(transparent_part._state, current_thread),
|
||||
traverser, force)) {
|
||||
int transparent_bin_index = transparent_part->_state->get_bin_index();
|
||||
int transparent_bin_index = transparent_part._state->get_bin_index();
|
||||
CullBin *bin = get_bin(transparent_bin_index);
|
||||
nassertv(bin != nullptr);
|
||||
check_flash_bin(transparent_part->_state, bin_manager, transparent_bin_index);
|
||||
bin->add_object(transparent_part, current_thread);
|
||||
} else {
|
||||
delete transparent_part;
|
||||
check_flash_bin(transparent_part._state, bin_manager, transparent_bin_index);
|
||||
bin->add_object(alloc_object(std::move(transparent_part)), current_thread);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we can draw the opaque part. This will end up in the opaque
|
||||
// bin.
|
||||
object->_state = object->_state->compose(get_dual_opaque_state());
|
||||
object._state = object._state->compose(get_dual_opaque_state());
|
||||
#ifndef NDEBUG
|
||||
if (!m_dual_opaque) {
|
||||
delete object;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -242,20 +239,18 @@ add_object(CullableObject *object, const CullTraverser *traverser) {
|
|||
}
|
||||
}
|
||||
|
||||
int bin_index = object->_state->get_bin_index();
|
||||
int bin_index = object._state->get_bin_index();
|
||||
CullBin *bin = get_bin(bin_index);
|
||||
nassertv(bin != nullptr);
|
||||
check_flash_bin(object->_state, bin_manager, bin_index);
|
||||
check_flash_bin(object._state, bin_manager, bin_index);
|
||||
|
||||
// Munge vertices as needed for the GSG's requirements, and the object's
|
||||
// current state.
|
||||
if (object->munge_geom(_gsg, _gsg->get_geom_munger(object->_state, current_thread), traverser, force)) {
|
||||
if (object.munge_geom(_gsg, _gsg->get_geom_munger(object._state, current_thread), traverser, force)) {
|
||||
// The object may or may not now be fully resident, but this may not
|
||||
// matter, since the GSG may have the necessary buffers already loaded.
|
||||
// We'll let the GSG ultimately decide whether to render it.
|
||||
bin->add_object(object, current_thread);
|
||||
} else {
|
||||
delete object;
|
||||
bin->add_object(alloc_object(std::move(object)), current_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -371,6 +366,33 @@ make_new_bin(int bin_index) {
|
|||
return bin_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AllocationPage replacing the old one.
|
||||
*/
|
||||
CullResult::AllocationPage *CullResult::
|
||||
new_page() {
|
||||
AllocationPage *page = new AllocationPage;
|
||||
page->_next = _page;
|
||||
_page = page;
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void CullResult::
|
||||
delete_page(AllocationPage *page) {
|
||||
size_t size = std::exchange(page->_size, 0);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
((CullableObject *)page->_memory)[i].~CullableObject();
|
||||
}
|
||||
AllocationPage *next = page->_next;
|
||||
if (next != nullptr) {
|
||||
delete_page(next);
|
||||
delete page;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a RenderState containing the given rescale normal attribute.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class EXPCL_PANDA_PGRAPH CullResult : public ReferenceCount {
|
|||
public:
|
||||
CullResult(GraphicsStateGuardianBase *gsg,
|
||||
const PStatCollector &draw_region_pcollector);
|
||||
CullResult(const CullResult ©) = delete;
|
||||
INLINE ~CullResult();
|
||||
|
||||
PUBLISHED:
|
||||
|
|
@ -52,7 +53,7 @@ PUBLISHED:
|
|||
|
||||
INLINE CullBin *get_bin(int bin_index);
|
||||
|
||||
void add_object(CullableObject *object, const CullTraverser *traverser);
|
||||
void add_object(CullableObject &&object, const CullTraverser *traverser);
|
||||
void finish_cull(SceneSetup *scene_setup, Thread *current_thread);
|
||||
void draw(Thread *current_thread);
|
||||
|
||||
|
|
@ -64,6 +65,11 @@ public:
|
|||
private:
|
||||
CullBin *make_new_bin(int bin_index);
|
||||
|
||||
struct AllocationPage;
|
||||
AllocationPage *new_page();
|
||||
void delete_page(AllocationPage *page);
|
||||
INLINE CullableObject *alloc_object(CullableObject &&object);
|
||||
|
||||
INLINE void check_flash_bin(CPT(RenderState) &state, CullBinManager *bin_manager, int bin_index);
|
||||
INLINE void check_flash_transparency(CPT(RenderState) &state, const LColor &color);
|
||||
|
||||
|
|
@ -88,6 +94,16 @@ private:
|
|||
|
||||
bool _show_transparency = false;
|
||||
|
||||
// Arena allocator for CullableObjects.
|
||||
struct AllocationPage {
|
||||
AllocationPage *_next = nullptr;
|
||||
static const size_t _capacity = 64;
|
||||
size_t _size = 0;
|
||||
alignas(CullableObject) unsigned char _memory[sizeof(CullableObject) * _capacity];
|
||||
};
|
||||
AllocationPage *_page;
|
||||
AllocationPage _first_page;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
|
|||
|
|
@ -259,15 +259,8 @@ draw_bounding_volume(const BoundingVolume *vol,
|
|||
|
||||
if (bounds_viz != nullptr) {
|
||||
_geoms_pcollector.add_level(2);
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(bounds_viz, get_bounds_outer_viz_state(),
|
||||
internal_transform);
|
||||
_cull_handler->record_object(outer_viz, this);
|
||||
|
||||
CullableObject *inner_viz =
|
||||
new CullableObject(std::move(bounds_viz), get_bounds_inner_viz_state(),
|
||||
internal_transform);
|
||||
_cull_handler->record_object(inner_viz, this);
|
||||
_cull_handler->record_object(CullableObject(bounds_viz, get_bounds_outer_viz_state(), internal_transform), this);
|
||||
_cull_handler->record_object(CullableObject(std::move(bounds_viz), get_bounds_inner_viz_state(), internal_transform), this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,11 +302,10 @@ show_bounds(CullTraverserData &data, bool tight) {
|
|||
|
||||
if (bounds_viz != nullptr) {
|
||||
_geoms_pcollector.add_level(1);
|
||||
CullableObject *outer_viz =
|
||||
new CullableObject(std::move(bounds_viz), get_bounds_outer_viz_state(),
|
||||
internal_transform);
|
||||
outer_viz->_instances = data._instances;
|
||||
_cull_handler->record_object(outer_viz, this);
|
||||
CullableObject outer_viz(std::move(bounds_viz), get_bounds_outer_viz_state(),
|
||||
internal_transform);
|
||||
outer_viz._instances = data._instances;
|
||||
_cull_handler->record_object(std::move(outer_viz), this);
|
||||
}
|
||||
} else if (data._instances == nullptr) {
|
||||
draw_bounding_volume(node->get_bounds(), internal_transform);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include "geomNode.h"
|
||||
#include "cullTraverserData.h"
|
||||
#include "pStatCollector.h"
|
||||
#include "deletedChain.h"
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "sceneSetup.h"
|
||||
#include "lightMutex.h"
|
||||
|
|
@ -46,7 +45,10 @@ public:
|
|||
CPT(TransformState) internal_transform);
|
||||
|
||||
INLINE CullableObject(const CullableObject ©);
|
||||
INLINE CullableObject(CullableObject &&from) noexcept = default;
|
||||
|
||||
INLINE void operator = (const CullableObject ©);
|
||||
INLINE CullableObject &operator = (CullableObject &&from) noexcept = default;
|
||||
|
||||
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger,
|
||||
const CullTraverser *traverser, bool force);
|
||||
|
|
@ -64,8 +66,6 @@ public:
|
|||
bool force, Thread *current_thread);
|
||||
|
||||
public:
|
||||
ALLOC_DELETED_CHAIN(CullableObject);
|
||||
|
||||
void output(std::ostream &out) const;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -538,10 +538,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
if (!geom->is_empty()) {
|
||||
CPT(RenderState) state = data._state->compose(geoms.get_geom_state(0));
|
||||
if (!state->has_cull_callback() || state->cull_callback(trav, data)) {
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), std::move(internal_transform));
|
||||
object->_instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
CullableObject object(std::move(geom), std::move(state), std::move(internal_transform));
|
||||
object._instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(std::move(object), trav);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -562,10 +561,9 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
if (data._instances != nullptr) {
|
||||
// Draw each individual instance. We don't bother culling each
|
||||
// individual Geom for each instance; that is probably way too slow.
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
object->_instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
CullableObject object(std::move(geom), std::move(state), internal_transform);
|
||||
object._instances = data._instances;
|
||||
trav->get_cull_handler()->record_object(std::move(object), trav);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -588,9 +586,8 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
}
|
||||
}
|
||||
|
||||
CullableObject *object =
|
||||
new CullableObject(std::move(geom), std::move(state), internal_transform);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
std::move(geom), std::move(state), internal_transform), trav);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,17 +141,15 @@ bool OccluderNode::
|
|||
cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
||||
// Normally, an OccluderNode is invisible. But if someone shows it, we will
|
||||
// draw a visualization, a checkerboard-textured polygon.
|
||||
CullableObject *occluder_viz =
|
||||
new CullableObject(get_occluder_viz(trav, data), get_occluder_viz_state(trav, data),
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(occluder_viz, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
get_occluder_viz(trav, data), get_occluder_viz_state(trav, data),
|
||||
data.get_internal_transform(trav)), trav);
|
||||
|
||||
// Also get the frame.
|
||||
nassertr(_frame_viz != nullptr, false);
|
||||
CullableObject *frame_viz =
|
||||
new CullableObject(_frame_viz, get_frame_viz_state(trav, data),
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(frame_viz, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
_frame_viz, get_frame_viz_state(trav, data),
|
||||
data.get_internal_transform(trav)), trav);
|
||||
|
||||
// Now carry on to render our child nodes.
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -140,10 +140,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
|
|||
// Normally, a PlaneNode is invisible. But if someone shows it, we will
|
||||
// draw a visualization, a nice yellow wireframe.
|
||||
|
||||
CullableObject *plane_viz =
|
||||
new CullableObject(get_viz(trav, data), data._state,
|
||||
data.get_internal_transform(trav));
|
||||
trav->get_cull_handler()->record_object(plane_viz, trav);
|
||||
trav->get_cull_handler()->record_object(CullableObject(
|
||||
get_viz(trav, data), data._state, data.get_internal_transform(trav)), trav);
|
||||
|
||||
// Now carry on to render our child nodes.
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -121,11 +121,10 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
// Geoms, however.
|
||||
CallbackObject *cbobj = get_draw_callback();
|
||||
if (cbobj != nullptr) {
|
||||
CullableObject *object =
|
||||
new CullableObject(nullptr, data._state,
|
||||
data.get_internal_transform(trav));
|
||||
object->set_draw_callback(cbobj);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
CullableObject object(nullptr, data._state,
|
||||
data.get_internal_transform(trav));
|
||||
object.set_draw_callback(cbobj);
|
||||
trav->get_cull_handler()->record_object(std::move(object), trav);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,11 +82,10 @@ add_for_draw(CullTraverser *trav, CullTraverserData &data) {
|
|||
// OK, render this node. Rendering this node means creating a
|
||||
// CullableObject for the Dispatcher. We don't need to pass any Geoms,
|
||||
// however.
|
||||
CullableObject *object =
|
||||
new CullableObject(nullptr, data._state,
|
||||
data.get_internal_transform(trav));
|
||||
object->set_draw_callback(_dispatcher);
|
||||
trav->get_cull_handler()->record_object(object, trav);
|
||||
CullableObject object(nullptr, data._state,
|
||||
data.get_internal_transform(trav));
|
||||
object.set_draw_callback(_dispatcher);
|
||||
trav->get_cull_handler()->record_object(std::move(object), trav);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,11 +48,10 @@ upcall() {
|
|||
// any Geoms, however.
|
||||
CallbackObject *cbobj = cbnode->get_draw_callback();
|
||||
if (cbobj != nullptr) {
|
||||
CullableObject *object =
|
||||
new CullableObject(nullptr, _data._state,
|
||||
_data.get_internal_transform(_trav));
|
||||
object->set_draw_callback(cbobj);
|
||||
_trav->get_cull_handler()->record_object(object, _trav);
|
||||
CullableObject object(nullptr, _data._state,
|
||||
_data.get_internal_transform(_trav));
|
||||
object.set_draw_callback(cbobj);
|
||||
_trav->get_cull_handler()->record_object(std::move(object), _trav);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue