mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
graphics-memory-limit
This commit is contained in:
parent
d9b8296fc8
commit
a8ec068c05
@ -1240,6 +1240,9 @@ end_frame(Thread *current_thread) {
|
||||
_texture_state_pcollector.flush_level();
|
||||
_transform_state_pcollector.flush_level();
|
||||
_draw_primitive_pcollector.flush_level();
|
||||
|
||||
// Evict any textures and/or vbuffers that exceed our texture memory.
|
||||
_prepared_objects->_graphics_memory_lru.begin_epoch();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,8 +84,6 @@ ConfigVariableBool dx_ignore_mipmaps
|
||||
// if this is set, more accurate but more expensive fog computations are performed
|
||||
ConfigVariableBool dx_use_rangebased_fog
|
||||
("dx-use-rangebased-fog", false);
|
||||
ConfigVariableBool dx_force_16bpptextures
|
||||
("dx-force-16bpptextures", false);
|
||||
ConfigVariableBool dx_no_dithering
|
||||
("dx-no-dithering", false);
|
||||
ConfigVariableBool dx_force_16bpp_zbuffer
|
||||
|
@ -39,7 +39,6 @@ extern ConfigVariableBool dx_broken_max_index;
|
||||
extern ConfigVariableBool dx_ignore_mipmaps;
|
||||
extern ConfigVariableBool dx_mipmap_everything;
|
||||
extern ConfigVariableBool dx_show_transforms;
|
||||
extern ConfigVariableBool dx_force_16bpptextures;
|
||||
extern ConfigVariableBool dx_no_dithering;
|
||||
extern ConfigVariableBool dx_force_anisotropic_filtering;
|
||||
extern ConfigVariableBool dx_force_16bpp_zbuffer;
|
||||
|
@ -277,6 +277,7 @@ update_texture(TextureContext *tc, bool force) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -427,6 +428,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
|
||||
dvbc->set_active(true);
|
||||
}
|
||||
}
|
||||
dvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
HRESULT hr = _d3d_device->SetVertexShader(dvbc->_fvf);
|
||||
#ifndef NDEBUG
|
||||
@ -524,6 +526,7 @@ apply_index_buffer(IndexBufferContext *ibc,
|
||||
dibc->set_active(true);
|
||||
}
|
||||
}
|
||||
dibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1572,7 +1575,11 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
SAFE_RELEASE(render_target);
|
||||
SAFE_RELEASE(tex_level_0);
|
||||
|
||||
if (!okflag) {
|
||||
if (okflag) {
|
||||
dtc->mark_loaded();
|
||||
dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
} else {
|
||||
// The copy failed. Fall back to copying it to RAM and back.
|
||||
// Terribly slow, but what are you going to do?
|
||||
return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
|
||||
|
@ -51,6 +51,39 @@ DXIndexBufferContext8::
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext8::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext8::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
|
||||
if (_ibuffer != NULL) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "deleting index buffer " << _ibuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_ibuffer, dxgsg8, "index buffer", RELEASE_ONCE);
|
||||
_ibuffer = NULL;
|
||||
}
|
||||
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext8::create_ibuffer
|
||||
// Access: Public
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
DXIndexBufferContext8(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
|
||||
virtual ~DXIndexBufferContext8();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
void create_ibuffer(DXScreenData &scrn,
|
||||
const GeomPrimitivePipelineReader *reader);
|
||||
bool upload_data(const GeomPrimitivePipelineReader *reader, bool force);
|
||||
|
@ -57,6 +57,35 @@ DXTextureContext8::
|
||||
delete_texture();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXTextureContext8::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXTextureContext8::
|
||||
evict_lru() {
|
||||
if (get_texture()->get_render_to_texture()) {
|
||||
// Don't evict the result of render-to-texture.
|
||||
mark_used_lru();
|
||||
return;
|
||||
}
|
||||
|
||||
dequeue_lru();
|
||||
delete_texture();
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXTextureContext8::create_texture
|
||||
// Access: Public
|
||||
@ -308,17 +337,49 @@ create_texture(DXScreenData &scrn) {
|
||||
// D3DXCheckTextureRequirements(), but it wouldn't handle all my
|
||||
// specialized low-memory cases perfectly
|
||||
|
||||
#define CONVTYPE_STMT
|
||||
|
||||
#define CHECK_FOR_FMT(FMT, CONV) \
|
||||
#define CHECK_FOR_FMT(FMT) \
|
||||
if (scrn._supported_tex_formats_mask & FMT##_FLAG) { \
|
||||
CONVTYPE_STMT; \
|
||||
target_pixel_format = D3DFMT_##FMT; \
|
||||
goto found_matching_format; }
|
||||
|
||||
if (texture_stored_compressed){
|
||||
// if the texture is already compressed, we need to choose the
|
||||
// corresponding format, otherwise we might end up
|
||||
// cross-compressing from e.g. DXT5 to DXT3
|
||||
switch (compression_mode){
|
||||
case Texture::CM_dxt1:
|
||||
CHECK_FOR_FMT(DXT1);
|
||||
break;
|
||||
case Texture::CM_dxt2:
|
||||
CHECK_FOR_FMT(DXT2);
|
||||
break;
|
||||
case Texture::CM_dxt3:
|
||||
CHECK_FOR_FMT(DXT3);
|
||||
break;
|
||||
case Texture::CM_dxt4:
|
||||
CHECK_FOR_FMT(DXT4);
|
||||
break;
|
||||
case Texture::CM_dxt5:
|
||||
CHECK_FOR_FMT(DXT5);
|
||||
break;
|
||||
}
|
||||
// if we can't support the texture's compressed image, we can't
|
||||
// load the texture.
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (compress_texture) {
|
||||
if (num_alpha_bits <= 1) {
|
||||
CHECK_FOR_FMT(DXT1);
|
||||
} else if (num_alpha_bits <= 4) {
|
||||
CHECK_FOR_FMT(DXT3);
|
||||
} else {
|
||||
CHECK_FOR_FMT(DXT5);
|
||||
}
|
||||
}
|
||||
|
||||
// handle each target bitdepth separately. might be less confusing
|
||||
// to reorg by num_color_channels (input type, rather than desired
|
||||
// 1st target)
|
||||
// to reorg by num_color_channels (input type)
|
||||
switch (target_bpp) {
|
||||
|
||||
// IMPORTANT NOTE:
|
||||
@ -329,37 +390,8 @@ create_texture(DXScreenData &scrn) {
|
||||
if (!((num_color_channels == 3) || (num_color_channels == 4)))
|
||||
break; //bail
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
if (compress_texture) {
|
||||
if (texture_stored_compressed){
|
||||
// if the texture is already compressed, we need to choose the corresponding format,
|
||||
// otherwise we might end up cross-compressing from e.g. DXT5 to DXT3
|
||||
switch (compression_mode){
|
||||
case Texture::CM_dxt2:
|
||||
CHECK_FOR_FMT(DXT2, Conv32toDXT2);
|
||||
break;
|
||||
case Texture::CM_dxt3:
|
||||
CHECK_FOR_FMT(DXT3, Conv32toDXT3);
|
||||
break;
|
||||
case Texture::CM_dxt4:
|
||||
CHECK_FOR_FMT(DXT4, Conv32toDXT4);
|
||||
break;
|
||||
case Texture::CM_dxt5:
|
||||
CHECK_FOR_FMT(DXT5, Conv32toDXT5);
|
||||
break;
|
||||
}
|
||||
// if no compressed format matches, just fall trhough to pick a different format
|
||||
}
|
||||
else
|
||||
CHECK_FOR_FMT(DXT3, Conv32toDXT3);
|
||||
}
|
||||
if (num_color_channels == 4) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, Conv32to32);
|
||||
} else {
|
||||
CHECK_FOR_FMT(A8R8G8B8, Conv24to32);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
if (num_alpha_bits>0) {
|
||||
nassertr(num_color_channels == 4, false);
|
||||
|
||||
@ -377,16 +409,13 @@ create_texture(DXScreenData &scrn) {
|
||||
// assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify
|
||||
// 32->16 conversion. This should be true on most cards.
|
||||
|
||||
#ifndef FORCE_16bpp_1555
|
||||
if (num_alpha_bits == 1)
|
||||
#endif
|
||||
{
|
||||
CHECK_FOR_FMT(A1R5G5B5, Conv32to16_1555);
|
||||
}
|
||||
if (num_alpha_bits == 1) {
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
}
|
||||
|
||||
// normally prefer 4444 due to better alpha channel resolution
|
||||
CHECK_FOR_FMT(A4R4G4B4, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(A1R5G5B5, Conv32to16_1555);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
|
||||
// At this point, bail. Don't worry about converting to
|
||||
// non-alpha formats yet, I think this will be a very rare case.
|
||||
@ -395,11 +424,11 @@ create_texture(DXScreenData &scrn) {
|
||||
// convert 3 or 4 channel to closest 16bpp color fmt
|
||||
|
||||
if (num_color_channels == 3) {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_4444);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
} else {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -407,23 +436,19 @@ create_texture(DXScreenData &scrn) {
|
||||
case 24:
|
||||
nassertr(num_color_channels == 3, false);
|
||||
|
||||
if (compress_texture) {
|
||||
CHECK_FOR_FMT(DXT1, Conv24toDXT1);
|
||||
}
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(R8G8B8, Conv24to24);
|
||||
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
|
||||
CHECK_FOR_FMT(X8R8G8B8, Conv24to32);
|
||||
}
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
// no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st)
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
@ -431,22 +456,16 @@ create_texture(DXScreenData &scrn) {
|
||||
nassertr(num_alpha_bits > 0, false);
|
||||
nassertr(num_color_channels == 2, false);
|
||||
|
||||
CHECK_FOR_FMT(A8L8, ConvLum16to16);
|
||||
CHECK_FOR_FMT(A8L8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, ConvLum16to32);
|
||||
if (num_alpha_bits == 1) {
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
}
|
||||
|
||||
#ifndef FORCE_16bpp_1555
|
||||
if (num_alpha_bits == 1)
|
||||
#endif
|
||||
{
|
||||
CHECK_FOR_FMT(A1R5G5B5, ConvLum16to16_1555);
|
||||
}
|
||||
|
||||
// normally prefer 4444 due to better alpha channel resolution
|
||||
CHECK_FOR_FMT(A4R4G4B4, ConvLum16to16_4444);
|
||||
CHECK_FOR_FMT(A1R5G5B5, ConvLum16to16_1555);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
} else {
|
||||
nassertr((num_color_channels == 3)||(num_color_channels == 4), false);
|
||||
// look for compatible 16bit fmts, if none then give up
|
||||
@ -454,13 +473,13 @@ create_texture(DXScreenData &scrn) {
|
||||
switch(num_alpha_bits) {
|
||||
case 0:
|
||||
if (num_color_channels == 3) {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
} else {
|
||||
nassertr(num_color_channels == 4, false);
|
||||
// it could be 4 if user asks us to throw away the alpha channel
|
||||
CHECK_FOR_FMT(R5G6B5, Conv32to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -469,13 +488,13 @@ create_texture(DXScreenData &scrn) {
|
||||
// could use 32bpp ARGB. fail if this particular fmt not
|
||||
// avail.
|
||||
nassertr(num_color_channels == 4, false);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
break;
|
||||
case 4:
|
||||
// app specifically requests 4-4-4-4 F_rgba4 case, as opposed
|
||||
// to F_rgba, which could use 32bpp ARGB
|
||||
nassertr(num_color_channels == 4, false);
|
||||
CHECK_FOR_FMT(A4R4G4B4, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
break;
|
||||
default:
|
||||
nassertr(false, false); // problem in get_bits_per_pixel()?
|
||||
@ -488,16 +507,14 @@ create_texture(DXScreenData &scrn) {
|
||||
nassertr(num_color_channels == 1, false);
|
||||
|
||||
// look for native lum fmt first
|
||||
CHECK_FOR_FMT(L8, ConvLum8to8);
|
||||
CHECK_FOR_FMT(L8, ConvLum8to16_A8L8);
|
||||
CHECK_FOR_FMT(L8);
|
||||
CHECK_FOR_FMT(L8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(R8G8B8, ConvLum8to24);
|
||||
CHECK_FOR_FMT(X8R8G8B8, ConvLum8to32);
|
||||
}
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
|
||||
CHECK_FOR_FMT(R5G6B5, ConvLum8to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, ConvLum8to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
|
||||
} else if (num_alpha_bits == 8) {
|
||||
// look for 16bpp A8L8, else 32-bit ARGB, else 16-4444.
|
||||
@ -507,13 +524,9 @@ create_texture(DXScreenData &scrn) {
|
||||
// model we need somehow (is it that voodoo assumes color is
|
||||
// white? isnt that what we do in ConvAlpha8to32 anyway?)
|
||||
|
||||
CHECK_FOR_FMT(A8L8, ConvAlpha8to16_A8L8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, ConvAlpha8to32);
|
||||
}
|
||||
|
||||
CHECK_FOR_FMT(A4R4G4B4, ConvAlpha8to16_4444);
|
||||
CHECK_FOR_FMT(A8L8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1506,7 +1519,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn) {
|
||||
int miplevel_count = _d3d_2d_texture->GetLevelCount(); // what if it's not a 2d texture?
|
||||
if (miplevel_count <= tex->get_num_loadable_ram_mipmap_images()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "Using pre-calculated mipmap levels for texture " << tex->get_name();
|
||||
<< "Using pre-calculated mipmap levels for texture " << tex->get_name() << "\n";
|
||||
|
||||
for (int mip_level = 1; mip_level < miplevel_count; ++mip_level) {
|
||||
hr = fill_d3d_texture_mipmap_pixels(mip_level, di, source_format);
|
||||
@ -1781,10 +1794,10 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) {
|
||||
return 24;
|
||||
case Texture::F_rgba8:
|
||||
case Texture::F_rgba:
|
||||
*alphbits = 8;
|
||||
return 32;
|
||||
case Texture::F_rgbm:
|
||||
if (format == Texture::F_rgbm) // does this make any sense?
|
||||
*alphbits = 1;
|
||||
else *alphbits = 8;
|
||||
*alphbits = 1;
|
||||
return 32;
|
||||
case Texture::F_rgb12:
|
||||
return 36;
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
DXTextureContext8(PreparedGraphicsObjects *pgo, Texture *tex);
|
||||
virtual ~DXTextureContext8();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
bool create_texture(DXScreenData &scrn);
|
||||
bool create_simple_texture(DXScreenData &scrn);
|
||||
void delete_texture();
|
||||
|
@ -177,6 +177,39 @@ DXVertexBufferContext8::
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext8::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext8::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
|
||||
if (_vbuffer != NULL) {
|
||||
if (dxgsg8_cat.is_debug()) {
|
||||
dxgsg8_cat.debug()
|
||||
<< "deleting vertex buffer " << _vbuffer << "\n";
|
||||
}
|
||||
|
||||
RELEASE(_vbuffer, dxgsg8, "vertex buffer", RELEASE_ONCE);
|
||||
_vbuffer = NULL;
|
||||
}
|
||||
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext8::create_vbuffer
|
||||
// Access: Public
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
DXVertexBufferContext8(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data);
|
||||
virtual ~DXVertexBufferContext8();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
void create_vbuffer(DXScreenData &scrn,
|
||||
const GeomVertexArrayDataHandle *reader);
|
||||
bool upload_data(const GeomVertexArrayDataHandle *reader, bool force);
|
||||
|
@ -87,8 +87,6 @@ ConfigVariableBool dx_ignore_mipmaps
|
||||
// if this is set, more accurate but more expensive fog computations are performed
|
||||
ConfigVariableBool dx_use_rangebased_fog
|
||||
("dx-use-rangebased-fog", false);
|
||||
ConfigVariableBool dx_force_16bpptextures
|
||||
("dx-force-16bpptextures", false);
|
||||
ConfigVariableBool dx_no_dithering
|
||||
("dx-no-dithering", false);
|
||||
ConfigVariableBool dx_force_16bpp_zbuffer
|
||||
|
@ -38,7 +38,6 @@ extern ConfigVariableBool dx_broken_max_index;
|
||||
extern ConfigVariableBool dx_ignore_mipmaps;
|
||||
extern ConfigVariableBool dx_mipmap_everything;
|
||||
extern ConfigVariableBool dx_show_transforms;
|
||||
extern ConfigVariableBool dx_force_16bpptextures;
|
||||
extern ConfigVariableBool dx_no_dithering;
|
||||
extern ConfigVariableBool dx_force_anisotropic_filtering;
|
||||
extern ConfigVariableBool dx_force_16bpp_zbuffer;
|
||||
|
@ -335,10 +335,10 @@ update_texture(TextureContext *tc, bool force) {
|
||||
Texture *tex = tc->get_texture();
|
||||
dxgsg9_cat.error()
|
||||
<< "Unable to re-create texture " << *tex << endl;
|
||||
cerr << "b\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -525,6 +525,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
|
||||
set_stream_source = true;
|
||||
}
|
||||
}
|
||||
dvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
if (shader_context == 0) {
|
||||
// FVF MODE
|
||||
@ -735,6 +736,7 @@ apply_index_buffer(IndexBufferContext *ibc,
|
||||
dibc->set_active(true);
|
||||
}
|
||||
}
|
||||
dibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2243,7 +2245,11 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
SAFE_RELEASE(render_target);
|
||||
SAFE_RELEASE(tex_level_0);
|
||||
|
||||
if (!okflag) {
|
||||
if (okflag) {
|
||||
dtc->mark_loaded();
|
||||
dtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
} else {
|
||||
// The copy failed. Fall back to copying it to RAM and back.
|
||||
// Terribly slow, but what are you going to do?
|
||||
return do_framebuffer_copy_to_ram(tex, z, dr, rb, true);
|
||||
|
@ -54,6 +54,29 @@ DXIndexBufferContext9::
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext9::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXIndexBufferContext9::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
free_ibuffer();
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXIndexBufferContext9::free_ibuffer
|
||||
// Access: Public
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
DXIndexBufferContext9(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
|
||||
virtual ~DXIndexBufferContext9();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
void free_ibuffer();
|
||||
void allocate_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader);
|
||||
void create_ibuffer(DXScreenData &scrn, const GeomPrimitivePipelineReader *reader);
|
||||
|
@ -68,6 +68,35 @@ DXTextureContext9::
|
||||
delete_texture();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXTextureContext9::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXTextureContext9::
|
||||
evict_lru() {
|
||||
if (get_texture()->get_render_to_texture()) {
|
||||
// Don't evict the result of render-to-texture.
|
||||
mark_used_lru();
|
||||
return;
|
||||
}
|
||||
|
||||
dequeue_lru();
|
||||
delete_texture();
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXTextureContext9::create_texture
|
||||
// Access: Public
|
||||
@ -318,14 +347,47 @@ create_texture(DXScreenData &scrn) {
|
||||
// D3DXCheckTextureRequirements(), but it wouldn't handle all my
|
||||
// specialized low-memory cases perfectly
|
||||
|
||||
#define CONVTYPE_STMT
|
||||
|
||||
#define CHECK_FOR_FMT(FMT, CONV) \
|
||||
#define CHECK_FOR_FMT(FMT) \
|
||||
if (scrn._supported_tex_formats_mask & FMT##_FLAG) { \
|
||||
CONVTYPE_STMT; \
|
||||
target_pixel_format = D3DFMT_##FMT; \
|
||||
goto found_matching_format; }
|
||||
|
||||
if (texture_stored_compressed){
|
||||
// if the texture is already compressed, we need to choose the
|
||||
// corresponding format, otherwise we might end up
|
||||
// cross-compressing from e.g. DXT5 to DXT3
|
||||
switch (compression_mode){
|
||||
case Texture::CM_dxt1:
|
||||
CHECK_FOR_FMT(DXT1);
|
||||
break;
|
||||
case Texture::CM_dxt2:
|
||||
CHECK_FOR_FMT(DXT2);
|
||||
break;
|
||||
case Texture::CM_dxt3:
|
||||
CHECK_FOR_FMT(DXT3);
|
||||
break;
|
||||
case Texture::CM_dxt4:
|
||||
CHECK_FOR_FMT(DXT4);
|
||||
break;
|
||||
case Texture::CM_dxt5:
|
||||
CHECK_FOR_FMT(DXT5);
|
||||
break;
|
||||
}
|
||||
// if we can't support the texture's compressed image, we can't
|
||||
// load the texture.
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (compress_texture) {
|
||||
if (num_alpha_bits <= 1) {
|
||||
CHECK_FOR_FMT(DXT1);
|
||||
} else if (num_alpha_bits <= 4) {
|
||||
CHECK_FOR_FMT(DXT3);
|
||||
} else {
|
||||
CHECK_FOR_FMT(DXT5);
|
||||
}
|
||||
}
|
||||
|
||||
// handle each target bitdepth separately. might be less confusing
|
||||
// to reorg by num_color_channels (input type, rather than desired
|
||||
// 1st target)
|
||||
@ -359,36 +421,7 @@ create_texture(DXScreenData &scrn) {
|
||||
if (!((num_color_channels == 3) || (num_color_channels == 4)))
|
||||
break; //bail
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
if (compress_texture) {
|
||||
if (texture_stored_compressed){
|
||||
// if the texture is already compressed, we need to choose the corresponding format,
|
||||
// otherwise we might end up cross-compressing from e.g. DXT5 to DXT3
|
||||
switch (compression_mode){
|
||||
case Texture::CM_dxt2:
|
||||
CHECK_FOR_FMT(DXT2, Conv32toDXT2);
|
||||
break;
|
||||
case Texture::CM_dxt3:
|
||||
CHECK_FOR_FMT(DXT3, Conv32toDXT3);
|
||||
break;
|
||||
case Texture::CM_dxt4:
|
||||
CHECK_FOR_FMT(DXT4, Conv32toDXT4);
|
||||
break;
|
||||
case Texture::CM_dxt5:
|
||||
CHECK_FOR_FMT(DXT5, Conv32toDXT5);
|
||||
break;
|
||||
}
|
||||
// if no compressed format matches, just fall trhough to pick a different format
|
||||
}
|
||||
else
|
||||
CHECK_FOR_FMT(DXT3, Conv32toDXT3);
|
||||
}
|
||||
if (num_color_channels == 4) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, Conv32to32);
|
||||
} else {
|
||||
CHECK_FOR_FMT(A8R8G8B8, Conv24to32);
|
||||
}
|
||||
}
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
if (num_alpha_bits>0) {
|
||||
nassertr(num_color_channels == 4, false);
|
||||
@ -407,16 +440,13 @@ create_texture(DXScreenData &scrn) {
|
||||
// assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify
|
||||
// 32->16 conversion. This should be true on most cards.
|
||||
|
||||
#ifndef FORCE_16bpp_1555
|
||||
if (num_alpha_bits == 1)
|
||||
#endif
|
||||
{
|
||||
CHECK_FOR_FMT(A1R5G5B5, Conv32to16_1555);
|
||||
if (num_alpha_bits == 1) {
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
}
|
||||
|
||||
// normally prefer 4444 due to better alpha channel resolution
|
||||
CHECK_FOR_FMT(A4R4G4B4, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(A1R5G5B5, Conv32to16_1555);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
|
||||
// At this point, bail. Don't worry about converting to
|
||||
// non-alpha formats yet, I think this will be a very rare case.
|
||||
@ -425,11 +455,11 @@ create_texture(DXScreenData &scrn) {
|
||||
// convert 3 or 4 channel to closest 16bpp color fmt
|
||||
|
||||
if (num_color_channels == 3) {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_4444);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
} else {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -437,24 +467,19 @@ create_texture(DXScreenData &scrn) {
|
||||
case 24:
|
||||
nassertr(num_color_channels == 3, false);
|
||||
|
||||
if (compress_texture) {
|
||||
CHECK_FOR_FMT(DXT1, Conv24toDXT1);
|
||||
}
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
// if (!(want_16bit_rgb_textures || dx_force_16bpptextures)) {
|
||||
CHECK_FOR_FMT(R8G8B8, Conv24to24);
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
|
||||
CHECK_FOR_FMT(X8R8G8B8, Conv24to32);
|
||||
}
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
// no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st)
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
@ -462,22 +487,16 @@ create_texture(DXScreenData &scrn) {
|
||||
nassertr(num_alpha_bits > 0, false);
|
||||
nassertr(num_color_channels == 2, false);
|
||||
|
||||
CHECK_FOR_FMT(A8L8, ConvLum16to16);
|
||||
CHECK_FOR_FMT(A8L8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, ConvLum16to32);
|
||||
}
|
||||
|
||||
#ifndef FORCE_16bpp_1555
|
||||
if (num_alpha_bits == 1)
|
||||
#endif
|
||||
{
|
||||
CHECK_FOR_FMT(A1R5G5B5, ConvLum16to16_1555);
|
||||
if (num_alpha_bits == 1) {
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
}
|
||||
|
||||
// normally prefer 4444 due to better alpha channel resolution
|
||||
CHECK_FOR_FMT(A4R4G4B4, ConvLum16to16_4444);
|
||||
CHECK_FOR_FMT(A1R5G5B5, ConvLum16to16_1555);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
} else {
|
||||
nassertr((num_color_channels == 3)||(num_color_channels == 4), false);
|
||||
// look for compatible 16bit fmts, if none then give up
|
||||
@ -485,13 +504,13 @@ create_texture(DXScreenData &scrn) {
|
||||
switch(num_alpha_bits) {
|
||||
case 0:
|
||||
if (num_color_channels == 3) {
|
||||
CHECK_FOR_FMT(R5G6B5, Conv24to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv24to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
} else {
|
||||
nassertr(num_color_channels == 4, false);
|
||||
// it could be 4 if user asks us to throw away the alpha channel
|
||||
CHECK_FOR_FMT(R5G6B5, Conv32to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -500,13 +519,13 @@ create_texture(DXScreenData &scrn) {
|
||||
// could use 32bpp ARGB. fail if this particular fmt not
|
||||
// avail.
|
||||
nassertr(num_color_channels == 4, false);
|
||||
CHECK_FOR_FMT(X1R5G5B5, Conv32to16_X555);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
break;
|
||||
case 4:
|
||||
// app specifically requests 4-4-4-4 F_rgba4 case, as opposed
|
||||
// to F_rgba, which could use 32bpp ARGB
|
||||
nassertr(num_color_channels == 4, false);
|
||||
CHECK_FOR_FMT(A4R4G4B4, Conv32to16_4444);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
break;
|
||||
default:
|
||||
nassertr(false, false); // problem in get_bits_per_pixel()?
|
||||
@ -519,16 +538,14 @@ create_texture(DXScreenData &scrn) {
|
||||
nassertr(num_color_channels == 1, false);
|
||||
|
||||
// look for native lum fmt first
|
||||
CHECK_FOR_FMT(L8, ConvLum8to8);
|
||||
CHECK_FOR_FMT(L8, ConvLum8to16_A8L8);
|
||||
CHECK_FOR_FMT(L8);
|
||||
CHECK_FOR_FMT(L8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(R8G8B8, ConvLum8to24);
|
||||
CHECK_FOR_FMT(X8R8G8B8, ConvLum8to32);
|
||||
}
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
|
||||
CHECK_FOR_FMT(R5G6B5, ConvLum8to16_0565);
|
||||
CHECK_FOR_FMT(X1R5G5B5, ConvLum8to16_X555);
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
|
||||
} else if (num_alpha_bits == 8) {
|
||||
// look for 16bpp A8L8, else 32-bit ARGB, else 16-4444.
|
||||
@ -538,13 +555,9 @@ create_texture(DXScreenData &scrn) {
|
||||
// model we need somehow (is it that voodoo assumes color is
|
||||
// white? isnt that what we do in ConvAlpha8to32 anyway?)
|
||||
|
||||
CHECK_FOR_FMT(A8L8, ConvAlpha8to16_A8L8);
|
||||
|
||||
if (!dx_force_16bpptextures) {
|
||||
CHECK_FOR_FMT(A8R8G8B8, ConvAlpha8to32);
|
||||
}
|
||||
|
||||
CHECK_FOR_FMT(A4R4G4B4, ConvAlpha8to16_4444);
|
||||
CHECK_FOR_FMT(A8L8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
CHECK_FOR_FMT(A4R4G4B4);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1739,7 +1752,7 @@ fill_d3d_texture_pixels(DXScreenData &scrn) {
|
||||
int miplevel_count = _d3d_2d_texture->GetLevelCount(); // what if it's not a 2d texture?
|
||||
if (miplevel_count <= tex->get_num_loadable_ram_mipmap_images()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "Using pre-calculated mipmap levels for texture " << tex->get_name();
|
||||
<< "Using pre-calculated mipmap levels for texture " << tex->get_name() << "\n";
|
||||
|
||||
for (int mip_level = 1; mip_level < miplevel_count; ++mip_level) {
|
||||
hr = fill_d3d_texture_mipmap_pixels(mip_level, di, source_format);
|
||||
@ -2031,10 +2044,10 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) {
|
||||
return 24;
|
||||
case Texture::F_rgba8:
|
||||
case Texture::F_rgba:
|
||||
*alphbits = 8;
|
||||
return 32;
|
||||
case Texture::F_rgbm:
|
||||
if (format == Texture::F_rgbm) // does this make any sense?
|
||||
*alphbits = 1;
|
||||
else *alphbits = 8;
|
||||
*alphbits = 1;
|
||||
return 32;
|
||||
case Texture::F_rgb12:
|
||||
return 36;
|
||||
|
@ -30,6 +30,8 @@ public:
|
||||
DXTextureContext9(PreparedGraphicsObjects *pgo, Texture *tex);
|
||||
virtual ~DXTextureContext9();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
bool create_texture(DXScreenData &scrn);
|
||||
bool create_simple_texture(DXScreenData &scrn);
|
||||
void delete_texture();
|
||||
|
@ -305,6 +305,29 @@ DXVertexBufferContext9::
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext9::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXVertexBufferContext9::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
free_vbuffer();
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DXVertexBufferContext9::free_vbuffer
|
||||
// Access: Public
|
||||
|
@ -29,6 +29,8 @@ public:
|
||||
DXVertexBufferContext9(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data, DXScreenData &scrn);
|
||||
virtual ~DXVertexBufferContext9();
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
void free_vbuffer();
|
||||
void allocate_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataHandle *reader);
|
||||
void create_vbuffer(DXScreenData &scrn, const GeomVertexArrayDataHandle *reader, string name);
|
||||
|
@ -2676,6 +2676,7 @@ update_texture(TextureContext *tc, bool force) {
|
||||
specify_texture(gtc->get_texture());
|
||||
gtc->mark_loaded();
|
||||
}
|
||||
gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
@ -2814,7 +2815,7 @@ record_deleted_display_list(GLuint index) {
|
||||
VertexBufferContext *CLP(GraphicsStateGuardian)::
|
||||
prepare_vertex_buffer(GeomVertexArrayData *data) {
|
||||
if (_supports_buffers) {
|
||||
CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(_prepared_objects, data);
|
||||
CLP(VertexBufferContext) *gvbc = new CLP(VertexBufferContext)(this, _prepared_objects, data);
|
||||
_glGenBuffers(1, &gvbc->_index);
|
||||
|
||||
if (GLCAT.is_debug() && CLP(debug_buffers)) {
|
||||
@ -2881,6 +2882,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
|
||||
|
||||
gvbc->mark_loaded(reader);
|
||||
}
|
||||
gvbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
maybe_gl_finish();
|
||||
report_my_gl_errors();
|
||||
@ -2998,7 +3000,7 @@ setup_array_data(const unsigned char *&client_pointer,
|
||||
IndexBufferContext *CLP(GraphicsStateGuardian)::
|
||||
prepare_index_buffer(GeomPrimitive *data) {
|
||||
if (_supports_buffers) {
|
||||
CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(_prepared_objects, data);
|
||||
CLP(IndexBufferContext) *gibc = new CLP(IndexBufferContext)(this, _prepared_objects, data);
|
||||
_glGenBuffers(1, &gibc->_index);
|
||||
|
||||
if (GLCAT.is_debug() && CLP(debug_buffers)) {
|
||||
@ -3067,6 +3069,7 @@ apply_index_buffer(IndexBufferContext *ibc,
|
||||
}
|
||||
gibc->mark_loaded(reader);
|
||||
}
|
||||
gibc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
maybe_gl_finish();
|
||||
report_my_gl_errors();
|
||||
@ -3356,6 +3359,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
}
|
||||
|
||||
gtc->mark_loaded();
|
||||
gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
report_my_gl_errors();
|
||||
|
||||
|
@ -533,6 +533,8 @@ public:
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class CLP(VertexBufferContext);
|
||||
friend class CLP(IndexBufferContext);
|
||||
friend class CLP(ShaderContext);
|
||||
friend class CLP(GraphicsBuffer);
|
||||
friend class CLP(OcclusionQueryContext);
|
||||
|
@ -19,8 +19,11 @@
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(IndexBufferContext)::
|
||||
CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
|
||||
IndexBufferContext(pgo, data)
|
||||
CLP(IndexBufferContext)(CLP(GraphicsStateGuardian) *glgsg,
|
||||
PreparedGraphicsObjects *pgo,
|
||||
GeomPrimitive *data) :
|
||||
IndexBufferContext(pgo, data),
|
||||
_glgsg(glgsg)
|
||||
{
|
||||
_index = 0;
|
||||
}
|
||||
|
@ -13,3 +13,43 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
TypeHandle CLP(IndexBufferContext)::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLIndexBufferContext::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(IndexBufferContext)::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
|
||||
// Make sure the buffer is unbound before we delete it.
|
||||
if (_glgsg->_current_ibuffer_index == _index) {
|
||||
if (GLCAT.is_debug() && CLP(debug_buffers)) {
|
||||
GLCAT.debug()
|
||||
<< "unbinding index buffer\n";
|
||||
}
|
||||
_glgsg->_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
_glgsg->_current_ibuffer_index = 0;
|
||||
}
|
||||
|
||||
// Free the buffer.
|
||||
_glgsg->_glDeleteBuffers(1, &_index);
|
||||
|
||||
// We still need a valid index number, though, in case we want to
|
||||
// re-load the buffer later.
|
||||
_glgsg->_glGenBuffers(1, &_index);
|
||||
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
@ -23,10 +23,15 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_GL CLP(IndexBufferContext) : public IndexBufferContext {
|
||||
public:
|
||||
INLINE CLP(IndexBufferContext)(PreparedGraphicsObjects *pgo,
|
||||
INLINE CLP(IndexBufferContext)(CLP(GraphicsStateGuardian) *glgsg,
|
||||
PreparedGraphicsObjects *pgo,
|
||||
GeomPrimitive *data);
|
||||
ALLOC_DELETED_CHAIN(CLP(IndexBufferContext));
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
CLP(GraphicsStateGuardian) *_glgsg;
|
||||
|
||||
// This is the GL "name" of the data object.
|
||||
GLuint _index;
|
||||
|
||||
|
@ -15,3 +15,35 @@
|
||||
#include "pnotify.h"
|
||||
|
||||
TypeHandle CLP(TextureContext)::_type_handle;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLTextureContext::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(TextureContext)::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
|
||||
// Free the texture resources.
|
||||
GLP(DeleteTextures)(1, &_index);
|
||||
|
||||
// We still need a valid index number, though, in case we want to
|
||||
// re-load the texture later.
|
||||
GLP(GenTextures)(1, &_index);
|
||||
|
||||
_already_applied = false;
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ public:
|
||||
INLINE CLP(TextureContext)(PreparedGraphicsObjects *pgo, Texture *tex);
|
||||
ALLOC_DELETED_CHAIN(CLP(TextureContext));
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
// This is the GL "name" of the texture object.
|
||||
GLuint _index;
|
||||
|
||||
|
@ -19,8 +19,11 @@
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLP(VertexBufferContext)::
|
||||
CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
|
||||
VertexBufferContext(pgo, data)
|
||||
CLP(VertexBufferContext)(CLP(GraphicsStateGuardian) *glgsg,
|
||||
PreparedGraphicsObjects *pgo,
|
||||
GeomVertexArrayData *data) :
|
||||
VertexBufferContext(pgo, data),
|
||||
_glgsg(glgsg)
|
||||
{
|
||||
_index = 0;
|
||||
}
|
||||
|
@ -13,3 +13,43 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
TypeHandle CLP(VertexBufferContext)::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GLVertexBufferContext::evict_lru
|
||||
// Access: Public, Virtual
|
||||
// Description: Evicts the page from the LRU. Called internally when
|
||||
// the LRU determines that it is full. May also be
|
||||
// called externally when necessary to explicitly evict
|
||||
// the page.
|
||||
//
|
||||
// It is legal for this method to either evict the page
|
||||
// as requested, do nothing (in which case the eviction
|
||||
// will be requested again at the next epoch), or
|
||||
// requeue itself on the tail of the queue (in which
|
||||
// case the eviction will be requested again much
|
||||
// later).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLP(VertexBufferContext)::
|
||||
evict_lru() {
|
||||
dequeue_lru();
|
||||
|
||||
// Make sure the buffer is unbound before we delete it.
|
||||
if (_glgsg->_current_vbuffer_index == _index) {
|
||||
if (GLCAT.is_debug() && CLP(debug_buffers)) {
|
||||
GLCAT.debug()
|
||||
<< "unbinding vertex buffer\n";
|
||||
}
|
||||
_glgsg->_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
_glgsg->_current_vbuffer_index = 0;
|
||||
}
|
||||
|
||||
// Free the buffer.
|
||||
_glgsg->_glDeleteBuffers(1, &_index);
|
||||
|
||||
// We still need a valid index number, though, in case we want to
|
||||
// re-load the buffer later.
|
||||
_glgsg->_glGenBuffers(1, &_index);
|
||||
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "vertexBufferContext.h"
|
||||
#include "deletedChain.h"
|
||||
|
||||
class CLP(GraphicsStateGuardian);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GLVertexBufferContext
|
||||
// Description : Caches a GeomVertexArrayData on the GL as a buffer
|
||||
@ -23,10 +25,15 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_GL CLP(VertexBufferContext) : public VertexBufferContext {
|
||||
public:
|
||||
INLINE CLP(VertexBufferContext)(PreparedGraphicsObjects *pgo,
|
||||
INLINE CLP(VertexBufferContext)(CLP(GraphicsStateGuardian) *glgsg,
|
||||
PreparedGraphicsObjects *pgo,
|
||||
GeomVertexArrayData *data);
|
||||
ALLOC_DELETED_CHAIN(CLP(VertexBufferContext));
|
||||
|
||||
virtual void evict_lru();
|
||||
|
||||
CLP(GraphicsStateGuardian) *_glgsg;
|
||||
|
||||
// This is the GL "name" of the data object.
|
||||
GLuint _index;
|
||||
|
||||
|
@ -374,6 +374,19 @@ ConfigVariableInt vertex_data_page_threads
|
||||
"is 0, this work will be done in the main thread, which may "
|
||||
"introduce occasional random chugs in rendering."));
|
||||
|
||||
ConfigVariableInt graphics_memory_limit
|
||||
("graphics-memory-limit", -1,
|
||||
PRC_DESC("This is a default limit that is imposed on each GSG at "
|
||||
"GSG creation time. It limits the total amount of graphics "
|
||||
"memory, including texture memory and vertex buffer memory, "
|
||||
"that will be consumed by the GSG, regardless of whether the "
|
||||
"hardware claims to provide more graphics memory than this. "
|
||||
"It is useful to put a ceiling on graphics memory consumed, since "
|
||||
"some drivers seem to allow the application to consume more "
|
||||
"memory than the hardware can realistically support. "
|
||||
"Set this to -1 to have no limit other than the normal "
|
||||
"hardware-imposed limit."));
|
||||
|
||||
ConfigureFn(config_gobj) {
|
||||
BufferContext::init_type();
|
||||
Geom::init_type();
|
||||
|
@ -92,6 +92,7 @@ extern EXPCL_PANDA_GOBJ ConfigVariableFilename vertex_save_file_directory;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableString vertex_save_file_prefix;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt vertex_data_small_size;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt vertex_data_page_threads;
|
||||
extern EXPCL_PANDA_GOBJ ConfigVariableInt graphics_memory_limit;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
INLINE IndexBufferContext::
|
||||
IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
|
||||
BufferContext(&pgo->_ibuffer_residency),
|
||||
SimpleLruPage(0),
|
||||
_data(data)
|
||||
{
|
||||
}
|
||||
@ -72,6 +73,18 @@ was_modified(const GeomPrimitivePipelineReader *reader) const {
|
||||
return get_modified() != reader->get_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: IndexBufferContext::update_data_size_bytes
|
||||
// Access: Public
|
||||
// Description: Should be called (usually by a derived class) when
|
||||
// the on-card size of this object has changed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void IndexBufferContext::
|
||||
update_data_size_bytes(size_t new_data_size_bytes) {
|
||||
BufferContext::update_data_size_bytes(new_data_size_bytes);
|
||||
SimpleLruPage::set_lru_size(new_data_size_bytes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: IndexBufferContext::mark_loaded
|
||||
// Access: Public
|
||||
@ -89,3 +102,15 @@ mark_loaded(const GeomPrimitivePipelineReader *reader) {
|
||||
// Assume the buffer is now resident.
|
||||
set_resident(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: IndexBufferContext::mark_unloaded
|
||||
// Access: Public
|
||||
// Description: Should be called after the buffer has been forced
|
||||
// out of graphics memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void IndexBufferContext::
|
||||
mark_unloaded() {
|
||||
update_modified(UpdateSeq::old());
|
||||
set_resident(false);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "bufferContext.h"
|
||||
#include "geomPrimitive.h"
|
||||
#include "preparedGraphicsObjects.h"
|
||||
#include "simpleLru.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : IndexBufferContext
|
||||
@ -32,7 +33,7 @@
|
||||
// allocate a vertex buffer for the array. OpenGL can
|
||||
// create a buffer object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GOBJ IndexBufferContext : public BufferContext {
|
||||
class EXPCL_PANDA_GOBJ IndexBufferContext : public BufferContext, public SimpleLruPage {
|
||||
public:
|
||||
INLINE IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data);
|
||||
|
||||
@ -44,7 +45,9 @@ PUBLISHED:
|
||||
INLINE bool was_modified(const GeomPrimitivePipelineReader *reader) const;
|
||||
|
||||
public:
|
||||
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
|
||||
INLINE void mark_loaded(const GeomPrimitivePipelineReader *reader);
|
||||
INLINE void mark_unloaded();
|
||||
|
||||
private:
|
||||
// This cannot be a PT(GeomPrimitive), because the data and
|
||||
|
@ -25,6 +25,38 @@ get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PreparedGraphicsObjects::set_graphics_memory_limit
|
||||
// Access: Public
|
||||
// Description: Sets an artificial cap on graphics memory that
|
||||
// will be imposed on this GSG.
|
||||
//
|
||||
// This limits the total amount of graphics memory,
|
||||
// including texture memory and vertex buffer memory,
|
||||
// that will be consumed by the GSG, regardless of
|
||||
// whether the hardware claims to provide more graphics
|
||||
// memory than this. It is useful to put a ceiling on
|
||||
// graphics memory consumed, since some drivers seem to
|
||||
// allow the application to consume more memory than the
|
||||
// hardware can realistically support.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PreparedGraphicsObjects::
|
||||
set_graphics_memory_limit(size_t limit) {
|
||||
_graphics_memory_lru.set_max_size(limit);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PreparedGraphicsObjects::get_graphics_memory_limit
|
||||
// Access: Public
|
||||
// Description: Returns the artificial cap on graphics memory that
|
||||
// will be imposed on this GSG. See
|
||||
// set_graphics_memory_limit().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE size_t PreparedGraphicsObjects::
|
||||
get_graphics_memory_limit() const {
|
||||
return _graphics_memory_lru.get_max_size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PreparedGraphicsObjects::release_all
|
||||
// Access: Public
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "reMutexHolder.h"
|
||||
#include "geomContext.h"
|
||||
#include "shaderContext.h"
|
||||
#include "config_gobj.h"
|
||||
|
||||
int PreparedGraphicsObjects::_name_index = 0;
|
||||
|
||||
@ -40,7 +41,8 @@ PreparedGraphicsObjects() :
|
||||
_index_buffer_cache_size(0),
|
||||
_texture_residency(_name, "texture"),
|
||||
_vbuffer_residency(_name, "vbuffer"),
|
||||
_ibuffer_residency(_name, "ibuffer")
|
||||
_ibuffer_residency(_name, "ibuffer"),
|
||||
_graphics_memory_lru("graphics_memory_lru", graphics_memory_limit)
|
||||
{
|
||||
// GLGSG will turn this flag on. This is a temporary hack to
|
||||
// disable this feature for DX8/DX9 for now, until we work out the
|
||||
|
@ -62,6 +62,9 @@ public:
|
||||
PUBLISHED:
|
||||
INLINE const string &get_name() const;
|
||||
|
||||
INLINE void set_graphics_memory_limit(size_t limit);
|
||||
INLINE size_t get_graphics_memory_limit() const;
|
||||
|
||||
INLINE void release_all();
|
||||
INLINE int get_num_queued() const;
|
||||
INLINE int get_num_prepared() const;
|
||||
@ -196,6 +199,8 @@ public:
|
||||
BufferResidencyTracker _vbuffer_residency;
|
||||
BufferResidencyTracker _ibuffer_residency;
|
||||
|
||||
SimpleLru _graphics_memory_lru;
|
||||
|
||||
public:
|
||||
// This is only public as a temporary hack. Don't mess with it
|
||||
// unless you know what you're doing.
|
||||
|
@ -50,7 +50,7 @@ set_max_size(size_t max_size) {
|
||||
MutexHolder holder(_global_lock);
|
||||
_max_size = max_size;
|
||||
if (_total_size > _max_size) {
|
||||
do_evict();
|
||||
do_evict_to(_max_size, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,22 @@ INLINE void SimpleLru::
|
||||
consider_evict() {
|
||||
MutexHolder holder(_global_lock);
|
||||
if (_total_size > _max_size) {
|
||||
do_evict();
|
||||
do_evict_to(_max_size, false);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SimpleLru::evict_to
|
||||
// Access: Published
|
||||
// Description: Evicts a sequence of objects until the queue fits
|
||||
// within the indicated target size, regardless of its
|
||||
// normal max size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void SimpleLru::
|
||||
evict_to(size_t target_size) {
|
||||
MutexHolder holder(_global_lock);
|
||||
if (_total_size > target_size) {
|
||||
do_evict_to(target_size, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,14 +114,15 @@ count_active_size() const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: SimpleLru::do_evict
|
||||
// Function: SimpleLru::do_evict_to
|
||||
// Access: Private
|
||||
// Description: Evicts pages until the LRU is within tolerance.
|
||||
// Assumes the lock is already held. Does not evict
|
||||
// "active" pages that were added within this epoch.
|
||||
// Description: Evicts pages until the LRU is within the indicated
|
||||
// size. Assumes the lock is already held. If
|
||||
// hard_evict is false, does not evict "active" pages
|
||||
// that were added within this epoch.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void SimpleLru::
|
||||
do_evict() {
|
||||
do_evict_to(size_t target_size, bool hard_evict) {
|
||||
if (_next == this) {
|
||||
// Nothing in the queue.
|
||||
return;
|
||||
@ -134,7 +135,7 @@ do_evict() {
|
||||
|
||||
// Now walk through the list.
|
||||
SimpleLruPage *node = (SimpleLruPage *)_next;
|
||||
while (_total_size > _max_size) {
|
||||
while (_total_size > target_size) {
|
||||
SimpleLruPage *next = (SimpleLruPage *)node->_next;
|
||||
|
||||
// We must release the lock while we call evict_lru().
|
||||
@ -146,7 +147,7 @@ do_evict() {
|
||||
// If we reach the original tail of the list, stop.
|
||||
return;
|
||||
}
|
||||
if (node == _active_marker) {
|
||||
if (!hard_evict && node == _active_marker) {
|
||||
// Also stop if we reach the active marker. Nodes beyond this
|
||||
// were added within this epoch.
|
||||
return;
|
||||
|
@ -38,13 +38,14 @@ PUBLISHED:
|
||||
size_t count_active_size() const;
|
||||
|
||||
INLINE void consider_evict();
|
||||
INLINE void evict_to(size_t target_size);
|
||||
INLINE void begin_epoch();
|
||||
|
||||
public:
|
||||
static Mutex &_global_lock;
|
||||
|
||||
private:
|
||||
void do_evict();
|
||||
void do_evict_to(size_t target_size, bool hard_evict);
|
||||
bool do_validate_size();
|
||||
|
||||
size_t _total_size;
|
||||
|
@ -21,6 +21,7 @@
|
||||
INLINE TextureContext::
|
||||
TextureContext(PreparedGraphicsObjects *pgo, Texture *tex) :
|
||||
BufferContext(&pgo->_texture_residency),
|
||||
SimpleLruPage(0),
|
||||
_texture(tex)
|
||||
{
|
||||
}
|
||||
@ -84,6 +85,18 @@ was_simple_image_modified() const {
|
||||
return _simple_image_modified != _texture->get_simple_image_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::update_data_size_bytes
|
||||
// Access: Public
|
||||
// Description: Should be called (usually by a derived class) when
|
||||
// the on-card size of this object has changed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextureContext::
|
||||
update_data_size_bytes(size_t new_data_size_bytes) {
|
||||
BufferContext::update_data_size_bytes(new_data_size_bytes);
|
||||
SimpleLruPage::set_lru_size(new_data_size_bytes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::mark_loaded
|
||||
// Access: Public
|
||||
@ -117,3 +130,19 @@ mark_simple_loaded() {
|
||||
// The texture's not exactly resident now, but some part of it is.
|
||||
set_resident(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::mark_unloaded
|
||||
// Access: Public
|
||||
// Description: Should be called after the texture has been forced
|
||||
// out of texture memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TextureContext::
|
||||
mark_unloaded() {
|
||||
_properties_modified = UpdateSeq::old();
|
||||
_image_modified = UpdateSeq::old();
|
||||
_simple_image_modified = UpdateSeq::old();
|
||||
update_modified(UpdateSeq::old());
|
||||
|
||||
set_resident(false);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "bufferContext.h"
|
||||
#include "texture.h"
|
||||
#include "preparedGraphicsObjects.h"
|
||||
#include "simpleLru.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TextureContext
|
||||
@ -34,7 +35,7 @@
|
||||
// texture and store it here. The texture stores all of
|
||||
// these handles internally.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GOBJ TextureContext : public BufferContext {
|
||||
class EXPCL_PANDA_GOBJ TextureContext : public BufferContext, public SimpleLruPage {
|
||||
public:
|
||||
INLINE TextureContext(PreparedGraphicsObjects *pgo, Texture *tex);
|
||||
|
||||
@ -47,8 +48,10 @@ PUBLISHED:
|
||||
INLINE bool was_simple_image_modified() const;
|
||||
|
||||
public:
|
||||
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
|
||||
INLINE void mark_loaded();
|
||||
INLINE void mark_simple_loaded();
|
||||
INLINE void mark_unloaded();
|
||||
|
||||
private:
|
||||
// This cannot be a PT(Texture), because the texture and the GSG
|
||||
|
@ -21,6 +21,7 @@
|
||||
INLINE VertexBufferContext::
|
||||
VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
|
||||
BufferContext(&pgo->_vbuffer_residency),
|
||||
SimpleLruPage(0),
|
||||
_data(data)
|
||||
{
|
||||
}
|
||||
@ -72,6 +73,18 @@ was_modified(const GeomVertexArrayDataHandle *reader) const {
|
||||
return get_modified() != reader->get_modified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VertexBufferContext::update_data_size_bytes
|
||||
// Access: Public
|
||||
// Description: Should be called (usually by a derived class) when
|
||||
// the on-card size of this object has changed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void VertexBufferContext::
|
||||
update_data_size_bytes(size_t new_data_size_bytes) {
|
||||
BufferContext::update_data_size_bytes(new_data_size_bytes);
|
||||
SimpleLruPage::set_lru_size(new_data_size_bytes);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VertexBufferContext::mark_loaded
|
||||
// Access: Public
|
||||
@ -89,3 +102,15 @@ mark_loaded(const GeomVertexArrayDataHandle *reader) {
|
||||
// Assume the buffer is now resident.
|
||||
set_resident(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: VertexBufferContext::mark_unloaded
|
||||
// Access: Public
|
||||
// Description: Should be called after the buffer has been forced
|
||||
// out of graphics memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void VertexBufferContext::
|
||||
mark_unloaded() {
|
||||
update_modified(UpdateSeq::old());
|
||||
set_resident(false);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "bufferContext.h"
|
||||
#include "geomVertexArrayData.h"
|
||||
#include "preparedGraphicsObjects.h"
|
||||
#include "simpleLru.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : VertexBufferContext
|
||||
@ -32,7 +33,7 @@
|
||||
// allocate a vertex buffer for the array. OpenGL can
|
||||
// create a buffer object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA_GOBJ VertexBufferContext : public BufferContext {
|
||||
class EXPCL_PANDA_GOBJ VertexBufferContext : public BufferContext, public SimpleLruPage {
|
||||
public:
|
||||
INLINE VertexBufferContext(PreparedGraphicsObjects *pgo,
|
||||
GeomVertexArrayData *data);
|
||||
@ -45,7 +46,9 @@ PUBLISHED:
|
||||
INLINE bool was_modified(const GeomVertexArrayDataHandle *reader) const;
|
||||
|
||||
public:
|
||||
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
|
||||
INLINE void mark_loaded(const GeomVertexArrayDataHandle *reader);
|
||||
INLINE void mark_unloaded();
|
||||
|
||||
private:
|
||||
// This cannot be a PT(GeomVertexArrayData), because the data and
|
||||
|
@ -79,16 +79,6 @@ ConfigVariableInt osx_mouse_wheel_scale
|
||||
PRC_DESC("Specify the number of units to spin the Mac mouse wheel to "
|
||||
"represent a single wheel_up or wheel_down message."));
|
||||
|
||||
ConfigVariableInt td_texture_ram
|
||||
("td-texture-ram", -1,
|
||||
PRC_DESC("This specifies the maximum amount of RAM to devote to keeping "
|
||||
"textures resident with the tinydisplay software renderer. When "
|
||||
"this limit is exceeded, textures over the limit that have not "
|
||||
"been rendered within the current frame will be evicted. "
|
||||
"(Textures will not be evicted while they are still in the "
|
||||
"frame, even if this means this limit remains exceeded.) "
|
||||
"Set it to -1 for no limit."));
|
||||
|
||||
ConfigVariableBool td_ignore_mipmaps
|
||||
("td-ignore-mipmaps", false,
|
||||
PRC_DESC("Configure this true to disable use of mipmaps on the "
|
||||
|
@ -50,8 +50,7 @@ PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcolle
|
||||
TinyGraphicsStateGuardian::
|
||||
TinyGraphicsStateGuardian(GraphicsPipe *pipe,
|
||||
TinyGraphicsStateGuardian *share_with) :
|
||||
GraphicsStateGuardian(CS_yup_right, pipe),
|
||||
_textures_lru("textures_lru", td_texture_ram)
|
||||
GraphicsStateGuardian(CS_yup_right, pipe)
|
||||
{
|
||||
_current_frame_buffer = NULL;
|
||||
_aux_frame_buffer = NULL;
|
||||
@ -466,9 +465,6 @@ end_frame(Thread *current_thread) {
|
||||
_pixel_count_flat_perspective_pcollector.flush_level();
|
||||
_pixel_count_smooth_perspective_pcollector.flush_level();
|
||||
#endif // DO_PSTATS
|
||||
|
||||
// Evict any textures that exceed our texture memory.
|
||||
_textures_lru.begin_epoch();
|
||||
}
|
||||
|
||||
|
||||
@ -1274,7 +1270,7 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
|
||||
|
||||
gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
|
||||
gtc->mark_loaded();
|
||||
gtc->enqueue_lru(&_textures_lru);
|
||||
gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1501,7 +1497,7 @@ update_texture(TextureContext *tc, bool force) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
gtc->enqueue_lru(&_textures_lru);
|
||||
gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
|
||||
|
||||
_c->current_texture = gltex;
|
||||
_c->zb->current_texture = gltex->levels;
|
||||
|
@ -145,8 +145,6 @@ private:
|
||||
bool _texture_replace;
|
||||
bool _filled_flat;
|
||||
|
||||
SimpleLru _textures_lru;
|
||||
|
||||
CPT(TransformState) _scissor_mat;
|
||||
|
||||
// Used during being_draw_primitives() .. end_draw_primitives().
|
||||
|
@ -20,7 +20,7 @@
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TinyTextureContext::
|
||||
TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex) :
|
||||
TextureContext(pgo, tex), SimpleLruPage(0)
|
||||
TextureContext(pgo, tex)
|
||||
{
|
||||
_gltex.num_levels = 0;
|
||||
_gltex.allocated_buffer = NULL;
|
||||
@ -36,16 +36,3 @@ INLINE TinyTextureContext::
|
||||
~TinyTextureContext() {
|
||||
nassertv(_gltex.num_levels == 0 && _gltex.allocated_buffer == NULL && _gltex.total_bytecount == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TinyTextureContext::update_data_size_bytes
|
||||
// Access: Public
|
||||
// Description: This is overloaded (non-virtually) to update both the
|
||||
// BufferContext and the LRU page with the same
|
||||
// information.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TinyTextureContext::
|
||||
update_data_size_bytes(size_t new_data_size_bytes) {
|
||||
TextureContext::update_data_size_bytes(new_data_size_bytes);
|
||||
SimpleLruPage::set_lru_size(new_data_size_bytes);
|
||||
}
|
||||
|
@ -48,5 +48,6 @@ evict_lru() {
|
||||
nassertv(gltex->num_levels == 0);
|
||||
}
|
||||
|
||||
set_resident(false);
|
||||
update_data_size_bytes(0);
|
||||
mark_unloaded();
|
||||
}
|
||||
|
@ -18,21 +18,19 @@
|
||||
#include "pandabase.h"
|
||||
#include "textureContext.h"
|
||||
#include "deletedChain.h"
|
||||
#include "simpleLru.h"
|
||||
#include "zgl.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TinyTextureContext
|
||||
// Description :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_TINYDISPLAY TinyTextureContext : public TextureContext, public SimpleLruPage {
|
||||
class EXPCL_TINYDISPLAY TinyTextureContext : public TextureContext {
|
||||
public:
|
||||
INLINE TinyTextureContext(PreparedGraphicsObjects *pgo, Texture *tex);
|
||||
ALLOC_DELETED_CHAIN(TinyTextureContext);
|
||||
|
||||
INLINE ~TinyTextureContext();
|
||||
|
||||
INLINE void update_data_size_bytes(size_t new_data_size_bytes);
|
||||
virtual void evict_lru();
|
||||
|
||||
GLTexture _gltex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user