-bgfx: Rework chain updating to minimize primlist locking, nw

This commit is contained in:
MooglyGuy 2019-10-22 09:55:15 +02:00
parent 9c64307ba8
commit 6c6b0f86a8
7 changed files with 187 additions and 112 deletions

View File

@ -76,14 +76,14 @@ void bgfx_chain::repopulate_targets()
}
}
void bgfx_chain::process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend)
void bgfx_chain::process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window& window, uint64_t blend)
{
screen_device_iterator screen_iterator(window.machine().root_device());
screen_device* screen_device = screen_iterator.byindex(screen);
uint16_t screen_count(window.target()->current_view()->screens().count());
uint16_t screen_width(floorf(prim->get_quad_width() + 0.5f));
uint16_t screen_height(floorf(prim->get_quad_height() + 0.5f));
uint16_t screen_width = prim.m_quad_width;
uint16_t screen_height = prim.m_quad_height;
uint32_t rotation_type =
(window.target()->orientation() & ROT90) == ROT90 ? 1 :
(window.target()->orientation() & ROT180) == ROT180 ? 2 :

View File

@ -17,7 +17,6 @@
#include "chainentry.h"
class render_primitive;
class bgfx_slider;
class bgfx_parameter;
class texture_manager;
@ -31,7 +30,7 @@ public:
bgfx_chain(std::string name, std::string author, bool transform, target_manager& targets, std::vector<bgfx_slider*> sliders, std::vector<bgfx_parameter*> params, std::vector<bgfx_chain_entry*> entries, std::vector<bgfx_target*> target_list, uint32_t screen_index);
~bgfx_chain();
void process(render_primitive* prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L);
void process(chain_manager::screen_prim &prim, int view, int screen, texture_manager& textures, osd_window &window, uint64_t blend = 0L);
void repopulate_targets();
// Getters

View File

@ -14,6 +14,7 @@
#include <bgfx/bgfx.h>
#include <bx/math.h>
#include "chainmanager.h"
#include "chainentry.h"
#include "effect.h"
@ -55,7 +56,7 @@ bgfx_chain_entry::~bgfx_chain_entry()
delete m_clear;
}
void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen)
void bgfx_chain_entry::submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen)
{
if (!setup_view(view, screen_width, screen_height, screen))
{
@ -68,8 +69,8 @@ void bgfx_chain_entry::submit(int view, render_primitive* prim, texture_manager&
}
bgfx::TransientVertexBuffer buffer;
put_screen_buffer(prim, &buffer);
bgfx::setVertexBuffer(0,&buffer);
put_screen_buffer(prim.m_screen_width, prim.m_screen_height, &buffer);
bgfx::setVertexBuffer(0, &buffer);
setup_auto_uniforms(prim, textures, screen_count, screen_width, screen_height, screen_scale_x, screen_scale_y, screen_offset_x, screen_offset_y, rotation_type, swap_xy, screen);
@ -145,13 +146,12 @@ void bgfx_chain_entry::setup_screencount_uniforms(uint16_t screen_count)
}
}
void bgfx_chain_entry::setup_sourcesize_uniform(render_primitive* prim) const
void bgfx_chain_entry::setup_sourcesize_uniform(chain_manager::screen_prim &prim) const
{
bgfx_uniform* source_dims = m_effect->uniform("u_source_dims");
if (source_dims != nullptr)
{
float values[2] = { float(prim->texture.width), float(prim->texture.height) };
source_dims->set(values, sizeof(float) * 2);
source_dims->set(&prim.m_tex_width, sizeof(float) * 2);
}
}
@ -203,12 +203,12 @@ void bgfx_chain_entry::setup_swapxy_uniform(bool swap_xy) const
}
}
void bgfx_chain_entry::setup_quaddims_uniform(render_primitive* prim) const
void bgfx_chain_entry::setup_quaddims_uniform(chain_manager::screen_prim &prim) const
{
bgfx_uniform* quad_dims_uniform = m_effect->uniform("u_quad_dims");
if (quad_dims_uniform != nullptr)
{
float values[2] = { float(floor((prim->bounds.x1 - prim->bounds.x0) + 0.5f)), float(floor((prim->bounds.y1 - prim->bounds.y0) + 0.5f)) };
float values[2] = { float(prim.m_quad_width), float(prim.m_quad_height) };
quad_dims_uniform->set(values, sizeof(float) * 2);
}
}
@ -223,7 +223,7 @@ void bgfx_chain_entry::setup_screenindex_uniform(int32_t screen) const
}
}
void bgfx_chain_entry::setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
void bgfx_chain_entry::setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen)
{
setup_screensize_uniforms(textures, screen_width, screen_height, screen);
setup_screenscale_uniforms(screen_scale_x, screen_scale_y);
@ -268,7 +268,7 @@ bool bgfx_chain_entry::setup_view(int view, uint16_t screen_width, uint16_t scre
return true;
}
void bgfx_chain_entry::put_screen_buffer(render_primitive* prim, bgfx::TransientVertexBuffer* buffer) const
void bgfx_chain_entry::put_screen_buffer(uint16_t screen_width, uint16_t screen_height, bgfx::TransientVertexBuffer* buffer) const
{
if (6 == bgfx::getAvailTransientVertexBuffer(6, ScreenVertex::ms_decl))
{
@ -292,6 +292,14 @@ void bgfx_chain_entry::put_screen_buffer(render_primitive* prim, bgfx::Transient
v[0] = v[1] = 1;
v[2] = v[3] = 0;
}
else if (renderer_type == bgfx::RendererType::Direct3D9)
{
for (int i = 0; i < 4; i++)
{
u[i] += 0.5f / screen_width;
v[i] += 0.5f / screen_height;
}
}
vertex[0].m_x = x[0];
vertex[0].m_y = y[0];

View File

@ -21,8 +21,8 @@
#include "inputpair.h"
#include "targetmanager.h"
#include "chainmanager.h"
class render_primitive;
class bgfx_effect;
class bgfx_target;
class bgfx_entry_uniform;
@ -37,7 +37,7 @@ public:
bgfx_chain_entry(std::string name, bgfx_effect* effect, clear_state* clear, std::vector<bgfx_suppressor*> suppressors, std::vector<bgfx_input_pair*> inputs, std::vector<bgfx_entry_uniform*> uniforms, target_manager& targets, std::string output);
~bgfx_chain_entry();
void submit(int view, render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen);
void submit(int view, chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, uint64_t blend, int32_t screen);
// Getters
std::string name() const { return m_name; }
@ -45,21 +45,21 @@ public:
bool skip();
private:
void setup_auto_uniforms(render_primitive* prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
void setup_auto_uniforms(chain_manager::screen_prim &prim, texture_manager& textures, uint16_t screen_count, uint16_t screen_width, uint16_t screen_height, float screen_scale_x, float screen_scale_y, float screen_offset_x, float screen_offset_y, uint32_t rotation_type, bool swap_xy, int32_t screen);
void setup_screensize_uniforms(texture_manager& textures, uint16_t screen_width, uint16_t screen_height, int32_t screen);
void setup_screenscale_uniforms(float screen_scale_x, float screen_scale_y);
void setup_screenoffset_uniforms(float screen_offset_x, float screen_offset_y);
void setup_screencount_uniforms(uint16_t screen_count);
void setup_sourcesize_uniform(render_primitive* prim) const;
void setup_sourcesize_uniform(chain_manager::screen_prim &prim) const;
void setup_targetsize_uniform(int32_t screen) const;
void setup_targetscale_uniform(int32_t screen) const;
void setup_rotationtype_uniform(uint32_t rotation_type) const;
void setup_swapxy_uniform(bool swap_xy) const;
void setup_quaddims_uniform(render_primitive* prim) const;
void setup_quaddims_uniform(chain_manager::screen_prim &prim) const;
void setup_screenindex_uniform(int32_t screen) const;
bool setup_view(int view, uint16_t screen_width, uint16_t screen_height, int32_t screen) const;
void put_screen_buffer(render_primitive* prim, bgfx::TransientVertexBuffer* buffer) const;
void put_screen_buffer(uint16_t screen_width, uint16_t screen_height, bgfx::TransientVertexBuffer* buffer) const;
std::string m_name;
bgfx_effect* m_effect;

View File

@ -298,75 +298,9 @@ bgfx_chain* chain_manager::screen_chain(uint32_t screen)
}
}
void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, render_primitive* prim, osd_window& window)
void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window)
{
uint16_t tex_width(prim->texture.width);
uint16_t tex_height(prim->texture.height);
bgfx_texture* texture = screen < m_screen_textures.size() ? m_screen_textures[screen] : nullptr;
bgfx_texture* palette = screen < m_screen_palettes.size() ? m_screen_palettes[screen] : nullptr;
const uint32_t src_format = (prim->flags & PRIMFLAG_TEXFORMAT_MASK) >> PRIMFLAG_TEXFORMAT_SHIFT;
const bool needs_conversion = m_converters[src_format] != nullptr;
std::string screen_index = std::to_string(screen);
std::string source_name = "source" + screen_index;
std::string screen_name = "screen" + screen_index;
std::string palette_name = "palette" + screen_index;
std::string full_name = needs_conversion ? source_name : screen_name;
if (texture && (texture->width() != tex_width || texture->height() != tex_height))
{
m_textures.add_provider(full_name, nullptr);
delete texture;
texture = nullptr;
if (palette)
{
m_textures.add_provider(palette_name, nullptr);
delete palette;
palette = nullptr;
}
}
bgfx::TextureFormat::Enum dst_format = bgfx::TextureFormat::RGBA8;
uint16_t pitch = tex_width;
const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, prim->flags & PRIMFLAG_TEXFORMAT_MASK,
tex_width, tex_height, prim->texture.rowpixels, prim->texture.palette, prim->texture.base, &pitch);
if (texture == nullptr)
{
bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, pitch);
m_textures.add_provider(full_name, texture);
if (prim->texture.palette)
{
uint16_t palette_width = (uint16_t)std::min(prim->texture.palette_length, 256U);
uint16_t palette_height = (uint16_t)std::max(prim->texture.palette_length / 256, 1U);
const bgfx::Memory *palmem = bgfx::copy(prim->texture.palette, palette_width * palette_height * 4);
palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width);
m_textures.add_provider(palette_name, palette);
}
if (screen >= m_screen_textures.size())
{
m_screen_textures.push_back(texture);
if (palette)
{
m_screen_palettes.push_back(palette);
}
}
}
else
{
texture->update(mem, pitch);
if (prim->texture.palette)
{
const bgfx::Memory *palmem = bgfx::copy(prim->texture.palette, palette->width() * palette->height() * 4);
palette->update(palmem);
}
}
const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, tex_width, tex_height, TARGET_STYLE_GUEST);
const bool any_targets_rebuilt = m_targets.update_target_sizes(screen, prim.m_tex_width, prim.m_tex_height, TARGET_STYLE_GUEST);
if (any_targets_rebuilt)
{
for (bgfx_chain* chain : m_screen_chains)
@ -379,25 +313,26 @@ void chain_manager::process_screen_quad(uint32_t view, uint32_t screen, render_p
}
bgfx_chain* chain = screen_chain(screen);
if (needs_conversion && !chain->has_converter())
{
chain->prepend_converter(m_converters[src_format], *this);
}
chain->process(prim, view, screen, m_textures, window, bgfx_util::get_blend_state(PRIMFLAG_GET_BLENDMODE(prim->flags)));
chain->process(prim, view, screen, m_textures, window, bgfx_util::get_blend_state(PRIMFLAG_GET_BLENDMODE(prim.m_flags)));
view += chain->applicable_passes();
}
std::vector<render_primitive*> chain_manager::count_screens(render_primitive* prim)
uint32_t chain_manager::count_screens(render_primitive* prim)
{
std::vector<render_primitive*> screens;
int screen_count = 0;
uint32_t screen_count = 0;
while (prim != nullptr)
{
if (PRIMFLAG_GET_SCREENTEX(prim->flags))
{
if (screen_count < m_screen_prims.size())
{
m_screen_prims[screen_count] = prim;
}
else
{
m_screen_prims.push_back(prim);
}
screen_count++;
screens.push_back(prim);
}
prim = prim->next();
}
@ -408,7 +343,12 @@ std::vector<render_primitive*> chain_manager::count_screens(render_primitive* pr
m_targets.update_screen_count(screen_count);
}
return screens;
if (screen_count < m_screen_prims.size())
{
m_screen_prims.resize(screen_count);
}
return screen_count;
}
void chain_manager::update_screen_count(uint32_t screen_count)
@ -487,19 +427,96 @@ void chain_manager::create_selection_slider(uint32_t screen_index)
m_core_sliders.push_back(std::move(state));
}
uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *starting_prim, osd_window& window)
uint32_t chain_manager::update_screen_textures(uint32_t view, render_primitive *starting_prim, osd_window& window)
{
std::vector<render_primitive*> screens = count_screens(starting_prim);
if (screens.size() == 0)
{
if (!count_screens(starting_prim))
return 0;
for (int screen = 0; screen < m_screen_prims.size(); screen++)
{
screen_prim &prim = m_screen_prims[screen];
uint16_t tex_width(prim.m_tex_width);
uint16_t tex_height(prim.m_tex_height);
bgfx_texture* texture = screen < m_screen_textures.size() ? m_screen_textures[screen] : nullptr;
bgfx_texture* palette = screen < m_screen_palettes.size() ? m_screen_palettes[screen] : nullptr;
const uint32_t src_format = (prim.m_flags & PRIMFLAG_TEXFORMAT_MASK) >> PRIMFLAG_TEXFORMAT_SHIFT;
const bool needs_conversion = m_converters[src_format] != nullptr;
std::string screen_index = std::to_string(screen);
std::string source_name = "source" + screen_index;
std::string screen_name = "screen" + screen_index;
std::string palette_name = "palette" + screen_index;
std::string full_name = needs_conversion ? source_name : screen_name;
if (texture && (texture->width() != tex_width || texture->height() != tex_height))
{
m_textures.add_provider(full_name, nullptr);
delete texture;
texture = nullptr;
if (palette)
{
m_textures.add_provider(palette_name, nullptr);
delete palette;
palette = nullptr;
}
}
bgfx::TextureFormat::Enum dst_format = bgfx::TextureFormat::RGBA8;
uint16_t pitch = tex_width;
const bgfx::Memory* mem = bgfx_util::mame_texture_data_to_bgfx_texture_data(dst_format, prim.m_flags & PRIMFLAG_TEXFORMAT_MASK,
tex_width, tex_height, prim.m_rowpixels, prim.m_prim->texture.palette, prim.m_prim->texture.base, &pitch);
if (texture == nullptr)
{
bgfx_texture *texture = new bgfx_texture(full_name, dst_format, tex_width, tex_height, mem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, pitch);
m_textures.add_provider(full_name, texture);
if (prim.m_prim->texture.palette)
{
uint16_t palette_width = (uint16_t)std::min(prim.m_palette_length, 256U);
uint16_t palette_height = (uint16_t)std::max(prim.m_palette_length / 256, 1U);
const bgfx::Memory *palmem = bgfx::copy(prim.m_prim->texture.palette, palette_width * palette_height * 4);
palette = new bgfx_texture(palette_name, bgfx::TextureFormat::BGRA8, palette_width, palette_height, palmem, BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_MIN_POINT | BGFX_SAMPLER_MAG_POINT | BGFX_SAMPLER_MIP_POINT, palette_width);
m_textures.add_provider(palette_name, palette);
}
if (screen >= m_screen_textures.size())
{
m_screen_textures.push_back(texture);
if (palette)
{
m_screen_palettes.push_back(palette);
}
}
}
else
{
texture->update(mem, pitch);
if (prim.m_prim->texture.palette)
{
const bgfx::Memory *palmem = bgfx::copy(prim.m_prim->texture.palette, palette->width() * palette->height() * 4);
palette->update(palmem);
}
}
bgfx_chain* chain = screen_chain(screen);
if (needs_conversion && !chain->has_converter())
{
chain->prepend_converter(m_converters[src_format], *this);
}
}
return m_screen_prims.size();
}
uint32_t chain_manager::process_screen_chains(uint32_t view, osd_window& window)
{
// Process each screen as necessary
uint32_t used_views = 0;
uint32_t screen_index = 0;
for (render_primitive* prim : screens)
for (screen_prim &prim : m_screen_prims)
{
if (m_current_chain[screen_index] == CHAIN_NONE || screen_chain(screen_index) == nullptr)
{
@ -507,8 +524,8 @@ uint32_t chain_manager::handle_screen_chains(uint32_t view, render_primitive *st
continue;
}
uint16_t screen_width(floorf(prim->get_full_quad_width() + 0.5f));
uint16_t screen_height(floorf(prim->get_full_quad_height() + 0.5f));
uint16_t screen_width = prim.m_screen_width;
uint16_t screen_height = prim.m_screen_height;
if (window.swap_xy())
{
std::swap(screen_width, screen_height);

View File

@ -23,6 +23,7 @@
#include "effectmanager.h"
#include "../frontend/mame/ui/menuitem.h"
#include "../frontend/mame/ui/sliderchangednotifier.h"
#include "render.h"
class running_machine;
class osd_window;
@ -52,7 +53,8 @@ public:
chain_manager(running_machine& machine, osd_options& options, texture_manager& textures, target_manager& targets, effect_manager& effects, uint32_t window_index, slider_dirty_notifier& slider_notifier);
~chain_manager();
uint32_t handle_screen_chains(uint32_t view, render_primitive *starting_prim, osd_window& window);
uint32_t update_screen_textures(uint32_t view, render_primitive *starting_prim, osd_window& window);
uint32_t process_screen_chains(uint32_t view, osd_window& window);
// Getters
running_machine& machine() const { return m_machine; }
@ -72,6 +74,40 @@ public:
// Setters
void restore_slider_settings(int32_t id, std::vector<std::vector<float>>& settings);
class screen_prim
{
public:
screen_prim() : m_prim(nullptr), m_screen_width(0), m_screen_height(0), m_quad_width(0), m_quad_height(0)
, m_tex_width(0), m_tex_height(0), m_rowpixels(0), m_palette_length(0), m_flags(0)
{
}
screen_prim(render_primitive *prim)
{
m_prim = prim;
m_screen_width = (uint16_t)floorf(prim->get_full_quad_width() + 0.5f);
m_screen_height = (uint16_t)floorf(prim->get_full_quad_height() + 0.5f);
m_quad_width = (uint16_t)floorf(prim->get_quad_width() + 0.5f);
m_quad_height = (uint16_t)floorf(prim->get_quad_height() + 0.5f);
m_tex_width = (float)prim->texture.width;
m_tex_height = (float)prim->texture.height;
m_rowpixels = prim->texture.rowpixels;
m_palette_length = prim->texture.palette_length;
m_flags = prim->flags;
}
render_primitive *m_prim;
uint16_t m_screen_width;
uint16_t m_screen_height;
uint16_t m_quad_width;
uint16_t m_quad_height;
float m_tex_width;
float m_tex_height;
int m_rowpixels;
uint32_t m_palette_length;
uint32_t m_flags;
};
private:
void load_chains();
void destroy_chains();
@ -91,8 +127,8 @@ private:
void create_selection_slider(uint32_t screen_index);
bool needs_sliders();
std::vector<render_primitive*> count_screens(render_primitive* prim);
void process_screen_quad(uint32_t view, uint32_t screen, render_primitive* prim, osd_window &window);
uint32_t count_screens(render_primitive* prim);
void process_screen_quad(uint32_t view, uint32_t screen, screen_prim &prim, osd_window& window);
running_machine& m_machine;
osd_options& m_options;
@ -111,6 +147,7 @@ private:
std::vector<bgfx_texture*> m_screen_textures;
std::vector<bgfx_texture*> m_screen_palettes;
std::vector<bgfx_effect*> m_converters;
std::vector<screen_prim> m_screen_prims;
static const uint32_t CHAIN_NONE;
};

View File

@ -467,6 +467,15 @@ void renderer_bgfx::put_packed_quad(render_primitive *prim, uint32_t hash, Scree
float u[4] = { u0, u1, u0, u1 };
float v[4] = { v0, v0, v1, v1 };
if (bgfx::getRendererType() == bgfx::RendererType::Direct3D9)
{
for (int i = 0; i < 4; i++)
{
u[i] += 0.5f / size;
v[i] += 0.5f / size;
}
}
if (PRIMFLAG_GET_TEXORIENT(prim->flags) & ORIENTATION_SWAP_XY)
{
std::swap(u[1], u[2]);
@ -834,9 +843,14 @@ int renderer_bgfx::draw(int update)
}
win->m_primlist->acquire_lock();
s_current_view += m_chains->handle_screen_chains(s_current_view, win->m_primlist->first(), *win.get());
uint32_t num_screens = m_chains->update_screen_textures(s_current_view, win->m_primlist->first(), *win.get());
win->m_primlist->release_lock();
if (num_screens)
{
s_current_view += m_chains->process_screen_chains(s_current_view, *win.get());
}
bool skip_frame = update_dimensions();
if (skip_frame)
{