mirror of
https://github.com/holub/mame
synced 2025-05-24 14:56:21 +03:00
Discrete subsystem:
- all list handling now based on dynamic_array_t (discrete.h) - more code rewrite to get rid of fixed allocations. - performance about the same as 0.140
This commit is contained in:
parent
745a7974aa
commit
90f1063951
@ -65,7 +65,7 @@
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#define DISCRETE_DEBUGLOG (1)
|
||||
#define DISCRETE_DEBUGLOG (0)
|
||||
|
||||
|
||||
/*************************************
|
||||
@ -84,12 +84,18 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const discrete_task *task;
|
||||
const double *ptr;
|
||||
int output_node;
|
||||
double buffer;
|
||||
} discrete_source_node;
|
||||
typedef dynamic_array_t<discrete_source_node *> source_node_list_t;
|
||||
double *node_buf;
|
||||
const double *source;
|
||||
volatile double *ptr;
|
||||
int node_num;
|
||||
} output_buffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile const double *ptr; /* pointer into linked_outbuf.nodebuf */
|
||||
output_buffer * linked_outbuf; /* what output are we connected to ? */
|
||||
double buffer; /* input[] will point here */
|
||||
} input_buffer;
|
||||
|
||||
class discrete_task
|
||||
{
|
||||
@ -106,23 +112,22 @@ public:
|
||||
}
|
||||
inline void unlock(void) { m_threadid = -1; }
|
||||
|
||||
discrete_device *device;
|
||||
//const linked_list_entry *list;
|
||||
node_step_list_t step_list;
|
||||
|
||||
/* list of source nodes */
|
||||
source_node_list_t source_list; /* discrete_source_node */
|
||||
dynamic_array_t<input_buffer> source_list; /* discrete_source_node */
|
||||
|
||||
int task_group;
|
||||
|
||||
double *m_ptr[DISCRETE_MAX_TASK_OUTPUTS];
|
||||
|
||||
protected:
|
||||
discrete_task(discrete_device *pdev)
|
||||
: device(pdev), task_group(0), m_threadid(-1), m_numbuffered(0)
|
||||
discrete_task(discrete_device &pdev)
|
||||
: task_group(0), m_device(pdev), m_threadid(-1)
|
||||
{
|
||||
source_list.clear();
|
||||
step_list.clear();
|
||||
m_buffers.clear();
|
||||
}
|
||||
|
||||
static void *task_callback(void *param, int threadid);
|
||||
@ -131,15 +136,13 @@ protected:
|
||||
void check(discrete_task *dest_task);
|
||||
void prepare_for_queue(int samples);
|
||||
|
||||
double *m_node_buf[DISCRETE_MAX_TASK_OUTPUTS];
|
||||
dynamic_array_t<output_buffer> m_buffers;
|
||||
discrete_device & m_device;
|
||||
|
||||
private:
|
||||
volatile INT32 m_threadid;
|
||||
int m_numbuffered;
|
||||
volatile int m_samples;
|
||||
|
||||
const double *m_source[DISCRETE_MAX_TASK_OUTPUTS];
|
||||
const discrete_base_node *m_nodes[DISCRETE_MAX_TASK_OUTPUTS];
|
||||
};
|
||||
|
||||
|
||||
@ -173,12 +176,12 @@ private:
|
||||
inline void discrete_task::step_nodes(void)
|
||||
{
|
||||
|
||||
for_each(discrete_source_node **, sn, &source_list)
|
||||
for_each(input_buffer *, sn, &source_list)
|
||||
{
|
||||
(*sn)->buffer = *(*sn)->ptr++;
|
||||
sn->buffer = *sn->ptr++;
|
||||
}
|
||||
|
||||
if (EXPECTED(!device->profiling()))
|
||||
if (EXPECTED(!m_device.profiling()))
|
||||
{
|
||||
for_each(discrete_step_interface **, entry, &step_list)
|
||||
{
|
||||
@ -201,8 +204,9 @@ inline void discrete_task::step_nodes(void)
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_numbuffered; i++)
|
||||
*(m_ptr[i]++) = *m_source[i];
|
||||
/* buffer the outputs */
|
||||
for_each(output_buffer *, outbuf, &m_buffers)
|
||||
*(outbuf->ptr++) = *outbuf->source;
|
||||
}
|
||||
|
||||
void *discrete_task::task_callback(void *param, int threadid)
|
||||
@ -230,11 +234,11 @@ bool discrete_task::process(void)
|
||||
int samples = MIN(m_samples, MAX_SAMPLES_PER_TASK_SLICE);
|
||||
|
||||
/* check dependencies */
|
||||
for_each(discrete_source_node **, sn, &source_list)
|
||||
for_each(input_buffer *, sn, &source_list)
|
||||
{
|
||||
int avail;
|
||||
|
||||
avail = (*sn)->task->m_ptr[(*sn)->output_node] - (*sn)->ptr;
|
||||
avail = sn->linked_outbuf->ptr - sn->ptr;
|
||||
assert_always(avail >= 0, "task_callback: available samples are negative");
|
||||
if (avail < samples)
|
||||
samples = avail;
|
||||
@ -260,13 +264,13 @@ void discrete_task::prepare_for_queue(int samples)
|
||||
{
|
||||
m_samples = samples;
|
||||
/* set up task buffers */
|
||||
for (int i = 0; i < m_numbuffered; i++)
|
||||
m_ptr[i] = m_node_buf[i];
|
||||
for_each(output_buffer *, ob, &m_buffers)
|
||||
ob->ptr = ob->node_buf;
|
||||
|
||||
/* initialize sources */
|
||||
for_each(discrete_source_node **, sn, &source_list)
|
||||
for_each(input_buffer *, sn, &source_list)
|
||||
{
|
||||
(*sn)->ptr = (*sn)->task->m_node_buf[(*sn)->output_node];
|
||||
sn->ptr = sn->linked_outbuf->node_buf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,43 +293,51 @@ void discrete_task::check(discrete_task *dest_task)
|
||||
/* loop over all active inputs */
|
||||
for (inputnum = 0; inputnum < dest_node->active_inputs(); inputnum++)
|
||||
{
|
||||
int inputnode = dest_node->input_node(inputnum);
|
||||
if IS_VALUE_A_NODE(inputnode)
|
||||
int inputnode_num = dest_node->input_node(inputnum);
|
||||
if IS_VALUE_A_NODE(inputnode_num)
|
||||
{
|
||||
if (NODE_DEFAULT_NODE(task_node->block_node()) == NODE_DEFAULT_NODE(inputnode))
|
||||
/* Fixme: sub nodes ! */
|
||||
if (NODE_DEFAULT_NODE(task_node->block_node()) == NODE_DEFAULT_NODE(inputnode_num))
|
||||
{
|
||||
discrete_source_node *source;
|
||||
input_buffer source;
|
||||
int i, found = -1;
|
||||
output_buffer *pbuf;
|
||||
|
||||
for (i = 0; i < m_numbuffered; i++)
|
||||
if (m_nodes[i]->block_node() == inputnode)
|
||||
for (i = 0; i < m_buffers.count(); i++)
|
||||
// if (m_buffers[i].node->block_node() == inputnode_num)
|
||||
if (m_buffers[i].node_num == inputnode_num)
|
||||
{
|
||||
found = i;
|
||||
pbuf = &m_buffers[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (found<0)
|
||||
{
|
||||
if (m_numbuffered >= DISCRETE_MAX_TASK_OUTPUTS)
|
||||
fatalerror("dso_task_start - Number of maximum buffered nodes exceeded");
|
||||
output_buffer buf;
|
||||
|
||||
m_node_buf[m_numbuffered] = auto_alloc_array(device->machine, double,
|
||||
buf.node_buf = auto_alloc_array(m_device.machine, double,
|
||||
((task_node->sample_rate() + STREAMS_UPDATE_FREQUENCY) / STREAMS_UPDATE_FREQUENCY));
|
||||
m_source[m_numbuffered] = (double *) dest_node->m_input[inputnum];
|
||||
m_nodes[m_numbuffered] = device->discrete_find_node(inputnode);
|
||||
i = m_numbuffered;
|
||||
m_numbuffered++;
|
||||
buf.ptr = buf.node_buf;
|
||||
buf.source = dest_node->m_input[inputnum];
|
||||
buf.node_num = inputnode_num;
|
||||
//buf.node = device->discrete_find_node(inputnode);
|
||||
i = m_buffers.count();
|
||||
pbuf = m_buffers.add(buf);
|
||||
}
|
||||
device->discrete_log("dso_task_start - buffering %d(%d) in task %p group %d referenced by %d group %d", NODE_INDEX(inputnode), NODE_CHILD_NODE_NUM(inputnode), this, task_group, dest_node->index(), dest_task->task_group);
|
||||
m_device.discrete_log("dso_task_start - buffering %d(%d) in task %p group %d referenced by %d group %d", NODE_INDEX(inputnode_num), NODE_CHILD_NODE_NUM(inputnode_num), this, task_group, dest_node->index(), dest_task->task_group);
|
||||
|
||||
/* register into source list */
|
||||
source = auto_alloc(device->machine, discrete_source_node);
|
||||
//source = auto_alloc(device->machine, discrete_source_node);
|
||||
//source.task = this;
|
||||
//source.output_node = i;
|
||||
source.linked_outbuf = pbuf;
|
||||
source.buffer = 0.0; /* please compiler */
|
||||
source.ptr = NULL;
|
||||
dest_task->source_list.add(source);
|
||||
source->task = this;
|
||||
source->output_node = i;
|
||||
|
||||
/* point the input to a buffered location */
|
||||
dest_node->m_input[inputnum] = &source->buffer;
|
||||
dest_node->m_input[inputnum] = &dest_task->source_list[dest_task->source_list.count()-1].buffer; // was copied! &source.buffer;
|
||||
|
||||
}
|
||||
}
|
||||
@ -353,7 +365,7 @@ discrete_base_node::~discrete_base_node(void)
|
||||
/* currently noting */
|
||||
}
|
||||
|
||||
void discrete_base_node::init(discrete_device * pdev, const discrete_sound_block *xblock)
|
||||
void discrete_base_node::init(discrete_device *pdev, const discrete_sound_block *xblock)
|
||||
{
|
||||
m_device = pdev;
|
||||
m_block = xblock;
|
||||
@ -674,7 +686,7 @@ void discrete_device::init_nodes(const sound_block_list_t &block_list)
|
||||
/* make sure we have one simple task
|
||||
* No need to create a node since there are no dependencies.
|
||||
*/
|
||||
task = auto_alloc_clear(machine, discrete_task(this));
|
||||
task = auto_alloc_clear(machine, discrete_task(*this));
|
||||
task_list.add(task);
|
||||
}
|
||||
|
||||
@ -706,7 +718,7 @@ void discrete_device::init_nodes(const sound_block_list_t &block_list)
|
||||
case DSO_TASK_START:
|
||||
if (task != NULL)
|
||||
fatalerror("init_nodes() - Nested DISCRETE_START_TASK.");
|
||||
task = auto_alloc_clear(machine, discrete_task(this));
|
||||
task = auto_alloc_clear(machine, discrete_task(*this));
|
||||
task->task_group = block->initial[0];
|
||||
if (task->task_group < 0 || task->task_group >= DISCRETE_MAX_TASK_GROUPS)
|
||||
fatalerror("discrete_dso_task: illegal task_group %d", task->task_group);
|
||||
|
@ -3756,7 +3756,7 @@ enum
|
||||
* add and delete may be slow - the focus is on access!
|
||||
*/
|
||||
|
||||
template<class T> class dynamic_array_t
|
||||
template<class T> struct dynamic_array_t
|
||||
{
|
||||
public:
|
||||
dynamic_array_t(int initial) {
|
||||
@ -3800,7 +3800,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void add(T object)
|
||||
inline T* add(T object)
|
||||
{
|
||||
if (m_count >= m_allocated)
|
||||
{
|
||||
@ -3813,6 +3813,7 @@ public:
|
||||
}
|
||||
m_arr[m_count] = object;
|
||||
m_count++;
|
||||
return &m_arr[m_count-1];
|
||||
}
|
||||
inline void delete(int index)
|
||||
{
|
||||
@ -4467,12 +4468,12 @@ public:
|
||||
virtual void stop(void) { }
|
||||
virtual void save_state(void);
|
||||
|
||||
virtual int max_output(void) { return 1; };
|
||||
|
||||
inline bool interface(discrete_step_interface *&intf) const { intf = m_step_intf; return (intf != NULL); }
|
||||
inline bool interface(discrete_input_interface *&intf) const { intf = m_input_intf; return (intf != NULL); }
|
||||
inline bool interface(discrete_output_interface *&intf) const { intf = m_output_intf; return (intf != NULL); }
|
||||
|
||||
virtual int max_output(void) { return 1; };
|
||||
|
||||
/* Return the node index, i.e. X from NODE(X) */
|
||||
inline int index(void) { return NODE_INDEX(m_block->node); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user