diff options
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 109 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.h | 1 |
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 | ||
| 266 | static 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 | |||
| 266 | void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | 272 | void 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 | ||
| 528 | bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { | 600 | bool 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; |