Compare commits

..

6 Commits

Author SHA1 Message Date
lizzie 10480f2f41 2026-09-07 10:21:23
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-07 10:21:23 +00:00
lizzie a770c2cd6f 2026-09-06 23:31:33
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-06 23:31:33 +00:00
lizzie 30fc92c7d8 2026-09-06 22:10:34
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-06 22:10:34 +00:00
lizzie 36d30694c3 Trigger build 2026-09-06 21:49:04 +00:00
lizzie d15474ded1 2026-09-05 17:42:18
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-05 23:57:32 +02:00
lizzie d542dd523c 2026-09-05 17:17:08
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-05 23:57:32 +02:00
13 changed files with 118 additions and 145 deletions
@@ -83,7 +83,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
SHOW_SHADERS_BUILDING("show_shaders_building"),
DEBUG_FLUSH_BY_LINE("flush_line"),
EXTENDED_LOGGING("extended_logging"),
DONT_SHOW_DRIVER_SHADER_WARNING("dont_show_driver_shader_warning"),
ENABLE_OVERLAY("enable_overlay"),
@@ -262,13 +262,6 @@ abstract class SettingsItem(
descriptionId = R.string.flush_by_line_description
)
)
put(
SwitchSetting(
BooleanSetting.EXTENDED_LOGGING,
titleId = R.string.extended_logging,
descriptionId = R.string.extended_logging_description
)
)
val dockedModeSetting = object : AbstractBooleanSetting {
override val key = BooleanSetting.USE_DOCKED_MODE.key
@@ -1323,7 +1323,6 @@ class SettingsFragmentPresenter(
add(HeaderSetting(R.string.log))
add(BooleanSetting.DEBUG_FLUSH_BY_LINE.key)
add(BooleanSetting.EXTENDED_LOGGING.key)
add(StringSetting.LOG_FILTER.key)
}
@@ -636,8 +636,6 @@
<string name="log">Logging</string>
<string name="flush_by_line">Flush debug logs by line</string>
<string name="flush_by_line_description">Flushes debugging logs on each line written, making debugging easier in cases of crashing or freezing.</string>
<string name="extended_logging">Enable extended logging</string>
<string name="extended_logging_description">Increases the maximum log file size from 100 MiB to 1 GiB.</string>
<string name="log_filter">Log filter</string>
<string name="log_filter_description">Controls Eden\'s log categories. Example: *:Info Service.LM:Debug</string>
+44 -40
View File
@@ -7,65 +7,69 @@
#version 460
#ifdef VULKAN
#define BINDING_COLOR_TEXTURE 1
#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
#define BINDING_COLOR_TEXTURE 0
#endif
layout (location = 0) in vec4 posPos;
layout (location = 0) out vec4 frag_color;
layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture;
const float FXAA_SPAN_MAX = 8.0;
const float FXAA_REDUCE_MUL = 1.0 / 8.0;
const float FXAA_REDUCE_MIN = 1.0 / 128.0;
#define FxaaTexLod0(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o) textureLodOffset(t, p, 0.0, o)
vec3 FxaaPixelShader(vec4 posPos, sampler2D tex) {
mat4x3 rgb_matrix = mat4x3(
textureLod(tex, posPos.zw, 0.0).xyz,
textureLodOffset(tex, posPos.zw, 0.0, ivec2(1, 0)).xyz,
textureLodOffset(tex, posPos.zw, 0.0, ivec2(0, 1)).xyz,
textureLodOffset(tex, posPos.zw, 0.0, ivec2(1, 1)).xyz
);
vec3 rgbM = textureLod(tex, posPos.xy, 0.0).xyz;
vec3 rgbNW = FxaaTexLod0(tex, posPos.zw).xyz;
vec3 rgbNE = FxaaTexOff(tex, posPos.zw, ivec2(1,0)).xyz;
vec3 rgbSW = FxaaTexOff(tex, posPos.zw, ivec2(0,1)).xyz;
vec3 rgbSE = FxaaTexOff(tex, posPos.zw, ivec2(1,1)).xyz;
vec3 rgbM = FxaaTexLod0(tex, posPos.xy).xyz;
/*---------------------------------------------------------*/
vec3 luma = vec3(0.299, 0.587, 0.114);
// vec4(dot(m1, l), dot(m2, l), ...) => m * l
vec4 lume_per_rgb = luma * rgb_matrix;
float lumaNW = dot(rgbNW, luma);
float lumaNE = dot(rgbNE, luma);
float lumaSW = dot(rgbSW, luma);
float lumaSE = dot(rgbSE, luma);
float lumaM = dot(rgbM, luma);
float lumaMin = min(lumaM, min(min(lume_per_rgb.x, lume_per_rgb.y), min(lume_per_rgb.z, lume_per_rgb.w)));
float lumaMax = max(lumaM, max(max(lume_per_rgb.x, lume_per_rgb.y), max(lume_per_rgb.z, lume_per_rgb.w)));
vec2 dir = vec2(
-((lume_per_rgb.x + lume_per_rgb.y) - (lume_per_rgb.z + lume_per_rgb.w)),
+((lume_per_rgb.x + lume_per_rgb.z) - (lume_per_rgb.y + lume_per_rgb.w))
);
float rcp_dir_min = 1.0 / (min(abs(dir.x), abs(dir.y)) + max(
(lume_per_rgb.x + lume_per_rgb.y + lume_per_rgb.z + lume_per_rgb.w) * (0.25 * FXAA_REDUCE_MUL),
FXAA_REDUCE_MIN
));
dir = min(
vec2(FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX), dir * rcp_dir_min)
);
// Constants (calculating via division is faster)
mat4x2 const_dir = mat4x2(
(1.0 / 3.0 - 0.5) / textureSize(tex, 0),
(2.0 / 3.0 - 0.5) / textureSize(tex, 0),
(0.0 / 3.0 - 0.5) / textureSize(tex, 0),
(3.0 / 3.0 - 0.5) / textureSize(tex, 0)
);
// dir * const_dir[i] => dir * const_dir => vec4
/*---------------------------------------------------------*/
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
/*---------------------------------------------------------*/
vec2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
/*---------------------------------------------------------*/
float dirReduce = max(
(lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
FXAA_REDUCE_MIN);
float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(vec2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) / textureSize(tex, 0);
/*--------------------------------------------------------*/
vec3 rgbA = (1.0 / 2.0) * (
textureLod(tex, fma(dir, const_dir[0], posPos.xy), 0.0).xyz +
textureLod(tex, fma(dir, const_dir[1], posPos.xy), 0.0).xyz
);
vec3 rgbB = fma(rgbA, vec3(1.0 / 2.0), (1.0 / 4.0) * (
textureLod(tex, fma(dir, const_dir[2], posPos.xy), 0.0).xyz +
textureLod(tex, fma(dir, const_dir[3], posPos.xy), 0.0).xyz
));
FxaaTexLod0(tex, posPos.xy + dir * (1.0 / 3.0 - 0.5)).xyz +
FxaaTexLod0(tex, posPos.xy + dir * (2.0 / 3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (
FxaaTexLod0(tex, posPos.xy + dir * (0.0 / 3.0 - 0.5)).xyz +
FxaaTexLod0(tex, posPos.xy + dir * (3.0 / 3.0 - 0.5)).xyz);
float lumaB = dot(rgbB, luma);
return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? rgbA : rgbB;
if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
return rgbB;
}
void main() {
frag_color = vec4(FxaaPixelShader(posPos, input_texture), texture(input_texture, posPos.xy).a);
frag_color = vec4(FxaaPixelShader(posPos, input_texture), texture(input_texture, posPos.xy).a);
}
+13 -17
View File
@@ -7,35 +7,31 @@ out gl_PerVertex {
vec4 gl_Position;
};
const vec2 vertices[3] =
vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3));
layout (location = 0) out vec4 posPos;
#ifdef VULKAN
#define BINDING_COLOR_TEXTURE 0
#define VERTEX_ID gl_VertexIndex
#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
#define BINDING_COLOR_TEXTURE 0
#define VERTEX_ID gl_VertexID
#endif
layout (binding = BINDING_COLOR_TEXTURE) uniform sampler2D input_texture;
const float FXAA_SUBPIX_SHIFT = 0;
void main() {
// 0b00 -> (-1, -1) 0b01 -> (-1, 3) 0b10 -> (3, -1)
// ((x * 4) - 1) => 3
// :: (v + 1) / 2 => ((x * 4) + 1) / 2
// => (x * 4 + 1) / 2 => x * (4 / 2) + 1 / 2
// :: (v+1)/2 => v/2 + 1/2 => v*(1/2) + (1/2)
gl_Position = vec4(vec2(
float(((VERTEX_ID & 1) << 2) - 1),
float(((VERTEX_ID & 2) << 1) - 1)
), 0.0, 1.0);
posPos = vec2(
float((VERTEX_ID & 1) << 1),
float((VERTEX_ID & 2) << 0)
).xyxy - vec4(
0.0,
0.0,
(0.5 + FXAA_SUBPIX_SHIFT) / textureSize(input_texture, 0)
);
vec2 vertex = vertices[VERTEX_ID];
gl_Position = vec4(vertex, 0.0, 1.0);
vec2 vert_tex_coord = (vertex + 1.0) / 2.0;
posPos.xy = vert_tex_coord;
posPos.zw = vert_tex_coord - (0.5 + FXAA_SUBPIX_SHIFT) / textureSize(input_texture, 0);
}
@@ -192,7 +192,7 @@ public:
if (host_visible) {
return StagingBufferRef{};
}
return staging_pool.Request(size_bytes, MemoryUsage::Upload);
return staging_pool.Request(device, size_bytes, MemoryUsage::Upload);
}();
u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data();
@@ -366,11 +366,11 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m
}
StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) {
return staging_pool.Request(size, MemoryUsage::Upload);
return staging_pool.Request(device, size, MemoryUsage::Upload);
}
StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_pool.Request(size, MemoryUsage::Download, deferred);
return staging_pool.Request(device, size, MemoryUsage::Download, deferred);
}
VkFormat BufferCacheRuntime::TexelBufferFormat(VideoCore::Surface::PixelFormat format) const {
@@ -149,7 +149,7 @@ public:
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
[[maybe_unused]] u32 binding_index,
u32 size) {
const StagingBufferRef ref = staging_pool.Request(size, MemoryUsage::Upload);
const StagingBufferRef ref = staging_pool.Request(device, size, MemoryUsage::Upload);
guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address,
static_cast<u32>(ref.offset), size);
return ref.mapped_span;
@@ -287,7 +287,7 @@ Uint8Pass::~Uint8Pass() = default;
std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
u32 src_offset) {
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal);
compute_pass_descriptor_queue.Acquire(scheduler, 2);
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
@@ -345,7 +345,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6;
const std::size_t staging_size = num_tri_vertices * sizeof(u32);
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal);
compute_pass_descriptor_queue.Acquire(scheduler, 2);
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
@@ -852,7 +852,7 @@ public:
void PushUnsyncedQueries() override {
CloseCounter();
auto staging_ref = staging_pool.Request(
auto staging_ref = staging_pool.Request(device,
pending_flush_queries.size() * TFBQueryBank::QUERY_SIZE, MemoryUsage::Download, true);
size_t offset_base = staging_ref.offset;
for (auto q : pending_flush_queries) {
@@ -1657,7 +1657,7 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
impl->copies_setup.clear();
impl->copies_setup.resize(impl->little_cache.size());
if constexpr (SyncValuesType::GeneratesBaseBuffer) {
ref = impl->staging_pool.Request(total_size, MemoryUsage::Upload);
ref = impl->staging_pool.Request(impl->device, total_size, MemoryUsage::Upload);
size_t current_offset = ref.offset;
size_t accumulated_size = 0;
for (size_t i = 0; i < values.size(); i++) {
@@ -28,55 +28,42 @@ using namespace Common::Literals;
// Maximum potential alignment of a Vulkan buffer
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
// Stream buffer size in bytes
// *NIX drivers are more sensitive to increased buffers for streaming.
// Windows ones however, can intake bigger buffers and generally do not OOM.
// - GTX 960 on Windows will not OOM with 256mib
// - GT 1030 on ^NIX will OOM with 256mib
#if defined(__FreeBSD__)
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
#else
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 256_MiB;
#endif
size_t GetStreamBufferSize(const Device& device) {
size_t GetStreamBufferSize(const Device& device, size_t max_stream_buffer_size, size_t max_alignment) {
if (!device.HasDebuggingToolAttached()) {
return MAX_STREAM_BUFFER_SIZE;
return max_stream_buffer_size;
}
VkDeviceSize size{0};
bool has_device_local_host_visible_heap{};
ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](
size_t index, VkMemoryHeap& heap) {
ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](size_t index, VkMemoryHeap& heap) {
has_device_local_host_visible_heap = true;
size = (std::max)(size, heap.size);
size = std::max<size_t>(size, heap.size);
});
if (has_device_local_host_visible_heap) {
// If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
// loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
// as the heap will be much larger.
if (size <= MAX_STREAM_BUFFER_SIZE) {
if (size <= max_stream_buffer_size) {
size = size * 40 / 100;
}
} else {
size = MAX_STREAM_BUFFER_SIZE;
size = max_stream_buffer_size;
}
return (std::min)(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE);
return std::min<size_t>(Common::AlignUp(size, max_alignment), max_stream_buffer_size);
}
} // Anonymous namespace
StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
Scheduler& scheduler_)
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size /
StagingBufferPool::NUM_SYNCS} {
StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_)
: memory_allocator{memory_allocator_}, scheduler{scheduler_}
, stream_buffer_size{GetStreamBufferSize(device, 256_MiB, MAX_ALIGNMENT)}
{
VkBufferCreateInfo stream_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = stream_buffer_size,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@@ -87,7 +74,20 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
if (device.IsBufferDeviceAddressSupported()) {
stream_ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
}
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
// *BSD drivers are more sensitive to increased buffers for streaming.
// Windows ones however, can intake bigger buffers and generally do not OOM.
// - GTX 960 on Windows will not OOM with 256mib
// - GT 1030 on ^BSD will OOM with 256mib
// This doesn't seem to be, however, universally true
try {
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
} catch (vk::Exception& e) {
LOG_ERROR(Render_Vulkan, "Can't fit {} bytes buffer, halving", stream_ci.size);
stream_buffer_size = GetStreamBufferSize(device, 128_MiB, MAX_ALIGNMENT);
stream_ci.size = stream_buffer_size;
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
}
region_size = stream_buffer_size / StagingBufferPool::NUM_SYNCS;
if (device.HasDebuggingToolAttached()) {
stream_buffer.SetObjectNameEXT("Stream Buffer");
}
@@ -100,11 +100,10 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
StagingBufferPool::~StagingBufferPool() = default;
StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) {
if (!deferred && usage == MemoryUsage::Upload && size <= region_size) {
return GetStreamBuffer(size);
}
return GetStagingBuffer(size, usage, deferred);
StagingBufferRef StagingBufferPool::Request(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
return (!deferred && usage == MemoryUsage::Upload && size <= region_size)
? GetStreamBuffer(device, size)
: GetStagingBuffer(device, size, usage, deferred);
}
void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) {
@@ -127,11 +126,10 @@ void StagingBufferPool::TickFrame() {
ReleaseCache(MemoryUsage::Download);
}
StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
if (AreRegionsActive(Region(free_iterator) + 1,
(std::min)(Region(iterator + size) + 1, NUM_SYNCS))) {
StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t size) {
if (AreRegionsActive(Region(free_iterator) + 1, (std::min)(Region(iterator + size) + 1, NUM_SYNCS))) {
// Avoid waiting for the previous usages to be free
return GetStagingBuffer(size, MemoryUsage::Upload);
return GetStagingBuffer(device, size, MemoryUsage::Upload);
}
const u64 current_tick = scheduler.CurrentTick();
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator),
@@ -140,15 +138,14 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
free_iterator = (std::max)(free_iterator, iterator + size);
if (iterator + size >= stream_buffer_size) {
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS,
current_tick);
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, current_tick);
used_iterator = 0;
iterator = 0;
free_iterator = size;
if (AreRegionsActive(0, Region(size) + 1)) {
// Avoid waiting for the previous usages to be free
return GetStagingBuffer(size, MemoryUsage::Upload);
return GetStagingBuffer(device, size, MemoryUsage::Upload);
}
}
const size_t offset = iterator;
@@ -156,7 +153,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
return StagingBufferRef{
.buffer = *stream_buffer,
.device_address = stream_buffer_address,
.offset = static_cast<VkDeviceSize>(offset),
.offset = VkDeviceSize(offset),
.mapped_span = stream_pointer.subspan(offset, size),
.usage{},
.log2_level{},
@@ -166,21 +163,18 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) const {
const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick();
return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end,
[gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; });
return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end, [gpu_tick](u64 sync_tick) {
return gpu_tick < sync_tick;
});
};
StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage,
bool deferred) {
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred)) {
StagingBufferRef StagingBufferPool::GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred))
return *ref;
}
return CreateStagingBuffer(size, usage, deferred);
return CreateStagingBuffer(device, size, usage, deferred);
}
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
MemoryUsage usage,
bool deferred) {
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred) {
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)];
const auto is_free = [this](const StagingBuffer& entry) {
@@ -202,7 +196,7 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s
return it->Ref();
}
StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred) {
StagingBufferRef StagingBufferPool::CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) {
auto const log2_size = Common::Log2Ceil<u32>(u32(size));
VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -33,11 +33,10 @@ class StagingBufferPool {
public:
static constexpr size_t NUM_SYNCS = 16;
explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator,
Scheduler& scheduler);
explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler);
~StagingBufferPool();
StagingBufferRef Request(size_t size, MemoryUsage usage, bool deferred = false);
StagingBufferRef Request(const Device& device, size_t size, MemoryUsage usage, bool deferred = false);
void FreeDeferred(StagingBufferRef& ref);
[[nodiscard]] VkBuffer StreamBuf() const noexcept {
@@ -84,27 +83,18 @@ private:
static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
StagingBufferRef GetStreamBuffer(size_t size);
StagingBufferRef GetStreamBuffer(const Device& device, size_t size);
bool AreRegionsActive(size_t region_begin, size_t region_end) const;
StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage, bool deferred = false);
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage,
bool deferred);
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred);
StagingBufferRef GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred = false);
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred);
StagingBufferRef CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred);
StagingBuffersCache& GetCache(MemoryUsage usage);
void ReleaseCache(MemoryUsage usage);
void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
size_t Region(size_t iter) const noexcept {
return iter / region_size;
}
const Device& device;
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
@@ -975,11 +975,11 @@ void TextureCacheRuntime::Finish() {
}
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.Request(size, MemoryUsage::Upload, deferred);
return staging_buffer_pool.Request(device, size, MemoryUsage::Upload, deferred);
}
StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.Request(size, MemoryUsage::Download, deferred);
return staging_buffer_pool.Request(device, size, MemoryUsage::Download, deferred);
}
void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) {