summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/service/audio/audren_u.cpp109
-rw-r--r--src/core/hle/service/audio/audren_u.h1
2 files changed, 93 insertions, 17 deletions
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 0f325fe07..621860e2e 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -263,12 +263,15 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
263 OpenAudioRendererImpl(ctx); 263 OpenAudioRendererImpl(ctx);
264} 264}
265 265
266static u64 CalculateNumPerformanceEntries(const AudioCore::AudioRendererParameter& params) {
267 // +1 represents the final mix.
268 return u64{params.effect_count} + params.submix_count + params.sink_count + params.voice_count +
269 1;
270}
271
266void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { 272void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
267 LOG_DEBUG(Service_Audio, "called"); 273 LOG_DEBUG(Service_Audio, "called");
268 274
269 IPC::RequestParser rp{ctx};
270 const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
271
272 // Several calculations below align the sizes being calculated 275 // Several calculations below align the sizes being calculated
273 // onto a 64 byte boundary. 276 // onto a 64 byte boundary.
274 static constexpr u64 buffer_alignment_size = 64; 277 static constexpr u64 buffer_alignment_size = 64;
@@ -278,6 +281,10 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
278 // the result of some of their calcularions on a 16 byte boundary. 281 // the result of some of their calcularions on a 16 byte boundary.
279 static constexpr u64 info_field_alignment_size = 16; 282 static constexpr u64 info_field_alignment_size = 16;
280 283
284 // Maximum detail entries that may exist at one time for performance
285 // frame statistics.
286 static constexpr u64 max_perf_detail_entries = 100;
287
281 // Size of the data structure representing the bulk of the voice-related state. 288 // Size of the data structure representing the bulk of the voice-related state.
282 static constexpr u64 voice_state_size = 0x100; 289 static constexpr u64 voice_state_size = 0x100;
283 290
@@ -440,14 +447,9 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
440 const u64 entry_size = is_v2 ? 0x18 : 0x10; 447 const u64 entry_size = is_v2 ? 0x18 : 0x10;
441 const u64 detail_size = is_v2 ? 0x18 : 0x10; 448 const u64 detail_size = is_v2 ? 0x18 : 0x10;
442 449
443 constexpr u64 max_detail_entries = 100; 450 const u64 entry_count = CalculateNumPerformanceEntries(params);
444
445 // + 1 to include the final mix, similar to calculating mix info.
446 const u64 entry_count = u64{params.effect_count} + params.submix_count + params.sink_count +
447 params.voice_count + 1;
448
449 const u64 size_per_frame = 451 const u64 size_per_frame =
450 header_size + (entry_size * entry_count) + (detail_size * max_detail_entries); 452 header_size + (entry_size * entry_count) + (detail_size * max_perf_detail_entries);
451 453
452 u64 size = 0; 454 u64 size = 0;
453 size += Common::AlignUp(size_per_frame * params.performance_frame_count + 1, 455 size += Common::AlignUp(size_per_frame * params.performance_frame_count + 1,
@@ -458,11 +460,81 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
458 }; 460 };
459 461
460 // Calculates the part of the size that relates to the audio command buffer. 462 // Calculates the part of the size that relates to the audio command buffer.
461 const auto calculate_command_buffer_size = [] { 463 const auto calculate_command_buffer_size =
462 constexpr u64 command_buffer_size = 0x18000; 464 [this](const AudioCore::AudioRendererParameter& params) {
463 constexpr u64 alignment = (buffer_alignment_size - 1) * 2; 465 constexpr u64 alignment = (buffer_alignment_size - 1) * 2;
464 return command_buffer_size + alignment; 466
465 }; 467 if (!IsFeatureSupported(AudioFeatures::VariadicCommandBuffer, params.revision)) {
468 constexpr u64 command_buffer_size = 0x18000;
469
470 return command_buffer_size + alignment;
471 }
472
473 // When the variadic command buffer is supported, this means
474 // the command generator for the audio renderer can issue commands
475 // that are (as one would expect), variable in size. So what we need to do
476 // is determine the maximum possible size for a few command data structures
477 // then multiply them by the amount of present commands indicated by the given
478 // respective audio parameters.
479
480 constexpr u64 max_biquad_filters = 2;
481 constexpr u64 max_mix_buffers = 24;
482
483 constexpr u64 biquad_filter_command_size = 0x2C;
484
485 constexpr u64 depop_mix_command_size = 0x24;
486 constexpr u64 depop_setup_command_size = 0x50;
487
488 constexpr u64 effect_command_max_size = 0x540;
489
490 constexpr u64 mix_command_size = 0x1C;
491 constexpr u64 mix_ramp_command_size = 0x24;
492 constexpr u64 mix_ramp_grouped_command_size = 0x13C;
493
494 constexpr u64 perf_command_size = 0x28;
495
496 constexpr u64 sink_command_size = 0x130;
497
498 constexpr u64 submix_command_max_size =
499 depop_mix_command_size + (mix_command_size * max_mix_buffers) * max_mix_buffers;
500
501 constexpr u64 volume_command_size = 0x1C;
502 constexpr u64 volume_ramp_command_size = 0x20;
503
504 constexpr u64 voice_biquad_filter_command_size =
505 biquad_filter_command_size * max_biquad_filters;
506 constexpr u64 voice_data_command_size = 0x9C;
507 const u64 voice_command_max_size =
508 (params.splitter_count * depop_setup_command_size) +
509 (voice_data_command_size + voice_biquad_filter_command_size +
510 volume_ramp_command_size + mix_ramp_grouped_command_size);
511
512 // Now calculate the individual elements that comprise the size and add them together.
513 const u64 effect_commands_size = params.effect_count * effect_command_max_size;
514
515 const u64 final_mix_commands_size =
516 depop_mix_command_size + volume_command_size * max_mix_buffers;
517
518 const u64 perf_commands_size =
519 perf_command_size *
520 (CalculateNumPerformanceEntries(params) + max_perf_detail_entries);
521
522 const u64 sink_commands_size = params.sink_count * sink_command_size;
523
524 const u64 splitter_commands_size =
525 params.num_splitter_send_channels * max_mix_buffers * mix_ramp_command_size;
526
527 const u64 submix_commands_size = params.submix_count * submix_command_max_size;
528
529 const u64 voice_commands_size = params.voice_count * voice_command_max_size;
530
531 return effect_commands_size + final_mix_commands_size + perf_commands_size +
532 sink_commands_size + splitter_commands_size + submix_commands_size +
533 voice_commands_size + alignment;
534 };
535
536 IPC::RequestParser rp{ctx};
537 const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
466 538
467 u64 size = 0; 539 u64 size = 0;
468 size += calculate_mix_buffer_sizes(params); 540 size += calculate_mix_buffer_sizes(params);
@@ -479,7 +551,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
479 size += calculate_sink_info_size(params); 551 size += calculate_sink_info_size(params);
480 size += calculate_voice_state_size(params); 552 size += calculate_voice_state_size(params);
481 size += calculate_perf_size(params); 553 size += calculate_perf_size(params);
482 size += calculate_command_buffer_size(); 554 size += calculate_command_buffer_size(params);
483 555
484 // finally, 4KB page align the size, and we're done. 556 // finally, 4KB page align the size, and we're done.
485 size = Common::AlignUp(size, 4096); 557 size = Common::AlignUp(size, 4096);
@@ -526,11 +598,14 @@ void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) {
526} 598}
527 599
528bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { 600bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
529 u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap 601 // Byte swap
602 const u32_be version_num = revision - Common::MakeMagic('R', 'E', 'V', '0');
603
530 switch (feature) { 604 switch (feature) {
531 case AudioFeatures::Splitter: 605 case AudioFeatures::Splitter:
532 return version_num >= 2U; 606 return version_num >= 2U;
533 case AudioFeatures::PerformanceMetricsVersion2: 607 case AudioFeatures::PerformanceMetricsVersion2:
608 case AudioFeatures::VariadicCommandBuffer:
534 return version_num >= 5U; 609 return version_num >= 5U;
535 default: 610 default:
536 return false; 611 return false;
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index b8f71c37c..1d3c8df61 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -29,6 +29,7 @@ private:
29 enum class AudioFeatures : u32 { 29 enum class AudioFeatures : u32 {
30 Splitter, 30 Splitter,
31 PerformanceMetricsVersion2, 31 PerformanceMetricsVersion2,
32 VariadicCommandBuffer,
32 }; 33 };
33 34
34 bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const; 35 bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const;