Direct3D: convert linked lists into vectors of unique pointers

This commit is contained in:
Giuseppe Gorgoglione 2016-07-01 01:42:29 +02:00
parent 05ae871334
commit 0312b918a8
4 changed files with 105 additions and 235 deletions

View File

@ -60,7 +60,7 @@ public:
class d3d_texture_manager
{
public:
d3d_texture_manager(): m_renderer(nullptr), m_texlist(nullptr), m_dynamic_supported(0), m_stretch_supported(0), m_yuv_format(), m_texture_caps(0), m_texture_max_aspect(0), m_texture_max_width(0), m_texture_max_height(0), m_default_texture(nullptr)
d3d_texture_manager(): m_renderer(nullptr), m_dynamic_supported(0), m_stretch_supported(0), m_yuv_format(), m_texture_caps(0), m_texture_max_aspect(0), m_texture_max_width(0), m_texture_max_height(0), m_default_texture(nullptr)
{ }
d3d_texture_manager(renderer_d3d9 *d3d);
@ -73,8 +73,6 @@ public:
texture_info * find_texinfo(const render_texinfo *texture, UINT32 flags);
UINT32 texture_compute_hash(const render_texinfo *texture, UINT32 flags);
texture_info * get_texlist() const { return m_texlist; }
void set_texlist(texture_info *texlist) { m_texlist = texlist; }
bool is_dynamic_supported() const { return (bool)m_dynamic_supported; }
void set_dynamic_supported(bool dynamic_supported) { m_dynamic_supported = dynamic_supported; }
bool is_stretch_supported() const { return (bool)m_stretch_supported; }
@ -89,10 +87,10 @@ public:
renderer_d3d9 * get_d3d() const { return m_renderer; }
std::vector<std::unique_ptr<texture_info>> m_texture_list; // list of active textures
private:
renderer_d3d9 * m_renderer;
texture_info * m_texlist; // list of active textures
int m_dynamic_supported; // are dynamic textures supported?
int m_stretch_supported; // is StretchRect with point filtering supported?
D3DFORMAT m_yuv_format; // format to use for YUV textures
@ -125,8 +123,6 @@ public:
void set_data(const render_texinfo *texsource, UINT32 flags);
texture_info * get_next() const { return m_next; }
UINT32 get_hash() const { return m_hash; }
void increment_frame_count() { m_cur_frame++; }
@ -151,8 +147,6 @@ private:
renderer_d3d9 * m_renderer; // renderer pointer
texture_info * m_next; // next texture in the list
UINT32 m_hash; // hash value for the texture
UINT32 m_flags; // rendering flags
render_texinfo m_texinfo; // copy of the texture info
@ -226,7 +220,7 @@ class cache_target
{
public:
// construction/destruction
cache_target(): target(nullptr), texture(nullptr), target_width(0), target_height(0), width(0), height(0), screen_index(0), next(nullptr), prev(nullptr)
cache_target(): target(nullptr), texture(nullptr), target_width(0), target_height(0), width(0), height(0), screen_index(0)
{ }
~cache_target();
@ -243,9 +237,6 @@ public:
int height;
int screen_index;
cache_target *next;
cache_target *prev;
};
/* d3d_render_target is the information about a Direct3D render target chain */
@ -253,8 +244,22 @@ class d3d_render_target
{
public:
// construction/destruction
d3d_render_target(): target_width(0), target_height(0), width(0), height(0), screen_index(0), page_index(0), next(nullptr), prev(nullptr), bloom_count(0)
{ }
d3d_render_target(): target_width(0), target_height(0), width(0), height(0), screen_index(0), page_index(0), bloom_count(0)
{
for (int index = 0; index < MAX_BLOOM_COUNT; index++)
{
bloom_texture[index] = nullptr;
bloom_surface[index] = nullptr;
}
for (int index = 0; index < 2; index++)
{
source_texture[index] = nullptr;
source_surface[index] = nullptr;
target_texture[index] = nullptr;
target_surface[index] = nullptr;
}
}
~d3d_render_target();
@ -277,9 +282,6 @@ public:
IDirect3DSurface9 *source_surface[2];
IDirect3DTexture9 *source_texture[2];
d3d_render_target *next;
d3d_render_target *prev;
IDirect3DSurface9 *bloom_surface[MAX_BLOOM_COUNT];
IDirect3DTexture9 *bloom_texture[MAX_BLOOM_COUNT];

View File

@ -48,7 +48,7 @@ shaders::shaders() :
black_surface(nullptr), black_texture(nullptr), render_snap(false), snap_rendered(false), snap_copy_target(nullptr), snap_copy_texture(nullptr), snap_target(nullptr), snap_texture(nullptr),
snap_width(0), snap_height(0), initialized(false), backbuffer(nullptr), curr_effect(nullptr), default_effect(nullptr), prescale_effect(nullptr), post_effect(nullptr),
distortion_effect(nullptr), focus_effect(nullptr), phosphor_effect(nullptr), deconverge_effect(nullptr), color_effect(nullptr), ntsc_effect(nullptr), bloom_effect(nullptr),
downsample_effect(nullptr), vector_effect(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), targethead(nullptr), cachehead(nullptr)
downsample_effect(nullptr), vector_effect(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr)
{
}
@ -69,22 +69,6 @@ shaders::~shaders()
global_free(options);
options = nullptr;
}
cache_target *currcache = cachehead;
while(cachehead != nullptr)
{
cachehead = currcache->next;
global_free(currcache);
currcache = cachehead;
}
d3d_render_target *currtarget = targethead;
while(targethead != nullptr)
{
targethead = currtarget->next;
global_free(currtarget);
currtarget = targethead;
}
}
@ -444,22 +428,14 @@ void shaders::remove_cache_target(cache_target *cache)
if (cache == nullptr)
return;
if (cache == cachehead)
for (auto it = m_cache_target_list.begin(); it != m_cache_target_list.end(); it++)
{
cachehead = cachehead->next;
if ((*it).get() == cache)
{
m_cache_target_list.erase(it);
break;
}
}
if (cache->prev != nullptr)
{
cache->prev->next = cache->next;
}
if (cache->next != nullptr)
{
cache->next->prev = cache->prev;
}
global_free(cache);
}
@ -482,29 +458,21 @@ void shaders::remove_render_target(d3d_render_target *rt)
if (rt == nullptr)
return;
if (rt == targethead)
{
targethead = targethead->next;
}
if (rt->prev != nullptr)
{
rt->prev->next = rt->next;
}
if (rt->next != nullptr)
{
rt->next->prev = rt->prev;
}
remove_cache_target(find_cache_target(rt->screen_index, rt->width, rt->height));
int screen_index = rt->screen_index;
int other_page = 1 - rt->page_index;
int width = rt->width;
int height = rt->height;
global_free(rt);
for (auto it = m_render_target_list.begin(); it != m_render_target_list.end(); it++)
{
if ((*it).get() == rt)
{
m_render_target_list.erase(it);
break;
}
}
remove_cache_target(find_cache_target(screen_index, width, height));
// Remove other double-buffered page (if it exists)
remove_render_target(width, height, screen_index, other_page);
@ -829,7 +797,9 @@ int shaders::create_resources()
texture.seqid = 0;
// now create it (no prescale, no wrap)
shadow_texture = global_alloc(texture_info(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)));
auto tex = std::make_unique<texture_info>(d3d->get_texture_manager(), &texture, 1, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
shadow_texture = tex.get();
d3d->get_texture_manager()->m_texture_list.push_back(std::move(tex));
}
const char *fx_dir = downcast<windows_options &>(machine->options()).screen_post_fx_dir();
@ -1067,17 +1037,7 @@ d3d_render_target* shaders::find_render_target(texture_info *texture)
UINT32 screen_index = screen_index_data >> 1;
UINT32 page_index = screen_index_data & 1;
d3d_render_target *curr = targethead;
while (curr != nullptr && (
curr->screen_index != screen_index ||
curr->page_index != page_index ||
curr->width != texture->get_width() ||
curr->height != texture->get_height()))
{
curr = curr->next;
}
return curr;
return find_render_target(texture->get_width(), texture->get_height(), screen_index, page_index);
}
@ -1087,17 +1047,18 @@ d3d_render_target* shaders::find_render_target(texture_info *texture)
d3d_render_target* shaders::find_render_target(int source_width, int source_height, UINT32 screen_index, UINT32 page_index)
{
d3d_render_target *curr = targethead;
while (curr != nullptr && (
curr->width != source_width ||
curr->height != source_height ||
curr->screen_index != screen_index ||
curr->page_index != page_index))
for (auto it = m_render_target_list.begin(); it != m_render_target_list.end(); it++)
{
curr = curr->next;
if ((*it)->width == source_width &&
(*it)->height == source_height &&
(*it)->screen_index == screen_index &&
(*it)->page_index == page_index)
{
return (*it).get();
}
}
return curr;
return nullptr;
}
@ -1107,16 +1068,17 @@ d3d_render_target* shaders::find_render_target(int source_width, int source_heig
cache_target *shaders::find_cache_target(UINT32 screen_index, int width, int height)
{
cache_target *curr = cachehead;
while (curr != nullptr && (
curr->screen_index != screen_index ||
curr->width != width ||
curr->height != height))
for (auto it = m_cache_target_list.begin(); it != m_cache_target_list.end(); it++)
{
curr = curr->next;
if ((*it)->screen_index == screen_index &&
(*it)->width == width &&
(*it)->height == height)
{
return (*it).get();
}
}
return curr;
return nullptr;
}
int shaders::ntsc_pass(d3d_render_target *rt, int source_index, poly_info *poly, int vertnum)
@ -1693,22 +1655,12 @@ void shaders::end_draw()
bool shaders::add_cache_target(renderer_d3d9* d3d, texture_info* texture, int source_width, int source_height, int target_width, int target_height, int screen_index)
{
cache_target* target = (cache_target*)global_alloc_clear<cache_target>();
auto target = std::make_unique<cache_target>();
if (!target->init(d3d, source_width, source_height, target_width, target_height, screen_index))
{
global_free(target);
return false;
}
target->next = cachehead;
target->prev = nullptr;
if (cachehead != nullptr)
{
cachehead->prev = target;
}
cachehead = target;
m_cache_target_list.push_back(std::move(target));
return true;
}
@ -1835,56 +1787,34 @@ bool shaders::add_render_target(renderer_d3d9* d3d, render_primitive *prim, text
UINT32 page_index = 0;
if (texture != nullptr)
{
d3d_render_target *existing_target = find_render_target(texture);
if (existing_target != nullptr)
{
remove_render_target(existing_target);
}
UINT32 screen_index_data = (UINT32)texture->get_texinfo().osddata;
screen_index = screen_index_data >> 1;
page_index = screen_index_data & 1;
remove_render_target(find_render_target(texture));
}
else
{
d3d_render_target *existing_target = find_render_target(source_width, source_height, 0, 0);
if (existing_target != nullptr)
{
remove_render_target(existing_target);
}
remove_render_target(find_render_target(source_width, source_height, 0, 0));
}
d3d_render_target* target = (d3d_render_target*)global_alloc_clear<d3d_render_target>();
auto target = std::make_unique<d3d_render_target>();
if (!target->init(d3d, source_width, source_height, target_width, target_height, screen_index, page_index))
{
global_free(target);
return false;
}
target->next = targethead;
target->prev = nullptr;
if (targethead != nullptr)
{
targethead->prev = target;
}
targethead = target;
// cached target only for screen texture and vector buffer
if (PRIMFLAG_GET_SCREENTEX(prim->flags) || PRIMFLAG_GET_VECTORBUF(prim->flags))
{
cache_target* cache = find_cache_target(target->screen_index, source_width, source_height);
if (cache == nullptr)
if (!find_cache_target(target->screen_index, source_width, source_height))
{
if (!add_cache_target(d3d, texture, source_width, source_height, target_width, target_height, target->screen_index))
{
global_free(target);
return false;
}
}
}
m_render_target_list.push_back(std::move(target));
return true;
}
@ -1953,21 +1883,9 @@ void shaders::delete_resources()
last_options = *options;
}
cache_target *currcache = cachehead;
while(cachehead != nullptr)
{
cachehead = currcache->next;
global_free(currcache);
currcache = cachehead;
}
m_cache_target_list.clear();
d3d_render_target *currtarget = targethead;
while(targethead != nullptr)
{
targethead = currtarget->next;
global_free(currtarget);
currtarget = targethead;
}
m_render_target_list.clear();
if (downsample_effect != nullptr)
{
@ -2510,16 +2428,10 @@ uniform::uniform(effect *shader, const char *name, uniform_type type, int id)
{
m_shader = shader;
m_type = type;
m_next = nullptr;
m_handle = m_shader->get_parameter(nullptr, name);
m_id = id;
}
void uniform::set_next(uniform *next)
{
m_next = next;
}
void uniform::update()
{
if (m_id >= CU_COUNT)
@ -2774,8 +2686,6 @@ effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, cons
LPD3DXBUFFER buffer_errors = nullptr;
m_shaders = shadersys;
m_uniform_head = nullptr;
m_uniform_tail = nullptr;
m_valid = false;
char name_cstr[1024];
@ -2806,45 +2716,17 @@ effect::effect(shaders *shadersys, IDirect3DDevice9 *dev, const char *name, cons
effect::~effect()
{
m_effect->Release();
m_effect = nullptr;
uniform *curr = m_uniform_head;
while (curr != nullptr)
{
uniform *next = curr->get_next();
delete curr;
curr = next;
}
m_uniform_head = nullptr;
m_uniform_tail = nullptr;
}
void effect::add_uniform(const char *name, uniform::uniform_type type, int id)
{
uniform *newuniform = new uniform(this, name, type, id);
if (newuniform == nullptr)
{
return;
}
if (m_uniform_head == nullptr)
{
m_uniform_head = newuniform;
}
if (m_uniform_tail != nullptr)
{
m_uniform_tail->set_next(newuniform);
}
m_uniform_tail = newuniform;
m_uniform_list.push_back(std::make_unique<uniform>(this, name, type, id));
}
void effect::update_uniforms()
{
uniform *curr = m_uniform_head;
while(curr != nullptr)
{
curr->update();
curr = curr->get_next();
}
for (auto &uniform : m_uniform_list)
(*uniform).update();
}
void effect::begin(UINT *passes, DWORD flags)

View File

@ -104,14 +104,9 @@ public:
uniform(effect *shader, const char *name, uniform_type type, int id);
void set_next(uniform *next);
uniform * get_next() { return m_next; }
void update();
protected:
uniform *m_next;
uniform_type m_type;
int m_id;
@ -152,8 +147,8 @@ public:
bool is_valid() { return m_valid; }
private:
uniform *m_uniform_head;
uniform *m_uniform_tail;
std::vector<std::unique_ptr<uniform>> m_uniform_list;
ID3DXEffect *m_effect;
shaders *m_shaders;
@ -412,8 +407,9 @@ private:
texture_info * curr_texture;
d3d_render_target * curr_render_target;
poly_info * curr_poly;
d3d_render_target * targethead;
cache_target * cachehead;
std::vector<std::unique_ptr<d3d_render_target>> m_render_target_list;
std::vector<std::unique_ptr<cache_target>> m_cache_target_list;
std::vector<slider*> internal_sliders;
std::vector<ui::menu_item> m_sliders;

View File

@ -378,7 +378,6 @@ d3d_texture_manager::d3d_texture_manager(renderer_d3d9 *d3d)
{
m_renderer = d3d;
m_texlist = nullptr;
m_default_texture = nullptr;
D3DCAPS9 caps;
@ -441,7 +440,9 @@ void d3d_texture_manager::create_resources()
texture.seqid = 0;
// now create it
m_default_texture = global_alloc(texture_info(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32)));
auto tex = std::make_unique<texture_info>(this, &texture, win->prescale(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32));
m_default_texture = tex.get();
m_texture_list.push_back(std::move(tex));
}
}
@ -452,12 +453,7 @@ void d3d_texture_manager::delete_resources()
m_default_texture = nullptr;
// free all textures
while (m_texlist != nullptr)
{
texture_info *tex = m_texlist;
m_texlist = tex->get_next();
global_free(tex);
}
m_texture_list.clear();
}
UINT32 d3d_texture_manager::texture_compute_hash(const render_texinfo *texture, UINT32 flags)
@ -468,37 +464,32 @@ UINT32 d3d_texture_manager::texture_compute_hash(const render_texinfo *texture,
texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, UINT32 flags)
{
UINT32 hash = texture_compute_hash(texinfo, flags);
texture_info *texture;
// find a match
for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != nullptr; texture = texture->get_next())
for (auto it = m_texture_list.begin(); it != m_texture_list.end(); it++)
{
UINT32 test_screen = (UINT32)texture->get_texinfo().osddata >> 1;
UINT32 test_page = (UINT32)texture->get_texinfo().osddata & 1;
UINT32 test_screen = (UINT32)(*it)->get_texinfo().osddata >> 1;
UINT32 test_page = (UINT32)(*it)->get_texinfo().osddata & 1;
UINT32 prim_screen = (UINT32)texinfo->osddata >> 1;
UINT32 prim_page = (UINT32)texinfo->osddata & 1;
if (test_screen != prim_screen || test_page != prim_page)
{
continue;
}
if (texture->get_hash() == hash &&
texture->get_texinfo().base == texinfo->base &&
texture->get_texinfo().width == texinfo->width &&
texture->get_texinfo().height == texinfo->height &&
((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0)
if ((*it)->get_hash() == hash &&
(*it)->get_texinfo().base == texinfo->base &&
(*it)->get_texinfo().width == texinfo->width &&
(*it)->get_texinfo().height == texinfo->height &&
(((*it)->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0)
{
// Reject a texture if it belongs to an out-of-date render target, so as to cause the HLSL system to re-cache
if (m_renderer->get_shaders()->enabled() && texinfo->width != 0 && texinfo->height != 0 && (flags & PRIMFLAG_SCREENTEX_MASK) != 0)
{
if (m_renderer->get_shaders()->find_render_target(texture) != nullptr)
{
return texture;
}
if (m_renderer->get_shaders()->find_render_target((*it).get()) != nullptr)
return (*it).get();
}
else
{
return texture;
return (*it).get();
}
}
}
@ -514,23 +505,23 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, U
UINT32 prim_screen = texinfo->osddata >> 1;
UINT32 prim_page = texinfo->osddata & 1;
for (texture = m_renderer->get_texture_manager()->get_texlist(); texture != nullptr; texture = texture->get_next())
for (auto it = m_texture_list.begin(); it != m_texture_list.end(); it++)
{
UINT32 test_screen = texture->get_texinfo().osddata >> 1;
UINT32 test_page = texture->get_texinfo().osddata & 1;
UINT32 test_screen = (*it)->get_texinfo().osddata >> 1;
UINT32 test_page = (*it)->get_texinfo().osddata & 1;
if (test_screen != prim_screen || test_page != prim_page)
{
continue;
}
// Clear out our old texture reference
if (texture->get_hash() == hash &&
texture->get_texinfo().base == texinfo->base &&
((texture->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 &&
(texture->get_texinfo().width != texinfo->width ||
texture->get_texinfo().height != texinfo->height))
if ((*it)->get_hash() == hash &&
(*it)->get_texinfo().base == texinfo->base &&
(((*it)->get_flags() ^ flags) & (PRIMFLAG_BLENDMODE_MASK | PRIMFLAG_TEXFORMAT_MASK)) == 0 &&
((*it)->get_texinfo().width != texinfo->width ||
(*it)->get_texinfo().height != texinfo->height))
{
m_renderer->get_shaders()->remove_render_target(texture);
m_renderer->get_shaders()->remove_render_target((*it).get());
}
}
}
@ -631,7 +622,9 @@ void d3d_texture_manager::update_textures()
{
int prescale = m_renderer->get_shaders()->enabled() ? 1 : win->prescale();
texture = global_alloc(texture_info(this, &prim.texture, prescale, prim.flags));
auto tex = std::make_unique<texture_info>(this, &prim.texture, prescale, prim.flags);
texture = tex.get();
m_texture_list.push_back(std::move(tex));
}
else
{
@ -2105,9 +2098,6 @@ texture_info::texture_info(d3d_texture_manager *manager, const render_texinfo* t
// copy the data to the texture
set_data(texsource, flags);
// add us to the texture list
m_next = m_texture_manager->get_texlist();
m_texture_manager->set_texlist(this);
return;
error: