Fixed crash of D3D when sliders menu is openend and resizing the window or switching between window and full screen mode

master
ImJezze 2016-06-19 14:18:40 +02:00
parent a45a1fcf0d
commit f056b622bc
4 changed files with 322 additions and 277 deletions

View File

@ -43,23 +43,13 @@ static void get_vector(const char *data, int count, float *out, bool report_erro
//============================================================
shaders::shaders() :
d3dintf(nullptr), machine(nullptr), d3d(nullptr), num_screens(0), curr_screen(0),
avi_output_file(nullptr), avi_frame(0), avi_copy_surface(nullptr), avi_copy_texture(nullptr), avi_final_target(nullptr), avi_final_texture(nullptr),
d3dintf(nullptr), machine(nullptr), d3d(nullptr), post_fx_enable(false), oversampling_enable(false), paused(true), num_screens(0), curr_screen(0), lastidx(-1),
shadow_texture(nullptr), options(nullptr), avi_output_file(nullptr), avi_frame(0), avi_copy_surface(nullptr), avi_copy_texture(nullptr), avi_final_target(nullptr), avi_final_texture(nullptr),
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), lines_pending(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), fsfx_vertices(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr)
snap_width(0), snap_height(0), lines_pending(false), 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), fsfx_vertices(nullptr), curr_texture(nullptr), curr_render_target(nullptr), curr_poly(nullptr), targethead(nullptr), cachehead(nullptr)
{
master_enable = false;
vector_enable = true;
oversampling_enable = false;
shadow_texture = nullptr;
options = nullptr;
paused = true;
lastidx = -1;
targethead = nullptr;
cachehead = nullptr;
initialized = false;
}
@ -74,6 +64,12 @@ shaders::~shaders()
delete slider;
}
if (options != nullptr)
{
global_free(options);
options = nullptr;
}
cache_target *currcache = cachehead;
while(cachehead != nullptr)
{
@ -98,7 +94,7 @@ shaders::~shaders()
void shaders::window_save()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -130,7 +126,7 @@ void shaders::window_save()
void shaders::window_record()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -155,7 +151,7 @@ void shaders::window_record()
void shaders::avi_update_snap(IDirect3DSurface9 *surface)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -208,7 +204,7 @@ void shaders::avi_update_snap(IDirect3DSurface9 *surface)
void shaders::render_snapshot(IDirect3DSurface9 *surface)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -310,7 +306,7 @@ void shaders::render_snapshot(IDirect3DSurface9 *surface)
void shaders::record_texture()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -353,7 +349,7 @@ void shaders::record_texture()
void shaders::end_avi_recording()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -368,53 +364,13 @@ void shaders::end_avi_recording()
}
//============================================================
// shaders::toggle
//============================================================
void shaders::toggle(std::vector<ui::menu_item>& sliders)
{
if (master_enable)
{
if (initialized)
{
// free shader resources before renderer resources
delete_resources(false);
}
master_enable = !master_enable;
// free shader resources and re-create
d3d->device_delete_resources();
d3d->device_create_resources();
}
else
{
master_enable = !master_enable;
// free shader resources and re-create
d3d->device_delete_resources();
d3d->device_create_resources();
if (!initialized)
{
// re-create shader resources after renderer resources
bool failed = create_resources(false, sliders);
if (failed)
{
master_enable = false;
}
}
}
}
//============================================================
// shaders::begin_avi_recording
//============================================================
void shaders::begin_avi_recording(const char *name)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -573,7 +529,7 @@ void shaders::remove_render_target(d3d_render_target *rt)
void shaders::set_texture(texture_info *texture)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -602,53 +558,64 @@ void shaders::set_texture(texture_info *texture)
// shaders::init
//============================================================
void shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer)
bool shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer)
{
osd_printf_verbose("Direct3D: Initialize HLSL\n");
if (initialized)
{
return false;
}
// check if no driver loaded (not all settings might be loaded yet)
if (&machine->system() == &GAME_NAME(___empty))
{
return false;
}
// check if another driver is loaded and reset last options
if (std::strcmp(machine->system().name, last_system_name) != 0)
{
strncpy(last_system_name, machine->system().name, sizeof(last_system_name));
last_options.params_init = false;
}
d3dx9_dll = osd::dynamic_module::open({ "d3dx9_43.dll" });
d3dx_create_effect_from_file_ptr = d3dx9_dll->bind<d3dx_create_effect_from_file_fn>("D3DXCreateEffectFromFileW");
if (!d3dx_create_effect_from_file_ptr)
{
osd_printf_verbose("Direct3D: Unable to find D3DXCreateEffectFromFileW\n");
d3dintf->post_fx_available = false;
return;
return false;
}
d3dintf->post_fx_available = true;
this->d3dintf = d3dintf;
this->machine = machine;
this->d3d = renderer;
this->options = renderer->get_shaders_options();
// check if no driver loaded (not all settings might be loaded yet)
if (&machine->system() == &GAME_NAME(___empty))
{
return;
}
// check if another driver is loaded
if (std::strcmp(machine->system().name, last_system_name) != 0)
{
strncpy(last_system_name, machine->system().name, sizeof(last_system_name));
options->params_init = false;
last_options.params_init = false;
}
enumerate_screens();
windows_options &winoptions = downcast<windows_options &>(machine->options());
master_enable = winoptions.d3d_hlsl_enable();
post_fx_enable = winoptions.d3d_hlsl_enable();
oversampling_enable = winoptions.d3d_hlsl_oversampling();
snap_width = winoptions.d3d_snap_width();
snap_height = winoptions.d3d_snap_height();
this->options = (hlsl_options*)global_alloc_clear<hlsl_options>();
this->options->params_init = false;
// copy last options if initialized
if (last_options.params_init)
{
osd_printf_verbose("Direct3D: First restore options\n");
options = &last_options;
}
// read options if not initialized
if (!options->params_init)
{
strncpy(options->shadow_mask_texture, winoptions.screen_shadow_mask_texture(), sizeof(options->shadow_mask_texture));
@ -719,9 +686,19 @@ void shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
options->bloom_level8_weight = winoptions.screen_bloom_lvl8_weight();
options->params_init = true;
osd_printf_verbose("Direct3D: First store options\n");
last_options = *options;
options = &last_options;
}
options->params_dirty = true;
initialized = true;
osd_printf_verbose("Direct3D: HLSL initialized\n");
return true;
}
@ -734,7 +711,7 @@ void shaders::init_fsfx_quad(void *vertbuf)
// Called at the start of each frame by the D3D code in order to reserve two triangles
// that are guaranteed to be at a fixed position so as to simply use D3DPT_TRIANGLELIST, 0, 2
// instead of having to do bookkeeping about a specific screen quad
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -805,15 +782,16 @@ void shaders::init_fsfx_quad(void *vertbuf)
// shaders::create_resources
//============================================================
int shaders::create_resources(bool reset, std::vector<ui::menu_item>& sliders)
int shaders::create_resources()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!initialized || !enabled())
{
return 0;
}
if (last_options.params_init)
{
osd_printf_verbose("Direct3D: Restore options\n");
options = &last_options;
}
@ -982,11 +960,6 @@ int shaders::create_resources(bool reset, std::vector<ui::menu_item>& sliders)
distortion_effect->add_uniform("SmoothBorderAmount", uniform::UT_FLOAT, uniform::CU_POST_SMOOTH_BORDER);
distortion_effect->add_uniform("ReflectionAmount", uniform::UT_FLOAT, uniform::CU_POST_REFLECTION);
initialized = true;
std::vector<ui::menu_item> my_sliders = init_slider_list();
sliders.insert(sliders.end(), my_sliders.begin(), my_sliders.end());
return 0;
}
@ -997,7 +970,7 @@ int shaders::create_resources(bool reset, std::vector<ui::menu_item>& sliders)
void shaders::begin_draw()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -1094,7 +1067,7 @@ void shaders::blit(
void shaders::end_frame()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -1587,7 +1560,7 @@ void shaders::ui_pass(poly_info *poly, int vertnum)
void shaders::render_quad(poly_info *poly, int vertnum)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -1644,7 +1617,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
curr_screen++;
}
else if (PRIMFLAG_GET_VECTOR(poly->get_flags()) && vector_enable)
else if (PRIMFLAG_GET_VECTOR(poly->get_flags()))
{
lines_pending = true;
@ -1673,7 +1646,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
osd_printf_verbose("Direct3D: Error %08lX during device SetRenderTarget call\n", result);
}
}
else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()) && vector_enable)
else if (PRIMFLAG_GET_VECTORBUF(poly->get_flags()))
{
curr_screen = curr_screen < num_screens ? curr_screen : 0;
@ -1748,7 +1721,7 @@ void shaders::render_quad(poly_info *poly, int vertnum)
void shaders::end_draw()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return;
}
@ -1790,6 +1763,11 @@ bool shaders::add_cache_target(renderer_d3d9* d3d, texture_info* texture, int so
d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_info *texture)
{
if (!enabled())
{
return nullptr;
}
auto win = d3d->assert_window();
int target_width = int(prim->get_quad_width() + 0.5f);
@ -1810,7 +1788,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_i
// check if the size of the screen quad has changed
if (target->target_width != target_width || target->target_height != target_height)
{
osd_printf_verbose("get_texture_target() - invalid size\n");
osd_printf_verbose("Direct3D: Get texture target - invalid size\n");
return nullptr;
}
}
@ -1821,7 +1799,7 @@ d3d_render_target* shaders::get_texture_target(render_primitive *prim, texture_i
d3d_render_target* shaders::get_vector_target(render_primitive *prim)
{
if (!vector_enable)
if (!enabled())
{
return nullptr;
}
@ -1850,7 +1828,7 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim)
// check if the size of the screen quad has changed
if (target->target_width != target_width || target->target_height != target_height)
{
osd_printf_verbose("get_vector_target() - invalid size\n");
osd_printf_verbose("Direct3D: Get vector target - invalid size\n");
return nullptr;
}
}
@ -1859,8 +1837,13 @@ d3d_render_target* shaders::get_vector_target(render_primitive *prim)
return target;
}
void shaders::create_vector_target(render_primitive *prim)
bool shaders::create_vector_target(render_primitive *prim)
{
if (!enabled())
{
return false;
}
auto win = d3d->assert_window();
// source and target size are the same for vector targets
@ -1876,11 +1859,13 @@ void shaders::create_vector_target(render_primitive *prim)
std::swap(target_width, target_height);
}
osd_printf_verbose("create_vector_target() - %d, %d\n", target_width, target_height);
osd_printf_verbose("Direct3D: Create vector target - %dx%d\n", target_width, target_height);
if (!add_render_target(d3d, prim, nullptr, source_width, source_height, target_width, target_height))
{
vector_enable = false;
return false;
}
return true;
}
@ -1966,7 +1951,7 @@ void shaders::enumerate_screens()
bool shaders::register_texture(render_primitive *prim, texture_info *texture)
{
if (!master_enable || !d3dintf->post_fx_available)
if (!enabled())
{
return false;
}
@ -1985,7 +1970,7 @@ bool shaders::register_texture(render_primitive *prim, texture_info *texture)
std::swap(target_width, target_height);
}
osd_printf_verbose("register_texture() - %d, %d\n", target_width, target_height);
osd_printf_verbose("Direct3D: Register texture - %dx%d\n", target_width, target_height);
if (!add_render_target(d3d, prim, texture, source_width, source_height, target_width, target_height))
{
return false;
@ -1999,21 +1984,21 @@ bool shaders::register_texture(render_primitive *prim, texture_info *texture)
// shaders::delete_resources
//============================================================
void shaders::delete_resources(bool reset)
void shaders::delete_resources()
{
if (!master_enable || !d3dintf->post_fx_available)
if (!initialized || !enabled())
{
return;
}
end_avi_recording();
if (options != nullptr)
{
osd_printf_verbose("Direct3D: Store options\n");
last_options = *options;
options = nullptr;
}
initialized = false;
cache_target *currcache = cachehead;
while(cachehead != nullptr)
{
@ -2490,9 +2475,9 @@ void *shaders::get_slider_option(int id, int index)
return nullptr;
}
std::vector<ui::menu_item> shaders::init_slider_list()
void shaders::init_slider_list()
{
std::vector<ui::menu_item> sliders;
m_sliders.clear();
for (slider* slider : internal_sliders)
{
@ -2503,7 +2488,7 @@ std::vector<ui::menu_item> shaders::init_slider_list()
auto first_screen = machine->first_screen();
if (first_screen == nullptr)
{
return sliders;
return;
}
int screen_type = first_screen->screen_type();
@ -2559,12 +2544,10 @@ std::vector<ui::menu_item> shaders::init_slider_list()
item.flags = 0;
item.ref = core_slider;
item.type = ui::menu_item_type::SLIDER;
sliders.push_back(item);
m_sliders.push_back(item);
}
}
}
return sliders;
}

View File

@ -301,14 +301,13 @@ public:
shaders();
~shaders();
void init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer);
bool init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *renderer);
bool enabled() { return master_enable; }
void toggle(std::vector<ui::menu_item>& sliders);
bool enabled() { return post_fx_enable && d3dintf->post_fx_available; }
void toggle() { post_fx_enable = initialized && !post_fx_enable; }
bool vector_enabled() { return master_enable && vector_enable; }
d3d_render_target* get_vector_target(render_primitive *prim);
void create_vector_target(render_primitive *prim);
bool create_vector_target(render_primitive *prim);
void begin_frame();
void end_frame();
@ -339,13 +338,14 @@ public:
void remove_render_target(int source_width, int source_height, UINT32 screen_index, UINT32 page_index);
void remove_render_target(d3d_render_target *rt);
int create_resources(bool reset, std::vector<ui::menu_item>& sliders);
void delete_resources(bool reset);
int create_resources();
void delete_resources();
// slider-related functions
virtual INT32 slider_changed(running_machine &machine, void *arg, int /*id*/, std::string *str, INT32 newval) override;
slider_state* slider_alloc(running_machine &machine, int id, const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, void *arg);
std::vector<ui::menu_item> init_slider_list();
void init_slider_list();
std::vector<ui::menu_item> get_slider_list() { return m_sliders; }
void *get_slider_option(int id, int index = 0);
private:
@ -382,8 +382,7 @@ private:
running_machine * machine;
renderer_d3d9 * d3d; // D3D renderer
bool master_enable; // overall enable flag
bool vector_enable; // vector post-processing enable flag
bool post_fx_enable; // overall enable flag
bool oversampling_enable; // oversampling enable flag
bool paused; // whether or not rendering is currently paused
int num_screens; // number of emulated physical screens
@ -442,6 +441,7 @@ private:
cache_target * cachehead;
std::vector<slider*> internal_sliders;
std::vector<ui::menu_item> m_sliders;
static slider_desc s_sliders[];
static hlsl_options last_options; // last used options

