Compare commits

...
Author SHA1 Message Date
yuzubot 5f39650a98 "Merge Tagged PR 11385" 2023-09-10 12:03:08 +00:00
yuzubot c554b388e3 "Merge Tagged PR 11435" 2023-09-10 12:03:07 +00:00
yuzubot ce6a034b1c "Merge Tagged PR 11436" 2023-09-10 12:03:07 +00:00
yuzubot 68b5902994 "Merge Tagged PR 11459" 2023-09-10 12:03:06 +00:00
yuzubot 8573360649 "Merge Tagged PR 11465" 2023-09-10 12:03:06 +00:00
yuzubot f5d28bca9e "Merge Tagged PR 11467" 2023-09-10 12:03:06 +00:00
16 changed files with 185 additions and 88 deletions

No files matched your search

+1
View File
@@ -85,6 +85,7 @@ if (MSVC)
/wd4100 # 'identifier': unreferenced formal parameter
/wd4324 # 'struct_name': structure was padded due to __declspec(align())
/wd4201 # nonstandard extension used : nameless struct/union
/wd4702 # unreachable code (when used with LTO)
)
if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS)
@@ -88,8 +88,13 @@ MailboxMessage AudioRenderer::Receive(Direction dir, bool block) {
return mailbox.Receive(dir, block);
}
void AudioRenderer::SetCommandBuffer(s32 session_id, CommandBuffer& buffer) noexcept {
command_buffers[session_id] = buffer;
void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept {
command_buffers[session_id].buffer = buffer;
command_buffers[session_id].size = size;
command_buffers[session_id].time_limit = time_limit;
command_buffers[session_id].applet_resource_user_id = applet_resource_user_id;
command_buffers[session_id].reset_buffer = reset;
}
u32 AudioRenderer::GetRemainCommandCount(s32 session_id) const noexcept {
@@ -75,7 +75,8 @@ public:
void Send(Direction dir, MailboxMessage message);
MailboxMessage Receive(Direction dir, bool block = true);
void SetCommandBuffer(s32 session_id, CommandBuffer& buffer) noexcept;
void SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u64 time_limit,
u64 applet_resource_user_id, bool reset) noexcept;
u32 GetRemainCommandCount(s32 session_id) const noexcept;
void ClearRemainCommandCount(s32 session_id) noexcept;
u64 GetRenderingStartTick(s32 session_id) const noexcept;
@@ -37,11 +37,6 @@ u32 CommandListProcessor::GetRemainingCommandCount() const {
return command_count - processed_command_count;
}
void CommandListProcessor::SetBuffer(const CpuAddr buffer, const u64 size) {
commands = reinterpret_cast<u8*>(buffer + sizeof(Renderer::CommandListHeader));
commands_buffer_size = size;
}
Sink::SinkStream* CommandListProcessor::GetOutputSinkStream() const {
return stream;
}
@@ -56,14 +56,6 @@ public:
*/
u32 GetRemainingCommandCount() const;
/**
* Set the command buffer.
*
* @param buffer - The buffer to use.
* @param size - The size of the buffer.
*/
void SetBuffer(CpuAddr buffer, u64 size);
/**
* Get the stream for this command list.
*
@@ -20,6 +20,12 @@ void AdpcmDataSourceVersion1Command::Process(const AudioRenderer::CommandListPro
auto out_buffer{processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count)};
for (auto& wave_buffer : wave_buffers) {
wave_buffer.loop_start_offset = wave_buffer.start_offset;
wave_buffer.loop_end_offset = wave_buffer.end_offset;
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
}
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::Adpcm},
.output{out_buffer},
@@ -123,11 +123,13 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
return 0;
}
auto samples_to_process{
std::min(req.end_offset - req.start_offset - req.offset, req.samples_to_read)};
auto start_pos{req.start_offset + req.offset};
auto samples_to_process{std::min(req.end_offset - start_pos, req.samples_to_read)};
if (samples_to_process == 0) {
return 0;
}
auto samples_to_read{samples_to_process};
auto start_pos{req.start_offset + req.offset};
auto samples_remaining_in_frame{start_pos % SamplesPerFrame};
auto position_in_frame{(start_pos / SamplesPerFrame) * NibblesPerFrame +
samples_remaining_in_frame};
@@ -225,13 +227,24 @@ static u32 DecodeAdpcm(Core::Memory::Memory& memory, std::span<s16> out_buffer,
* @param args - The wavebuffer data, and information for how to decode it.
*/
void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuffersArgs& args) {
static constexpr auto EndWaveBuffer = [](auto& voice_state, auto& wavebuffer, auto& index,
auto& played_samples, auto& consumed) -> void {
voice_state.wave_buffer_valid[index] = false;
voice_state.loop_count = 0;
if (wavebuffer.stream_ended) {
played_samples = 0;
}
index = (index + 1) % MaxWaveBuffers;
consumed++;
};
auto& voice_state{*args.voice_state};
auto remaining_sample_count{args.sample_count};
auto fraction{voice_state.fraction};
const auto sample_rate_ratio{
(Common::FixedPoint<49, 15>(args.source_sample_rate) / args.target_sample_rate) *
args.pitch};
const auto sample_rate_ratio{Common::FixedPoint<49, 15>(
(f32)args.source_sample_rate / (f32)args.target_sample_rate * (f32)args.pitch)};
const auto size_required{fraction + remaining_sample_count * sample_rate_ratio};
if (size_required < 0) {
@@ -298,22 +311,23 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
auto end_offset{wavebuffer.end_offset};
if (wavebuffer.loop && voice_state.loop_count > 0 &&
wavebuffer.loop_start_offset != 0 && wavebuffer.loop_end_offset != 0 &&
wavebuffer.loop_start_offset <= wavebuffer.loop_end_offset) {
start_offset = wavebuffer.loop_start_offset;
end_offset = wavebuffer.loop_end_offset;
}
DecodeArg decode_arg{.buffer{wavebuffer.buffer},
.buffer_size{wavebuffer.buffer_size},
.start_offset{start_offset},
.end_offset{end_offset},
.channel_count{args.channel_count},
.coefficients{},
.adpcm_context{nullptr},
.target_channel{args.channel},
.offset{offset},
.samples_to_read{samples_to_read - samples_read}};
DecodeArg decode_arg{
.buffer{wavebuffer.buffer},
.buffer_size{wavebuffer.buffer_size},
.start_offset{start_offset},
.end_offset{end_offset},
.channel_count{args.channel_count},
.coefficients{},
.adpcm_context{nullptr},
.target_channel{args.channel},
.offset{offset},
.samples_to_read{samples_to_read - samples_read},
};
s32 samples_decoded{0};
@@ -350,42 +364,30 @@ void DecodeFromWaveBuffers(Core::Memory::Memory& memory, const DecodeFromWaveBuf
temp_buffer_pos += samples_decoded;
offset += samples_decoded;
if (samples_decoded == 0 || offset >= end_offset - start_offset) {
offset = 0;
if (!wavebuffer.loop) {
voice_state.wave_buffer_valid[wavebuffer_index] = false;
voice_state.loop_count = 0;
if (samples_decoded && offset < end_offset - start_offset) {
continue;
}
if (wavebuffer.stream_ended) {
played_sample_count = 0;
}
wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
wavebuffers_consumed++;
} else {
voice_state.loop_count++;
if (wavebuffer.loop_count >= 0 &&
(voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
voice_state.wave_buffer_valid[wavebuffer_index] = false;
voice_state.loop_count = 0;
if (wavebuffer.stream_ended) {
played_sample_count = 0;
}
wavebuffer_index = (wavebuffer_index + 1) % MaxWaveBuffers;
wavebuffers_consumed++;
}
if (samples_decoded == 0) {
is_buffer_starved = true;
break;
}
if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
played_sample_count = 0;
}
offset = 0;
if (wavebuffer.loop) {
voice_state.loop_count++;
if (wavebuffer.loop_count >= 0 &&
(voice_state.loop_count > wavebuffer.loop_count || samples_decoded == 0)) {
EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
wavebuffers_consumed);
}
if (samples_decoded == 0) {
is_buffer_starved = true;
break;
}
if (args.IsVoicePlayedSampleCountResetAtLoopPointSupported) {
played_sample_count = 0;
}
} else {
EndWaveBuffer(voice_state, wavebuffer, wavebuffer_index, played_sample_count,
wavebuffers_consumed);
}
}
@@ -21,6 +21,12 @@ void PcmFloatDataSourceVersion1Command::Process(
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
for (auto& wave_buffer : wave_buffers) {
wave_buffer.loop_start_offset = wave_buffer.start_offset;
wave_buffer.loop_end_offset = wave_buffer.end_offset;
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
}
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::PcmFloat},
.output{out_buffer},
@@ -23,6 +23,12 @@ void PcmInt16DataSourceVersion1Command::Process(
auto out_buffer = processor.mix_buffers.subspan(output_index * processor.sample_count,
processor.sample_count);
for (auto& wave_buffer : wave_buffers) {
wave_buffer.loop_start_offset = wave_buffer.start_offset;
wave_buffer.loop_end_offset = wave_buffer.end_offset;
wave_buffer.loop_count = wave_buffer.loop ? -1 : 0;
}
DecodeFromWaveBuffersArgs args{
.sample_format{SampleFormat::PcmInt16},
.output{out_buffer},
+5 -11
View File
@@ -609,17 +609,11 @@ void System::SendCommandToDsp() {
time_limit_percent = 70.0f;
}
AudioRenderer::CommandBuffer command_buffer{
.buffer{translated_addr},
.size{command_size},
.time_limit{
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))},
.applet_resource_user_id{applet_resource_user_id},
.reset_buffer{reset_command_buffers},
};
audio_renderer.SetCommandBuffer(session_id, command_buffer);
auto time_limit{
static_cast<u64>((time_limit_percent / 100) * 2'880'000.0 *
(static_cast<f32>(render_time_limit_percent) / 100.0f))};
audio_renderer.SetCommandBuffer(session_id, translated_addr, command_size, time_limit,
applet_resource_user_id, reset_command_buffers);
reset_command_buffers = false;
command_buffer_size = command_size;
if (remaining_command_count == 0) {
+2
View File
@@ -406,6 +406,7 @@ struct System::Impl {
gpu_core->NotifyShutdown();
}
Network::CancelPendingSocketOperations();
kernel.SuspendApplication(true);
if (services) {
services->KillNVNFlinger();
@@ -427,6 +428,7 @@ struct System::Impl {
debugger.reset();
kernel.Shutdown();
memory.Reset();
Network::RestartSocketOperations();
if (auto room_member = room_network.GetRoomMember().lock()) {
Network::GameInfo game_info{};
+86 -3
View File
@@ -48,15 +48,32 @@ enum class CallType {
using socklen_t = int;
SOCKET interrupt_socket = static_cast<SOCKET>(-1);
void InterruptSocketOperations() {
closesocket(interrupt_socket);
}
void AcknowledgeInterrupt() {
interrupt_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
}
void Initialize() {
WSADATA wsa_data;
(void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
AcknowledgeInterrupt();
}
void Finalize() {
InterruptSocketOperations();
WSACleanup();
}
SOCKET GetInterruptSocket() {
return interrupt_socket;
}
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
sockaddr_in result;
@@ -157,9 +174,42 @@ constexpr int SD_RECEIVE = SHUT_RD;
constexpr int SD_SEND = SHUT_WR;
constexpr int SD_BOTH = SHUT_RDWR;
void Initialize() {}
int interrupt_pipe_fd[2] = {-1, -1};
void Finalize() {}
void Initialize() {
if (pipe(interrupt_pipe_fd) != 0) {
LOG_ERROR(Network, "Failed to create interrupt pipe!");
}
int flags = fcntl(interrupt_pipe_fd[0], F_GETFL);
ASSERT_MSG(fcntl(interrupt_pipe_fd[0], F_SETFL, flags | O_NONBLOCK) == 0,
"Failed to set nonblocking state for interrupt pipe");
}
void Finalize() {
if (interrupt_pipe_fd[0] >= 0) {
close(interrupt_pipe_fd[0]);
}
if (interrupt_pipe_fd[1] >= 0) {
close(interrupt_pipe_fd[1]);
}
}
void InterruptSocketOperations() {
u8 value = 0;
ASSERT(write(interrupt_pipe_fd[1], &value, sizeof(value)) == 1);
}
void AcknowledgeInterrupt() {
u8 value = 0;
ssize_t ret = read(interrupt_pipe_fd[0], &value, sizeof(value));
if (ret != 1 && errno != EAGAIN && errno != EWOULDBLOCK) {
LOG_ERROR(Network, "Failed to acknowledge interrupt on shutdown");
}
}
SOCKET GetInterruptSocket() {
return interrupt_pipe_fd[0];
}
sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
sockaddr_in result;
@@ -490,6 +540,14 @@ NetworkInstance::~NetworkInstance() {
Finalize();
}
void CancelPendingSocketOperations() {
InterruptSocketOperations();
}
void RestartSocketOperations() {
AcknowledgeInterrupt();
}
std::optional<IPv4Address> GetHostIPv4Address() {
const auto network_interface = Network::GetSelectedNetworkInterface();
if (!network_interface.has_value()) {
@@ -560,7 +618,14 @@ std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
return result;
});
const int result = WSAPoll(host_pollfds.data(), static_cast<ULONG>(num), timeout);
host_pollfds.push_back(WSAPOLLFD{
.fd = GetInterruptSocket(),
.events = POLLIN,
.revents = 0,
});
const int result =
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), timeout);
if (result == 0) {
ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
[](WSAPOLLFD fd) { return fd.revents == 0; }));
@@ -627,6 +692,24 @@ Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
std::vector<WSAPOLLFD> host_pollfds{
WSAPOLLFD{fd, POLLIN, 0},
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
};
while (true) {
const int pollres =
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
if (host_pollfds[1].revents != 0) {
// Interrupt signaled before a client could be accepted, break
return {AcceptResult{}, Errno::AGAIN};
}
if (pollres > 0) {
break;
}
}
const SOCKET new_socket = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
if (new_socket == INVALID_SOCKET) {
+3
View File
@@ -96,6 +96,9 @@ public:
~NetworkInstance();
};
void CancelPendingSocketOperations();
void RestartSocketOperations();
#ifdef _WIN32
constexpr IPv4Address TranslateIPv4(in_addr addr) {
auto& bytes = addr.S_un.S_un_b;
@@ -204,9 +204,7 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind
if (def.count > 1) {
throw NotImplementedException("Indirect texture sample");
}
const Id sampler_id{def.id};
const Id id{ctx.OpLoad(ctx.sampled_texture_buffer_type, sampler_id)};
return ctx.OpImage(ctx.image_buffer_type, id);
return ctx.OpLoad(ctx.image_buffer_type, def.id);
} else {
const TextureDefinition& def{ctx.textures.at(info.descriptor_index)};
if (def.count > 1) {
@@ -74,6 +74,11 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
throw InvalidArgument("Invalid image format {}", format);
}
spv::ImageFormat GetImageFormatForBuffer(ImageFormat format) {
const auto spv_format = GetImageFormat(format);
return spv_format == spv::ImageFormat::Unknown ? spv::ImageFormat::R32ui : spv_format;
}
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
const spv::ImageFormat format{GetImageFormat(desc.format)};
const Id type{ctx.U32[1]};
@@ -1242,9 +1247,8 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) {
}
const spv::ImageFormat format{spv::ImageFormat::Unknown};
image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format);
sampled_texture_buffer_type = TypeSampledImage(image_buffer_type);
const Id type{TypePointer(spv::StorageClass::UniformConstant, sampled_texture_buffer_type)};
const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)};
texture_buffers.reserve(info.texture_buffer_descriptors.size());
for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) {
if (desc.count != 1) {
@@ -1271,7 +1275,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
if (desc.count != 1) {
throw NotImplementedException("Array of image buffers");
}
const spv::ImageFormat format{GetImageFormat(desc.format)};
const spv::ImageFormat format{GetImageFormatForBuffer(desc.format)};
const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
@@ -206,7 +206,6 @@ public:
Id output_u32{};
Id image_buffer_type{};
Id sampled_texture_buffer_type{};
Id image_u32{};
std::array<UniformDefinitions, Info::MAX_CBUFS> cbufs{};