Avoid complete reinit on apply_state_changes.
Clean up multi-pass logic a bit in D3D9.
This commit is contained in:
parent
068beedf3c
commit
8bb4cbae46
|
@ -329,28 +329,9 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3DVideo::viewport_need_restore()
|
|
||||||
{
|
|
||||||
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
|
||||||
if (memcmp(&viewport_state.custom, &custom, sizeof(custom)))
|
|
||||||
return true;
|
|
||||||
if (viewport_state.scale_integer != g_settings.video.scale_integer)
|
|
||||||
return true;
|
|
||||||
if (fabs(viewport_state.aspect_ratio - g_extern.system.aspect_ratio) > 0.0001)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void D3DVideo::calculate_rect(unsigned width, unsigned height,
|
void D3DVideo::calculate_rect(unsigned width, unsigned height,
|
||||||
bool keep, float desired_aspect)
|
bool keep, float desired_aspect)
|
||||||
{
|
{
|
||||||
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
|
||||||
|
|
||||||
viewport_state.custom = custom;
|
|
||||||
viewport_state.scale_integer = g_settings.video.scale_integer;
|
|
||||||
viewport_state.aspect_ratio = desired_aspect;
|
|
||||||
|
|
||||||
if (g_settings.video.scale_integer)
|
if (g_settings.video.scale_integer)
|
||||||
{
|
{
|
||||||
struct rarch_viewport vp = {0};
|
struct rarch_viewport vp = {0};
|
||||||
|
@ -363,6 +344,7 @@ void D3DVideo::calculate_rect(unsigned width, unsigned height,
|
||||||
{
|
{
|
||||||
if (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
if (g_settings.video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
|
||||||
{
|
{
|
||||||
|
const rarch_viewport_t &custom = g_extern.console.screen.viewports.custom_vp;
|
||||||
set_viewport(custom.x, custom.y, custom.width, custom.height);
|
set_viewport(custom.x, custom.y, custom.width, custom.height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -438,6 +420,7 @@ D3DVideo::D3DVideo(const video_info_t *info) :
|
||||||
g_pD3D(nullptr), dev(nullptr), font(nullptr),
|
g_pD3D(nullptr), dev(nullptr), font(nullptr),
|
||||||
rotation(0), needs_restore(false), cgCtx(nullptr)
|
rotation(0), needs_restore(false), cgCtx(nullptr)
|
||||||
{
|
{
|
||||||
|
should_resize = false;
|
||||||
gfx_set_dwm();
|
gfx_set_dwm();
|
||||||
|
|
||||||
#ifdef HAVE_OVERLAY
|
#ifdef HAVE_OVERLAY
|
||||||
|
@ -611,6 +594,22 @@ bool D3DVideo::frame(const void *frame,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (should_resize)
|
||||||
|
{
|
||||||
|
calculate_rect(screen_width, screen_height, video_info.force_aspect, g_extern.system.aspect_ratio);
|
||||||
|
chain->set_final_viewport(final_viewport);
|
||||||
|
recompute_pass_sizes();
|
||||||
|
|
||||||
|
// render_chain() only clears out viewport, clear out everything.
|
||||||
|
D3DRECT clear_rect;
|
||||||
|
clear_rect.x1 = clear_rect.y1 = 0;
|
||||||
|
clear_rect.x2 = screen_width;
|
||||||
|
clear_rect.y2 = screen_height;
|
||||||
|
dev->Clear(1, &clear_rect, D3DCLEAR_TARGET, 0, 1, 0);
|
||||||
|
|
||||||
|
should_resize = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!chain->render(frame, width, height, pitch, rotation))
|
if (!chain->render(frame, width, height, pitch, rotation))
|
||||||
{
|
{
|
||||||
RARCH_ERR("[D3D9]: Failed to render scene.\n");
|
RARCH_ERR("[D3D9]: Failed to render scene.\n");
|
||||||
|
@ -803,6 +802,22 @@ void D3DVideo::init_multipass()
|
||||||
shader.pass[i].fbo.type_x = shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT;
|
shader.pass[i].fbo.type_x = shader.pass[i].fbo.type_y = RARCH_SCALE_INPUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool use_extra_pass = shader.passes < GFX_MAX_SHADERS && shader.pass[shader.passes - 1].fbo.valid;
|
||||||
|
if (use_extra_pass)
|
||||||
|
{
|
||||||
|
shader.passes++;
|
||||||
|
gfx_shader_pass &dummy_pass = shader.pass[shader.passes - 1];
|
||||||
|
dummy_pass.fbo.scale_x = dummy_pass.fbo.scale_y = 1.0f;
|
||||||
|
dummy_pass.fbo.type_x = dummy_pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||||
|
dummy_pass.filter = RARCH_FILTER_UNSPEC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gfx_shader_pass &pass = shader.pass[shader.passes - 1];
|
||||||
|
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
||||||
|
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3DVideo::set_shader(const std::string &path)
|
bool D3DVideo::set_shader(const std::string &path)
|
||||||
|
@ -839,6 +854,43 @@ void D3DVideo::process_shader()
|
||||||
init_singlepass();
|
init_singlepass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void D3DVideo::recompute_pass_sizes()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LinkInfo link_info = {0};
|
||||||
|
link_info.pass = &shader.pass[0];
|
||||||
|
link_info.tex_w = link_info.tex_h = video_info.input_scale * RARCH_SCALE_BASE;
|
||||||
|
|
||||||
|
unsigned current_width = link_info.tex_w;
|
||||||
|
unsigned current_height = link_info.tex_h;
|
||||||
|
unsigned out_width = 0;
|
||||||
|
unsigned out_height = 0;
|
||||||
|
|
||||||
|
chain->set_pass_size(0, current_width, current_height);
|
||||||
|
for (unsigned i = 1; i < shader.passes; i++)
|
||||||
|
{
|
||||||
|
RenderChain::convert_geometry(link_info,
|
||||||
|
out_width, out_height,
|
||||||
|
current_width, current_height, final_viewport);
|
||||||
|
|
||||||
|
link_info.tex_w = next_pow2(out_width);
|
||||||
|
link_info.tex_h = next_pow2(out_height);
|
||||||
|
|
||||||
|
chain->set_pass_size(i, link_info.tex_w, link_info.tex_h);
|
||||||
|
|
||||||
|
current_width = out_width;
|
||||||
|
current_height = out_height;
|
||||||
|
|
||||||
|
link_info.pass = &shader.pass[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[D3D9]: Render chain error: (%s).\n", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool D3DVideo::init_chain(const video_info_t &video_info)
|
bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -846,14 +898,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||||
// Setup information for first pass.
|
// Setup information for first pass.
|
||||||
LinkInfo link_info = {0};
|
LinkInfo link_info = {0};
|
||||||
|
|
||||||
if (shader.passes == 1 && !shader.pass[0].fbo.valid)
|
|
||||||
{
|
|
||||||
gfx_shader_pass &pass = shader.pass[0];
|
|
||||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
|
||||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
|
||||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
link_info.pass = &shader.pass[0];
|
link_info.pass = &shader.pass[0];
|
||||||
link_info.tex_w = link_info.tex_h = video_info.input_scale * RARCH_SCALE_BASE;
|
link_info.tex_w = link_info.tex_h = video_info.input_scale * RARCH_SCALE_BASE;
|
||||||
|
|
||||||
|
@ -870,8 +914,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||||
unsigned out_width = 0;
|
unsigned out_width = 0;
|
||||||
unsigned out_height = 0;
|
unsigned out_height = 0;
|
||||||
|
|
||||||
bool use_extra_pass = shader.pass[shader.passes - 1].fbo.valid;
|
|
||||||
|
|
||||||
for (unsigned i = 1; i < shader.passes; i++)
|
for (unsigned i = 1; i < shader.passes; i++)
|
||||||
{
|
{
|
||||||
RenderChain::convert_geometry(link_info,
|
RenderChain::convert_geometry(link_info,
|
||||||
|
@ -885,32 +927,6 @@ bool D3DVideo::init_chain(const video_info_t &video_info)
|
||||||
current_width = out_width;
|
current_width = out_width;
|
||||||
current_height = out_height;
|
current_height = out_height;
|
||||||
|
|
||||||
if (i == shader.passes - 1 && !use_extra_pass)
|
|
||||||
{
|
|
||||||
gfx_shader_pass &pass = shader.pass[i];
|
|
||||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
|
||||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
|
||||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain->add_pass(link_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_extra_pass)
|
|
||||||
{
|
|
||||||
RenderChain::convert_geometry(link_info,
|
|
||||||
out_width, out_height,
|
|
||||||
current_width, current_height, final_viewport);
|
|
||||||
|
|
||||||
gfx_shader_pass &pass = shader.pass[shader.passes - 1];
|
|
||||||
pass.filter = video_info.smooth ? RARCH_FILTER_LINEAR : RARCH_FILTER_NEAREST;
|
|
||||||
pass.fbo.scale_x = pass.fbo.scale_y = 1.0f;
|
|
||||||
pass.fbo.type_x = pass.fbo.type_y = RARCH_SCALE_VIEWPORT;
|
|
||||||
|
|
||||||
link_info.pass = &pass;
|
|
||||||
link_info.tex_w = next_pow2(out_width);
|
|
||||||
link_info.tex_h = next_pow2(out_height);
|
|
||||||
|
|
||||||
chain->add_pass(link_info);
|
chain->add_pass(link_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1409,15 +1425,14 @@ static void d3d9_set_aspect_ratio(void *data, unsigned aspect_ratio_idx)
|
||||||
|
|
||||||
g_extern.system.aspect_ratio = aspectratio_lut[aspect_ratio_idx].value;
|
g_extern.system.aspect_ratio = aspectratio_lut[aspect_ratio_idx].value;
|
||||||
d3d->info().force_aspect = true;
|
d3d->info().force_aspect = true;
|
||||||
d3d->restore();
|
d3d->should_resize = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d3d9_apply_state_changes(void *data)
|
static void d3d9_apply_state_changes(void *data)
|
||||||
{
|
{
|
||||||
D3DVideo *d3d = reinterpret_cast<D3DVideo*>(data);
|
D3DVideo *d3d = reinterpret_cast<D3DVideo*>(data);
|
||||||
if (d3d->viewport_need_restore())
|
d3d->should_resize = true;
|
||||||
d3d->restore();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void d3d9_set_osd_msg(void *data, const char *msg, void *userdata)
|
static void d3d9_set_osd_msg(void *data, const char *msg, void *userdata)
|
||||||
|
|
|
@ -95,7 +95,7 @@ class D3DVideo
|
||||||
bool restore();
|
bool restore();
|
||||||
void render_msg(const char *msg, font_params_t *params = nullptr);
|
void render_msg(const char *msg, font_params_t *params = nullptr);
|
||||||
|
|
||||||
bool viewport_need_restore();
|
bool should_resize;
|
||||||
inline video_info_t& info() { return video_info; }
|
inline video_info_t& info() { return video_info; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -106,13 +106,7 @@ class D3DVideo
|
||||||
IDirect3DDevice9 *dev;
|
IDirect3DDevice9 *dev;
|
||||||
LPD3DXFONT font;
|
LPD3DXFONT font;
|
||||||
|
|
||||||
struct
|
void recompute_pass_sizes();
|
||||||
{
|
|
||||||
rarch_viewport_t custom;
|
|
||||||
float aspect_ratio;
|
|
||||||
bool scale_integer;
|
|
||||||
} viewport_state;
|
|
||||||
|
|
||||||
void calculate_rect(unsigned width, unsigned height, bool keep, float aspect);
|
void calculate_rect(unsigned width, unsigned height, bool keep, float aspect);
|
||||||
void set_viewport(int x, int y, unsigned width, unsigned height);
|
void set_viewport(int x, int y, unsigned width, unsigned height);
|
||||||
unsigned screen_width;
|
unsigned screen_width;
|
||||||
|
|
|
@ -108,6 +108,36 @@ void RenderChain::clear()
|
||||||
luts.clear();
|
luts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderChain::set_final_viewport(const D3DVIEWPORT9& final_viewport)
|
||||||
|
{
|
||||||
|
this->final_viewport = final_viewport;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderChain::set_pass_size(unsigned pass_index, unsigned width, unsigned height)
|
||||||
|
{
|
||||||
|
Pass &pass = passes[pass_index];
|
||||||
|
if (width != pass.info.tex_w || height != pass.info.tex_h)
|
||||||
|
{
|
||||||
|
pass.tex->Release();
|
||||||
|
pass.info.tex_w = width;
|
||||||
|
pass.info.tex_h = height;
|
||||||
|
|
||||||
|
if (FAILED(dev->CreateTexture(width, height, 1,
|
||||||
|
D3DUSAGE_RENDERTARGET,
|
||||||
|
passes.back().info.pass->fbo.fp_fbo ? D3DFMT_A32B32G32R32F : D3DFMT_A8R8G8B8,
|
||||||
|
D3DPOOL_DEFAULT,
|
||||||
|
&pass.tex, nullptr)))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to create texture ...");
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->SetTexture(0, pass.tex);
|
||||||
|
dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
|
||||||
|
dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
|
||||||
|
dev->SetTexture(0, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RenderChain::add_pass(const LinkInfo &info)
|
void RenderChain::add_pass(const LinkInfo &info)
|
||||||
{
|
{
|
||||||
Pass pass;
|
Pass pass;
|
||||||
|
@ -620,7 +650,18 @@ void RenderChain::render_pass(Pass &pass, unsigned pass_index)
|
||||||
bind_luts(pass);
|
bind_luts(pass);
|
||||||
bind_tracker(pass, pass_index);
|
bind_tracker(pass, pass_index);
|
||||||
|
|
||||||
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
|
// Clear out whole framebuffer incase we change viewports mid-way to avoid stale garbage.
|
||||||
|
if (pass_index < passes.size())
|
||||||
|
{
|
||||||
|
D3DRECT clear_rect;
|
||||||
|
clear_rect.x1 = clear_rect.y1 = 0;
|
||||||
|
clear_rect.x2 = passes[pass_index].info.tex_w;
|
||||||
|
clear_rect.y2 = passes[pass_index].info.tex_h;
|
||||||
|
dev->Clear(1, &clear_rect, D3DCLEAR_TARGET, 0, 1, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
|
||||||
|
|
||||||
if (SUCCEEDED(dev->BeginScene()))
|
if (SUCCEEDED(dev->BeginScene()))
|
||||||
{
|
{
|
||||||
dev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
dev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||||
|
|
|
@ -51,6 +51,8 @@ class RenderChain
|
||||||
PixelFormat fmt,
|
PixelFormat fmt,
|
||||||
const D3DVIEWPORT9 &final_viewport);
|
const D3DVIEWPORT9 &final_viewport);
|
||||||
|
|
||||||
|
void set_pass_size(unsigned pass, unsigned width, unsigned height);
|
||||||
|
void set_final_viewport(const D3DVIEWPORT9 &final_viewport);
|
||||||
void add_pass(const LinkInfo &info);
|
void add_pass(const LinkInfo &info);
|
||||||
void add_lut(const std::string &id, const std::string &path, bool smooth);
|
void add_lut(const std::string &id, const std::string &path, bool smooth);
|
||||||
void add_state_tracker(std::shared_ptr<state_tracker_t> tracker);
|
void add_state_tracker(std::shared_ptr<state_tracker_t> tracker);
|
||||||
|
|
Loading…
Reference in New Issue