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:
Couriersud 2011-01-16 13:19:31 +00:00
parent 745a7974aa
commit 90f1063951
2 changed files with 65 additions and 52 deletions

View File

@ -65,7 +65,7 @@
* *
*************************************/ *************************************/
#define DISCRETE_DEBUGLOG (1) #define DISCRETE_DEBUGLOG (0)
/************************************* /*************************************
@ -84,12 +84,18 @@
typedef struct typedef struct
{ {
const discrete_task *task; double *node_buf;
const double *ptr; const double *source;
int output_node; volatile double *ptr;
double buffer; int node_num;
} discrete_source_node; } output_buffer;
typedef dynamic_array_t<discrete_source_node *> source_node_list_t;
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 class discrete_task
{ {
@ -106,23 +112,22 @@ public:
} }
inline void unlock(void) { m_threadid = -1; } inline void unlock(void) { m_threadid = -1; }
discrete_device *device;
//const linked_list_entry *list; //const linked_list_entry *list;
node_step_list_t step_list; node_step_list_t step_list;
/* list of source nodes */ /* 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; int task_group;
double *m_ptr[DISCRETE_MAX_TASK_OUTPUTS];
protected: protected:
discrete_task(discrete_device *pdev) discrete_task(discrete_device &pdev)
: device(pdev), task_group(0), m_threadid(-1), m_numbuffered(0) : task_group(0), m_device(pdev), m_threadid(-1)
{ {
source_list.clear(); source_list.clear();
step_list.clear(); step_list.clear();
m_buffers.clear();
} }
static void *task_callback(void *param, int threadid); static void *task_callback(void *param, int threadid);
@ -131,15 +136,13 @@ protected:
void check(discrete_task *dest_task); void check(discrete_task *dest_task);
void prepare_for_queue(int samples); 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: private:
volatile INT32 m_threadid; volatile INT32 m_threadid;
int m_numbuffered;
volatile int m_samples; 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) 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) 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++) /* buffer the outputs */
*(m_ptr[i]++) = *m_source[i]; for_each(output_buffer *, outbuf, &m_buffers)
*(outbuf->ptr++) = *outbuf->source;
} }
void *discrete_task::task_callback(void *param, int threadid) 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); int samples = MIN(m_samples, MAX_SAMPLES_PER_TASK_SLICE);
/* check dependencies */ /* check dependencies */
for_each(discrete_source_node **, sn, &source_list) for_each(input_buffer *, sn, &source_list)
{ {
int avail; 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"); assert_always(avail >= 0, "task_callback: available samples are negative");
if (avail < samples) if (avail < samples)
samples = avail; samples = avail;
@ -260,13 +264,13 @@ void discrete_task::prepare_for_queue(int samples)
{ {
m_samples = samples; m_samples = samples;
/* set up task buffers */ /* set up task buffers */
for (int i = 0; i < m_numbuffered; i++) for_each(output_buffer *, ob, &m_buffers)
m_ptr[i] = m_node_buf[i]; ob->ptr = ob->node_buf;
/* initialize sources */ /* 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 */ /* loop over all active inputs */
for (inputnum = 0; inputnum < dest_node->active_inputs(); inputnum++) for (inputnum = 0; inputnum < dest_node->active_inputs(); inputnum++)
{ {
int inputnode = dest_node->input_node(inputnum); int inputnode_num = dest_node->input_node(inputnum);
if IS_VALUE_A_NODE(inputnode) 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; int i, found = -1;
output_buffer *pbuf;
for (i = 0; i < m_numbuffered; i++) for (i = 0; i < m_buffers.count(); i++)
if (m_nodes[i]->block_node() == inputnode) // if (m_buffers[i].node->block_node() == inputnode_num)
if (m_buffers[i].node_num == inputnode_num)
{ {
found = i; found = i;
pbuf = &m_buffers[i];
break; break;
} }
if (found<0) if (found<0)
{ {
if (m_numbuffered >= DISCRETE_MAX_TASK_OUTPUTS) output_buffer buf;
fatalerror("dso_task_start - Number of maximum buffered nodes exceeded");
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)); ((task_node->sample_rate() + STREAMS_UPDATE_FREQUENCY) / STREAMS_UPDATE_FREQUENCY));
m_source[m_numbuffered] = (double *) dest_node->m_input[inputnum]; buf.ptr = buf.node_buf;
m_nodes[m_numbuffered] = device->discrete_find_node(inputnode); buf.source = dest_node->m_input[inputnum];
i = m_numbuffered; buf.node_num = inputnode_num;
m_numbuffered++; //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 */ /* 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); dest_task->source_list.add(source);
source->task = this;
source->output_node = i;
/* point the input to a buffered location */ /* 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 */ /* 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_device = pdev;
m_block = xblock; 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 /* make sure we have one simple task
* No need to create a node since there are no dependencies. * 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); task_list.add(task);
} }
@ -706,7 +718,7 @@ void discrete_device::init_nodes(const sound_block_list_t &block_list)
case DSO_TASK_START: case DSO_TASK_START:
if (task != NULL) if (task != NULL)
fatalerror("init_nodes() - Nested DISCRETE_START_TASK."); 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]; task->task_group = block->initial[0];
if (task->task_group < 0 || task->task_group >= DISCRETE_MAX_TASK_GROUPS) if (task->task_group < 0 || task->task_group >= DISCRETE_MAX_TASK_GROUPS)
fatalerror("discrete_dso_task: illegal task_group %d", task->task_group); fatalerror("discrete_dso_task: illegal task_group %d", task->task_group);

View File

@ -3756,7 +3756,7 @@ enum
* add and delete may be slow - the focus is on access! * 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: public:
dynamic_array_t(int initial) { dynamic_array_t(int initial) {
@ -3800,7 +3800,7 @@ public:
return *this; return *this;
} }
inline void add(T object) inline T* add(T object)
{ {
if (m_count >= m_allocated) if (m_count >= m_allocated)
{ {
@ -3813,6 +3813,7 @@ public:
} }
m_arr[m_count] = object; m_arr[m_count] = object;
m_count++; m_count++;
return &m_arr[m_count-1];
} }
inline void delete(int index) inline void delete(int index)
{ {
@ -4467,12 +4468,12 @@ public:
virtual void stop(void) { } virtual void stop(void) { }
virtual void save_state(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_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_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); } 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) */ /* Return the node index, i.e. X from NODE(X) */
inline int index(void) { return NODE_INDEX(m_block->node); } inline int index(void) { return NODE_INDEX(m_block->node); }