integrate with new adaptive lru

This commit is contained in:
David Rose 2008-09-05 00:35:06 +00:00
parent bd4486aadf
commit c0b1f01a70
8 changed files with 6 additions and 516 deletions

View File

@ -71,9 +71,6 @@
#define SDK_VERSION(major,minor) tostring(major) << "." << tostring(minor)
#define DIRECTX_SDK_VERSION SDK_VERSION (_DXSDK_PRODUCT_MAJOR, _DXSDK_PRODUCT_MINOR) << "." << SDK_VERSION (_DXSDK_BUILD_MAJOR, _DXSDK_BUILD_MINOR)
#define DEBUG_LRU false
TypeHandle DXGraphicsStateGuardian9::_type_handle;
D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
@ -140,9 +137,6 @@ DXGraphicsStateGuardian9(GraphicsPipe *pipe) :
_gsg_managed_vertex_buffers = dx_management;
_gsg_managed_index_buffers = dx_management;
_enable_lru = dx_lru_management;
_lru = 0;
_last_fvf = 0;
_vertex_shader_version_major = 0;
@ -177,11 +171,6 @@ DXGraphicsStateGuardian9::
_d3d_device->SetTexture(0, NULL); // this frees reference to the old texture
}
free_nondx_resources();
if (_lru) {
delete _lru;
_lru = 0;
}
}
////////////////////////////////////////////////////////////////////
@ -235,10 +224,6 @@ apply_texture(int i, TextureContext *tc) {
DXTextureContext9 *dtc = DCAST(DXTextureContext9, tc);
Texture *tex = tc->get_texture();
if (_lru) {
_lru -> access_page (dtc -> _lru_page);
}
Texture::WrapMode wrap_u, wrap_v, wrap_w;
DWORD address_u;
@ -481,10 +466,6 @@ apply_vertex_buffer(VertexBufferContext *vbc,
stream = 0;
offset = 0;
if (_lru) {
_lru -> access_page (dvbc -> _lru_page);
}
if (dvbc->_vbuffer == NULL) {
// Attempt to create a new vertex buffer.
if (vertex_buffers &&
@ -691,10 +672,6 @@ apply_index_buffer(IndexBufferContext *ibc,
const GeomPrimitivePipelineReader *reader, bool force) {
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, reader);
@ -1067,11 +1044,6 @@ begin_frame(Thread *current_thread) {
return false;
}
if (_lru)
{
_lru -> begin_frame ( );
}
HRESULT hr = _d3d_device->BeginScene();
if (FAILED(hr)) {
@ -1226,86 +1198,6 @@ DBG_S dxgsg9_cat.debug ( ) << "@@@@@@@@@@ end_frame \n"; DBG_E
return;
}
if (_lru) {
int frames;
int maximum_updates;
// LRU update
maximum_updates = dx_lru_maximum_page_updates_per_frame;
_lru -> partial_lru_update (maximum_updates);
// LRU debug
if (false && dxgsg9_cat.is_debug()) {
dxgsg9_cat.debug() << "* start_priority_index " << _lru -> _m.start_priority_index << "\n";
dxgsg9_cat.debug() << "* start_update_lru_page " << _lru -> _m.start_update_lru_page << "\n";
}
frames = dx_lru_debug_frames_til_output;
if (dx_lru_debug && frames > 0 && (_lru -> _m.current_frame_identifier % frames) == 0) {
if (dxgsg9_cat.is_error()) {
UINT available_texture_memory;
available_texture_memory = _d3d_device->GetAvailableTextureMem ( );
dxgsg9_cat.error() << "* LRU: total_pages " << _lru -> _m.total_pages << "/" << _lru -> _m.maximum_pages << " upf " << dx_lru_maximum_page_updates_per_frame << " fto " << dx_lru_debug_frames_til_output << "\n";
dxgsg9_cat.error() << "* DX available_texture_memory = " << available_texture_memory << "\n";
dxgsg9_cat.error() << "* delta_memory " << _available_texture_memory - (available_texture_memory + (_lru -> _m.maximum_memory - _lru -> _m.available_memory)) << "\n";
dxgsg9_cat.error() << "* available_memory " << _lru -> _m.available_memory << "/" << _lru -> _m.maximum_memory << "\n";
dxgsg9_cat.error() << "* total lifetime pages created " << _lru -> _m.identifier << "\n";
dxgsg9_cat.error() << "* total_lifetime_page_ins " << _lru -> _m.total_lifetime_page_ins << "\n";
dxgsg9_cat.error() << "* total_lifetime_page_outs " << _lru -> _m.total_lifetime_page_outs << "\n";
dxgsg9_cat.error() << "* total_page_access " << _lru -> _m.total_page_access << " avg page access " << ((float) _lru -> _m.total_page_access / (float) frames) << "\n";
dxgsg9_cat.error() << "* total_lru_pages_in_pool " << _lru -> _m.total_lru_pages_in_pool << "\n";
dxgsg9_cat.error() << "* total_lru_pages_in_free_pool " << _lru -> _m.total_lru_pages_in_free_pool << "\n";
dxgsg9_cat.error() << "* avg unique page access size " << (_lru -> _m.total_page_access_size / (double) frames) << "\n";
dxgsg9_cat.error() << "* avg of all page access size " << ((_lru -> _m.total_page_access_size + _lru -> _m.total_page_all_access_size) / (double) frames) << "\n";
_lru -> _m.total_page_access = 0;
_lru -> _m.total_page_access_size = 0;
_lru -> _m.total_page_all_access_size = 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.error() << "* priority " << index << " pages " << _lru -> _m.lru_page_count_array [index] << "\n";
}
}
_lru -> calculate_lru_statistics ( );
for (index = 0; index < _lru -> _m.maximum_page_types; index++) {
PageTypeStatistics *page_type_statistics;
page_type_statistics = &_lru -> _m.page_type_statistics_array [index];
dxgsg9_cat.error() << "\n" <<
" page type " << index <<
" total pages " << page_type_statistics -> total_pages <<
" in " << page_type_statistics -> total_pages_in <<
" size " << page_type_statistics -> total_memory_in <<
" out " << page_type_statistics -> total_pages_out <<
" size " << page_type_statistics -> total_memory_out <<
"\n";
}
void display_lru (int type, int priority, Lru *lru);
int type;
if (dx_lru_debug_textures) {
type = GPT_Texture;
display_lru (type, -1, _lru);
}
if (dx_lru_debug_vertex_buffers) {
type = GPT_VertexBuffer;
display_lru (type, -1, _lru);
}
}
}
}
#if defined(DO_PSTATS)
if (_texmgrmem_total_pcollector.is_active()) {
#define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval
@ -2456,151 +2348,6 @@ do_framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
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
Thread *current_thread = Thread::get_current_thread();
CPT(GeomVertexArrayDataHandle) reader = vertex_buffer->get_data()->get_handle(current_thread);
/*
Not sure if this is the correct thing to do. Can we return false
from the page_in function? Will we get called again next frame if
we do?
if (_incomplete_render) {
// Check if the data is resident before continuing.
const unsigned char *data_pointer = reader->get_read_pointer(false);
if (data_pointer == NULL) {
return false;
}
}
*/
vertex_buffer -> allocate_vbuffer (*(gsg->_screen), reader);
// update vertex buffer
vertex_buffer -> upload_data(reader, true);
vertex_buffer -> set_resident(true);
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 ( );
vertex_buffer -> set_resident(false);
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
Thread *current_thread = Thread::get_current_thread();
GeomPrimitivePipelineReader reader(index_buffer->get_data(), current_thread);
/*
Not sure if this is the correct thing to do. Can we return false
from the page_in function? Will we get called again next frame if
we do?
if (_incomplete_render) {
// Check if the data is resident before continuing.
const unsigned char *data_pointer = reader.get_read_pointer(false);
if (data_pointer == NULL) {
return false;
}
}
*/
index_buffer -> allocate_ibuffer (*(gsg->_screen), &reader);
// update vertex buffer
index_buffer -> upload_data (&reader, true);
index_buffer -> set_resident(true);
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 ( );
index_buffer -> set_resident(false);
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;
}
bool texture_page_in_function (LruPage *lru_page)
{
DXGraphicsStateGuardian9 *gsg;
DXTextureContext9 *texture;
gsg = (DXGraphicsStateGuardian9 *) (lru_page -> _m.lru -> _m.context);
texture = (DXTextureContext9 *) lru_page -> _m.lru_page_type.pointer;
texture -> create_texture (*(gsg->_screen));
texture -> set_resident(true);
if (DEBUG_LRU && dxgsg9_cat.is_debug())
{
dxgsg9_cat.debug() << " *** page IN TEX " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
}
return true;
}
bool texture_page_out_function (LruPage *lru_page)
{
DXTextureContext9 *texture;
texture = (DXTextureContext9 *) lru_page -> _m.lru_page_type.pointer;
texture -> delete_texture ( );
texture -> set_resident(false);
if (DEBUG_LRU && dxgsg9_cat.is_debug())
{
dxgsg9_cat.debug() << " *** page OUT TEX " << lru_page -> _m.identifier << " size " << lru_page -> _m.size << "\n";
}
return true;
}
void DXGraphicsStateGuardian9::reset_render_states (void)
{
int index;
@ -2843,80 +2590,6 @@ reset() {
}
_available_texture_memory = available_texture_memory;
if (_lru == 0) {
if (dx_management == false && _enable_lru) {
int error;
int maximum_memory;
int maximum_pages;
Lru *lru;
int absolute_minimum_memory_requirement;
int minimum_memory_requirement;
int maximum_memory_requirement;
int free_memory_requirement;
maximum_pages = dx_lru_maximum_pages;
absolute_minimum_memory_requirement = 5000000;
minimum_memory_requirement = dx_lru_minimum_memory_requirement;
maximum_memory_requirement = dx_lru_maximum_memory_requirement;
free_memory_requirement = dx_lru_free_memory_requirement;
error = false;
maximum_memory = available_texture_memory - free_memory_requirement;
if (maximum_memory < minimum_memory_requirement) {
if (maximum_memory < absolute_minimum_memory_requirement) {
// video memory size is too small
dxgsg9_cat.error() << "Available video memory is too low " << _available_texture_memory << "\n";
error = true;
}
else {
// video memory is way too low, so take all of it
maximum_memory = available_texture_memory;
// need to warn user about low video memory
dxgsg9_cat.warning() << "Available video memory " << maximum_memory << " is below the minimum requirement of " << minimum_memory_requirement << "\n";
}
}
else {
if (maximum_memory_requirement != 0) {
if (maximum_memory >= maximum_memory_requirement) {
// cap video memory used
maximum_memory = maximum_memory_requirement;
}
} else {
// take all video memory
}
}
// no LRU if there is an error, go back to DirectX managed
if (error) {
_gsg_managed_textures = true;
_gsg_managed_vertex_buffers = true;
_gsg_managed_index_buffers = true;
} else {
int maximum_page_types;
maximum_page_types = GPT_TotalPageTypes;
lru = new Lru (maximum_memory, maximum_pages, maximum_page_types);
if (lru) {
// register page in and out callbacks
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 -> register_lru_page_type (GPT_Texture, texture_page_in_function, texture_page_out_function);
lru -> _m.context = (void *) this;
}
_lru = lru;
}
}
}
// check for render to texture support
D3DDEVICE_CREATION_PARAMETERS creation_parameters;
@ -5500,9 +5173,12 @@ check_dx_allocation (HRESULT result, int allocation_size, int attempts)
case D3DERR_OUTOFVIDEOMEMORY:
case E_OUTOFMEMORY:
if (_lru) {
// increase the page out size as the number of attempts increases
if (_lru -> page_out_lru (allocation_size * attempts)) {
// increase the page out size as the number of attempts increases
{
size_t current_size = _prepared_objects->_graphics_memory_lru.get_total_size();
size_t target_size = max(current_size - allocation_size * attempts, 0);
_prepared_objects->_graphics_memory_lru.evict_to(target_size);
if (_prepared_objects->_graphics_memory_lru.get_total_size() < current_size) {
retry = true;
}
}
@ -6075,82 +5751,3 @@ KEY_ELEMENT *add_to_key_list (KEY key, KEY_LIST *key_list)
return key_element;
}
void display_lru (int type, int priority, Lru *lru)
{
int index;
KEY_LIST *all_key_list;
all_key_list = new_key_list ( );
for (index = 0; index < LPP_TotalPriorities; index++)
{
if (priority == -1 || index == priority)
{
LruPage *lru_page;
LruPage *next_lru_page;
lru_page = lru -> _m.lru_page_array[index];
KEY_LIST *key_list;
key_list = new_key_list ( );
while (lru_page)
{
if (type == lru_page -> _m.v.type)
{
// cout << " " << lru_page -> _m.name << "\n";
KEY_ELEMENT *key_element;
key_element = add_to_key_list (lru_page -> _m.name, key_list);
key_element = add_to_key_list (lru_page -> _m.name, all_key_list);
}
next_lru_page = lru_page -> _m.next;
lru_page = next_lru_page;
}
if (key_list -> total_key_elements > 0)
{
dxgsg9_cat.error() << "priority " << index << "\n";
KEY_ELEMENT *key_element;
KEY_ELEMENT *key_element_next;
key_element = first_key_element (key_list);
while (key_element)
{
key_element_next = next_key_element (key_element);
dxgsg9_cat.error() << " " << key_element -> count << " " << key_element -> key << "\n";
key_element = key_element_next;
}
}
delete_key_list (key_list);
}
}
if (all_key_list -> total_key_elements > 0)
{
KEY_ELEMENT *key_element;
KEY_ELEMENT *key_element_next;
dxgsg9_cat.error() << "ALL KEYS \n";
key_element = first_key_element (all_key_list);
while (key_element)
{
key_element_next = next_key_element (key_element);
dxgsg9_cat.error() << " " << key_element -> count << " " << key_element -> key << "\n";
key_element = key_element_next;
}
}
delete_key_list (all_key_list);
}

View File

@ -324,11 +324,8 @@ protected:
int _gsg_managed_textures;
int _gsg_managed_vertex_buffers;
int _gsg_managed_index_buffers;
int _enable_lru;
UINT _available_texture_memory;
Lru *_lru;
DWORD _last_fvf;
#define MAXIMUM_TEXTURES 16

View File

@ -33,7 +33,6 @@ DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
_ibuffer(NULL)
{
_managed = -1;
_lru_page = 0;
}
////////////////////////////////////////////////////////////////////
@ -45,13 +44,6 @@ 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;
}
}
////////////////////////////////////////////////////////////////////
@ -174,13 +166,6 @@ create_ibuffer(DXScreenData &scrn,
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,
current_thread);
@ -189,30 +174,6 @@ create_ibuffer(DXScreenData &scrn,
data_size = reader->get_data_size_bytes();
this -> allocate_ibuffer(scrn, reader);
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.v.type = GPT_IndexBuffer;
lru_page -> _m.lru_page_type.pointer = this;
lru -> add_cached_page (LPP_New, lru_page);
_lru_page = lru_page;
}
}
}
}
}
////////////////////////////////////////////////////////////////////

