feat: Introduce new shader environment, OpenGL renderer components, and HLE socket/DNS services with internal network support.

This commit is contained in:
2025-12-30 00:13:48 -03:00
parent 664ff7cc85
commit bd1d270e97
11 changed files with 89 additions and 7 deletions

View File

@@ -29,7 +29,7 @@ SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"
{4, nullptr, "GetHostStringErrorRequest"},
{5, &SFDNSRES::GetGaiStringErrorRequest, "GetGaiStringErrorRequest"},
{6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
{7, nullptr, "GetNameInfoRequest"},
{7, &SFDNSRES::GetNameInfoRequest, "GetNameInfoRequest"},
{8, &SFDNSRES::RequestCancelHandleRequest, "RequestCancelHandleRequest"},
{9, nullptr, "CancelRequest"},
{10, &SFDNSRES::GetHostByNameRequestWithOptions, "GetHostByNameRequestWithOptions"},
@@ -382,6 +382,54 @@ void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
}
void SFDNSRES::GetNameInfoRequest(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto addr_in = rp.PopRaw<SockAddrIn>();
const u32 flags = rp.Pop<u32>();
const u32 cancel_handle = rp.Pop<u32>();
const u64 process_id = rp.Pop<u64>();
LOG_DEBUG(Service, "called. flags={}, cancel_handle={}, process_id={}", flags, cancel_handle,
process_id);
struct OutputParameters {
u32 data_size;
GetAddrInfoError gai_error;
NetDbError netdb_error;
Errno bsd_errno;
};
static_assert(sizeof(OutputParameters) == 0x10);
const auto res = Network::GetNameInfo(Translate(addr_in));
if (res.second != 0) {
const auto network_error = Network::TranslateGetAddrInfoErrorFromNative(res.second);
const auto service_error = Translate(network_error);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.PushRaw(OutputParameters{
.data_size = 0,
.gai_error = service_error,
.netdb_error = GetAddrInfoErrorToNetDbError(service_error),
.bsd_errno = GetAddrInfoErrorToErrno(service_error),
});
return;
}
const std::string& host = res.first;
const u32 data_size = static_cast<u32>(host.size() + 1);
ctx.WriteBuffer(host.data(), data_size, 0);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
rb.PushRaw(OutputParameters{
.data_size = data_size,
.gai_error = GetAddrInfoError::SUCCESS,
.netdb_error = NetDbError::Success,
.bsd_errno = Errno::SUCCESS,
});
}
void SFDNSRES::GetNameInfoRequestWithOptions(HLERequestContext& ctx) {
struct InputParameters {
u32 flags;

View File

@@ -22,6 +22,7 @@ private:
void GetHostByNameRequestWithOptions(HLERequestContext& ctx);
void GetAddrInfoRequest(HLERequestContext& ctx);
void GetAddrInfoRequestWithOptions(HLERequestContext& ctx);
void GetNameInfoRequest(HLERequestContext& ctx);
void GetNameInfoRequestWithOptions(HLERequestContext& ctx);
void ResolverSetOptionRequest(HLERequestContext& ctx);
void RequestCancelHandleRequest(HLERequestContext& ctx);

View File

@@ -16,10 +16,12 @@ enum class Errno : u32 {
SUCCESS = 0,
BADF = 9,
AGAIN = 11,
ACCES = 13,
INVAL = 22,
MFILE = 24,
PIPE = 32,
MSGSIZE = 90,
ADDRINUSE = 98,
CONNABORTED = 103,
CONNRESET = 104,
NOTCONN = 107,

View File

@@ -37,6 +37,10 @@ Errno Translate(Network::Errno value) {
return Errno::CONNRESET;
case Network::Errno::INPROGRESS:
return Errno::INPROGRESS;
case Network::Errno::ACCES:
return Errno::ACCES;
case Network::Errno::ADDRINUSE:
return Errno::ADDRINUSE;
default:
UNIMPLEMENTED_MSG("Unimplemented errno={}", value);
return Errno::SUCCESS;
@@ -261,7 +265,9 @@ PollEvents Translate(Network::PollEvents flags) {
Network::SockAddrIn Translate(SockAddrIn value) {
// Note: 6 is incorrect, but can be passed by homebrew (because libnx sets
// sin_len to 6 when deserializing getaddrinfo results).
ASSERT(value.len == 0 || value.len == sizeof(value) || value.len == 6);
if (value.len != 0 && value.len != sizeof(value) && value.len != 6) {
LOG_WARNING(Service, "Unexpected SockAddrIn length={}", value.len);
}
return {
.family = Translate(static_cast<Domain>(value.family)),

View File

@@ -85,6 +85,7 @@ sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
#endif
switch (static_cast<Domain>(input.family)) {
case Domain::Unspecified:
case Domain::INET:
result.sin_family = AF_INET;
break;
@@ -128,6 +129,7 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
case 0:
return Errno::SUCCESS;
case WSAEBADF:
case WSAENOTSOCK:
return Errno::BADF;
case WSAEINVAL:
return Errno::INVAL;
@@ -161,6 +163,10 @@ Errno TranslateNativeError(int e, CallType call_type = CallType::Other) {
return Errno::TIMEDOUT;
case WSAEINPROGRESS:
return Errno::INPROGRESS;
case WSAEACCES:
return Errno::ACCES;
case WSAEADDRINUSE:
return Errno::ADDRINUSE;
default:
UNIMPLEMENTED_MSG("Unimplemented errno={}", e);
return Errno::OTHER;
@@ -886,7 +892,9 @@ std::pair<s32, Errno> Socket::SendTo(u32 flags, std::span<const u8> message,
Errno Socket::Close() {
[[maybe_unused]] const int result = closesocket(fd);
ASSERT(result == 0);
if (result != 0) {
GetAndLogLastError();
}
fd = INVALID_SOCKET;
return Errno::SUCCESS;

View File

@@ -48,6 +48,8 @@ enum class Errno {
TIMEDOUT,
MSGSIZE,
INPROGRESS,
ACCES,
ADDRINUSE,
OTHER,
};

View File

@@ -446,10 +446,12 @@ void EmitIsHelperInvocation(EmitContext& ctx, IR::Inst& inst) {
void EmitSR_WScaleFactorXY(EmitContext& ctx, IR::Inst& inst) {
LOG_WARNING(Shader, "(STUBBED) called");
ctx.AddU32("{}=0x3c003c00u;", inst);
}
void EmitSR_WScaleFactorZ(EmitContext& ctx, IR::Inst& inst) {
LOG_WARNING(Shader, "(STUBBED) called");
ctx.AddU32("{}=0x3f800000u;", inst);
}
void EmitYDirection(EmitContext& ctx, IR::Inst& inst) {

View File

@@ -58,6 +58,9 @@ std::string FormatFloat(std::string_view value, IR::Type type) {
if (value == "nan") {
return "utof(0x7fc00000)";
}
if (value == "-nan") {
return "utof(0xffc00000)";
}
if (value == "inf") {
return "utof(0x7f800000)";
}

View File

@@ -33,6 +33,8 @@ static OGLProgram LinkSeparableProgram(GLuint shader) {
glGetProgramInfoLog(program.handle, log_length, nullptr, log.data());
if (link_status == GL_FALSE) {
LOG_ERROR(Render_OpenGL, "{}", log);
glDeleteProgram(program.handle);
program.handle = 0;
} else {
LOG_WARNING(Render_OpenGL, "{}", log);
}

View File

@@ -116,9 +116,14 @@ void WindowAdaptPass::DrawToFramebuffer(ProgramManager& program_manager, std::li
glBindTextureUnit(0, textures[i]);
glProgramUniformMatrix3x2fv(vert.handle, ModelViewMatrixLocation, 1, GL_FALSE,
matrices[i].data());
glProgramUniform2ui(frag.handle, ScreenSizeLocation,
static_cast<GLuint>(layout.screen.GetWidth()),
static_cast<GLuint>(layout.screen.GetHeight()));
if (frag.handle != 0) {
const GLint screen_size_loc = glGetUniformLocation(frag.handle, "screen_size");
if (screen_size_loc != -1) {
glProgramUniform2ui(frag.handle, screen_size_loc,
static_cast<GLuint>(layout.screen.GetWidth()),
static_cast<GLuint>(layout.screen.GetHeight()));
}
}
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices[i]), std::data(vertices[i]));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

View File

@@ -277,7 +277,10 @@ std::optional<u64> GenericEnvironment::TryFindSize() {
Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit,
bool via_header_index, u32 raw) {
const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)};
ASSERT(handle.first <= tic_limit);
if (handle.first > tic_limit) {
LOG_WARNING(Shader, "Texture ID {} is out of bounds (limit {})", handle.first, tic_limit);
return {};
}
const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)};
Tegra::Texture::TICEntry entry;
gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry));