Files
KytyPS5/src/graphics/host_gpu/renderer/streamBuffer.cpp
T
2026-07-18 09:01:52 +02:00

98 lines
3.0 KiB
C++

#include "graphics/host_gpu/renderer/streamBuffer.h"
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/profiler.h"
#include "graphics/host_gpu/graphicContext.h"
#include "graphics/host_gpu/utils.h"
#include "graphics/host_gpu/vma.h"
#include <atomic>
#include <cstring>
namespace Libs::Graphics {
namespace {
std::atomic<uint64_t> g_stream_buffer_count {0};
} // namespace
HostStreamBuffer::HostStreamBuffer() = default;
HostStreamBuffer::~HostStreamBuffer() {
Release();
}
void HostStreamBuffer::EnsureBuffer(GraphicContext* ctx) {
if (m_buffer != nullptr) {
if (m_ctx != ctx || m_mapped == nullptr) {
EXIT("host stream buffer changed graphics context\n");
}
return;
}
KYTY_PROFILER_BLOCK("HostStreamBuffer::create");
m_ctx = ctx;
m_buffer = std::make_unique<VulkanBuffer>();
m_buffer->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT;
m_buffer->memory.property = static_cast<uint32_t>(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
VulkanCreateBuffer(ctx, CAPACITY, m_buffer.get());
VulkanMapMemory(ctx, &m_buffer->memory, &m_mapped);
const auto count = g_stream_buffer_count.fetch_add(1, std::memory_order_relaxed) + 1;
LOGF("HostStreamBuffer: created serial=%" PRIu64 " capacity=%" PRIu64 "\n", count, CAPACITY);
}
bool HostStreamBuffer::Copy(GraphicContext* ctx, const void* src, uint64_t size, uint64_t alignment,
VulkanBuffer** out_buffer, uint64_t* out_offset, uint64_t* out_range) {
KYTY_PROFILER_FUNCTION();
if (ctx == nullptr || src == nullptr || out_buffer == nullptr || out_offset == nullptr ||
out_range == nullptr) {
EXIT("invalid host stream upload\n");
}
std::lock_guard lock(m_mutex);
if (size == 0) {
return false;
}
if (alignment == 0) {
alignment = 1;
}
if ((alignment & (alignment - 1)) != 0 || m_offset > UINT64_MAX - (alignment - 1)) {
return false;
}
const auto offset = (m_offset + alignment - 1) & ~(alignment - 1);
if (offset > CAPACITY || size > CAPACITY - offset) {
return false;
}
EnsureBuffer(ctx);
std::memcpy(static_cast<uint8_t*>(m_mapped) + offset, src, static_cast<size_t>(size));
m_offset = offset + size;
*out_buffer = m_buffer.get();
*out_offset = offset;
*out_range = size;
return true;
}
void HostStreamBuffer::Reset() noexcept {
std::lock_guard lock(m_mutex);
m_offset = 0;
}
void HostStreamBuffer::Release() noexcept {
std::lock_guard lock(m_mutex);
if (m_buffer != nullptr) {
if (m_ctx == nullptr || m_mapped == nullptr) {
EXIT("invalid host stream buffer release state\n");
}
VulkanUnmapMemory(m_ctx, &m_buffer->memory);
VulkanDeleteBuffer(m_ctx, m_buffer.get());
m_buffer.reset();
}
m_ctx = nullptr;
m_mapped = nullptr;
m_offset = 0;
}
} // namespace Libs::Graphics