@ -29,96 +29,8 @@ void AudioRenderer::Start() {
CreateSinkStreams ( ) ;
CreateSinkStreams ( ) ;
mailbox . Initialize ( AppMailboxId : : AudioRenderer ) ;
mailbox . Initialize ( AppMailboxId : : AudioRenderer ) ;
// Main AudioRenderer thread, responsible for processing the command lists.
main_thread = std : : jthread ( [ this ] ( std : : stop_token stop_token ) {
Common : : SetCurrentThreadName ( " DSP_AudioRenderer_Main " ) ;
Common : : SetCurrentThreadPriority ( Common : : ThreadPriority : : High ) ;
// TODO: Create buffer map/unmap thread + mailbox
// TODO: Create gMix devices, initialize them here
if ( mailbox . Receive ( Direction : : DSP ) ! = Message : : InitializeOK ) {
LOG_ERROR ( Service_Audio , " ADSP Audio Renderer -- Failed to receive initialize message from host! " ) ;
return ;
}
mailbox . Send ( Direction : : Host , Message : : InitializeOK ) ;
// 0.12 seconds (2,304,000 / 19,200,000)
constexpr u64 max_process_time { 2'304'000ULL } ;
while ( ! stop_token . stop_requested ( ) ) {
auto msg { mailbox . Receive ( Direction : : DSP ) } ;
switch ( msg ) {
case Message : : Shutdown :
mailbox . Send ( Direction : : Host , Message : : Shutdown ) ;
return ;
case Message : : Render : {
if ( system . IsShuttingDown ( ) ) {
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 200 ) ) ;
mailbox . Send ( Direction : : Host , Message : : RenderResponse ) ;
continue ;
}
std : : array < bool , MaxRendererSessions > buffers_reset { } ;
std : : array < u64 , MaxRendererSessions > render_times_taken { } ;
const auto start_time { system . CoreTiming ( ) . GetGlobalTimeUs ( ) . count ( ) } ;
for ( u32 index = 0 ; index < MaxRendererSessions ; index + + ) {
auto & command_buffer { command_buffers [ index ] } ;
auto & command_list_processor { command_list_processors [ index ] } ;
// Check this buffer is valid, as it may not be used.
if ( command_buffer . buffer ! = 0 ) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if ( command_buffer . remaining_command_count = = 0 ) {
command_list_processor . Initialize ( system , * command_buffer . process ,
command_buffer . buffer ,
command_buffer . size , streams [ index ] ) ;
}
if ( command_buffer . reset_buffer & & ! buffers_reset [ index ] ) {
streams [ index ] - > ClearQueue ( ) ;
buffers_reset [ index ] = true ;
}
u64 max_time { max_process_time } ;
if ( index = = 1 & & command_buffer . applet_resource_user_id = =
command_buffers [ 0 ] . applet_resource_user_id ) {
max_time = max_process_time - render_times_taken [ 0 ] ;
if ( render_times_taken [ 0 ] > max_process_time ) {
max_time = 0 ;
}
}
max_time = ( std : : min ) ( command_buffer . time_limit , max_time ) ;
command_list_processor . SetProcessTimeMax ( max_time ) ;
if ( index = = 0 ) {
streams [ index ] - > WaitFreeSpace ( stop_token ) ;
}
// Process the command list
{
render_times_taken [ index ] =
command_list_processor . Process ( index ) - start_time ;
}
const auto end_time { system . CoreTiming ( ) . GetGlobalTimeUs ( ) . count ( ) } ;
command_buffer . remaining_command_count =
command_list_processor . GetRemainingCommandCount ( ) ;
command_buffer . render_time_taken_us = end_time - start_time ;
}
}
mailbox . Send ( Direction : : Host , Message : : RenderResponse ) ;
} break ;
default :
LOG_WARNING ( Service_Audio , " ADSP AudioRenderer received an invalid message, msg={:02X}! " , msg ) ;
break ;
}
}
} ) ;
main_thread = std : : jthread ( [ this ] ( std : : stop_token stop_token ) { Main ( stop_token ) ; } ) ;
mailbox . Send ( Direction : : DSP , Message : : InitializeOK ) ;
mailbox . Send ( Direction : : DSP , Message : : InitializeOK ) ;
if ( mailbox . Receive ( Direction : : Host ) ! = Message : : InitializeOK ) {
if ( mailbox . Receive ( Direction : : Host ) ! = Message : : InitializeOK ) {
@ -217,4 +129,95 @@ void AudioRenderer::CreateSinkStreams() {
}
}
}
}
void AudioRenderer : : Main ( std : : stop_token stop_token ) {
Common : : SetCurrentThreadName ( " DSP_AudioRenderer_Main " ) ;
Common : : SetCurrentThreadPriority ( Common : : ThreadPriority : : High ) ;
// TODO: Create buffer map/unmap thread + mailbox
// TODO: Create gMix devices, initialize them here
if ( mailbox . Receive ( Direction : : DSP ) ! = Message : : InitializeOK ) {
LOG_ERROR ( Service_Audio , " ADSP Audio Renderer -- Failed to receive initialize message from host! " ) ;
return ;
}
mailbox . Send ( Direction : : Host , Message : : InitializeOK ) ;
// 0.12 seconds (2,304,000 / 19,200,000)
constexpr u64 max_process_time { 2'304'000ULL } ;
while ( ! stop_token . stop_requested ( ) ) {
auto msg { mailbox . Receive ( Direction : : DSP ) } ;
switch ( msg ) {
case Message : : Shutdown :
mailbox . Send ( Direction : : Host , Message : : Shutdown ) ;
return ;
case Message : : Render : {
if ( system . IsShuttingDown ( ) ) {
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 200 ) ) ;
mailbox . Send ( Direction : : Host , Message : : RenderResponse ) ;
continue ;
}
std : : array < bool , MaxRendererSessions > buffers_reset { } ;
std : : array < u64 , MaxRendererSessions > render_times_taken { } ;
const auto start_time { system . CoreTiming ( ) . GetGlobalTimeUs ( ) . count ( ) } ;
for ( u32 index = 0 ; index < MaxRendererSessions ; index + + ) {
auto & command_buffer { command_buffers [ index ] } ;
auto & command_list_processor { command_list_processors [ index ] } ;
// Check this buffer is valid, as it may not be used.
if ( command_buffer . buffer ! = 0 ) {
// If there are no remaining commands (from the previous list),
// this is a new command list, initialize it.
if ( command_buffer . remaining_command_count = = 0 ) {
command_list_processor . Initialize ( system , * command_buffer . process ,
command_buffer . buffer ,
command_buffer . size , streams [ index ] ) ;
}
if ( command_buffer . reset_buffer & & ! buffers_reset [ index ] ) {
streams [ index ] - > ClearQueue ( ) ;
buffers_reset [ index ] = true ;
}
u64 max_time { max_process_time } ;
if ( index = = 1 & & command_buffer . applet_resource_user_id = =
command_buffers [ 0 ] . applet_resource_user_id ) {
max_time = max_process_time - render_times_taken [ 0 ] ;
if ( render_times_taken [ 0 ] > max_process_time ) {
max_time = 0 ;
}
}
max_time = ( std : : min ) ( command_buffer . time_limit , max_time ) ;
command_list_processor . SetProcessTimeMax ( max_time ) ;
if ( index = = 0 ) {
streams [ index ] - > WaitFreeSpace ( stop_token ) ;
}
// Process the command list
{
render_times_taken [ index ] =
command_list_processor . Process ( index ) - start_time ;
}
const auto end_time { system . CoreTiming ( ) . GetGlobalTimeUs ( ) . count ( ) } ;
command_buffer . remaining_command_count =
command_list_processor . GetRemainingCommandCount ( ) ;
command_buffer . render_time_taken_us = end_time - start_time ;
}
}
mailbox . Send ( Direction : : Host , Message : : RenderResponse ) ;
} break ;
default :
LOG_WARNING ( Service_Audio , " ADSP AudioRenderer received an invalid message, msg={:02X}! " , msg ) ;
break ;
}
}
}
} // namespace AudioCore::ADSP::AudioRenderer
} // namespace AudioCore::ADSP::AudioRenderer