mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 18:31:55 -04:00
Preliminary LRU.
Only manages vertex buffers and index buffers at this time. Textures still need to added to LRU. Code needs reformatting and cleanup, error handling, and messaging. Config options need to be added.
This commit is contained in:
parent
1dbdffc35c
commit
2c28f1a62f
@ -64,6 +64,11 @@
|
||||
#include <d3dx9.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
#define DEBUG_LRU false
|
||||
#define DEFAULT_ENABLE_LRU true
|
||||
|
||||
|
||||
TypeHandle DXGraphicsStateGuardian9::_type_handle;
|
||||
|
||||
D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
|
||||
@ -117,6 +122,14 @@ DXGraphicsStateGuardian9(const FrameBufferProperties &properties) :
|
||||
Geom::GR_indexed_other |
|
||||
Geom::GR_triangle_strip | Geom::GR_triangle_fan |
|
||||
Geom::GR_flat_first_vertex;
|
||||
|
||||
_gsg_managed_textures = false;
|
||||
_gsg_managed_vertex_buffers = false;
|
||||
_gsg_managed_index_buffers = false;
|
||||
|
||||
_enable_lru = DEFAULT_ENABLE_LRU;
|
||||
|
||||
_lru = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -130,6 +143,12 @@ DXGraphicsStateGuardian9::
|
||||
_d3d_device->SetTexture(0, NULL); // this frees reference to the old texture
|
||||
}
|
||||
free_nondx_resources();
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
delete _lru;
|
||||
_lru = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -315,6 +334,11 @@ void DXGraphicsStateGuardian9::
|
||||
apply_vertex_buffer(VertexBufferContext *vbc) {
|
||||
DXVertexBufferContext9 *dvbc = DCAST(DXVertexBufferContext9, vbc);
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
_lru -> access_page (dvbc -> _lru_page);
|
||||
}
|
||||
|
||||
if (dvbc->_vbuffer == NULL) {
|
||||
// Attempt to create a new vertex buffer.
|
||||
if (vertex_buffers &&
|
||||
@ -416,6 +440,11 @@ void DXGraphicsStateGuardian9::
|
||||
apply_index_buffer(IndexBufferContext *ibc) {
|
||||
DXIndexBufferContext9 *dibc = DCAST(DXIndexBufferContext9, ibc);
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
_lru -> access_page (dibc -> _lru_page);
|
||||
}
|
||||
|
||||
if (dibc->_ibuffer == NULL) {
|
||||
// Attempt to create a new index buffer.
|
||||
dibc->create_ibuffer(*_screen);
|
||||
@ -679,6 +708,12 @@ prepare_lens() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool DXGraphicsStateGuardian9::
|
||||
begin_frame() {
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
_lru -> begin_frame ( );
|
||||
}
|
||||
|
||||
return GraphicsStateGuardian::begin_frame();
|
||||
}
|
||||
|
||||
@ -766,6 +801,47 @@ end_scene() {
|
||||
void DXGraphicsStateGuardian9::
|
||||
end_frame() {
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
int frames;
|
||||
int maximum_updates;
|
||||
|
||||
// LRU *****
|
||||
maximum_updates = 10;
|
||||
_lru -> partial_lru_update (maximum_updates);
|
||||
// _lru -> update_entire_lru ( );
|
||||
|
||||
frames = 256;
|
||||
if ((_lru -> _m.current_frame_identifier % frames) == 0)
|
||||
{
|
||||
if (dxgsg9_cat.is_debug())
|
||||
{
|
||||
dxgsg9_cat.debug() << "* LRU: total_pages " << _lru -> _m.total_pages << "\n";
|
||||
dxgsg9_cat.debug() << "* available_memory " << _lru -> _m.available_memory << "\n";
|
||||
dxgsg9_cat.debug() << "* total lifetime pages created " << _lru -> _m.identifier << "\n";
|
||||
dxgsg9_cat.debug() << "* total_lifetime_page_ins " << _lru -> _m.total_lifetime_page_ins << "\n";
|
||||
dxgsg9_cat.debug() << "* total_lifetime_page_outs " << _lru -> _m.total_lifetime_page_outs << "\n";
|
||||
dxgsg9_cat.debug() << "* total_page_access " << _lru -> _m.total_page_access << " avg page access " << ((float) _lru -> _m.total_page_access / (float) frames) << "\n";
|
||||
dxgsg9_cat.debug() << "* total_lru_pages_in_pool " << _lru -> _m.total_lru_pages_in_pool << "\n";
|
||||
dxgsg9_cat.debug() << "* total_lru_pages_in_free_pool " << _lru -> _m.total_lru_pages_in_free_pool << "\n";
|
||||
|
||||
_lru -> _m.total_page_access = 0;
|
||||
|
||||
_lru -> count_priority_level_pages ( );
|
||||
|
||||
int index;
|
||||
|
||||
for (index = 0; index < LPP_TotalPriorities; index++)
|
||||
{
|
||||
if (_lru -> _m.lru_page_count_array [index])
|
||||
{
|
||||
dxgsg9_cat.debug() << "* priority " << index << " pages " << _lru -> _m.lru_page_count_array [index] << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DO_PSTATS)
|
||||
if (_texmgrmem_total_pcollector.is_active()) {
|
||||
#define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
|
||||
@ -983,7 +1059,7 @@ draw_tristrips(const GeomTristrips *primitive) {
|
||||
} else {
|
||||
// Indexed, client arrays, one long triangle strip.
|
||||
D3DFORMAT index_type = get_index_type(primitive->get_index_type());
|
||||
draw_indexed_primitive_up
|
||||
draw_indexed_primitive_up
|
||||
(D3DPT_TRIANGLESTRIP,
|
||||
min_vertex, max_vertex,
|
||||
primitive->get_num_vertices() - 2,
|
||||
@ -1001,7 +1077,7 @@ draw_tristrips(const GeomTristrips *primitive) {
|
||||
|
||||
} else {
|
||||
// Indexed, client arrays, one long triangle strip.
|
||||
draw_primitive_up(D3DPT_TRIANGLESTRIP,
|
||||
draw_primitive_up(D3DPT_TRIANGLESTRIP,
|
||||
primitive->get_num_vertices() - 2,
|
||||
primitive->get_first_vertex(),
|
||||
primitive->get_num_vertices(),
|
||||
@ -1039,7 +1115,7 @@ draw_tristrips(const GeomTristrips *primitive) {
|
||||
unsigned int max = maxs.get_data1i();
|
||||
_d3d_device->DrawIndexedPrimitive
|
||||
(D3DPT_TRIANGLESTRIP,
|
||||
0,
|
||||
0,
|
||||
min, max - min + 1,
|
||||
start, ends[i] - start - 2);
|
||||
|
||||
@ -1058,7 +1134,7 @@ draw_tristrips(const GeomTristrips *primitive) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
unsigned int min = mins.get_data1i();
|
||||
unsigned int max = maxs.get_data1i();
|
||||
draw_indexed_primitive_up
|
||||
draw_indexed_primitive_up
|
||||
(D3DPT_TRIANGLESTRIP,
|
||||
min, max,
|
||||
ends[i] - start - 2,
|
||||
@ -1091,7 +1167,7 @@ draw_tristrips(const GeomTristrips *primitive) {
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_tristrip_pcollector.add_level(ends[i] - start);
|
||||
draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
|
||||
draw_primitive_up(D3DPT_TRIANGLESTRIP, ends[i] - start - 2,
|
||||
first_vertex + start,
|
||||
ends[i] - start,
|
||||
array_data, stride);
|
||||
@ -1158,7 +1234,7 @@ draw_trifans(const GeomTrifans *primitive) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
unsigned int min = mins.get_data1i();
|
||||
unsigned int max = maxs.get_data1i();
|
||||
draw_indexed_primitive_up
|
||||
draw_indexed_primitive_up
|
||||
(D3DPT_TRIANGLEFAN,
|
||||
min, max,
|
||||
ends[i] - start - 2,
|
||||
@ -1191,7 +1267,7 @@ draw_trifans(const GeomTrifans *primitive) {
|
||||
unsigned int start = 0;
|
||||
for (size_t i = 0; i < ends.size(); i++) {
|
||||
_vertices_trifan_pcollector.add_level(ends[i] - start);
|
||||
draw_primitive_up(D3DPT_TRIANGLEFAN,
|
||||
draw_primitive_up(D3DPT_TRIANGLEFAN,
|
||||
ends[i] - start - 2,
|
||||
first_vertex,
|
||||
ends[i] - start,
|
||||
@ -1666,6 +1742,81 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool vertex_buffer_page_in_function (LruPage *lru_page)
|
||||
{
|
||||
DXGraphicsStateGuardian9 *gsg;
|
||||
DXVertexBufferContext9 *vertex_buffer;
|
||||
|
||||
gsg = (DXGraphicsStateGuardian9 *) (lru_page -> _m.lru -> _m.context);
|
||||
vertex_buffer = (DXVertexBufferContext9 *) lru_page -> _m.lru_page_type.pointer;
|
||||
|
||||
// allocate vertex buffer
|
||||
vertex_buffer -> allocate_vbuffer (*(gsg->_screen));
|
||||
|
||||
// update vertex buffer
|
||||
vertex_buffer -> upload_data ( );
|
||||
|
||||
if (DEBUG_LRU && dxgsg9_cat.is_debug())
|
||||
{
|
||||
dxgsg9_cat.debug() << " *** page IN VB " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vertex_buffer_page_out_function (LruPage *lru_page)
|
||||
{
|
||||
DXVertexBufferContext9 *vertex_buffer;
|
||||
|
||||
vertex_buffer = (DXVertexBufferContext9 *) lru_page -> _m.lru_page_type.pointer;
|
||||
vertex_buffer -> free_vbuffer ( );
|
||||
|
||||
if (DEBUG_LRU && dxgsg9_cat.is_debug())
|
||||
{
|
||||
dxgsg9_cat.debug() << " *** page OUT VB " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool index_buffer_page_in_function (LruPage *lru_page)
|
||||
{
|
||||
DXGraphicsStateGuardian9 *gsg;
|
||||
DXIndexBufferContext9 *index_buffer;
|
||||
|
||||
gsg = (DXGraphicsStateGuardian9 *) (lru_page -> _m.lru -> _m.context);
|
||||
index_buffer = (DXIndexBufferContext9 *) lru_page -> _m.lru_page_type.pointer;
|
||||
|
||||
// allocate vertex buffer
|
||||
index_buffer -> allocate_ibuffer (*(gsg->_screen));
|
||||
|
||||
// update vertex buffer
|
||||
index_buffer -> upload_data ( );
|
||||
|
||||
if (DEBUG_LRU && dxgsg9_cat.is_debug())
|
||||
{
|
||||
dxgsg9_cat.debug() << " *** page IN IB " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool index_buffer_page_out_function (LruPage *lru_page)
|
||||
{
|
||||
DXIndexBufferContext9 *index_buffer;
|
||||
|
||||
index_buffer = (DXIndexBufferContext9 *) lru_page -> _m.lru_page_type.pointer;
|
||||
index_buffer -> free_ibuffer ( );
|
||||
|
||||
if (DEBUG_LRU && dxgsg9_cat.is_debug())
|
||||
{
|
||||
dxgsg9_cat.debug() << " *** page OUT IB " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXGraphicsStateGuardian9::reset
|
||||
// Access: Public, Virtual
|
||||
@ -1736,6 +1887,60 @@ reset() {
|
||||
_supports_texture_saved_result = ((d3d_caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP) != 0);
|
||||
_supports_texture_dot3 = true;
|
||||
|
||||
_screen->_supports_dynamic_textures = ((d3d_caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) != 0);
|
||||
|
||||
_screen->_managed_textures = _gsg_managed_textures;
|
||||
_screen->_managed_vertex_buffers = _gsg_managed_vertex_buffers;
|
||||
_screen->_managed_index_buffers = _gsg_managed_index_buffers;
|
||||
|
||||
UINT available_texture_memory;
|
||||
|
||||
available_texture_memory = _d3d_device->GetAvailableTextureMem ( );
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug() << "*** GetAvailableTextureMem = " << available_texture_memory << "\n";
|
||||
}
|
||||
_available_texture_memory = available_texture_memory;
|
||||
|
||||
if (_lru)
|
||||
{
|
||||
delete _lru;
|
||||
_lru = 0;
|
||||
}
|
||||
|
||||
if (_enable_lru)
|
||||
{
|
||||
if (available_texture_memory >= 256000000)
|
||||
{
|
||||
// _enable_lru = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_enable_lru)
|
||||
{
|
||||
int maximum_memory;
|
||||
int maximum_pages;
|
||||
Lru *lru;
|
||||
|
||||
maximum_memory = available_texture_memory;
|
||||
|
||||
// TEST LRU *****
|
||||
maximum_memory = 20000000;
|
||||
maximum_pages = 20000;
|
||||
|
||||
lru = new Lru (maximum_memory, maximum_pages);
|
||||
if (lru)
|
||||
{
|
||||
lru -> _m.minimum_memory = 1000000;
|
||||
|
||||
lru -> register_lru_page_type (GPT_VertexBuffer, vertex_buffer_page_in_function, vertex_buffer_page_out_function);
|
||||
lru -> register_lru_page_type (GPT_IndexBuffer, index_buffer_page_in_function, index_buffer_page_out_function);
|
||||
|
||||
lru -> _m.context = (void *) this;
|
||||
}
|
||||
|
||||
_lru = lru;
|
||||
}
|
||||
|
||||
// check for render to texture support
|
||||
D3DDEVICE_CREATION_PARAMETERS creation_parameters;
|
||||
|
||||
@ -3207,6 +3412,8 @@ set_context(DXScreenData *new_context) {
|
||||
_screen = new_context;
|
||||
_d3d_device = _screen->_d3d_device; //copy this one field for speed of deref
|
||||
_swap_chain = _screen->_swap_chain; //copy this one field for speed of deref
|
||||
|
||||
_screen->_dxgsg9 = this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -3487,9 +3694,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
|
||||
}
|
||||
|
||||
// Calling this forces all of the textures and vbuffers to be
|
||||
// regenerated, a prerequisite to calling Reset(). Actually, this
|
||||
// shouldn't be necessary, because all of our textures and
|
||||
// vbuffers are stored in the D3DPOOL_MANAGED memory class.
|
||||
// regenerated, a prerequisite to calling Reset().
|
||||
release_all();
|
||||
|
||||
// Just to be extra-conservative for now, we'll go ahead and
|
||||
@ -3498,6 +3703,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
|
||||
release_all_vertex_buffers();
|
||||
release_all_index_buffers();
|
||||
|
||||
// must be called before reset
|
||||
_prepared_objects->update(this);
|
||||
|
||||
hr = _d3d_device->Reset(&_presentation_reset);
|
||||
@ -3942,4 +4148,3 @@ draw_indexed_primitive_up(D3DPRIMITIVETYPE primitive_type,
|
||||
index_data, index_type, safe_buffer_start - stride * min_index, stride);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,16 @@
|
||||
#include "fog.h"
|
||||
#include "pointerToArray.h"
|
||||
|
||||
#include "lru.h"
|
||||
|
||||
enum GsgPageType
|
||||
{
|
||||
GPT_Error,
|
||||
GPT_Texture,
|
||||
GPT_VertexBuffer,
|
||||
GPT_IndexBuffer,
|
||||
};
|
||||
|
||||
class Light;
|
||||
|
||||
class DXVertexBufferContext9;
|
||||
@ -186,8 +196,9 @@ protected:
|
||||
|
||||
INLINE static unsigned char *get_safe_buffer_start();
|
||||
|
||||
protected:
|
||||
public:
|
||||
DXScreenData *_screen;
|
||||
protected:
|
||||
LPDIRECT3DDEVICE9 _d3d_device; // same as _screen->_d3d_device, cached for spd
|
||||
IDirect3DSwapChain9 *_swap_chain;
|
||||
D3DPRESENT_PARAMETERS _presentation_reset; // This is built during reset device
|
||||
@ -234,6 +245,14 @@ protected:
|
||||
static unsigned char *_temp_buffer;
|
||||
static unsigned char *_safe_buffer_start;
|
||||
|
||||
int _gsg_managed_textures;
|
||||
int _gsg_managed_vertex_buffers;
|
||||
int _gsg_managed_index_buffers;
|
||||
int _enable_lru;
|
||||
UINT _available_texture_memory;
|
||||
|
||||
Lru *_lru;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
@ -259,6 +278,8 @@ private:
|
||||
friend class wdxGraphicsWindowGroup9;
|
||||
friend class DXTextureContext9;
|
||||
friend class wdxGraphicsBuffer9;
|
||||
friend class DXVertexBufferContext9;
|
||||
friend class DXIndexBufferContext9;
|
||||
};
|
||||
|
||||
#include "dxGraphicsStateGuardian9.I"
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "pStatTimer.h"
|
||||
#include <d3dx9.h>
|
||||
|
||||
#define DEBUG_INDEX_BUFFER false
|
||||
|
||||
TypeHandle DXIndexBufferContext9::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -35,6 +37,8 @@ DXIndexBufferContext9(GeomPrimitive *data) :
|
||||
IndexBufferContext(data),
|
||||
_ibuffer(NULL)
|
||||
{
|
||||
_managed = -1;
|
||||
_lru_page = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -44,17 +48,90 @@ DXIndexBufferContext9(GeomPrimitive *data) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DXIndexBufferContext9::
|
||||
~DXIndexBufferContext9() {
|
||||
|
||||
this -> free_ibuffer ( );
|
||||
|
||||
if (_lru_page)
|
||||
{
|
||||
_lru_page -> _m.lru -> remove_page (_lru_page);
|
||||
_lru_page -> _m.lru -> free_page (_lru_page);
|
||||
_lru_page = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext9::free_ibuffer
|
||||
// Access: Public
|
||||
// Description: Free index buffer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext9::
|
||||
free_ibuffer(void) {
|
||||
if (_ibuffer != NULL) {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "deleting index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
|
||||
if (DEBUG_INDEX_BUFFER)
|
||||
{
|
||||
RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ibuffer -> Release ( );
|
||||
}
|
||||
|
||||
_ibuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext9::allocate_ibuffer
|
||||
// Access: Public
|
||||
// Description: Allocates index buffer memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext9::
|
||||
allocate_ibuffer(DXScreenData &scrn) {
|
||||
|
||||
D3DFORMAT index_type =
|
||||
DXGraphicsStateGuardian9::get_index_type(get_data()->get_index_type());
|
||||
|
||||
int data_size;
|
||||
DWORD usage;
|
||||
D3DPOOL pool;
|
||||
|
||||
data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
_managed = scrn._managed_index_buffers;
|
||||
if (_managed)
|
||||
{
|
||||
usage = D3DUSAGE_WRITEONLY;
|
||||
pool = D3DPOOL_MANAGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
}
|
||||
|
||||
HRESULT hr = scrn._d3d_device->CreateIndexBuffer
|
||||
(data_size, usage, index_type, pool, &_ibuffer, NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.warning()
|
||||
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_ibuffer = NULL;
|
||||
} else {
|
||||
if (DEBUG_INDEX_BUFFER && dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "creating index buffer " << _ibuffer << ": "
|
||||
<< get_data()->get_num_vertices() << " indices ("
|
||||
<< get_data()->get_vertices()->get_array_format()->get_column(0)->get_numeric_type()
|
||||
<< ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext9::create_ibuffer
|
||||
// Access: Public
|
||||
@ -63,34 +140,45 @@ DXIndexBufferContext9::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext9::
|
||||
create_ibuffer(DXScreenData &scrn) {
|
||||
if (_ibuffer != NULL) {
|
||||
RELEASE(_ibuffer, dxgsg9, "index buffer", RELEASE_ONCE);
|
||||
_ibuffer = NULL;
|
||||
|
||||
this -> free_ibuffer ( );
|
||||
|
||||
if (_lru_page)
|
||||
{
|
||||
_lru_page -> _m.lru -> remove_page (_lru_page);
|
||||
_lru_page -> _m.lru -> free_page (_lru_page);
|
||||
_lru_page = 0;
|
||||
}
|
||||
|
||||
PStatTimer timer(GraphicsStateGuardian::_create_index_buffer_pcollector);
|
||||
|
||||
D3DFORMAT index_type =
|
||||
DXGraphicsStateGuardian9::get_index_type(get_data()->get_index_type());
|
||||
int data_size;
|
||||
|
||||
HRESULT hr = scrn._d3d_device->CreateIndexBuffer
|
||||
data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
// (get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY,
|
||||
// index_type, D3DPOOL_MANAGED, &_ibuffer, NULL);
|
||||
(get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
|
||||
index_type, D3DPOOL_DEFAULT, &_ibuffer, NULL);
|
||||
this -> allocate_ibuffer(scrn);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.warning()
|
||||
<< "CreateIndexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_ibuffer = NULL;
|
||||
} else {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "creating index buffer " << _ibuffer << ": "
|
||||
<< get_data()->get_num_vertices() << " indices ("
|
||||
<< get_data()->get_vertices()->get_array_format()->get_column(0)->get_numeric_type()
|
||||
<< ")\n";
|
||||
if (_ibuffer)
|
||||
{
|
||||
if (_managed == false)
|
||||
{
|
||||
Lru *lru;
|
||||
|
||||
lru = scrn._dxgsg9 -> _lru;
|
||||
if (lru)
|
||||
{
|
||||
LruPage *lru_page;
|
||||
|
||||
lru_page = lru -> allocate_page (data_size);
|
||||
if (lru_page)
|
||||
{
|
||||
lru_page -> _m.type = GPT_IndexBuffer;
|
||||
lru_page -> _m.lru_page_type.pointer = this;
|
||||
|
||||
lru -> add_cached_page (LPP_New, lru_page);
|
||||
_lru_page = lru_page;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,11 +202,17 @@ upload_data() {
|
||||
<< " bytes into index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
BYTE *local_pointer;
|
||||
|
||||
// HRESULT hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, 0);
|
||||
HRESULT hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
|
||||
|
||||
if (_managed)
|
||||
{
|
||||
hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _ibuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "IndexBuffer::Lock failed" << D3DERRORSTRING(hr);
|
||||
|
@ -33,10 +33,14 @@ public:
|
||||
DXIndexBufferContext9(GeomPrimitive *data);
|
||||
virtual ~DXIndexBufferContext9();
|
||||
|
||||
void free_ibuffer(void);
|
||||
void allocate_ibuffer(DXScreenData &scrn);
|
||||
void create_ibuffer(DXScreenData &scrn);
|
||||
void upload_data();
|
||||
|
||||
IDirect3DIndexBuffer9 *_ibuffer;
|
||||
int _managed;
|
||||
LruPage *_lru_page;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -47,6 +47,7 @@ DXTextureContext9(Texture *tex) :
|
||||
_d3d_volume_texture = NULL;
|
||||
_d3d_cube_texture = NULL;
|
||||
_has_mipmaps = false;
|
||||
_managed = -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -637,15 +638,35 @@ create_texture(DXScreenData &scrn) {
|
||||
D3DPOOL pool;
|
||||
|
||||
if (_texture->get_render_to_texture ()) {
|
||||
// REQUIRED
|
||||
// REQUIRED PARAMETERS
|
||||
_managed = false;
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_RENDERTARGET;
|
||||
target_pixel_format = scrn._render_to_texture_d3d_format;
|
||||
}
|
||||
else {
|
||||
pool = D3DPOOL_MANAGED;
|
||||
// pool = D3DPOOL_DEFAULT;
|
||||
usage = 0;
|
||||
_managed = scrn._managed_textures;
|
||||
if (_managed)
|
||||
{
|
||||
pool = D3DPOOL_MANAGED;
|
||||
usage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scrn._supports_dynamic_textures)
|
||||
{
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_DYNAMIC;
|
||||
}
|
||||
else
|
||||
{
|
||||
// can't lock textures so go back to managed for now
|
||||
// need to use UpdateTexture or UpdateSurface
|
||||
_managed = true;
|
||||
pool = D3DPOOL_MANAGED;
|
||||
usage = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (_texture->get_texture_type()) {
|
||||
|
@ -59,6 +59,7 @@ private:
|
||||
IDirect3DVolumeTexture9 *_d3d_volume_texture;
|
||||
IDirect3DCubeTexture9 *_d3d_cube_texture;
|
||||
|
||||
int _managed;
|
||||
bool _has_mipmaps;
|
||||
|
||||
public:
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "config_dxgsg9.h"
|
||||
#include <d3dx9.h>
|
||||
|
||||
#define DEBUG_VERTEX_BUFFER false
|
||||
|
||||
TypeHandle DXVertexBufferContext9::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -46,6 +48,8 @@ DXVertexBufferContext9(GeomVertexArrayData *data) :
|
||||
int num_columns = array_format->get_num_columns();
|
||||
|
||||
_fvf = 0;
|
||||
_managed = -1;
|
||||
_lru_page = 0;
|
||||
|
||||
if (n < num_columns &&
|
||||
array_format->get_column(n)->get_name() == InternalName::get_vertex()) {
|
||||
@ -170,17 +174,87 @@ DXVertexBufferContext9(GeomVertexArrayData *data) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DXVertexBufferContext9::
|
||||
~DXVertexBufferContext9() {
|
||||
|
||||
free_vbuffer ( );
|
||||
|
||||
if (_lru_page)
|
||||
{
|
||||
_lru_page -> _m.lru -> remove_page (_lru_page);
|
||||
_lru_page -> _m.lru -> free_page (_lru_page);
|
||||
_lru_page = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext9::free_vbuffer
|
||||
// Access: Public
|
||||
// Description: Frees vertex buffer memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext9::
|
||||
free_vbuffer(void) {
|
||||
|
||||
if (_vbuffer != NULL) {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "deleting vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_vbuffer, dxgsg9, "vertex buffer", RELEASE_ONCE);
|
||||
if (DEBUG_VERTEX_BUFFER)
|
||||
{
|
||||
RELEASE(_vbuffer, dxgsg9, "vertex buffer", RELEASE_ONCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_vbuffer -> Release ( );
|
||||
}
|
||||
|
||||
_vbuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext9::allocate_vbuffer
|
||||
// Access: Public
|
||||
// Description: Allocates vertex buffer memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext9::
|
||||
allocate_vbuffer(DXScreenData &scrn) {
|
||||
|
||||
int data_size;
|
||||
HRESULT hr;
|
||||
DWORD usage;
|
||||
D3DPOOL pool;
|
||||
|
||||
data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
_managed = scrn._managed_vertex_buffers;
|
||||
if (_managed)
|
||||
{
|
||||
pool = D3DPOOL_MANAGED;
|
||||
usage = D3DUSAGE_WRITEONLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC;
|
||||
}
|
||||
|
||||
hr = scrn._d3d_device->CreateVertexBuffer
|
||||
(data_size, usage, _fvf, pool, &_vbuffer, NULL);
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.warning()
|
||||
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_vbuffer = NULL;
|
||||
} else {
|
||||
if (DEBUG_VERTEX_BUFFER && dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "created vertex buffer " << _vbuffer << ": "
|
||||
<< get_data()->get_num_rows() << " vertices "
|
||||
<< *get_data()->get_array_format() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext9::create_vbuffer
|
||||
// Access: Public
|
||||
@ -189,30 +263,45 @@ DXVertexBufferContext9::
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext9::
|
||||
create_vbuffer(DXScreenData &scrn) {
|
||||
if (_vbuffer != NULL) {
|
||||
RELEASE(_vbuffer, dxgsg9, "vertex buffer", RELEASE_ONCE);
|
||||
_vbuffer = NULL;
|
||||
|
||||
free_vbuffer ( );
|
||||
|
||||
if (_lru_page)
|
||||
{
|
||||
_lru_page -> _m.lru -> remove_page (_lru_page);
|
||||
_lru_page -> _m.lru -> free_page (_lru_page);
|
||||
_lru_page = 0;
|
||||
}
|
||||
|
||||
PStatTimer timer(GraphicsStateGuardian::_create_vertex_buffer_pcollector);
|
||||
|
||||
HRESULT hr = scrn._d3d_device->CreateVertexBuffer
|
||||
int data_size;
|
||||
|
||||
// (get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY,
|
||||
// _fvf, D3DPOOL_MANAGED, &_vbuffer, NULL);
|
||||
(get_data()->get_data_size_bytes(), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC,
|
||||
_fvf, D3DPOOL_DEFAULT, &_vbuffer, NULL);
|
||||
data_size = get_data()->get_data_size_bytes();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.warning()
|
||||
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
||||
_vbuffer = NULL;
|
||||
} else {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "created vertex buffer " << _vbuffer << ": "
|
||||
<< get_data()->get_num_rows() << " vertices "
|
||||
<< *get_data()->get_array_format() << "\n";
|
||||
this -> allocate_vbuffer(scrn);
|
||||
|
||||
if (_vbuffer)
|
||||
{
|
||||
if (_managed == false)
|
||||
{
|
||||
Lru *lru;
|
||||
|
||||
lru = scrn._dxgsg9 -> _lru;
|
||||
if (lru)
|
||||
{
|
||||
LruPage *lru_page;
|
||||
|
||||
lru_page = lru -> allocate_page (data_size);
|
||||
if (lru_page)
|
||||
{
|
||||
lru_page -> _m.type = GPT_VertexBuffer;
|
||||
lru_page -> _m.lru_page_type.pointer = this;
|
||||
|
||||
lru -> add_cached_page (LPP_New, lru_page);
|
||||
_lru_page = lru_page;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -236,11 +325,17 @@ upload_data() {
|
||||
<< " bytes into vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
BYTE *local_pointer;
|
||||
|
||||
// HRESULT hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, 0);
|
||||
HRESULT hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
|
||||
|
||||
if (_managed)
|
||||
{
|
||||
hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _vbuffer->Lock(0, data_size, (void **) &local_pointer, D3DLOCK_DISCARD);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
|
||||
|
@ -33,11 +33,15 @@ public:
|
||||
DXVertexBufferContext9(GeomVertexArrayData *data);
|
||||
virtual ~DXVertexBufferContext9();
|
||||
|
||||
void free_vbuffer(void);
|
||||
void allocate_vbuffer(DXScreenData &scrn);
|
||||
void create_vbuffer(DXScreenData &scrn);
|
||||
void upload_data();
|
||||
|
||||
IDirect3DVertexBuffer9 *_vbuffer;
|
||||
int _fvf;
|
||||
int _managed;
|
||||
LruPage *_lru_page;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -8,4 +8,5 @@
|
||||
#include "wdxGraphicsPipe9.cxx"
|
||||
#include "wdxGraphicsWindow9.cxx"
|
||||
#include "dxGraphicsDevice9.cxx"
|
||||
#include "lru.cxx"
|
||||
|
||||
|
@ -187,6 +187,8 @@ typedef enum {
|
||||
#define RECT_XSIZE(REC) (REC.right-REC.left)
|
||||
#define RECT_YSIZE(REC) (REC.bottom-REC.top)
|
||||
|
||||
class DXGraphicsStateGuardian9;
|
||||
|
||||
struct DXScreenData {
|
||||
LPDIRECT3DDEVICE9 _d3d_device;
|
||||
IDirect3DSwapChain9 *_swap_chain;
|
||||
@ -209,6 +211,14 @@ struct DXScreenData {
|
||||
D3DPRESENT_PARAMETERS _presentation_params; // not redundant with _display_mode since width/height must be 0 for windowed mode
|
||||
D3DADAPTER_IDENTIFIER9 _dx_device_id;
|
||||
D3DFORMAT _render_to_texture_d3d_format;
|
||||
|
||||
int _managed_textures;
|
||||
int _managed_vertex_buffers;
|
||||
int _managed_index_buffers;
|
||||
|
||||
bool _supports_dynamic_textures;
|
||||
|
||||
DXGraphicsStateGuardian9 *_dxgsg9;
|
||||
};
|
||||
|
||||
|
||||
|
1191
panda/src/dxgsg9/lru.cxx
Normal file
1191
panda/src/dxgsg9/lru.cxx
Normal file
File diff suppressed because it is too large
Load Diff
206
panda/src/dxgsg9/lru.h
Normal file
206
panda/src/dxgsg9/lru.h
Normal file
@ -0,0 +1,206 @@
|
||||
|
||||
#ifndef LRU_H
|
||||
#define LRU_H
|
||||
|
||||
|
||||
#define MAXIMUM_LRU_PAGE_TYPES 8
|
||||
#define FRAME_MAXIMUM_PRIORITY_CHANGES 256
|
||||
|
||||
|
||||
class Lru;
|
||||
class LruPage;
|
||||
|
||||
enum LruPagePriority
|
||||
{
|
||||
LPP_Highest = 0,
|
||||
LPP_High = 10,
|
||||
LPP_New = 20,
|
||||
LPP_Normal = 25,
|
||||
LPP_Intermediate = 30,
|
||||
LPP_Low = 40,
|
||||
LPP_TotalPriorities = 50,
|
||||
|
||||
LPP_PageOut = LPP_TotalPriorities - 1
|
||||
};
|
||||
|
||||
typedef union _LruPageType
|
||||
{
|
||||
void *pointer;
|
||||
|
||||
}
|
||||
LruPageType;
|
||||
|
||||
typedef bool (*LruPageTypeFunction) (LruPage *lru_page);
|
||||
|
||||
class LruPage
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
LruPage ( );
|
||||
~LruPage ( );
|
||||
void change_priority (int delta);
|
||||
|
||||
public:
|
||||
|
||||
typedef struct _LruPageVariables
|
||||
{
|
||||
LruPageType lru_page_type;
|
||||
|
||||
int size;
|
||||
LruPagePriority priority;
|
||||
int priority_change;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int type : 4;
|
||||
unsigned int lock : 1;
|
||||
unsigned int in_cache : 1;
|
||||
unsigned int in_memory : 1;
|
||||
unsigned int on_disk : 1;
|
||||
};
|
||||
|
||||
int first_frame_identifier; // creation time
|
||||
int last_frame_identifier; // previous time page was used
|
||||
int current_frame_identifier;
|
||||
int update_frame_identifier;
|
||||
|
||||
int current_frame_usage;
|
||||
int last_frame_usage;
|
||||
|
||||
int total_frame_page_faults;
|
||||
int total_page_faults;
|
||||
|
||||
int total_usage;
|
||||
int update_total_usage;
|
||||
|
||||
int identifier; // this is also the number of pages created during the lifetime of the LRU
|
||||
|
||||
float average_frame_utilization;
|
||||
|
||||
LruPage *previous;
|
||||
LruPage *next;
|
||||
Lru *lru;
|
||||
}
|
||||
LruPageVariables;
|
||||
|
||||
LruPageVariables _m;
|
||||
|
||||
friend class Lru;
|
||||
};
|
||||
|
||||
|
||||
class Lru
|
||||
{
|
||||
public:
|
||||
|
||||
Lru (int maximum_memory, int maximum_pages);
|
||||
~Lru ( );
|
||||
|
||||
bool register_lru_page_type (int index, LruPageTypeFunction page_in_function, LruPageTypeFunction page_out_function);
|
||||
|
||||
LruPage *allocate_page (int size);
|
||||
void update_start_update_lru_page (LruPage *lru_page);
|
||||
|
||||
void free_page (LruPage *lru_page);
|
||||
|
||||
void add_page (LruPagePriority priority, LruPage *lru_page);
|
||||
void add_cached_page (LruPagePriority priority, LruPage *lru_page);
|
||||
void remove_page (LruPage *lru_page);
|
||||
|
||||
void lock_page (LruPage *lru_page);
|
||||
void unlock_page (LruPage *lru_page);
|
||||
|
||||
void access_page (LruPage *lru_page);
|
||||
|
||||
void set_maximum_frame_bandwidth_utilization (float maximum_frame_bandwidth_utilization);
|
||||
|
||||
void begin_frame ( );
|
||||
|
||||
void update_entire_lru ( );
|
||||
void partial_lru_update (int maximum_updates);
|
||||
void partial_lru_update_old (int approximate_maximum_updates);
|
||||
|
||||
// set maximum number of page updates per frame
|
||||
// pause/resume updates/current_frame_identifier
|
||||
|
||||
void unlock_all_pages (void);
|
||||
|
||||
void count_priority_level_pages (void);
|
||||
|
||||
private:
|
||||
bool page_out_lru (int memory_required);
|
||||
void update_page_priorities (void);
|
||||
void update_lru_page (LruPage *lru_page);
|
||||
void update_lru_page_old (LruPage *lru_page);
|
||||
|
||||
public:
|
||||
typedef struct _LruVariables
|
||||
{
|
||||
// LruPagePriority lists
|
||||
LruPage *lru_page_array [LPP_TotalPriorities];
|
||||
|
||||
int total_pages;
|
||||
int available_memory;
|
||||
int current_frame_identifier;
|
||||
|
||||
int maximum_memory;
|
||||
int minimum_memory; // target amount of memory to keep free if possible
|
||||
|
||||
int total_lifetime_page_ins;
|
||||
int total_lifetime_page_outs;
|
||||
|
||||
int total_page_ins_last_frame;
|
||||
int total_page_outs_last_frame;
|
||||
|
||||
int total_page_ins;
|
||||
int total_page_outs;
|
||||
|
||||
int total_page_access;
|
||||
|
||||
int minimum_page_out_frames; // number of frames required before page out
|
||||
int maximum_page_updates_per_frame; // unused pages
|
||||
|
||||
int start_priority_index;
|
||||
int update_overflow;
|
||||
LruPage *start_update_lru_page;
|
||||
|
||||
int identifier;
|
||||
|
||||
float weight;
|
||||
float maximum_frame_bandwidth_utilization;
|
||||
|
||||
float frame_bandwidth_factor;
|
||||
|
||||
LruPageTypeFunction page_in_function_array [MAXIMUM_LRU_PAGE_TYPES];
|
||||
LruPageTypeFunction page_out_function_array [MAXIMUM_LRU_PAGE_TYPES];
|
||||
|
||||
int total_lru_page_priority_changes;
|
||||
LruPage *lru_page_priority_change_array [FRAME_MAXIMUM_PRIORITY_CHANGES];
|
||||
|
||||
void *context;
|
||||
|
||||
int lru_page_count_array [LPP_TotalPriorities];
|
||||
|
||||
int maximum_pages;
|
||||
int total_lru_pages_in_pool;
|
||||
int total_lru_pages_in_free_pool;
|
||||
LruPage **lru_page_pool;
|
||||
LruPage **lru_page_free_pool;
|
||||
}
|
||||
LruVariables;
|
||||
|
||||
LruVariables _m;
|
||||
|
||||
friend class LruPage;
|
||||
};
|
||||
|
||||
float calculate_exponential_moving_average (float value, float weight, float average);
|
||||
bool default_page_in_function (LruPage *lru_page);
|
||||
bool default_page_out_function (LruPage *lru_page);
|
||||
|
||||
void test_ema (void);
|
||||
void test_lru (void);
|
||||
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user