early-access version 3764

main
pineappleEA 2023-07-20 19:02:37 +02:00
parent 30259960bd
commit bbf6b05a26
46 changed files with 3295 additions and 2352 deletions

View File

@ -289,10 +289,11 @@ find_package(Boost 1.79.0 REQUIRED context)
find_package(enet 1.3 MODULE)
find_package(fmt 9 REQUIRED)
find_package(inih 52 MODULE COMPONENTS INIReader)
find_package(LLVM MODULE COMPONENTS Demangle)
find_package(LLVM 17 MODULE COMPONENTS Demangle)
find_package(lz4 REQUIRED)
find_package(nlohmann_json 3.8 REQUIRED)
find_package(Opus 1.3 MODULE)
find_package(VulkanMemoryAllocator CONFIG)
find_package(ZLIB 1.2 REQUIRED)
find_package(zstd 1.5 REQUIRED)

View File

@ -1,7 +1,7 @@
yuzu emulator early access
=============
This is the source code for early-access 3754.
This is the source code for early-access 3764.
## Legal Notice

View File

@ -144,9 +144,9 @@ endif()
add_subdirectory(nx_tzdb)
# VMA
add_library(vma vma/vma.cpp)
target_include_directories(vma PUBLIC ./vma/VulkanMemoryAllocator/include)
target_link_libraries(vma PRIVATE Vulkan::Headers)
if (NOT TARGET GPUOpen::VulkanMemoryAllocator)
add_subdirectory(VulkanMemoryAllocator)
endif()
if (NOT TARGET LLVM::Demangle)
add_library(demangle demangle/ItaniumDemangle.cpp)

View File

@ -20,9 +20,7 @@
#include <cstdlib>
#include <cstring>
#include <functional>
#include <numeric>
#include <utility>
#include <vector>
using namespace llvm;
using namespace llvm::itanium_demangle;
@ -81,8 +79,8 @@ struct DumpVisitor {
}
void printStr(const char *S) { fprintf(stderr, "%s", S); }
void print(StringView SV) {
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
void print(std::string_view SV) {
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());
}
void print(const Node *N) {
if (N)
@ -90,14 +88,6 @@ struct DumpVisitor {
else
printStr("<null>");
}
void print(NodeOrString NS) {
if (NS.isNode())
print(NS.asNode());
else if (NS.isString())
print(NS.asString());
else
printStr("NodeOrString()");
}
void print(NodeArray A) {
++Depth;
printStr("{");
@ -116,13 +106,11 @@ struct DumpVisitor {
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
void print(bool B) { printStr(B ? "true" : "false"); }
template <class T>
typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
template <class T> std::enable_if_t<std::is_unsigned<T>::value> print(T N) {
fprintf(stderr, "%llu", (unsigned long long)N);
}
template <class T>
typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
template <class T> std::enable_if_t<std::is_signed<T>::value> print(T N) {
fprintf(stderr, "%lld", (long long)N);
}
@ -185,6 +173,50 @@ struct DumpVisitor {
return printStr("TemplateParamKind::Template");
}
}
void print(Node::Prec P) {
switch (P) {
case Node::Prec::Primary:
return printStr("Node::Prec::Primary");
case Node::Prec::Postfix:
return printStr("Node::Prec::Postfix");
case Node::Prec::Unary:
return printStr("Node::Prec::Unary");
case Node::Prec::Cast:
return printStr("Node::Prec::Cast");
case Node::Prec::PtrMem:
return printStr("Node::Prec::PtrMem");
case Node::Prec::Multiplicative:
return printStr("Node::Prec::Multiplicative");
case Node::Prec::Additive:
return printStr("Node::Prec::Additive");
case Node::Prec::Shift:
return printStr("Node::Prec::Shift");
case Node::Prec::Spaceship:
return printStr("Node::Prec::Spaceship");
case Node::Prec::Relational:
return printStr("Node::Prec::Relational");
case Node::Prec::Equality:
return printStr("Node::Prec::Equality");
case Node::Prec::And:
return printStr("Node::Prec::And");
case Node::Prec::Xor:
return printStr("Node::Prec::Xor");
case Node::Prec::Ior:
return printStr("Node::Prec::Ior");
case Node::Prec::AndIf:
return printStr("Node::Prec::AndIf");
case Node::Prec::OrIf:
return printStr("Node::Prec::OrIf");
case Node::Prec::Conditional:
return printStr("Node::Prec::Conditional");
case Node::Prec::Assign:
return printStr("Node::Prec::Assign");
case Node::Prec::Comma:
return printStr("Node::Prec::Comma");
case Node::Prec::Default:
return printStr("Node::Prec::Default");
}
}
void newLine() {
printStr("\n");
@ -334,36 +366,21 @@ public:
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
size_t *N, int *Status) {
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
if (Status)
*Status = demangle_invalid_args;
char *llvm::itaniumDemangle(std::string_view MangledName) {
if (MangledName.empty())
return nullptr;
}
int InternalStatus = demangle_success;
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
OutputStream S;
Demangler Parser(MangledName.data(),
MangledName.data() + MangledName.length());
Node *AST = Parser.parse();
if (!AST)
return nullptr;
if (AST == nullptr)
InternalStatus = demangle_invalid_mangled_name;
else if (!initializeOutputStream(Buf, N, S, 1024))
InternalStatus = demangle_memory_alloc_failure;
else {
assert(Parser.ForwardTemplateRefs.empty());
AST->print(S);
S += '\0';
if (N != nullptr)
*N = S.getCurrentPosition();
Buf = S.getBuffer();
}
if (Status)
*Status = InternalStatus;
return InternalStatus == demangle_success ? Buf : nullptr;
OutputBuffer OB;
assert(Parser.ForwardTemplateRefs.empty());
AST->print(OB);
OB += '\0';
return OB.getBuffer();
}
ItaniumPartialDemangler::ItaniumPartialDemangler()
@ -396,14 +413,12 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
}
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
OutputStream S;
if (!initializeOutputStream(Buf, N, S, 128))
return nullptr;
RootNode->print(S);
S += '\0';
OutputBuffer OB(Buf, N);
RootNode->print(OB);
OB += '\0';
if (N != nullptr)
*N = S.getCurrentPosition();
return S.getBuffer();
*N = OB.getCurrentPosition();
return OB.getBuffer();
}
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
@ -417,8 +432,8 @@ char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
case Node::KAbiTagAttr:
Name = static_cast<const AbiTagAttr *>(Name)->Base;
continue;
case Node::KStdQualifiedName:
Name = static_cast<const StdQualifiedName *>(Name)->Child;
case Node::KModuleEntity:
Name = static_cast<const ModuleEntity *>(Name)->Name;
continue;
case Node::KNestedName:
Name = static_cast<const NestedName *>(Name)->Name;
@ -441,9 +456,7 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
return nullptr;
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
OutputStream S;
if (!initializeOutputStream(Buf, N, S, 128))
return nullptr;
OutputBuffer OB(Buf, N);
KeepGoingLocalFunction:
while (true) {
@ -458,27 +471,27 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
break;
}
if (Name->getKind() == Node::KModuleEntity)
Name = static_cast<const ModuleEntity *>(Name)->Name;
switch (Name->getKind()) {
case Node::KStdQualifiedName:
S += "std";
break;
case Node::KNestedName:
static_cast<const NestedName *>(Name)->Qual->print(S);
static_cast<const NestedName *>(Name)->Qual->print(OB);
break;
case Node::KLocalName: {
auto *LN = static_cast<const LocalName *>(Name);
LN->Encoding->print(S);
S += "::";
LN->Encoding->print(OB);
OB += "::";
Name = LN->Entity;
goto KeepGoingLocalFunction;
}
default:
break;
}
S += '\0';
OB += '\0';
if (N != nullptr)
*N = S.getCurrentPosition();
return S.getBuffer();
*N = OB.getCurrentPosition();
return OB.getBuffer();
}
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
@ -494,17 +507,15 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
return nullptr;
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
OutputStream S;
if (!initializeOutputStream(Buf, N, S, 128))
return nullptr;
OutputBuffer OB(Buf, N);
S += '(';
Params.printWithComma(S);
S += ')';
S += '\0';
OB += '(';
Params.printWithComma(OB);
OB += ')';
OB += '\0';
if (N != nullptr)
*N = S.getCurrentPosition();
return S.getBuffer();
*N = OB.getCurrentPosition();
return OB.getBuffer();
}
char *ItaniumPartialDemangler::getFunctionReturnType(
@ -512,18 +523,16 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
if (!isFunction())
return nullptr;
OutputStream S;
if (!initializeOutputStream(Buf, N, S, 128))
return nullptr;
OutputBuffer OB(Buf, N);
if (const Node *Ret =
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
Ret->print(S);
Ret->print(OB);
S += '\0';
OB += '\0';
if (N != nullptr)
*N = S.getCurrentPosition();
return S.getBuffer();
*N = OB.getCurrentPosition();
return OB.getBuffer();
}
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
@ -563,8 +572,8 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
case Node::KNestedName:
N = static_cast<const NestedName *>(N)->Name;
break;
case Node::KStdQualifiedName:
N = static_cast<const StdQualifiedName *>(N)->Child;
case Node::KModuleEntity:
N = static_cast<const ModuleEntity *>(N)->Name;
break;
}
}

