Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
88 changes: 61 additions & 27 deletions src/common/small_cache.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <iterator>
#include <map>
#include <string>

Expand All @@ -20,32 +21,46 @@ class SmallCache {
public:
using map_iter = typename std::map<KeyT, T>::iterator;

using iterator_category = std::forward_iterator_tag;
using value_type = std::pair<const KeyT, T>;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;

iterator(SmallCache* cache_, usize fast_index_)
: cache{cache_}, fast_index{fast_index_} {
advance_fast();
AdvanceFast();
}

iterator(SmallCache* cache, map_iter slow_it)
: cache(cache), fast_index(fast_cache_size), slow_it(slow_it) {}
: cache{cache}, fast_index{fast_cache_size}, slow_it{slow_it} {}

std::pair<const KeyT&, T&> operator*() const {
if (fast_index < fast_cache_size) {
auto& e = cache->fast_cache[fast_index];
return {e.key, e.value};
}
return {slow_it->first, slow_it->second};
reference operator*() const {
if (fast_index < fast_cache_size)
return cache->fast_cache[fast_index].value();

return *slow_it;
}

pointer operator->() const { return &(**this); }

iterator& operator++() {
if (fast_index < fast_cache_size) {
++fast_index;
advance_fast();
AdvanceFast();
} else {
++slow_it;
}

return *this;
}

iterator operator++(int) {
iterator tmp = *this;
++(*this);
return tmp;
}

bool operator==(const iterator& other) const {
return cache == other.cache && fast_index == other.fast_index &&
(fast_index < fast_cache_size || slow_it == other.slow_it);
Expand All @@ -56,9 +71,9 @@ class SmallCache {
}

private:
void advance_fast() {
void AdvanceFast() {
while (fast_index < fast_cache_size &&
!cache->fast_cache[fast_index].occupied) {
!cache->fast_cache[fast_index].has_value()) {
++fast_index;
}

Expand All @@ -72,9 +87,29 @@ class SmallCache {
map_iter slow_it;
};

SmallCache() = default;

SmallCache(const SmallCache&) = delete;
SmallCache& operator=(const SmallCache&) = delete;

SmallCache(SmallCache&&) = default;
SmallCache& operator=(SmallCache&&) = default;

// TODO: const versions as well
iterator begin() { return iterator(this, 0); }
iterator end() { return iterator(this, slow_cache.end()); }

// Functions
usize GetCount() const {
usize count = 0;
for (auto& entry : fast_cache) {
if (entry.has_value())
count++;
}

return count + slow_cache.size();
}

void Clear() {
fast_cache.fill({});
slow_cache.clear();
Expand All @@ -84,23 +119,26 @@ class SmallCache {
AlreadyPresent,
};

T& Add(KeyT key, const T& value = {}) {
template <typename... Args>
T& Add(KeyT key, Args&&... args) {
// Insert into fast cache if possible
for (auto& entry : fast_cache) {
if (!entry.occupied) {
entry.occupied = true;
entry.key = key;
entry.value = value;
return entry.value;
if (!entry.has_value()) {
entry.emplace(
std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(std::forward<Args>(args)...));
return entry.value().second;
} else {
ASSERT_THROWING(entry.key != key, Common,
ASSERT_THROWING(entry.value().first != key, Common,
AddError::AlreadyPresent,
"Entry already present");
}
}

// Fallback to slow cache
auto res = slow_cache.emplace(key, value);
auto res = slow_cache.emplace(
std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(std::forward<Args>(args)...));
ASSERT_THROWING(res.second, Common, AddError::AlreadyPresent,
"Entry already present");
return res.first->second;
Expand All @@ -109,7 +147,7 @@ class SmallCache {
iterator Remove(iterator it) {
// Fast cache
if (it.fast_index < fast_cache_size) {
fast_cache[it.fast_index].occupied = false;
fast_cache[it.fast_index] = std::nullopt;

// Advance to the next element
iterator next = it;
Expand All @@ -132,7 +170,7 @@ class SmallCache {
iterator FindIter(KeyT key) {
// Fast cache
for (u32 i = 0; i < fast_cache_size; i++) {
if (fast_cache[i].occupied && fast_cache[i].key == key)
if (fast_cache[i].has_value() && fast_cache[i].value().first == key)
return iterator(this, i);
}

Expand All @@ -150,7 +188,7 @@ class SmallCache {
if (it == end())
return std::nullopt;

return &(*it).second;
return &it->second;
}

T& FindOrAdd(KeyT key) {
Expand All @@ -162,11 +200,7 @@ class SmallCache {
}

private:
struct FastCacheEntry {
bool occupied{false};
KeyT key;
T value;
};
using FastCacheEntry = std::optional<std::pair<const KeyT, T>>;

std::array<FastCacheEntry, fast_cache_size> fast_cache;
std::map<KeyT, T> slow_cache;
Expand Down
8 changes: 5 additions & 3 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,9 @@ add_library(hydra-core
hw/tegra_x1/gpu/renderer/buffer_view.hpp
hw/tegra_x1/gpu/renderer/buffer_cache.cpp
hw/tegra_x1/gpu/renderer/buffer_cache.hpp
hw/tegra_x1/gpu/renderer/texture_base.hpp
hw/tegra_x1/gpu/renderer/texture_decoder.cpp
hw/tegra_x1/gpu/renderer/texture_decoder.hpp
hw/tegra_x1/gpu/renderer/texture.hpp
hw/tegra_x1/gpu/renderer/texture_view.cpp
hw/tegra_x1/gpu/renderer/texture_view.hpp
hw/tegra_x1/gpu/renderer/texture_cache.cpp
hw/tegra_x1/gpu/renderer/texture_cache.hpp
hw/tegra_x1/gpu/renderer/sampler_base.hpp
Expand Down Expand Up @@ -588,6 +588,8 @@ add_library(hydra-core
hw/tegra_x1/gpu/renderer/metal/buffer.hpp
hw/tegra_x1/gpu/renderer/metal/texture.cpp
hw/tegra_x1/gpu/renderer/metal/texture.hpp
hw/tegra_x1/gpu/renderer/metal/texture_view.cpp
hw/tegra_x1/gpu/renderer/metal/texture_view.hpp
hw/tegra_x1/gpu/renderer/metal/sampler.cpp
hw/tegra_x1/gpu/renderer/metal/sampler.hpp
hw/tegra_x1/gpu/renderer/metal/render_pass.cpp
Expand Down
149 changes: 148 additions & 1 deletion src/core/c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
#include "core/horizon/loader/nca_loader.hpp"
#include "core/horizon/loader/plugins/manager.hpp"
#include "core/horizon/ui/handler_base.hpp"
#include <string>
#include "core/hw/tegra_x1/gpu/gpu.hpp"
#include "core/hw/tegra_x1/gpu/renderer/texture.hpp"

#define HYDRA_EXPORT extern "C" __attribute__((visibility("default")))

Expand Down Expand Up @@ -990,3 +991,149 @@ HYDRA_EXPORT uint64_t hydra_debugger_resolved_stack_frame_get_address(
resolved_stack_frame)
->addr;
}

// Texture cache

// Texture cache
HYDRA_EXPORT void hydra_texture_cache_lock() {
hydra::RENDERER_INSTANCE.GetTextureCache().GetMutex().lock();
}

HYDRA_EXPORT void hydra_texture_cache_unlock() {
hydra::RENDERER_INSTANCE.GetTextureCache().GetMutex().unlock();
}

HYDRA_EXPORT uint32_t hydra_texture_cache_get_texture_memory_count() {
// HACK
return static_cast<uint32_t>(
hydra::RENDERER_INSTANCE.GetTextureCache().GetMemoryCount());
}

HYDRA_EXPORT const void*
hydra_texture_cache_get_texture_memory(uint32_t index) {
return &hydra::RENDERER_INSTANCE.GetTextureCache().GetMemory(index);
}

// Texture memory
HYDRA_EXPORT uint32_t
hydra_texture_memory_get_texture_group_count(const void* mem) {
// HACK
return static_cast<uint32_t>(
static_cast<const hydra::hw::tegra_x1::gpu::renderer::TextureMem*>(mem)
->GetTextureGroupCount());
}

HYDRA_EXPORT const void*
hydra_texture_memory_get_texture_group(const void* mem, uint32_t index) {
return &static_cast<const hydra::hw::tegra_x1::gpu::renderer::TextureMem*>(
mem)
->GetTextureGroup(index);
}

// Texture group
HYDRA_EXPORT uint32_t
hydra_texture_group_get_texture_storage_count(const void* group) {
// HACK
return static_cast<uint32_t>(
static_cast<const hydra::hw::tegra_x1::gpu::renderer::TextureGroup*>(
group)
->GetStorageCount());
}

HYDRA_EXPORT const void*
hydra_texture_group_get_texture_storage(const void* group, uint32_t index) {
return &static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureGroup*>(group)
->GetStorage(index);
}

// Texture storage
HYDRA_EXPORT const void*
hydra_texture_storage_get_texture_descriptor(const void* storage) {
return &static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureStorage*>(
storage)
->base->GetDescriptor();
}

// Texture descriptor
HYDRA_EXPORT uint64_t hydra_texture_descriptor_get_ptr(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->ptr;
}

HYDRA_EXPORT HydraTextureType
hydra_texture_descriptor_get_type(const void* descriptor) {
return static_cast<HydraTextureType>(
static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->type);
}

HYDRA_EXPORT HydraTextureFormat
hydra_texture_descriptor_get_format(const void* descriptor) {
return static_cast<HydraTextureFormat>(
static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->format);
}

HYDRA_EXPORT uint32_t
hydra_texture_descriptor_get_width(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->width;
}

HYDRA_EXPORT uint32_t
hydra_texture_descriptor_get_height(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->height;
}

HYDRA_EXPORT uint32_t
hydra_texture_descriptor_get_depth(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->depth;
}

HYDRA_EXPORT uint32_t
hydra_texture_descriptor_get_level_count(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->level_count;
}

HYDRA_EXPORT uint32_t
hydra_texture_descriptor_get_layer_count(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->layer_count;
}

HYDRA_EXPORT uint64_t
hydra_texture_descriptor_get_layer_size(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->layer_size;
}

HYDRA_EXPORT uint64_t
hydra_texture_descriptor_get_size(const void* descriptor) {
return static_cast<
const hydra::hw::tegra_x1::gpu::renderer::TextureDescriptor*>(
descriptor)
->GetSize();
}
Loading