View File

@ -38,7 +38,6 @@ public:
IDirect3DIndexBuffer9 *_ibuffer;
int _managed;
LruPage *_lru_page;
public:
static TypeHandle get_class_type() {

View File

@ -48,7 +48,6 @@ DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex) :
_d3d_cube_texture = NULL;
_has_mipmaps = false;
_managed = -1;
_lru_page = 0;
}
////////////////////////////////////////////////////////////////////
@ -58,13 +57,6 @@ DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex) :
////////////////////////////////////////////////////////////////////
DXTextureContext9::
~DXTextureContext9() {
if (_lru_page)
{
_lru_page -> _m.lru -> remove_page (_lru_page);
_lru_page -> _m.lru -> free_page (_lru_page);
_lru_page = 0;
}
delete_texture();
}
@ -960,24 +952,6 @@ create_texture(DXScreenData &scrn) {
// must not put render to texture into LRU
if (!_managed && !tex->get_render_to_texture()) {
if (_lru_page == 0) {
Lru *lru;
lru = scrn._dxgsg9 -> _lru;
if (lru) {
LruPage *lru_page;
lru_page = lru -> allocate_page (data_size);
if (lru_page) {
lru_page -> _m.v.type = GPT_Texture;
lru_page -> _m.lru_page_type.pointer = this;
lru_page -> _m.name = tex->get_filename();
lru -> add_cached_page (LPP_New, lru_page);
_lru_page = lru_page;
}
}
}
tex->texture_uploaded(scrn._dxgsg9);
}
mark_loaded();

View File

@ -64,9 +64,6 @@ private:
int _managed;
public:
LruPage *_lru_page;
private:
bool _has_mipmaps;

View File

@ -158,7 +158,6 @@ DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data,
_fvf = 0;
_managed = -1;
_lru_page = 0;
_direct_3d_vertex_declaration = 0;
_shader_context = 0;
@ -297,12 +296,6 @@ 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;
}
}
////////////////////////////////////////////////////////////////////
@ -422,12 +415,6 @@ create_vbuffer(DXScreenData &scrn,
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,
current_thread);
@ -436,27 +423,6 @@ create_vbuffer(DXScreenData &scrn,
data_size = reader->get_data_size_bytes();
this -> allocate_vbuffer(scrn, reader);
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.v.type = GPT_VertexBuffer;
lru_page -> _m.lru_page_type.pointer = this;
lru_page -> _m.name = name;
lru -> add_cached_page (LPP_New, lru_page);
_lru_page = lru_page;
}
}
}
}
}
////////////////////////////////////////////////////////////////////

View File

@ -40,7 +40,6 @@ public:
int _fvf;
int _managed;
LruPage *_lru_page;
VERTEX_ELEMENT_TYPE *_vertex_element_type_array;
DIRECT_3D_VERTEX_DECLARATION _direct_3d_vertex_declaration;