summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Lioncash2019-04-29 18:34:09 -0400
committerGravatar Lioncash2019-04-30 23:52:28 -0400
commit2bcb8a20b4752788e1413ba02b37c0f393d77e98 (patch)
treea24c512710ce26d5420dc9401665b0f08edd9003 /src/core
parentservice/audren_u: Handle version 2 of performance frame info in GetWorkBuffer... (diff)
downloadyuzu-2bcb8a20b4752788e1413ba02b37c0f393d77e98.tar.gz
yuzu-2bcb8a20b4752788e1413ba02b37c0f393d77e98.tar.xz
yuzu-2bcb8a20b4752788e1413ba02b37c0f393d77e98.zip
service/audren_u: Handle variadic command buffers in GetWorkBufferSize()
Also introduced in REV5 was a variable-size audio command buffer. This also affects how the size of the work buffer should be determined, so we can add handling for this as well. Thankfully, no other alterations were made to how the work buffer size is calculated in 7.0.0-8.0.0. There were indeed changes made to to how some of the actual audio commands are generated though (particularly in REV7), however they don't apply here.
Diffstat (limited to 'src/core')
-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;