View File

@ -137,7 +137,7 @@ int renderer_d3d9::create()
void renderer_d3d9::toggle_fsfx()
{
set_restarting(true);
set_toggle(true);
}
void renderer_d3d9::record()
@ -184,14 +184,14 @@ render_primitive_list *renderer_d3d9::get_primitives()
bool renderer_d3d9::init(running_machine &machine)
{
d3dintf = global_alloc(d3d_base);
d3dintf->d3d9_dll = osd::dynamic_module::open({ "d3d9.dll" });
d3d9_create_fn d3d9_create_ptr = d3dintf->d3d9_dll->bind<d3d9_create_fn>("Direct3DCreate9");
if (d3d9_create_ptr == nullptr)
{
osd_printf_verbose("Direct3D: Unable to find Direct3D 9 runtime library\n");
return true;
return true;
}
d3dintf->d3dobj = (*d3d9_create_ptr)(D3D_SDK_VERSION);
@ -520,21 +520,23 @@ texture_info *d3d_texture_manager::find_texinfo(const render_texinfo *texinfo, U
renderer_d3d9::renderer_d3d9(std::shared_ptr<osd_window> window)
: osd_renderer(window, FLAG_NONE), m_adapter(0), m_width(0), m_height(0), m_refresh(0), m_create_error_count(0), m_device(nullptr), m_gamma_supported(0), m_pixformat(),
m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_restarting(false), m_mod2x_supported(0), m_mod4x_supported(0),
m_vertexbuf(nullptr), m_lockedbuf(nullptr), m_numverts(0), m_vectorbatch(nullptr), m_batchindex(0), m_numpolys(0), m_toggle(false),
m_screen_format(), m_last_texture(nullptr), m_last_texture_flags(0), m_last_blendenable(0), m_last_blendop(0), m_last_blendsrc(0), m_last_blenddst(0), m_last_filter(0),
m_last_wrap(), m_last_modmode(0), m_hlsl_buf(nullptr), m_shaders(nullptr), m_shaders_options(nullptr), m_texture_manager(nullptr)
m_last_wrap(), m_last_modmode(0), m_hlsl_buf(nullptr), m_shaders(nullptr), m_texture_manager(nullptr)
{
}
int renderer_d3d9::initialize()
{
osd_printf_verbose("Direct3D: Initialize\n");
// configure the adapter for the mode we want
if (config_adapter_mode())
{
return false;
}
// create the device immediately for the full screen case (defer for window mode)
// create the device immediately for the full screen case (defer for window mode in update_window_size())
auto win = assert_window();
if (win->fullscreen() && device_create(win->main_window()->platform_window<HWND>()))
{
@ -552,13 +554,24 @@ int renderer_d3d9::pre_window_draw_check()
if (win->m_resize_state == RESIZE_STATE_RESIZING)
return 0;
// if we're restarting the renderer, leave things alone
if (m_restarting)
// check if shaders should be toggled
if (m_toggle)
{
m_sliders.clear();
m_shaders->toggle(m_sliders);
m_toggle = false;
m_restarting = false;
// free resources
device_delete_resources();
m_shaders->toggle();
m_sliders_dirty = true;
// re-create resources
if (device_create_resources())
{
osd_printf_verbose("Direct3D: failed to recreate resources for device; failing permanently\n");
device_delete();
return 1;
}
}
// if we have a device, check the cooperative level
@ -630,11 +643,14 @@ void d3d_texture_manager::update_textures()
}
else if(PRIMFLAG_GET_VECTORBUF(prim.flags))
{
if (m_renderer->get_shaders()->vector_enabled())
if (m_renderer->get_shaders()->enabled())
{
if (!m_renderer->get_shaders()->get_vector_target(&prim))
{
m_renderer->get_shaders()->create_vector_target(&prim);
if (!m_renderer->get_shaders()->create_vector_target(&prim))
{
d3dintf->post_fx_available = false;
}
}
}
}
@ -736,6 +752,65 @@ void renderer_d3d9::end_frame()
osd_printf_verbose("Direct3D: Error %08lX during device present call\n", result);
}
void renderer_d3d9::update_presentation_parameters()
{
auto win = assert_window();
memset(&m_presentation, 0, sizeof(m_presentation));
m_presentation.BackBufferWidth = m_width;
m_presentation.BackBufferHeight = m_height;
m_presentation.BackBufferFormat = m_pixformat;
m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1;
m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_presentation.hDeviceWindow = win->platform_window<HWND>();
m_presentation.Windowed = !win->fullscreen() || win->win_has_menu();
m_presentation.EnableAutoDepthStencil = FALSE;
m_presentation.AutoDepthStencilFormat = D3DFMT_D16;
m_presentation.Flags = 0;
m_presentation.FullScreen_RefreshRateInHz = m_refresh;
m_presentation.PresentationInterval = (
(video_config.triplebuf && win->fullscreen())
|| video_config.waitvsync
|| video_config.syncrefresh)
? D3DPRESENT_INTERVAL_ONE
: D3DPRESENT_INTERVAL_IMMEDIATE;
}
void renderer_d3d9::update_gamma_ramp()
{
if (m_gamma_supported)
{
return;
}
auto win = assert_window();
// create a standard ramp
D3DGAMMARAMP ramp;
// set the gamma if we need to
if (win->fullscreen())
{
// only set the gamma if it's not 1.0
windows_options &options = downcast<windows_options &>(win->machine().options());
float brightness = options.full_screen_brightness();
float contrast = options.full_screen_contrast();
float gamma = options.full_screen_gamma();
if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f)
{
for (int i = 0; i < 256; i++)
{
ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8;
}
}
}
m_device->SetGammaRamp(0, 0, &ramp);
}
//============================================================
// device_create
//============================================================
@ -749,22 +824,8 @@ int renderer_d3d9::device_create(HWND device_hwnd)
}
// verify the caps
int verify = device_verify_caps();
if (verify == 2)
if (device_verify_caps())
{
osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n");
return 1;
}
if (verify == 1)
{
osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n");
}
// verify texture formats
HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
if (FAILED(result))
{
osd_printf_error("Error: A8R8G8B8 format textures not supported\n");
return 1;
}
@ -773,12 +834,20 @@ int renderer_d3d9::device_create(HWND device_hwnd)
try_again:
// try for XRGB first
m_screen_format = D3DFMT_X8R8G8B8;
result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format);
HRESULT result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat,
m_texture_manager->is_dynamic_supported()
? D3DUSAGE_DYNAMIC
: 0,
D3DRTYPE_TEXTURE, m_screen_format);
if (FAILED(result))
{
// if not, try for ARGB
m_screen_format = D3DFMT_A8R8G8B8;
result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, m_texture_manager->is_dynamic_supported() ? D3DUSAGE_DYNAMIC : 0, D3DRTYPE_TEXTURE, m_screen_format);
result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat,
m_texture_manager->is_dynamic_supported()
? D3DUSAGE_DYNAMIC
: 0,
D3DRTYPE_TEXTURE, m_screen_format);
if (FAILED(result) && m_texture_manager->is_dynamic_supported())
{
m_texture_manager->set_dynamic_supported(FALSE);
@ -791,29 +860,12 @@ try_again:
}
}
auto win = assert_window();
// initialize the D3D presentation parameters
memset(&m_presentation, 0, sizeof(m_presentation));
m_presentation.BackBufferWidth = m_width;
m_presentation.BackBufferHeight = m_height;
m_presentation.BackBufferFormat = m_pixformat;
m_presentation.BackBufferCount = video_config.triplebuf ? 2 : 1;
m_presentation.MultiSampleType = D3DMULTISAMPLE_NONE;
m_presentation.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_presentation.hDeviceWindow = win->platform_window<HWND>();
m_presentation.Windowed = !win->fullscreen() || win->win_has_menu();
m_presentation.EnableAutoDepthStencil = FALSE;
m_presentation.AutoDepthStencilFormat = D3DFMT_D16;
m_presentation.Flags = 0;
m_presentation.FullScreen_RefreshRateInHz = m_refresh;
m_presentation.PresentationInterval = ((video_config.triplebuf && win->fullscreen()) ||
video_config.waitvsync || video_config.syncrefresh) ?
D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
update_presentation_parameters();
// create the D3D device
result = d3dintf->d3dobj->CreateDevice(m_adapter, D3DDEVTYPE_HAL, device_hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device);
result = d3dintf->d3dobj->CreateDevice(
m_adapter, D3DDEVTYPE_HAL, device_hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &m_presentation, &m_device);
if (FAILED(result))
{
// if we got a "DEVICELOST" error, it may be transitory; count it and only fail if
@ -834,52 +886,7 @@ try_again:
m_create_error_count = 0;
osd_printf_verbose("Direct3D: Device created at %dx%d\n", m_width, m_height);
// set the gamma if we need to
if (win->fullscreen())
{
// only set the gamma if it's not 1.0f
windows_options &options = downcast<windows_options &>(win->machine().options());
float brightness = options.full_screen_brightness();
float contrast = options.full_screen_contrast();
float gamma = options.full_screen_gamma();
if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f)
{
// warn if we can't do it
if (!m_gamma_supported)
{
osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n");
}
else
{
// create a standard ramp and set it
D3DGAMMARAMP ramp;
for (int i = 0; i < 256; i++)
{
ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8;
}
m_device->SetGammaRamp(0, 0, &ramp);
}
}
}
// create shader options only once
if (m_shaders_options == nullptr)
{
m_shaders_options = (hlsl_options*)global_alloc_clear<hlsl_options>();
m_shaders_options->params_init = false;
}
m_shaders = (shaders*)global_alloc_clear<shaders>();
m_shaders->init(d3dintf, &win->machine(), this);
m_sliders.clear();
int failed = m_shaders->create_resources(false, m_sliders);
if (failed)
{
return failed;
}
m_sliders_dirty = true;
update_gamma_ramp();
return device_create_resources();
}
@ -891,11 +898,35 @@ try_again:
int renderer_d3d9::device_create_resources()
{
auto win = assert_window();
// create shaders only once
if (m_shaders == nullptr)
{
m_shaders = (shaders*)global_alloc_clear<shaders>();
}
if (m_shaders->init(d3dintf, &win->machine(), this))
{
m_shaders->init_slider_list();
m_sliders_dirty = true;
}
// create resources
if (m_shaders->create_resources())
{
osd_printf_verbose("Direct3D: failed to create HLSL resources for device\n");
return 1;
}
// allocate a vertex buffer to use
HRESULT result = m_device->CreateVertexBuffer(sizeof(vertex) * VERTEX_BUFFER_SIZE,
D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY,
VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW),
D3DPOOL_DEFAULT, &m_vertexbuf, nullptr);
HRESULT result = m_device->CreateVertexBuffer(
sizeof(vertex) * VERTEX_BUFFER_SIZE,
D3DUSAGE_DYNAMIC | D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY,
VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available)
? D3DFVF_XYZW
: D3DFVF_XYZRHW),
D3DPOOL_DEFAULT, &m_vertexbuf, nullptr);
if (FAILED(result))
{
osd_printf_error("Error creating vertex buffer (%08X)\n", (UINT32)result);
@ -903,8 +934,10 @@ int renderer_d3d9::device_create_resources()
}
// set the vertex format
result = m_device->SetFVF((D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() &&
d3dintf->post_fx_available) ? D3DFVF_XYZW : D3DFVF_XYZRHW)));
result = m_device->SetFVF(
(D3DFORMAT)(VERTEX_BASE_FORMAT | ((m_shaders->enabled() && d3dintf->post_fx_available)
? D3DFVF_XYZW
: D3DFVF_XYZRHW)));
if (FAILED(result))
{
osd_printf_error("Error setting vertex format (%08X)\n", (UINT32)result);
@ -955,16 +988,15 @@ int renderer_d3d9::device_create_resources()
renderer_d3d9::~renderer_d3d9()
{
if (get_shaders() != nullptr && get_shaders()->recording())
get_shaders()->window_record();
device_delete();
if (m_shaders_options != nullptr)
{
global_free(m_shaders_options);
m_shaders_options = nullptr;
}
// todo: throws error when switching from full screen to window mode
//if (m_shaders != nullptr)
//{
// // delete the HLSL interface
// global_free(m_shaders);
// m_shaders = nullptr;
//}
}
void renderer_d3d9::exit()
@ -978,19 +1010,11 @@ void renderer_d3d9::exit()
void renderer_d3d9::device_delete()
{
if (m_shaders != nullptr)
{
// free our effects
m_sliders.clear();
m_shaders->delete_resources(false);
// delete the HLSL interface
global_free(m_shaders);
}
// free our base resources
device_delete_resources();
// we do not delete the HLSL interface here
if (m_texture_manager != nullptr)
{
global_free(m_texture_manager);
@ -1012,6 +1036,11 @@ void renderer_d3d9::device_delete()
void renderer_d3d9::device_delete_resources()
{
if (m_shaders != nullptr)
{
m_shaders->delete_resources();
}
if (m_texture_manager != nullptr)
{
m_texture_manager->delete_resources();
@ -1032,12 +1061,14 @@ void renderer_d3d9::device_delete_resources()
int renderer_d3d9::device_verify_caps()
{
int retval = 0;
int verify = 0;
D3DCAPS9 caps;
HRESULT result = d3dintf->d3dobj->GetDeviceCaps(m_adapter, D3DDEVTYPE_HAL, &caps);
if (FAILED(result))
{
osd_printf_verbose("Direct3D: Error %08lX during GetDeviceCaps call\n", result);
}
if (caps.MaxPixelShader30InstructionSlots < 512)
{
@ -1049,40 +1080,59 @@ int renderer_d3d9::device_verify_caps()
if (!(caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE))
{
osd_printf_verbose("Direct3D: Error - Device does not support immediate presentations\n");
retval = 2;
verify = 2;
}
if (!(caps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE))
{
osd_printf_verbose("Direct3D: Error - Device does not support per-refresh presentations\n");
retval = 2;
verify = 2;
}
// verify device capabilities
if (!(caps.DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP))
{
osd_printf_verbose("Direct3D: Warning - Device does not support queued rendering after a page flip\n");
retval = 1;
verify = 1;
}
if (!(caps.DevCaps & D3DDEVCAPS_HWRASTERIZATION))
{
osd_printf_verbose("Direct3D: Warning - Device does not support hardware rasterization\n");
retval = 1;
verify = 1;
}
// verify texture operation capabilities
if (!(caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE))
{
osd_printf_verbose("Direct3D: Warning - Device does not support texture modulation\n");
retval = 1;
verify = 1;
}
// set a simpler flag to indicate mod2x and mod4x texture modes
m_mod2x_supported = ((caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE2X) != 0);
m_mod4x_supported = ((caps.TextureOpCaps & D3DTEXOPCAPS_MODULATE4X) != 0);
m_gamma_supported = ((caps.Caps2 & D3DCAPS2_FULLSCREENGAMMA) != 0);
if (!m_gamma_supported)
{
osd_printf_warning("Direct3D: Warning - device does not support full screen gamma correction.\n");
}
return retval;
// verify texture formats
result = d3dintf->d3dobj->CheckDeviceFormat(m_adapter, D3DDEVTYPE_HAL, m_pixformat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
if (FAILED(result))
{
osd_printf_error("Error: A8R8G8B8 format textures not supported\n");
verify = 2;
}
if (verify == 2)
{
osd_printf_error("Error: Device does not meet minimum requirements for Direct3D rendering\n");
return 1;
}
if (verify == 1)
{
osd_printf_warning("Warning: Device may not perform well for Direct3D rendering\n");
return 1;
}
return 0;
}
@ -1103,8 +1153,6 @@ int renderer_d3d9::device_test_cooperative()
osd_printf_verbose("Direct3D: resetting device\n");
// free all existing resources and call reset on the device
m_sliders.clear();
m_shaders->delete_resources(true);
device_delete_resources();
result = m_device->Reset(&m_presentation);
@ -1122,15 +1170,8 @@ int renderer_d3d9::device_test_cooperative()
device_delete();
return 1;
}
m_sliders.clear();
if (m_shaders->create_resources(true, m_sliders))
{
osd_printf_verbose("Direct3D: failed to recreate HLSL resources for device; failing permanently\n");
device_delete();
return 1;
}
}
return 0;
}
@ -1870,6 +1911,28 @@ void renderer_d3d9::primitive_flush_pending()
}
std::vector<ui::menu_item> renderer_d3d9::get_slider_list()
{
m_sliders_dirty = false;
std::vector<ui::menu_item> sliders;
sliders.insert(sliders.end(), m_sliders.begin(), m_sliders.end());
if (m_shaders != nullptr && m_shaders->enabled())
{
std::vector<ui::menu_item> s_slider = m_shaders->get_slider_list();
sliders.insert(sliders.end(), s_slider.begin(), s_slider.end());
}
return sliders;
}
void renderer_d3d9::set_sliders_dirty()
{
m_sliders_dirty = true;
}
//============================================================
// texture_info destructor
//============================================================

View File

@ -23,6 +23,7 @@
#undef interface
#include "d3d/d3dcomm.h"
#include "sliderdirtynotifier.h"
#include "modules/lib/osdlib.h"
//============================================================
@ -49,7 +50,7 @@ class shaders;
struct hlsl_options;
/* renderer is the information about Direct3D for the current screen */
class renderer_d3d9 : public osd_renderer
class renderer_d3d9 : public osd_renderer, public slider_dirty_notifier
{
public:
renderer_d3d9(std::shared_ptr<osd_window> window);
@ -64,6 +65,8 @@ public:
virtual void save() override;
virtual void record() override;
virtual void toggle_fsfx() override;
virtual std::vector<ui::menu_item> get_slider_list() override;
virtual void set_sliders_dirty() override;
int initialize();
@ -71,6 +74,8 @@ public:
int device_create_resources();
void device_delete();
void device_delete_resources();
void update_presentation_parameters();
void update_gamma_ramp();
int device_verify_caps();
int device_test_cooperative();
@ -117,9 +122,7 @@ public:
VOID ** get_locked_buffer_ptr()const { return (VOID **)&m_lockedbuf; }
void set_locked_buffer(vertex *lockedbuf) { m_lockedbuf = lockedbuf; }
void set_restarting(bool restarting) { m_restarting = restarting; }
bool is_mod2x_supported() const { return (bool)m_mod2x_supported; }
bool is_mod4x_supported() const { return (bool)m_mod4x_supported; }
void set_toggle(bool toggle) { m_toggle = toggle; }
D3DFORMAT get_screen_format() const { return m_screen_format; }
D3DFORMAT get_pixel_format() const { return m_pixformat; }
@ -131,7 +134,6 @@ public:
texture_info * get_default_texture();
shaders * get_shaders() const { return m_shaders; }
hlsl_options * get_shaders_options() const { return m_shaders_options; }
private:
int m_adapter; // ordinal adapter number
@ -156,10 +158,8 @@ private:
poly_info m_poly[VERTEX_BUFFER_SIZE/3];// array to hold polygons as they are created
int m_numpolys; // number of accumulated polygons
bool m_restarting; // if we're restarting
bool m_toggle; // if we're toggle fsfx
int m_mod2x_supported; // is D3DTOP_MODULATE2X supported?
int m_mod4x_supported; // is D3DTOP_MODULATE4X supported?
D3DFORMAT m_screen_format; // format to use for screen textures
texture_info * m_last_texture; // previous texture
@ -174,9 +174,8 @@ private:
void * m_hlsl_buf; // HLSL vertex data
shaders * m_shaders; // HLSL interface
hlsl_options * m_shaders_options; // HLSL options
d3d_texture_manager * m_texture_manager; // texture manager
d3d_texture_manager * m_texture_manager; // texture manager
};
#endif // OSD_WINDOWS