Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7938540
use proper gpu capture boundaries
SamoZ256 Jan 18, 2026
91fec50
shader-decomp: fix tld4 destinations
SamoZ256 Jan 18, 2026
01939a8
shader-decomp: add signedness helpers & xmad
SamoZ256 Jan 18, 2026
c774e7c
shader-decomp: rework const memory
SamoZ256 Jan 18, 2026
8e11478
metal: enable position invariance
SamoZ256 Jan 18, 2026
4caf081
shader-decomp: fix memory load overwriting dst
SamoZ256 Jan 18, 2026
14d118c
shader-decomp: simplify texture component mask
SamoZ256 Jan 18, 2026
b867a8b
shader-decomp: interpolation attributes
SamoZ256 Jan 18, 2026
62202c1
display: fix deadlock
SamoZ256 Jan 18, 2026
0202ee0
make surface composition non-blocking
SamoZ256 Jan 19, 2026
46cf7d8
hid: fix performance regressions
SamoZ256 Jan 19, 2026
8a0ad8a
hypervisor: check if memory allocation succeeded
SamoZ256 Jan 19, 2026
7362f84
add an option to recover from guest segfaults
SamoZ256 Jan 19, 2026
e4ce86d
applets/controller: make dummy response
SamoZ256 Jan 19, 2026
5c8dd76
gpu: srgb images
SamoZ256 Jan 19, 2026
a20c41a
gpu: rewrite buffer cache
SamoZ256 Jan 19, 2026
21e251e
gpu: guess render target width
SamoZ256 Jan 19, 2026
99a76de
clean up range
SamoZ256 Jan 19, 2026
49c471f
renderer: clean up buffer cache & prepare for inline copies
SamoZ256 Jan 19, 2026
0d7138f
renderer: buffer view
SamoZ256 Jan 20, 2026
7447ba8
renderer: optimize buffer cache lookup
SamoZ256 Jan 20, 2026
872d842
engines/3d(hack): more conservative width adjust
SamoZ256 Jan 20, 2026
3a48c5d
cpu: set proper memory permissions
SamoZ256 Jan 21, 2026
4b1ce2d
cpu: track memory writes
SamoZ256 Jan 21, 2026
c88838f
engines/3d: fix const buffer invalidation range
SamoZ256 Jan 21, 2026
6f92a3d
renderer: only update buffer if needed
SamoZ256 Jan 21, 2026
373ddb0
Merge pull request #94 from SamoZ256/page-tracking
SamoZ256 Jan 21, 2026
32da62f
renderer: use memory invalidation for texture cache
SamoZ256 Jan 22, 2026
af0b3f1
common: clean up small cache
SamoZ256 Jan 22, 2026
9e27895
loader/nro: fix segment sizes
SamoZ256 Jan 22, 2026
4626b19
Merge pull request #95 from SamoZ256/gpu-caches
SamoZ256 Jan 22, 2026
75fbf0e
engines/3d(hack): always enable viewport transform
SamoZ256 Jan 22, 2026
66f9135
shader-decomp: fix iscadd shift
SamoZ256 Jan 22, 2026
313039b
gpu: texture types
SamoZ256 Jan 24, 2026
02ab132
gpu: begin texture cache rework
SamoZ256 Jan 29, 2026
9afbff8
renderer: synchronize data between textures
SamoZ256 Jan 29, 2026
d2bbd83
renderer: rg8snorm image format
SamoZ256 Jan 29, 2026
f58e88f
gpu: decode full texture
SamoZ256 Jan 29, 2026
9957ed9
Merge pull request #96 from SamoZ256/texture-merge
SamoZ256 Jan 29, 2026
ada4a06
dynarmic: fix crash
SamoZ256 Jan 31, 2026
9b0a2e2
gpu: rework command buffers
SamoZ256 Feb 3, 2026
9032b1a
gpu: simplify mutexes
SamoZ256 Feb 3, 2026
b41da22
gpu: process commands on a separate thread
SamoZ256 Feb 3, 2026
2e42ef6
gpu: fix pfifo deadlock
SamoZ256 Feb 4, 2026
d12832e
Merge pull request #100 from SamoZ256/gpu-threading
SamoZ256 Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_library(hydra-common
macros.hpp
type_aliases.hpp
types.hpp
range.hpp
traits.hpp
functions.hpp
atomic.hpp
Expand All @@ -15,6 +16,7 @@ add_library(hydra-common
pool.hpp
static_pool.hpp
dynamic_pool.hpp
small_cache.hpp
filesystem.hpp
log.cpp
log.hpp
Expand Down
2 changes: 2 additions & 0 deletions src/common/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "common/objc.hpp"
#include "common/optional_helper.hpp"
#include "common/platform.hpp"
#include "common/range.hpp"
#include "common/small_cache.hpp"
#include "common/static_pool.hpp"
#include "common/string.hpp"
#include "common/time.hpp"
Expand Down
5 changes: 5 additions & 0 deletions src/common/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void Config::LoadDefaults() {
log_fs_access = GetDefaultLogFsAccess();
debug_logging = GetDefaultDebugLogging();
process_args = GetDefaultProcessArgs();
recover_from_segfault = GetDefaultRecoverFromSegfault();
gdb_enabled = GetDefaultGdbEnabled();
gdb_port = GetDefaultGdbPort();
gdb_wait_for_client = GetDefaultGdbWaitForClient();
Expand Down Expand Up @@ -218,6 +219,7 @@ void Config::Serialize() {
debug["log_fs_access"] = log_fs_access;
debug["debug_logging"] = debug_logging;
debug["process_args"] = process_args;
debug["recover_from_segfault"] = recover_from_segfault;
debug["gdb_enabled"] = gdb_enabled;
debug["gdb_port"] = gdb_port;
debug["gdb_wait_for_client"] = gdb_wait_for_client;
Expand Down Expand Up @@ -303,6 +305,8 @@ void Config::Deserialize() {
GetDefaultDebugLogging());
process_args = toml::find_or<std::vector<std::string>>(
debug, "process_args", GetDefaultProcessArgs());
recover_from_segfault = toml::find_or<bool>(
debug, "recover_from_segfault", GetDefaultRecoverFromSegfault());
gdb_enabled =
toml::find_or<bool>(debug, "gdb_enabled", GetDefaultGdbEnabled());
gdb_port = toml::find_or<u16>(debug, "gdb_port", GetDefaultGdbPort());
Expand Down Expand Up @@ -365,6 +369,7 @@ void Config::Log() {
LOG_INFO(Other, "Log FS access: {}", log_fs_access);
LOG_INFO(Other, "Debug logging: {}", debug_logging);
LOG_INFO(Other, "Process arguments: {}", process_args);
LOG_INFO(Other, "Recover from segfault: {}", recover_from_segfault);
LOG_INFO(Other, "GDB enabled: {}", gdb_enabled);
LOG_INFO(Other, "GDB port: {}", gdb_port);
LOG_INFO(Other, "GDB wait for client: {}", gdb_wait_for_client);
Expand Down
3 changes: 3 additions & 0 deletions src/common/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class Config {
bool log_fs_access;
bool debug_logging;
std::vector<std::string> process_args;
bool recover_from_segfault;
bool gdb_enabled;
u16 gdb_port;
bool gdb_wait_for_client;
Expand Down Expand Up @@ -154,6 +155,7 @@ class Config {
bool GetDefaultLogFsAccess() const { return false; }
bool GetDefaultDebugLogging() const { return false; }
std::vector<std::string> GetDefaultProcessArgs() const { return {}; }
bool GetDefaultRecoverFromSegfault() const { return false; }
bool GetDefaultGdbEnabled() const { return false; }
u16 GetDefaultGdbPort() const { return 1234; }
bool GetDefaultGdbWaitForClient() const { return false; }
Expand All @@ -179,6 +181,7 @@ class Config {
REF_GETTER(log_fs_access, GetLogFsAccess);
REF_GETTER(debug_logging, GetDebugLogging);
REF_GETTER(process_args, GetProcessArgs);
REF_GETTER(recover_from_segfault, GetRecoverFromSegfault);
REF_GETTER(gdb_enabled, GetGdbEnabled);
REF_GETTER(gdb_port, GetGdbPort);
REF_GETTER(gdb_wait_for_client, GetGdbWaitForClient);
Expand Down
10 changes: 1 addition & 9 deletions src/common/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ T align(T v, T alignment) {

template <typename T>
bool is_aligned(T v, T alignment) {
return (v & (alignment - 1)) == 0x0;
return (v % alignment) == 0x0;
}

template <typename T>
Expand Down Expand Up @@ -136,14 +136,6 @@ inline std::string u64_to_str(u64 value) {
return std::string(str, std::min(strlen(str), size_t(8)));
}

template <typename T>
void push_unique(std::vector<T>& vec, T value) {
auto it = std::find_if(vec.begin(), vec.end(),
[&](const T v) { return v == value; });
if (it == vec.end())
vec.push_back(value);
}

inline std::string demangle(const char* mangled_name) {
i32 status;
std::unique_ptr<char, void (*)(void*)> result{
Expand Down
19 changes: 10 additions & 9 deletions src/common/io/sparse_stream.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#pragma once

#include "common/io/stream.hpp"
#include "common/range.hpp"

namespace hydra::io {

struct SparseStreamEntry {
range<u64> range;
Range<u64> range;
IStream* stream;
};

Expand Down Expand Up @@ -38,9 +39,9 @@ class SparseStream : public IStream {

const auto entry = GetEntry(seek);
const auto max_read_size = std::min(
entry.range.end - seek, static_cast<u64>(buffer.size()));
entry.range.GetEnd() - seek, static_cast<u64>(buffer.size()));
if (entry.stream) {
entry.stream->SeekTo(seek - entry.range.begin);
entry.stream->SeekTo(seek - entry.range.GetBegin());
entry.stream->ReadRaw(buffer.subspan(0, max_read_size));
} else {
std::fill(buffer.begin(),
Expand All @@ -59,9 +60,9 @@ class SparseStream : public IStream {

const auto entry = GetEntry(seek);
const auto max_write_size = std::min(
entry.range.end - seek, static_cast<u64>(buffer.size()));
entry.range.GetEnd() - seek, static_cast<u64>(buffer.size()));
if (entry.stream) {
entry.stream->SeekTo(seek - entry.range.begin);
entry.stream->SeekTo(seek - entry.range.GetBegin());
entry.stream->WriteRaw(buffer.subspan(0, max_write_size));
}

Expand Down Expand Up @@ -92,23 +93,23 @@ class SparseStream : public IStream {
auto next_it =
std::upper_bound(entries.begin(), entries.end(), offset,
[](u64 offset, const SparseStreamEntry& entry) {
return offset < entry.range.begin;
return offset < entry.range.GetBegin();
});

// If the offset is before the first entry, return an empty entry
if (next_it == entries.begin())
return {.stream = nullptr, .range = {0, next_it->range.begin}};
return {.stream = nullptr, .range = {0, next_it->range.GetBegin()}};

auto it = std::prev(next_it);

// Check if entry is past the range
if (!it->range.Contains(offset)) {
if (next_it == entries.end())
return {.stream = nullptr,
.range = {it->range.end, size - offset}};
.range = {it->range.GetEnd(), size - offset}};

return {.stream = nullptr,
.range = {it->range.end, next_it->range.begin}};
.range = {it->range.GetEnd(), next_it->range.GetBegin()}};
}

// Cache the entry and return it
Expand Down
3 changes: 2 additions & 1 deletion src/common/log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@

#define ASSERT_ALIGNMENT(value, alignment, c, name) \
ASSERT(is_aligned<decltype(value)>(value, alignment), c, \
name " must be {}-byte aligned", alignment)
name " must be {:#x}-byte aligned (value: {:#x})", alignment, \
value)

#ifdef HYDRA_DEBUG
#define ASSERT_DEBUG(condition, c, ...) ASSERT(condition, c, __VA_ARGS__)
Expand Down
5 changes: 5 additions & 0 deletions src/common/macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@
decltype(member)& name() { return member; }
#define CONST_REF_GETTER(member, name) \
const decltype(member)& name() const { return member; }
#define CONSTEXPR_GETTER(member, name) \
constexpr decltype(member) name() const { return member; }

#define SETTER(member, name) \
void name(const decltype(member) member##_) { member = member##_; }
Expand Down Expand Up @@ -131,6 +133,9 @@
setter_name) \
CONST_REF_GETTER(member, getter_name) \
CONST_REF_SETTER(member, setter_name)
#define CONSTEXPR_GETTER_AND_SETTER(member, getter_name, setter_name) \
CONSTEXPR_GETTER(member, getter_name) \
SETTER(member, setter_name)

#define PARENS ()

Expand Down
89 changes: 89 additions & 0 deletions src/common/range.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#pragma once

#include "common/functions.hpp"
#include "common/log.hpp"
#include "common/macros.hpp"
#include "common/type_aliases.hpp"

namespace hydra {

template <typename T>
class Range {
public:
static constexpr Range<T> FromSize(T begin_, T size) {
return Range<T>(begin_, begin_ + size);
}

constexpr Range() : begin{0}, end{0} {}
constexpr Range(T begin_, T end_) : begin{begin_}, end{end_} {}

bool operator==(const Range<T>& other) const {
return begin == other.begin && end == other.end;
}

void operator+=(T offset) {
begin += offset;
end += offset;
}

void operator-=(T offset) {
begin -= offset;
end -= offset;
}

// Size
constexpr T GetSize() const { return end - begin; }
constexpr void SetSize(T size) { end = begin + size; }

// Intersection
bool Contains(T value) const { return value >= begin && value < end; }
bool Contains(const Range<T>& other) const {
return other.begin >= begin && other.end <= end;
}

bool Intersects(const Range<T>& other) const {
return begin < other.end && end > other.begin;
}

// Combining
Range<T> ClampedTo(const Range<T>& bounds) const {
return Range<T>(std::max(begin, bounds.begin),
std::min(end, bounds.end));
}

Range<T> Union(const Range<T>& other) const {
return Range<T>(std::min(begin, other.begin), std::max(end, other.end));
}

private:
T begin;
T end;

public:
CONSTEXPR_GETTER_AND_SETTER(begin, GetBegin, SetBegin);
CONSTEXPR_GETTER_AND_SETTER(end, GetEnd, SetEnd);
};

} // namespace hydra

template <typename T>
struct fmt::formatter<hydra::Range<T>> : formatter<string_view> {
fmt::formatter<T> value_formatter;

constexpr auto parse(fmt::format_parse_context& ctx) {
return value_formatter.parse(ctx);
}

template <typename FormatContext>
auto format(const hydra::Range<T>& range, FormatContext& ctx) const {
auto out = ctx.out();

*out++ = '<';
out = value_formatter.format(range.GetBegin(), ctx);
out = fmt::format_to(out, "...");
out = value_formatter.format(range.GetEnd(), ctx);
*out++ = ')';

return out;
}
};
Loading
Loading