View File

@ -12,6 +12,7 @@
#include <cstddef>
#include <string>
#include <string_view>
namespace llvm {
/// This is a llvm local version of __cxa_demangle. Other than the name and
@ -29,9 +30,10 @@ enum : int {
demangle_success = 0,
};
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
int *status);
/// Returns a non-NULL pointer to a NUL-terminated C style string
/// that should be explicitly freed, if successful. Otherwise, may return
/// nullptr if mangled_name is not a valid mangling or is nullptr.
char *itaniumDemangle(std::string_view mangled_name);
enum MSDemangleFlags {
MSDF_None = 0,
@ -40,10 +42,34 @@ enum MSDemangleFlags {
MSDF_NoCallingConvention = 1 << 2,
MSDF_NoReturnType = 1 << 3,
MSDF_NoMemberType = 1 << 4,
MSDF_NoVariableType = 1 << 5,
};
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
/// Returns a pointer to the start of a null-terminated demangled string on
/// success, or nullptr on error.
/// If n_read is non-null and demangling was successful, it receives how many
/// bytes of the input string were consumed.
/// status receives one of the demangle_ enum entries above if it's not nullptr.
/// Flags controls various details of the demangled representation.
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
int *status, MSDemangleFlags Flags = MSDF_None);
// Demangles a Rust v0 mangled symbol.
char *rustDemangle(std::string_view MangledName);
// Demangles a D mangled symbol.
char *dlangDemangle(std::string_view MangledName);
/// Attempt to demangle a string using different demangling schemes.
/// The function uses heuristics to determine which demangling scheme to use.
/// \param MangledName - reference to string to demangle.
/// \returns - the demangled string, or a copy of the input string if no
/// demangling occurred.
std::string demangle(std::string_view MangledName);
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
/// "Partial" demangler. This supports demangling a string into an AST
/// (typically an intermediate stage in itaniumDemangle) and querying certain
/// properties or partially printing the demangled name.
@ -59,7 +85,7 @@ struct ItaniumPartialDemangler {
bool partialDemangle(const char *MangledName);
/// Just print the entire mangled name into Buf. Buf and N behave like the
/// second and third parameters to itaniumDemangle.
/// second and third parameters to __cxa_demangle.
char *finishDemangle(char *Buf, size_t *N) const;
/// Get the base name of a function. This doesn't include trailing template
@ -95,6 +121,7 @@ struct ItaniumPartialDemangler {
bool isSpecialName() const;
~ItaniumPartialDemangler();
private:
void *RootNode;
void *Context;

View File

@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEMANGLE_COMPILER_H
#define LLVM_DEMANGLE_COMPILER_H
#ifndef LLVM_DEMANGLE_DEMANGLECONFIG_H
#define LLVM_DEMANGLE_DEMANGLECONFIG_H
#ifndef __has_feature
#define __has_feature(x) 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
//===--- ItaniumNodes.def ------------*- mode:c++;eval:(read-only-mode) -*-===//
// Do not edit! See README.txt.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-FileCopyrightText: Part of the LLVM Project
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Define the demangler's node names
#ifndef NODE
#error Define NODE to handle nodes
#endif
NODE(NodeArrayNode)
NODE(DotSuffix)
NODE(VendorExtQualType)
NODE(QualType)
NODE(ConversionOperatorType)
NODE(PostfixQualifiedType)
NODE(ElaboratedTypeSpefType)
NODE(NameType)
NODE(AbiTagAttr)
NODE(EnableIfAttr)
NODE(ObjCProtoName)
NODE(PointerType)
NODE(ReferenceType)
NODE(PointerToMemberType)
NODE(ArrayType)
NODE(FunctionType)
NODE(NoexceptSpec)
NODE(DynamicExceptionSpec)
NODE(FunctionEncoding)
NODE(LiteralOperator)
NODE(SpecialName)
NODE(CtorVtableSpecialName)
NODE(QualifiedName)
NODE(NestedName)
NODE(LocalName)
NODE(ModuleName)
NODE(ModuleEntity)
NODE(VectorType)
NODE(PixelVectorType)
NODE(BinaryFPType)
NODE(BitIntType)
NODE(SyntheticTemplateParamName)
NODE(TypeTemplateParamDecl)
NODE(NonTypeTemplateParamDecl)
NODE(TemplateTemplateParamDecl)
NODE(TemplateParamPackDecl)
NODE(ParameterPack)
NODE(TemplateArgumentPack)
NODE(ParameterPackExpansion)
NODE(TemplateArgs)
NODE(ForwardTemplateReference)
NODE(NameWithTemplateArgs)
NODE(GlobalQualifiedName)
NODE(ExpandedSpecialSubstitution)
NODE(SpecialSubstitution)
NODE(CtorDtorName)
NODE(DtorName)
NODE(UnnamedTypeName)
NODE(ClosureTypeName)
NODE(StructuredBindingName)
NODE(BinaryExpr)
NODE(ArraySubscriptExpr)
NODE(PostfixExpr)
NODE(ConditionalExpr)
NODE(MemberExpr)
NODE(SubobjectExpr)
NODE(EnclosingExpr)
NODE(CastExpr)
NODE(SizeofParamPackExpr)
NODE(CallExpr)
NODE(NewExpr)
NODE(DeleteExpr)
NODE(PrefixExpr)
NODE(FunctionParam)
NODE(ConversionExpr)
NODE(PointerToMemberConversionExpr)
NODE(InitListExpr)
NODE(FoldExpr)
NODE(ThrowExpr)
NODE(BoolExpr)
NODE(StringLiteral)
NODE(LambdaExpr)
NODE(EnumLiteral)
NODE(IntegerLiteral)
NODE(FloatLiteral)
NODE(DoubleLiteral)
NODE(LongDoubleLiteral)
NODE(BracedExpr)
NODE(BracedRangeExpr)
#undef NODE

View File

@ -1,5 +1,5 @@
//===--- StringView.h -------------------------------------------*- C++ -*-===//
//
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
// Do not edit! See README.txt.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-FileCopyrightText: Part of the LLVM Project
@ -8,6 +8,9 @@
//===----------------------------------------------------------------------===//
//
// FIXME: Use std::string_view instead when we support C++17.
// There are two copies of this file in the source tree. The one under
// libcxxabi is the original and the one under llvm is the copy. Use
// cp-to-llvm.sh to update the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
@ -15,7 +18,6 @@
#define DEMANGLE_STRINGVIEW_H
#include "DemangleConfig.h"
#include <algorithm>
#include <cassert>
#include <cstring>
@ -37,29 +39,23 @@ public:
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
StringView() : First(nullptr), Last(nullptr) {}
StringView substr(size_t From) const {
return StringView(begin() + From, size() - From);
StringView substr(size_t Pos, size_t Len = npos) const {
assert(Pos <= size());
if (Len > size() - Pos)
Len = size() - Pos;
return StringView(begin() + Pos, Len);
}
size_t find(char C, size_t From = 0) const {
size_t FindBegin = std::min(From, size());
// Avoid calling memchr with nullptr.
if (FindBegin < size()) {
if (From < size()) {
// Just forward to memchr, which is faster than a hand-rolled loop.
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
if (const void *P = ::memchr(First + From, C, size() - From))
return size_t(static_cast<const char *>(P) - First);
}
return npos;
}
StringView substr(size_t From, size_t To) const {
if (To >= size())
To = size() - 1;
if (From >= size())
From = size() - 1;
return StringView(First + From, First + To);
}
StringView dropFront(size_t N = 1) const {
if (N >= size())
N = size();
@ -106,7 +102,7 @@ public:
bool startsWith(StringView Str) const {
if (Str.size() > size())
return false;
return std::equal(Str.begin(), Str.end(), begin());
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
}
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
@ -119,7 +115,7 @@ public:
inline bool operator==(const StringView &LHS, const StringView &RHS) {
return LHS.size() == RHS.size() &&
std::equal(LHS.begin(), LHS.end(), RHS.begin());
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
}
DEMANGLE_NAMESPACE_END

View File

@ -0,0 +1,39 @@
//===--- StringViewExtras.h ----------*- mode:c++;eval:(read-only-mode) -*-===//
// Do not edit! See README.txt.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-FileCopyrightText: Part of the LLVM Project
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// There are two copies of this file in the source tree. The one under
// libcxxabi is the original and the one under llvm is the copy. Use
// cp-to-llvm.sh to update the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_STRINGVIEW_H
#define DEMANGLE_STRINGVIEW_H
#include "DemangleConfig.h"
#include <string_view>
DEMANGLE_NAMESPACE_BEGIN
inline bool starts_with(std::string_view self, char C) noexcept {
return !self.empty() && *self.begin() == C;
}
inline bool starts_with(std::string_view haystack,
std::string_view needle) noexcept {
if (needle.size() > haystack.size())
return false;
haystack.remove_suffix(haystack.size() - needle.size());
return haystack == needle;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@ -1,5 +1,5 @@
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
//
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
// Do not edit! See README.txt.
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-FileCopyrightText: Part of the LLVM Project
@ -7,70 +7,83 @@
//
//===----------------------------------------------------------------------===//
//
// Provide some utility classes for use in the demangler(s).
// Provide some utility classes for use in the demangler.
// There are two copies of this file in the source tree. The one in libcxxabi
// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
// the copy. See README.txt for more details.
//
//===----------------------------------------------------------------------===//
#ifndef DEMANGLE_UTILITY_H
#define DEMANGLE_UTILITY_H
#include "StringView.h"
#include "DemangleConfig.h"
#include <array>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <exception>
#include <limits>
#include <string_view>
DEMANGLE_NAMESPACE_BEGIN
// Stream that AST nodes write their string representation into after the AST
// has been parsed.
class OutputStream {
char *Buffer;
size_t CurrentPosition;
size_t BufferCapacity;
class OutputBuffer {
char *Buffer = nullptr;
size_t CurrentPosition = 0;
size_t BufferCapacity = 0;
// Ensure there is at least n more positions in buffer.
// Ensure there are at least N more positions in the buffer.
void grow(size_t N) {
if (N + CurrentPosition >= BufferCapacity) {
size_t Need = N + CurrentPosition;
if (Need > BufferCapacity) {
// Reduce the number of reallocations, with a bit of hysteresis. The
// number here is chosen so the first allocation will more-than-likely not
// allocate more than 1K.
Need += 1024 - 32;
BufferCapacity *= 2;
if (BufferCapacity < N + CurrentPosition)
BufferCapacity = N + CurrentPosition;
if (BufferCapacity < Need)
BufferCapacity = Need;
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
if (Buffer == nullptr)
std::terminate();
}
}
void writeUnsigned(uint64_t N, bool isNeg = false) {
// Handle special case...
if (N == 0) {
*this << '0';
return;
}
OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
std::array<char, 21> Temp;
char *TempPtr = Temp.data() + Temp.size();
char Temp[21];
char *TempPtr = std::end(Temp);
while (N) {
*--TempPtr = '0' + char(N % 10);
// Output at least one character.
do {
*--TempPtr = char('0' + N % 10);
N /= 10;
}
} while (N);
// Add negative sign...
// Add negative sign.
if (isNeg)
*--TempPtr = '-';
this->operator<<(StringView(TempPtr, std::end(Temp)));
return operator+=(
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
}
public:
OutputStream(char *StartBuf, size_t Size)
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
OutputStream() = default;
void reset(char *Buffer_, size_t BufferCapacity_) {
CurrentPosition = 0;
Buffer = Buffer_;
BufferCapacity = BufferCapacity_;
OutputBuffer(char *StartBuf, size_t Size)
: Buffer(StartBuf), BufferCapacity(Size) {}
OutputBuffer(char *StartBuf, size_t *SizePtr)
: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
OutputBuffer() = default;
// Non-copyable
OutputBuffer(const OutputBuffer &) = delete;
OutputBuffer &operator=(const OutputBuffer &) = delete;
operator std::string_view() const {
return std::string_view(Buffer, CurrentPosition);
}
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
@ -78,115 +91,116 @@ public:
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
OutputStream &operator+=(StringView R) {
size_t Size = R.size();
if (Size == 0)
return *this;
grow(Size);
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
CurrentPosition += Size;
/// When zero, we're printing template args and '>' needs to be parenthesized.
/// Use a counter so we can simply increment inside parentheses.
unsigned GtIsGt = 1;
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
void printOpen(char Open = '(') {
GtIsGt++;
*this += Open;
}
void printClose(char Close = ')') {
GtIsGt--;
*this += Close;
}
OutputBuffer &operator+=(std::string_view R) {
if (size_t Size = R.size()) {
grow(Size);
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
CurrentPosition += Size;
}
return *this;
}
OutputStream &operator+=(char C) {
OutputBuffer &operator+=(char C) {
grow(1);
Buffer[CurrentPosition++] = C;
return *this;
}
OutputStream &operator<<(StringView R) { return (*this += R); }
OutputBuffer &prepend(std::string_view R) {
size_t Size = R.size();
OutputStream &operator<<(char C) { return (*this += C); }
grow(Size);
std::memmove(Buffer + Size, Buffer, CurrentPosition);
std::memcpy(Buffer, &*R.begin(), Size);
CurrentPosition += Size;
OutputStream &operator<<(long long N) {
if (N < 0)
writeUnsigned(static_cast<unsigned long long>(-N), true);
else
writeUnsigned(static_cast<unsigned long long>(N));
return *this;
}
OutputStream &operator<<(unsigned long long N) {
writeUnsigned(N, false);
return *this;
OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
OutputBuffer &operator<<(char C) { return (*this += C); }
OutputBuffer &operator<<(long long N) {
return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
}
OutputStream &operator<<(long N) {
OutputBuffer &operator<<(unsigned long long N) {
return writeUnsigned(N, false);
}
OutputBuffer &operator<<(long N) {
return this->operator<<(static_cast<long long>(N));
}
OutputStream &operator<<(unsigned long N) {
OutputBuffer &operator<<(unsigned long N) {
return this->operator<<(static_cast<unsigned long long>(N));
}
OutputStream &operator<<(int N) {
OutputBuffer &operator<<(int N) {
return this->operator<<(static_cast<long long>(N));
}
OutputStream &operator<<(unsigned int N) {
OutputBuffer &operator<<(unsigned int N) {
return this->operator<<(static_cast<unsigned long long>(N));
}
void insert(size_t Pos, const char *S, size_t N) {
assert(Pos <= CurrentPosition);
if (N == 0)
return;
grow(N);
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
std::memcpy(Buffer + Pos, S, N);
CurrentPosition += N;
}
size_t getCurrentPosition() const { return CurrentPosition; }
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
char back() const {
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
assert(CurrentPosition);
return Buffer[CurrentPosition - 1];
}
bool empty() const { return CurrentPosition == 0; }
char *getBuffer() { return Buffer; }
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
size_t getBufferCapacity() { return BufferCapacity; }
size_t getBufferCapacity() const { return BufferCapacity; }
};
template <class T> class SwapAndRestore {
T &Restore;
T OriginalValue;
bool ShouldRestore = true;
template <class T> class ScopedOverride {
T &Loc;
T Original;
public:
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
SwapAndRestore(T &Restore_, T NewVal)
: Restore(Restore_), OriginalValue(Restore) {
Restore = std::move(NewVal);
}
~SwapAndRestore() {
if (ShouldRestore)
Restore = std::move(OriginalValue);
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
Loc_ = std::move(NewVal);
}
~ScopedOverride() { Loc = std::move(Original); }
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
void restoreNow(bool Force) {
if (!Force && !ShouldRestore)
return;
Restore = std::move(OriginalValue);
ShouldRestore = false;
}
SwapAndRestore(const SwapAndRestore &) = delete;
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
ScopedOverride(const ScopedOverride &) = delete;
ScopedOverride &operator=(const ScopedOverride &) = delete;
};
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
size_t InitSize) {
size_t BufferSize;
if (Buf == nullptr) {
Buf = static_cast<char *>(std::malloc(InitSize));
if (Buf == nullptr)
return false;
BufferSize = InitSize;
} else
BufferSize = *N;
S.reset(Buf, BufferSize);
return true;
}
DEMANGLE_NAMESPACE_END
#endif

View File

@ -12,6 +12,7 @@ import androidx.core.content.res.ResourcesCompat
import androidx.recyclerview.widget.RecyclerView
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
import org.yuzu.yuzu_emu.model.HomeSetting
class HomeSettingAdapter(private val activity: AppCompatActivity, var options: List<HomeSetting>) :
@ -34,7 +35,14 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
override fun onClick(view: View) {
val holder = view.tag as HomeOptionViewHolder
holder.option.onClick.invoke()
if (holder.option.isEnabled.invoke()) {
holder.option.onClick.invoke()
} else {
MessageDialogFragment.newInstance(
holder.option.disabledTitleId,
holder.option.disabledMessageId
).show(activity.supportFragmentManager, MessageDialogFragment.TAG)
}
}
inner class HomeOptionViewHolder(val binding: CardHomeOptionBinding) :
@ -65,6 +73,12 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
R.drawable.premium_background
)
}
if (!option.isEnabled.invoke()) {
binding.optionTitle.alpha = 0.5f
binding.optionDescription.alpha = 0.5f
binding.optionIcon.alpha = 0.5f
}
}
}
}

View File

@ -73,102 +73,113 @@ class HomeSettingsFragment : Fragment() {
HomeSetting(
R.string.advanced_settings,
R.string.settings_description,
R.drawable.ic_settings
) { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
R.drawable.ic_settings,
{ SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
)
)
add(
HomeSetting(
R.string.open_user_folder,
R.string.open_user_folder_description,
R.drawable.ic_folder_open
) { openFileManager() }
R.drawable.ic_folder_open,
{ openFileManager() }
)
)
add(
HomeSetting(
R.string.preferences_theme,
R.string.theme_and_color_description,
R.drawable.ic_palette
) { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
)
if (GpuDriverHelper.supportsCustomDriverLoading()) {
add(
HomeSetting(
R.string.install_gpu_driver,
R.string.install_gpu_driver_description,
R.drawable.ic_exit
) { driverInstaller() }
R.drawable.ic_palette,
{ SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
)
}
)
add(
HomeSetting(
R.string.install_gpu_driver,
R.string.install_gpu_driver_description,
R.drawable.ic_exit,
{ driverInstaller() },
{ GpuDriverHelper.supportsCustomDriverLoading() },
R.string.custom_driver_not_supported,
R.string.custom_driver_not_supported_description
)
)
add(
HomeSetting(
R.string.install_amiibo_keys,
R.string.install_amiibo_keys_description,
R.drawable.ic_nfc
) { mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
R.drawable.ic_nfc,
{ mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
)
)
add(
HomeSetting(
R.string.install_game_content,
R.string.install_game_content_description,
R.drawable.ic_system_update_alt
) { mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
R.drawable.ic_system_update_alt,
{ mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
)
)
add(
HomeSetting(
R.string.select_games_folder,
R.string.select_games_folder_description,
R.drawable.ic_add
) {
mainActivity.getGamesDirectory.launch(
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
)
}
R.drawable.ic_add,
{
mainActivity.getGamesDirectory.launch(
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
)
}
)
)
add(
HomeSetting(
R.string.manage_save_data,
R.string.import_export_saves_description,
R.drawable.ic_save
) {
ImportExportSavesFragment().show(
parentFragmentManager,
ImportExportSavesFragment.TAG
)
}
R.drawable.ic_save,
{
ImportExportSavesFragment().show(
parentFragmentManager,
ImportExportSavesFragment.TAG
)
}
)
)
add(
HomeSetting(
R.string.install_prod_keys,
R.string.install_prod_keys_description,
R.drawable.ic_unlock
) { mainActivity.getProdKey.launch(arrayOf("*/*")) }
R.drawable.ic_unlock,
{ mainActivity.getProdKey.launch(arrayOf("*/*")) }
)
)
add(
HomeSetting(
R.string.install_firmware,
R.string.install_firmware_description,
R.drawable.ic_firmware
) { mainActivity.getFirmware.launch(arrayOf("application/zip")) }
R.drawable.ic_firmware,
{ mainActivity.getFirmware.launch(arrayOf("application/zip")) }
)
)
add(
HomeSetting(
R.string.share_log,
R.string.share_log_description,
R.drawable.ic_log
) { shareLog() }
R.drawable.ic_log,
{ shareLog() }
)
)
add(
HomeSetting(
R.string.about,
R.string.about_description,
R.drawable.ic_info_outline
) {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
parentFragmentManager.primaryNavigationFragment?.findNavController()
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
}
R.drawable.ic_info_outline,
{
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
parentFragmentManager.primaryNavigationFragment?.findNavController()
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
}
)
)
}
@ -178,12 +189,13 @@ class HomeSettingsFragment : Fragment() {
HomeSetting(
R.string.get_early_access,
R.string.get_early_access_description,
R.drawable.ic_diamond
) {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
parentFragmentManager.primaryNavigationFragment?.findNavController()
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
}
R.drawable.ic_diamond,
{
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
parentFragmentManager.primaryNavigationFragment?.findNavController()
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
}
)
)
}

View File

@ -7,5 +7,8 @@ data class HomeSetting(
val titleId: Int,
val descriptionId: Int,
val iconId: Int,
val onClick: () -> Unit
val onClick: () -> Unit,
val isEnabled: () -> Boolean = { true },
val disabledTitleId: Int = 0,
val disabledMessageId: Int = 0
)

View File

@ -113,6 +113,8 @@
<string name="install_game_content_success_install">%1$d installed successfully</string>
<string name="install_game_content_success_overwrite">%1$d overwritten successfully</string>
<string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
<string name="custom_driver_not_supported">Custom drivers not supported</string>
<string name="custom_driver_not_supported_description">Custom driver loading isn\'t currently supported for this device.\nCheck this option again in the future to see if support was added!</string>
<!-- About screen strings -->
<string name="gaia_is_not_real">Gaia isn\'t real</string>
@ -230,7 +232,7 @@
<!-- ROM loading errors -->
<string name="loader_error_encrypted">Your ROM is encrypted</string>
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop">installed titles</a>.]]></string>
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop">installed titles</a>.]]></string>
<string name="loader_error_encrypted_keys_description"><![CDATA[Please ensure your <a href="https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys">prod.keys</a> file is installed so that games can be decrypted.]]></string>
<string name="loader_error_video_core">An error occurred initializing the video core</string>
<string name="loader_error_video_core_description">This is usually caused by an incompatible GPU driver. Installing a custom GPU driver may resolve this problem.</string>

View File

@ -23,7 +23,7 @@ std::string DemangleSymbol(const std::string& mangled) {
SCOPE_EXIT({ std::free(demangled); });
if (is_itanium(mangled)) {
demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr);
demangled = llvm::itaniumDemangle(mangled.c_str());
}
if (!demangled) {

View File

@ -30,8 +30,8 @@ DetachedTasks::~DetachedTasks() {
void DetachedTasks::AddTask(std::function<void()> task) {
std::unique_lock lock{instance->mutex};
++instance->count;
std::thread([task{std::move(task)}]() {
task();
std::thread([task_{std::move(task)}]() {
task_();
std::unique_lock thread_lock{instance->mutex};
--instance->count;
std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));

View File

@ -3,9 +3,10 @@
#pragma once
#include "common/common_types.h"
#include <optional>
#include <string>
#include "common/common_types.h"
namespace Network {

View File

@ -285,6 +285,7 @@ add_library(core STATIC
hle/kernel/kernel.cpp
hle/kernel/kernel.h
hle/kernel/memory_types.h
hle/kernel/message_buffer.h
hle/kernel/physical_core.cpp
hle/kernel/physical_core.h
hle/kernel/physical_memory.h
@ -875,7 +876,7 @@ elseif (APPLE)
elseif (WIN32)
target_sources(core PRIVATE
hle/service/ssl/ssl_backend_schannel.cpp)
target_link_libraries(core PRIVATE secur32)
target_link_libraries(core PRIVATE crypt32 secur32)
else()
target_sources(core PRIVATE
hle/service/ssl/ssl_backend_none.cpp)

View File

@ -20,12 +20,132 @@
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/message_buffer.h"
#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/memory.h"
namespace Kernel {
namespace {
template <bool MoveHandleAllowed>
Result ProcessMessageSpecialData(KProcess& dst_process, KProcess& src_process, KThread& src_thread,
MessageBuffer& dst_msg, const MessageBuffer& src_msg,
MessageBuffer::SpecialHeader& src_special_header) {
// Copy the special header to the destination.
s32 offset = dst_msg.Set(src_special_header);
// Copy the process ID.
if (src_special_header.GetHasProcessId()) {
offset = dst_msg.SetProcessId(offset, src_process.GetProcessId());
}
// Prepare to process handles.
auto& dst_handle_table = dst_process.GetHandleTable();
auto& src_handle_table = src_process.GetHandleTable();
Result result = ResultSuccess;
// Process copy handles.
for (auto i = 0; i < src_special_header.GetCopyHandleCount(); ++i) {
// Get the handles.
const Handle src_handle = src_msg.GetHandle(offset);
Handle dst_handle = Svc::InvalidHandle;
// If we're in a success state, try to move the handle to the new table.
if (R_SUCCEEDED(result) && src_handle != Svc::InvalidHandle) {
KScopedAutoObject obj =
src_handle_table.GetObjectForIpc(src_handle, std::addressof(src_thread));
if (obj.IsNotNull()) {
Result add_result =
dst_handle_table.Add(std::addressof(dst_handle), obj.GetPointerUnsafe());
if (R_FAILED(add_result)) {
result = add_result;
dst_handle = Svc::InvalidHandle;
}
} else {
result = ResultInvalidHandle;
}
}
// Set the handle.
offset = dst_msg.SetHandle(offset, dst_handle);
}
// Process move handles.
if constexpr (MoveHandleAllowed) {
for (auto i = 0; i < src_special_header.GetMoveHandleCount(); ++i) {
// Get the handles.
const Handle src_handle = src_msg.GetHandle(offset);
Handle dst_handle = Svc::InvalidHandle;
// Whether or not we've succeeded, we need to remove the handles from the source table.
if (src_handle != Svc::InvalidHandle) {
if (R_SUCCEEDED(result)) {
KScopedAutoObject obj =
src_handle_table.GetObjectForIpcWithoutPseudoHandle(src_handle);
if (obj.IsNotNull()) {
Result add_result = dst_handle_table.Add(std::addressof(dst_handle),
obj.GetPointerUnsafe());
src_handle_table.Remove(src_handle);
if (R_FAILED(add_result)) {
result = add_result;
dst_handle = Svc::InvalidHandle;
}
} else {
result = ResultInvalidHandle;
}
} else {
src_handle_table.Remove(src_handle);
}
}
// Set the handle.
offset = dst_msg.SetHandle(offset, dst_handle);
}
}
R_RETURN(result);
}
void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) {
// Parse the message.
const MessageBuffer dst_msg(dst_msg_ptr, dst_buffer_size);
const MessageBuffer::MessageHeader dst_header(dst_msg);
const MessageBuffer::SpecialHeader dst_special_header(dst_msg, dst_header);
// Check that the size is big enough.
if (MessageBuffer::GetMessageBufferSize(dst_header, dst_special_header) > dst_buffer_size) {
return;
}
// Set the special header.
int offset = dst_msg.Set(dst_special_header);
// Clear the process id, if needed.
if (dst_special_header.GetHasProcessId()) {
offset = dst_msg.SetProcessId(offset, 0);
}
// Clear handles, as relevant.
auto& dst_handle_table = dst_process.GetHandleTable();
for (auto i = 0;
i < (dst_special_header.GetCopyHandleCount() + dst_special_header.GetMoveHandleCount());
++i) {
const Handle handle = dst_msg.GetHandle(offset);
if (handle != Svc::InvalidHandle) {
dst_handle_table.Remove(handle);
}
offset = dst_msg.SetHandle(offset, Svc::InvalidHandle);
}
}
} // namespace
using ThreadQueueImplForKServerSessionRequest = KThreadQueue;
KServerSession::KServerSession(KernelCore& kernel)
@ -223,12 +343,27 @@ Result KServerSession::SendReply(bool is_hle) {
// the reply has already been written in this case.
} else {
Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
KThread* server_thread = GetCurrentThreadPointer(m_kernel);
KProcess& src_process = *client_thread->GetOwnerProcess();
KProcess& dst_process = *server_thread->GetOwnerProcess();
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
auto* src_msg_buffer = memory.GetPointer(server_thread->GetTlsAddress());
auto* dst_msg_buffer = memory.GetPointer(client_message);
auto* src_msg_buffer = memory.GetPointer<u32>(server_thread->GetTlsAddress());
auto* dst_msg_buffer = memory.GetPointer<u32>(client_message);
std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
// Translate special header ad-hoc.
MessageBuffer src_msg(src_msg_buffer, client_buffer_size);
MessageBuffer::MessageHeader src_header(src_msg);
MessageBuffer::SpecialHeader src_special_header(src_msg, src_header);
if (src_header.GetHasSpecialHeader()) {
MessageBuffer dst_msg(dst_msg_buffer, client_buffer_size);
result = ProcessMessageSpecialData<true>(dst_process, src_process, *server_thread,
dst_msg, src_msg, src_special_header);
if (R_FAILED(result)) {
CleanupSpecialData(dst_process, dst_msg_buffer, client_buffer_size);
}
}
}
} else {
result = ResultSessionClosed;
@ -330,12 +465,28 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
->PopulateFromIncomingCommandBuffer(client_thread->GetOwnerProcess()->GetHandleTable(),
cmd_buf);
} else {
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
KThread* server_thread = GetCurrentThreadPointer(m_kernel);
KProcess& src_process = *client_thread->GetOwnerProcess();
KProcess& dst_process = *server_thread->GetOwnerProcess();
UNIMPLEMENTED_IF(client_thread->GetOwnerProcess() != server_thread->GetOwnerProcess());
auto* src_msg_buffer = memory.GetPointer(client_message);
auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTlsAddress());
auto* src_msg_buffer = memory.GetPointer<u32>(client_message);
auto* dst_msg_buffer = memory.GetPointer<u32>(server_thread->GetTlsAddress());
std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
// Translate special header ad-hoc.
// TODO: fix this mess
MessageBuffer src_msg(src_msg_buffer, client_buffer_size);
MessageBuffer::MessageHeader src_header(src_msg);
MessageBuffer::SpecialHeader src_special_header(src_msg, src_header);
if (src_header.GetHasSpecialHeader()) {
MessageBuffer dst_msg(dst_msg_buffer, client_buffer_size);
Result res = ProcessMessageSpecialData<false>(dst_process, src_process, *client_thread,
dst_msg, src_msg, src_special_header);
if (R_FAILED(res)) {
CleanupSpecialData(dst_process, dst_msg_buffer, client_buffer_size);
}
}
}
// We succeeded.

View File

@ -302,12 +302,12 @@ Result KThread::InitializeServiceThread(Core::System& system, KThread* thread,
std::function<void()>&& func, s32 prio, s32 virt_core,
KProcess* owner) {
system.Kernel().GlobalSchedulerContext().AddThread(thread);
std::function<void()> func2{[&system, func{std::move(func)}] {
std::function<void()> func2{[&system, func_{std::move(func)}] {
// Similar to UserModeThreadStarter.
system.Kernel().CurrentScheduler()->OnThreadStart();
// Run the guest function.
func();
func_();
// Exit.
Svc::ExitThread(system);

View File

@ -1089,15 +1089,15 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
KThread::Register(kernel, thread);
return std::jthread(
[&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] {
[&kernel, thread, thread_name_{std::move(thread_name)}, func_{std::move(func)}] {
// Set the thread name.
Common::SetCurrentThreadName(thread_name.c_str());
Common::SetCurrentThreadName(thread_name_.c_str());
// Set the thread as current.
kernel.RegisterHostThread(thread);
// Run the callback.
func();
func_();
// Close the thread.
// This will free the process if it is the last reference.

View File

@ -0,0 +1,612 @@
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/alignment.h"
#include "common/bit_field.h"
#include "core/hle/kernel/k_thread.h"
namespace Kernel {
constexpr inline size_t MessageBufferSize = 0x100;
class MessageBuffer {
public:
class MessageHeader {
private:
static constexpr inline u64 NullTag = 0;
public:
enum class ReceiveListCountType : u32 {
None = 0,
ToMessageBuffer = 1,
ToSingleBuffer = 2,
CountOffset = 2,
CountMax = 13,
};
private:
union {
std::array<u32, 2> raw;
struct {
// Define fields for the first header word.
union {
BitField<0, 16, u16> tag;
BitField<16, 4, u32> pointer_count;
BitField<20, 4, u32> send_count;
BitField<24, 4, u32> receive_count;
BitField<28, 4, u32> exchange_count;
};
// Define fields for the second header word.
union {
BitField<0, 10, u32> raw_count;
BitField<10, 4, ReceiveListCountType> receive_list_count;
BitField<14, 6, u32> reserved0;
BitField<20, 11, u32> receive_list_offset;
BitField<31, 1, u32> has_special_header;
};
};
} m_header;
public:
constexpr MessageHeader() : m_header{} {}
constexpr MessageHeader(u16 tag, bool special, s32 ptr, s32 send, s32 recv, s32 exch,
s32 raw, ReceiveListCountType recv_list)
: m_header{} {
m_header.raw[0] = 0;
m_header.raw[1] = 0;
m_header.tag.Assign(tag);
m_header.pointer_count.Assign(ptr);
m_header.send_count.Assign(send);
m_header.receive_count.Assign(recv);
m_header.exchange_count.Assign(exch);
m_header.raw_count.Assign(raw);
m_header.receive_list_count.Assign(recv_list);
m_header.has_special_header.Assign(special);
}
explicit MessageHeader(const MessageBuffer& buf) : m_header{} {
buf.Get(0, m_header.raw.data(), 2);
}
explicit MessageHeader(const u32* msg) : m_header{{msg[0], msg[1]}} {}
constexpr u16 GetTag() const {
return m_header.tag;
}
constexpr s32 GetPointerCount() const {
return m_header.pointer_count;
}
constexpr s32 GetSendCount() const {
return m_header.send_count;
}
constexpr s32 GetReceiveCount() const {
return m_header.receive_count;
}
constexpr s32 GetExchangeCount() const {
return m_header.exchange_count;
}
constexpr s32 GetMapAliasCount() const {
return this->GetSendCount() + this->GetReceiveCount() + this->GetExchangeCount();
}
constexpr s32 GetRawCount() const {
return m_header.raw_count;
}
constexpr ReceiveListCountType GetReceiveListCount() const {
return m_header.receive_list_count;
}
constexpr s32 GetReceiveListOffset() const {
return m_header.receive_list_offset;
}
constexpr bool GetHasSpecialHeader() const {
return m_header.has_special_header.Value() != 0;
}
constexpr void SetReceiveListCount(ReceiveListCountType recv_list) {
m_header.receive_list_count.Assign(recv_list);
}
constexpr const u32* GetData() const {
return m_header.raw.data();
}
static constexpr size_t GetDataSize() {
return sizeof(m_header);
}
};
class SpecialHeader {
private:
union {
std::array<u32, 1> raw;
// Define fields for the header word.
BitField<0, 1, u32> has_process_id;
BitField<1, 4, u32> copy_handle_count;
BitField<5, 4, u32> move_handle_count;
} m_header;
bool m_has_header;
public:
constexpr explicit SpecialHeader(bool pid, s32 copy, s32 move)
: m_header{}, m_has_header(true) {
m_header.has_process_id.Assign(pid);
m_header.copy_handle_count.Assign(copy);
m_header.move_handle_count.Assign(move);
}
constexpr explicit SpecialHeader(bool pid, s32 copy, s32 move, bool _has_header)
: m_header{}, m_has_header(_has_header) {
m_header.has_process_id.Assign(pid);
m_header.copy_handle_count.Assign(copy);
m_header.move_handle_count.Assign(move);
}
explicit SpecialHeader(const MessageBuffer& buf, const MessageHeader& hdr)
: m_header{}, m_has_header(hdr.GetHasSpecialHeader()) {
if (m_has_header) {
buf.Get(static_cast<s32>(MessageHeader::GetDataSize() / sizeof(u32)),
m_header.raw.data(), sizeof(m_header) / sizeof(u32));
}
}
constexpr bool GetHasProcessId() const {
return m_header.has_process_id.Value() != 0;
}
constexpr s32 GetCopyHandleCount() const {
return m_header.copy_handle_count;
}
constexpr s32 GetMoveHandleCount() const {
return m_header.move_handle_count;
}
constexpr const u32* GetHeader() const {
return m_header.raw.data();
}
constexpr size_t GetHeaderSize() const {
if (m_has_header) {
return sizeof(m_header);
} else {
return 0;
}
}
constexpr size_t GetDataSize() const {
if (m_has_header) {
return (this->GetHasProcessId() ? sizeof(u64) : 0) +
(this->GetCopyHandleCount() * sizeof(Handle)) +
(this->GetMoveHandleCount() * sizeof(Handle));
} else {
return 0;
}
}
};
class MapAliasDescriptor {
public:
enum class Attribute : u32 {
Ipc = 0,
NonSecureIpc = 1,
NonDeviceIpc = 3,
};
private:
static constexpr u32 SizeLowCount = 32;
static constexpr u32 SizeHighCount = 4;
static constexpr u32 AddressLowCount = 32;
static constexpr u32 AddressMidCount = 4;
constexpr u32 GetAddressMid(u64 address) {
return static_cast<u32>(address >> AddressLowCount) & ((1U << AddressMidCount) - 1);
}
constexpr u32 GetAddressHigh(u64 address) {
return static_cast<u32>(address >> (AddressLowCount + AddressMidCount));
}
private:
union {
std::array<u32, 3> raw;
struct {
// Define fields for the first two words.
u32 size_low;
u32 address_low;
// Define fields for the packed descriptor word.
union {
BitField<0, 2, Attribute> attributes;
BitField<2, 3, u32> address_high;
BitField<5, 19, u32> reserved;
BitField<24, 4, u32> size_high;
BitField<28, 4, u32> address_mid;
};
};
} m_data;
public:
constexpr MapAliasDescriptor() : m_data{} {}
MapAliasDescriptor(const void* buffer, size_t _size, Attribute attr = Attribute::Ipc)
: m_data{} {
const u64 address = reinterpret_cast<u64>(buffer);
const u64 size = static_cast<u64>(_size);
m_data.size_low = static_cast<u32>(size);
m_data.address_low = static_cast<u32>(address);
m_data.attributes.Assign(attr);
m_data.address_mid.Assign(GetAddressMid(address));
m_data.size_high.Assign(static_cast<u32>(size >> SizeLowCount));
m_data.address_high.Assign(GetAddressHigh(address));
}
MapAliasDescriptor(const MessageBuffer& buf, s32 index) : m_data{} {
buf.Get(index, m_data.raw.data(), 3);
}
constexpr uintptr_t GetAddress() const {
return (static_cast<u64>((m_data.address_high << AddressMidCount) | m_data.address_mid)
<< AddressLowCount) |
m_data.address_low;
}
constexpr uintptr_t GetSize() const {
return (static_cast<u64>(m_data.size_high) << SizeLowCount) | m_data.size_low;
}
constexpr Attribute GetAttribute() const {
return m_data.attributes;
}
constexpr const u32* GetData() const {
return m_data.raw.data();
}
static constexpr size_t GetDataSize() {
return sizeof(m_data);
}
};
class PointerDescriptor {
private:
static constexpr u32 AddressLowCount = 32;
static constexpr u32 AddressMidCount = 4;
constexpr u32 GetAddressMid(u64 address) {
return static_cast<u32>(address >> AddressLowCount) & ((1u << AddressMidCount) - 1);
}
constexpr u32 GetAddressHigh(u64 address) {
return static_cast<u32>(address >> (AddressLowCount + AddressMidCount));
}
private:
union {
std::array<u32, 2> raw;
struct {
// Define fields for the packed descriptor word.
union {
BitField<0, 4, u32> index;
BitField<4, 2, u32> reserved0;
BitField<6, 3, u32> address_high;
BitField<9, 3, u32> reserved1;
BitField<12, 4, u32> address_mid;
BitField<16, 16, u32> size;
};
// Define fields for the second word.
u32 address_low;
};
} m_data;
public:
constexpr PointerDescriptor() : m_data{} {}
PointerDescriptor(const void* buffer, size_t size, s32 index) : m_data{} {
const u64 address = reinterpret_cast<u64>(buffer);
m_data.index.Assign(index);
m_data.address_high.Assign(GetAddressHigh(address));
m_data.address_mid.Assign(GetAddressMid(address));
m_data.size.Assign(static_cast<u32>(size));
m_data.address_low = static_cast<u32>(address);
}
PointerDescriptor(const MessageBuffer& buf, s32 index) : m_data{} {
buf.Get(index, m_data.raw.data(), 2);
}
constexpr s32 GetIndex() const {
return m_data.index;
}
constexpr uintptr_t GetAddress() const {
return (static_cast<u64>((m_data.address_high << AddressMidCount) | m_data.address_mid)
<< AddressLowCount) |
m_data.address_low;
}
constexpr size_t GetSize() const {
return m_data.size;
}
constexpr const u32* GetData() const {
return m_data.raw.data();
}
static constexpr size_t GetDataSize() {
return sizeof(m_data);
}
};
class ReceiveListEntry {
private:
static constexpr u32 AddressLowCount = 32;
constexpr u32 GetAddressHigh(u64 address) {
return static_cast<u32>(address >> (AddressLowCount));
}
private:
union {
std::array<u32, 2> raw;
struct {
// Define fields for the first word.
u32 address_low;
// Define fields for the packed descriptor word.
union {
BitField<0, 7, u32> address_high;
BitField<7, 9, u32> reserved;
BitField<16, 16, u32> size;
};
};
} m_data;
public:
constexpr ReceiveListEntry() : m_data{} {}
ReceiveListEntry(const void* buffer, size_t size) : m_data{} {
const u64 address = reinterpret_cast<u64>(buffer);
m_data.address_low = static_cast<u32>(address);
m_data.address_high.Assign(GetAddressHigh(address));
m_data.size.Assign(static_cast<u32>(size));
}
ReceiveListEntry(u32 a, u32 b) : m_data{{a, b}} {}
constexpr uintptr_t GetAddress() const {
return (static_cast<u64>(m_data.address_high) << AddressLowCount) | m_data.address_low;
}
constexpr size_t GetSize() const {
return m_data.size;
}
constexpr const u32* GetData() const {
return m_data.raw.data();
}
static constexpr size_t GetDataSize() {
return sizeof(m_data);
}
};
private:
u32* m_buffer;
size_t m_size;
public:
constexpr MessageBuffer(u32* b, size_t sz) : m_buffer(b), m_size(sz) {}
constexpr explicit MessageBuffer(u32* b) : m_buffer(b), m_size(MessageBufferSize) {}
constexpr void* GetBufferForDebug() const {
return m_buffer;
}
constexpr size_t GetBufferSize() const {
return m_size;
}
void Get(s32 index, u32* dst, size_t count) const {
// Ensure that this doesn't get re-ordered.
std::atomic_thread_fence(std::memory_order_seq_cst);
// Get the words.
static_assert(sizeof(*dst) == sizeof(*m_buffer));
memcpy(dst, m_buffer + index, count * sizeof(*dst));
}
s32 Set(s32 index, u32* src, size_t count) const {
// Ensure that this doesn't get re-ordered.
std::atomic_thread_fence(std::memory_order_seq_cst);
// Set the words.
memcpy(m_buffer + index, src, count * sizeof(*src));
// Ensure that this doesn't get re-ordered.
std::atomic_thread_fence(std::memory_order_seq_cst);
return static_cast<s32>(index + count);
}
template <typename T>
const T& GetRaw(s32 index) const {
return *reinterpret_cast<const T*>(m_buffer + index);
}
template <typename T>
s32 SetRaw(s32 index, const T& val) const {
*reinterpret_cast<const T*>(m_buffer + index) = val;
return index + (Common::AlignUp(sizeof(val), sizeof(*m_buffer)) / sizeof(*m_buffer));
}
void GetRawArray(s32 index, void* dst, size_t len) const {
memcpy(dst, m_buffer + index, len);
}
void SetRawArray(s32 index, const void* src, size_t len) const {
memcpy(m_buffer + index, src, len);
}
void SetNull() const {
this->Set(MessageHeader());
}
s32 Set(const MessageHeader& hdr) const {
memcpy(m_buffer, hdr.GetData(), hdr.GetDataSize());
return static_cast<s32>(hdr.GetDataSize() / sizeof(*m_buffer));
}
s32 Set(const SpecialHeader& spc) const {
const s32 index = static_cast<s32>(MessageHeader::GetDataSize() / sizeof(*m_buffer));
memcpy(m_buffer + index, spc.GetHeader(), spc.GetHeaderSize());
return static_cast<s32>(index + (spc.GetHeaderSize() / sizeof(*m_buffer)));
}
s32 SetHandle(s32 index, const Handle& hnd) const {
memcpy(m_buffer + index, std::addressof(hnd), sizeof(hnd));
return static_cast<s32>(index + (sizeof(hnd) / sizeof(*m_buffer)));
}
s32 SetProcessId(s32 index, const u64 pid) const {
memcpy(m_buffer + index, std::addressof(pid), sizeof(pid));
return static_cast<s32>(index + (sizeof(pid) / sizeof(*m_buffer)));
}
s32 Set(s32 index, const MapAliasDescriptor& desc) const {
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
}
s32 Set(s32 index, const PointerDescriptor& desc) const {
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
}
s32 Set(s32 index, const ReceiveListEntry& desc) const {
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
}
s32 Set(s32 index, const u32 val) const {
memcpy(m_buffer + index, std::addressof(val), sizeof(val));
return static_cast<s32>(index + (sizeof(val) / sizeof(*m_buffer)));
}
Result GetAsyncResult() const {
MessageHeader hdr(m_buffer);
MessageHeader null{};
if (memcmp(hdr.GetData(), null.GetData(), MessageHeader::GetDataSize()) != 0) [[unlikely]] {
R_SUCCEED();
}
return Result(m_buffer[MessageHeader::GetDataSize() / sizeof(*m_buffer)]);
}
void SetAsyncResult(Result res) const {
const s32 index = this->Set(MessageHeader());
const auto value = res.raw;
memcpy(m_buffer + index, std::addressof(value), sizeof(value));
}
u32 Get32(s32 index) const {
return m_buffer[index];
}
u64 Get64(s32 index) const {
u64 value;
memcpy(std::addressof(value), m_buffer + index, sizeof(value));
return value;
}
u64 GetProcessId(s32 index) const {
return this->Get64(index);
}
Handle GetHandle(s32 index) const {
static_assert(sizeof(Handle) == sizeof(*m_buffer));
return Handle(m_buffer[index]);
}
static constexpr s32 GetSpecialDataIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
return static_cast<s32>((MessageHeader::GetDataSize() / sizeof(u32)) +
(spc.GetHeaderSize() / sizeof(u32)));
}
static constexpr s32 GetPointerDescriptorIndex(const MessageHeader& hdr,
const SpecialHeader& spc) {
return static_cast<s32>(GetSpecialDataIndex(hdr, spc) + (spc.GetDataSize() / sizeof(u32)));
}
static constexpr s32 GetMapAliasDescriptorIndex(const MessageHeader& hdr,
const SpecialHeader& spc) {
return GetPointerDescriptorIndex(hdr, spc) +
static_cast<s32>(hdr.GetPointerCount() * PointerDescriptor::GetDataSize() /
sizeof(u32));
}
static constexpr s32 GetRawDataIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
return GetMapAliasDescriptorIndex(hdr, spc) +
static_cast<s32>(hdr.GetMapAliasCount() * MapAliasDescriptor::GetDataSize() /
sizeof(u32));
}
static constexpr s32 GetReceiveListIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
if (const s32 recv_list_index = hdr.GetReceiveListOffset()) {
return recv_list_index;
} else {
return GetRawDataIndex(hdr, spc) + hdr.GetRawCount();
}
}
static constexpr size_t GetMessageBufferSize(const MessageHeader& hdr,
const SpecialHeader& spc) {
// Get the size of the plain message.
size_t msg_size = GetReceiveListIndex(hdr, spc) * sizeof(u32);
// Add the size of the receive list.
const auto count = hdr.GetReceiveListCount();
switch (count) {
case MessageHeader::ReceiveListCountType::None:
break;
case MessageHeader::ReceiveListCountType::ToMessageBuffer:
break;
case MessageHeader::ReceiveListCountType::ToSingleBuffer:
msg_size += ReceiveListEntry::GetDataSize();
break;
default:
msg_size += (static_cast<s32>(count) -
static_cast<s32>(MessageHeader::ReceiveListCountType::CountOffset)) *
ReceiveListEntry::GetDataSize();
break;
}
return msg_size;
}
};
} // namespace Kernel

View File

@ -506,8 +506,8 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
idle_time_detection_extension = rp.Pop<u32>();
LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
idle_time_detection_extension);
LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
idle_time_detection_extension);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);

View File

@ -7,6 +7,7 @@
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/server_manager.h"
#include "network/network.h"
namespace {

View File

@ -4,14 +4,15 @@
#pragma once
#include "core/hle/service/service.h"
#include "network/network.h"
#include "network/room.h"
#include "network/room_member.h"
namespace Core {
class System;
}
namespace Network {
class RoomNetwork;
}
namespace Service::NIFM {
void LoopProcess(Core::System& system);

View File

@ -3,15 +3,15 @@
#pragma once
#include "core/hle/result.h"
#include "common/common_types.h"
#include <memory>
#include <span>
#include <string>
#include <vector>
#include "common/common_types.h"
#include "core/hle/result.h"
namespace Network {
class SocketBase;
}

View File

@ -1,10 +1,10 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ssl/ssl_backend.h"
#include "common/logging/log.h"
#include "core/hle/service/ssl/ssl_backend.h"
namespace Service::SSL {
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {

View File

@ -1,14 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
#include "common/fs/file.h"
#include "common/hex_util.h"
#include "common/string_util.h"
#include <mutex>
#include <openssl/bio.h>
@ -16,6 +8,14 @@
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include "common/fs/file.h"
#include "common/hex_util.h"
#include "common/string_util.h"
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
using namespace Common::FS;
namespace Service::SSL {

View File

@ -1,16 +1,16 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
#include <mutex>
#include "common/error.h"
#include "common/fs/file.h"
#include "common/hex_util.h"
#include "common/string_util.h"
#include <mutex>
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
namespace {
@ -20,6 +20,7 @@ namespace {
#define SECURITY_WIN32
#include <schnlsp.h>
#include <security.h>
#include <wincrypt.h>
std::once_flag one_time_init_flag;
bool one_time_init_success = false;

View File

@ -1,18 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
#include <mutex>
#include <Security/SecureTransport.h>
// SecureTransport has been deprecated in its entirety in favor of
// Network.framework, but that does not allow layering TLS on top of an
// arbitrary socket.
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include <Security/SecureTransport.h>
#pragma GCC diagnostic pop
#endif
#include "core/hle/service/ssl/ssl_backend.h"
#include "core/internal_network/network.h"
#include "core/internal_network/sockets.h"
namespace {

View File

@ -10,6 +10,7 @@
#include "core/internal_network/network.h"
#include "core/internal_network/network_interface.h"
#include "core/internal_network/socket_proxy.h"
#include "network/network.h"
#if YUZU_UNIX
#include <sys/socket.h>

View File

@ -10,10 +10,12 @@
#include "common/common_funcs.h"
#include "core/internal_network/sockets.h"
#include "network/network.h"
#include "network/room_member.h"
namespace Network {
class RoomNetwork;
class ProxySocket : public SocketBase {
public:
explicit ProxySocket(RoomNetwork& room_network_) noexcept;

View File

@ -15,12 +15,13 @@
#include "common/common_types.h"
#include "core/internal_network/network.h"
#include "network/network.h"
// TODO: C++20 Replace std::vector usages with std::span
namespace Network {
struct ProxyPacket;
class SocketBase {
public:
#ifdef YUZU_UNIX

View File

@ -274,6 +274,7 @@ add_library(video_core STATIC
vulkan_common/vulkan_wrapper.h
vulkan_common/nsight_aftermath_tracker.cpp
vulkan_common/nsight_aftermath_tracker.h
vulkan_common/vma.cpp
)
create_target_directory_groups(video_core)
@ -291,7 +292,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
add_dependencies(video_core host_shaders)
target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers vma)
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
if (ENABLE_NSIGHT_AFTERMATH)
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
@ -324,6 +325,9 @@ else()
# xbyak
set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow")
# VMA
set_source_files_properties(vulkan_common/vma.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers")
endif()
if (ARCHITECTURE_x86_64)

View File

@ -442,6 +442,11 @@ void BufferCache<P>::UnbindComputeStorageBuffers() {
template <class P>
void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
bool is_written) {
if (ssbo_index >= channel_state->compute_storage_buffers.size()) [[unlikely]] {
LOG_ERROR(HW_GPU, "Storage buffer index {} exceeds maximum storage buffer count",
ssbo_index);
return;
}
channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index;
channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
@ -464,6 +469,11 @@ void BufferCache<P>::UnbindComputeTextureBuffers() {
template <class P>
void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
PixelFormat format, bool is_written, bool is_image) {
if (tbo_index >= channel_state->compute_texture_buffers.size()) [[unlikely]] {
LOG_ERROR(HW_GPU, "Texture buffer index {} exceeds maximum texture buffer count",
tbo_index);
return;
}
channel_state->enabled_compute_texture_buffers |= 1U << tbo_index;
channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {

View File

@ -67,7 +67,7 @@ constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
constexpr u32 NUM_STORAGE_BUFFERS = 16;
constexpr u32 NUM_TEXTURE_BUFFERS = 16;
constexpr u32 NUM_TEXTURE_BUFFERS = 32;
constexpr u32 NUM_STAGES = 5;
using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;

View File

@ -38,8 +38,8 @@ void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callb
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
return;
}
auto async_callback{[callback = std::move(callback)](bool invert_y) {
std::thread t{callback, invert_y};
auto async_callback{[callback_ = std::move(callback)](bool invert_y) {
std::thread t{callback_, invert_y};
t.detach();
}};
renderer_settings.screenshot_bits = data;

View File

@ -231,24 +231,25 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
}
const bool in_parallel = thread_worker != nullptr;
const auto backend = device.GetShaderBackend();
auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv),
auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
shader_notify, backend, in_parallel,
force_context_flush](ShaderContext::Context*) mutable {
for (size_t stage = 0; stage < 5; ++stage) {
switch (backend) {
case Settings::ShaderBackend::GLSL:
if (!sources[stage].empty()) {
source_programs[stage] = CreateProgram(sources[stage], Stage(stage));
if (!sources_[stage].empty()) {
source_programs[stage] = CreateProgram(sources_[stage], Stage(stage));
}
break;
case Settings::ShaderBackend::GLASM:
if (!sources[stage].empty()) {
assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage));
if (!sources_[stage].empty()) {
assembly_programs[stage] =
CompileProgram(sources_[stage], AssemblyStage(stage));
}
break;
case Settings::ShaderBackend::SPIRV:
if (!sources_spirv[stage].empty()) {
source_programs[stage] = CreateProgram(sources_spirv[stage], Stage(stage));
if (!sources_spirv_[stage].empty()) {
source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage));
}
break;
}

View File

@ -288,9 +288,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
ComputePipelineKey key;
file.read(reinterpret_cast<char*>(&key), sizeof(key));
queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
queue_work([this, key, env_ = std::move(env), &state, &callback](Context* ctx) mutable {
ctx->pools.ReleaseContents();
auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)};
auto pipeline{CreateComputePipeline(ctx->pools, key, env_, true)};
std::scoped_lock lock{state.mutex};
if (pipeline) {
compute_cache.emplace(key, std::move(pipeline));
@ -305,9 +305,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
GraphicsPipelineKey key;
file.read(reinterpret_cast<char*>(&key), sizeof(key));
queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
queue_work([this, key, envs_ = std::move(envs), &state, &callback](Context* ctx) mutable {
boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
for (auto& env : envs) {
for (auto& env : envs_) {
env_ptrs.push_back(&env);
}
ctx->pools.ReleaseContents();

View File

@ -206,8 +206,8 @@ public:
const size_t sub_first_offset = static_cast<size_t>(first % 4) * GetQuadsNum(num_indices);
const size_t offset =
(sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type);
scheduler.Record([buffer = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) {
cmdbuf.BindIndexBuffer(buffer, offset, index_type_);
scheduler.Record([buffer_ = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) {
cmdbuf.BindIndexBuffer(buffer_, offset, index_type_);
});
}
@ -528,17 +528,18 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
buffer_handles.push_back(handle);
}
if (device.IsExtExtendedDynamicStateSupported()) {
scheduler.Record([bindings = std::move(bindings),
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers2EXT(
bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
bindings.offsets.data(), bindings.sizes.data(), bindings.strides.data());
scheduler.Record([bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers2EXT(bindings_.min_index,
bindings_.max_index - bindings_.min_index,
buffer_handles_.data(), bindings_.offsets.data(),
bindings_.sizes.data(), bindings_.strides.data());
});
} else {
scheduler.Record([bindings = std::move(bindings),
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers(bindings.min_index, bindings.max_index - bindings.min_index,
buffer_handles.data(), bindings.offsets.data());
scheduler.Record([bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers(bindings_.min_index, bindings_.max_index - bindings_.min_index,
buffer_handles_.data(), bindings_.offsets.data());
});
}
}
@ -573,11 +574,11 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<
for (u32 index = 0; index < bindings.buffers.size(); ++index) {
buffer_handles.push_back(bindings.buffers[index]->Handle());
}
scheduler.Record([bindings = std::move(bindings),
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles.size()),
buffer_handles.data(), bindings.offsets.data(),
bindings.sizes.data());
scheduler.Record([bindings_ = std::move(bindings),
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles_.size()),
buffer_handles_.data(), bindings_.offsets.data(),
bindings_.sizes.data());
});
}

View File

@ -469,9 +469,9 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
ComputePipelineCacheKey key;
file.read(reinterpret_cast<char*>(&key), sizeof(key));
workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable {
workers.QueueWork([this, key, env_ = std::move(env), &state, &callback]() mutable {
ShaderPools pools;
auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)};
auto pipeline{CreateComputePipeline(pools, key, env_, state.statistics.get(), false)};
std::scoped_lock lock{state.mutex};
if (pipeline) {
compute_cache.emplace(key, std::move(pipeline));
@ -500,10 +500,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
(key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
return;
}
workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable {
workers.QueueWork([this, key, envs_ = std::move(envs), &state, &callback]() mutable {
ShaderPools pools;
boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
for (auto& env : envs) {
for (auto& env : envs_) {
env_ptrs.push_back(&env);
}
auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs),
@ -702,8 +702,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
if (!pipeline || pipeline_cache_filename.empty()) {
return pipeline;
}
serialization_thread.QueueWork([this, key, env = std::move(env)] {
SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
serialization_thread.QueueWork([this, key, env_ = std::move(env)] {
SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env_},
pipeline_cache_filename, CACHE_VERSION);
});
return pipeline;

View File

@ -98,10 +98,10 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend
: HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_},
query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} {
const vk::Device* logical = &cache.GetDevice().GetLogical();
cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) {
cache.GetScheduler().Record([logical, query_ = query](vk::CommandBuffer cmdbuf) {
const bool use_precise = Settings::IsGPULevelHigh();
logical->ResetQueryPool(query.first, query.second, 1);
cmdbuf.BeginQuery(query.first, query.second,
logical->ResetQueryPool(query_.first, query_.second, 1);
cmdbuf.BeginQuery(query_.first, query_.second,
use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
});
}
@ -111,8 +111,9 @@ HostCounter::~HostCounter() {
}
void HostCounter::EndQuery() {
cache.GetScheduler().Record(
[query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); });
cache.GetScheduler().Record([query_ = query](vk::CommandBuffer cmdbuf) {
cmdbuf.EndQuery(query_.first, query_.second);
});
}
u64 HostCounter::BlockingQuery(bool async) const {

View File

@ -1412,7 +1412,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
}
scheduler->RequestOutsideRenderPassOperationContext();
scheduler->Record([buffers = std::move(buffers_vector), image = *original_image,
aspect_mask = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
const VkImageMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
@ -1424,7 +1424,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = aspect_mask,
.aspectMask = aspect_mask_,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
@ -1456,7 +1456,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image,
.subresourceRange{
.aspectMask = aspect_mask,
.aspectMask = aspect_mask_,
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,

View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#define VMA_IMPLEMENTATION
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include <vk_mem_alloc.h>

View File

@ -135,11 +135,11 @@ void RoomJson::Delete() {
LOG_ERROR(WebService, "Room must be registered to be deleted");
return;
}
Common::DetachedTasks::AddTask(
[host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() {
// create a new client here because the this->client might be destroyed.
Client{host, username, token}.DeleteJson(fmt::format("/lobby/{}", room_id), "", false);
});
Common::DetachedTasks::AddTask([host_{this->host}, username_{this->username},
token_{this->token}, room_id_{this->room_id}]() {
// create a new client here because the this->client might be destroyed.
Client{host_, username_, token_}.DeleteJson(fmt::format("/lobby/{}", room_id_), "", false);
});
}
} // namespace WebService