mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-25 14:42:44 +00:00
vk_stream_buffer: Remove copy code path
This commit is contained in:
parent
33a0597603
commit
730eb1dad7
|
@ -23,16 +23,15 @@ constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000;
|
||||||
VKStreamBuffer::VKStreamBuffer(const VKDevice& device, VKMemoryManager& memory_manager,
|
VKStreamBuffer::VKStreamBuffer(const VKDevice& device, VKMemoryManager& memory_manager,
|
||||||
VKScheduler& scheduler, u64 size, vk::BufferUsageFlags usage,
|
VKScheduler& scheduler, u64 size, vk::BufferUsageFlags usage,
|
||||||
vk::AccessFlags access, vk::PipelineStageFlags pipeline_stage)
|
vk::AccessFlags access, vk::PipelineStageFlags pipeline_stage)
|
||||||
: device{device}, scheduler{scheduler},
|
: device{device}, scheduler{scheduler}, buffer_size{size}, access{access}, pipeline_stage{
|
||||||
has_device_exclusive_memory{!memory_manager.IsMemoryUnified()},
|
pipeline_stage} {
|
||||||
buffer_size{size}, access{access}, pipeline_stage{pipeline_stage} {
|
|
||||||
CreateBuffers(memory_manager, usage);
|
CreateBuffers(memory_manager, usage);
|
||||||
ReserveWatches(WATCHES_INITIAL_RESERVE);
|
ReserveWatches(WATCHES_INITIAL_RESERVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VKStreamBuffer::~VKStreamBuffer() = default;
|
VKStreamBuffer::~VKStreamBuffer() = default;
|
||||||
|
|
||||||
std::tuple<u8*, u64, vk::Buffer, bool> VKStreamBuffer::Reserve(u64 size, bool keep_in_host) {
|
std::tuple<u8*, u64, bool> VKStreamBuffer::Reserve(u64 size) {
|
||||||
ASSERT(size <= buffer_size);
|
ASSERT(size <= buffer_size);
|
||||||
mapped_size = size;
|
mapped_size = size;
|
||||||
|
|
||||||
|
@ -44,10 +43,7 @@ std::tuple<u8*, u64, vk::Buffer, bool> VKStreamBuffer::Reserve(u64 size, bool ke
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
use_device = has_device_exclusive_memory && !keep_in_host;
|
return {mapped_pointer + offset, offset, invalidation_mark.has_value()};
|
||||||
|
|
||||||
const vk::Buffer buffer = use_device ? *device_buffer : *mappable_buffer;
|
|
||||||
return {mapped_pointer + offset, offset, buffer, invalidation_mark.has_value()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) {
|
VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) {
|
||||||
|
@ -61,24 +57,6 @@ VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) {
|
||||||
invalidation_mark = std::nullopt;
|
invalidation_mark = std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only copy to VRAM when requested.
|
|
||||||
if (use_device) {
|
|
||||||
const auto& dld = device.GetDispatchLoader();
|
|
||||||
const u32 graphics_family = device.GetGraphicsFamily();
|
|
||||||
const auto cmdbuf = exctx.GetCommandBuffer();
|
|
||||||
|
|
||||||
// Buffers are mirrored, that's why the copy is done with the same offset on both buffers.
|
|
||||||
const vk::BufferCopy copy_region(offset, offset, size);
|
|
||||||
cmdbuf.copyBuffer(*mappable_buffer, *device_buffer, {copy_region}, dld);
|
|
||||||
|
|
||||||
// Protect the buffer from GPU usage until the copy has finished.
|
|
||||||
const vk::BufferMemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, access,
|
|
||||||
graphics_family, graphics_family, *device_buffer,
|
|
||||||
offset, size);
|
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, pipeline_stage, {}, {},
|
|
||||||
{barrier}, {}, dld);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used_watches + 1 >= watches.size()) {
|
if (used_watches + 1 >= watches.size()) {
|
||||||
// Ensure that there are enough watches.
|
// Ensure that there are enough watches.
|
||||||
ReserveWatches(WATCHES_RESERVE_CHUNK);
|
ReserveWatches(WATCHES_RESERVE_CHUNK);
|
||||||
|
@ -92,26 +70,14 @@ VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStreamBuffer::CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage) {
|
void VKStreamBuffer::CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage) {
|
||||||
vk::BufferUsageFlags mappable_usage = usage;
|
const vk::BufferCreateInfo buffer_ci({}, buffer_size, usage, vk::SharingMode::eExclusive, 0,
|
||||||
if (has_device_exclusive_memory) {
|
nullptr);
|
||||||
mappable_usage |= vk::BufferUsageFlagBits::eTransferSrc;
|
|
||||||
}
|
|
||||||
const vk::BufferCreateInfo buffer_ci({}, buffer_size, mappable_usage,
|
|
||||||
vk::SharingMode::eExclusive, 0, nullptr);
|
|
||||||
|
|
||||||
const auto dev = device.GetLogical();
|
const auto dev = device.GetLogical();
|
||||||
const auto& dld = device.GetDispatchLoader();
|
const auto& dld = device.GetDispatchLoader();
|
||||||
mappable_buffer = dev.createBufferUnique(buffer_ci, nullptr, dld);
|
buffer = dev.createBufferUnique(buffer_ci, nullptr, dld);
|
||||||
mappable_commit = memory_manager.Commit(*mappable_buffer, true);
|
commit = memory_manager.Commit(*buffer, true);
|
||||||
mapped_pointer = mappable_commit->GetData();
|
mapped_pointer = commit->GetData();
|
||||||
|
|
||||||
if (has_device_exclusive_memory) {
|
|
||||||
const vk::BufferCreateInfo buffer_ci({}, buffer_size,
|
|
||||||
usage | vk::BufferUsageFlagBits::eTransferDst,
|
|
||||||
vk::SharingMode::eExclusive, 0, nullptr);
|
|
||||||
device_buffer = dev.createBufferUnique(buffer_ci, nullptr, dld);
|
|
||||||
device_commit = memory_manager.Commit(*device_buffer, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKStreamBuffer::ReserveWatches(std::size_t grow_size) {
|
void VKStreamBuffer::ReserveWatches(std::size_t grow_size) {
|
||||||
|
|
|
@ -31,15 +31,18 @@ public:
|
||||||
/**
|
/**
|
||||||
* Reserves a region of memory from the stream buffer.
|
* Reserves a region of memory from the stream buffer.
|
||||||
* @param size Size to reserve.
|
* @param size Size to reserve.
|
||||||
* @param keep_in_host Mapped buffer will be in host memory, skipping the copy to device local.
|
|
||||||
* @returns A tuple in the following order: Raw memory pointer (with offset added), buffer
|
* @returns A tuple in the following order: Raw memory pointer (with offset added), buffer
|
||||||
* offset, Vulkan buffer handle, buffer has been invalited.
|
* offset and a boolean that's true when buffer has been invalidated.
|
||||||
*/
|
*/
|
||||||
std::tuple<u8*, u64, vk::Buffer, bool> Reserve(u64 size, bool keep_in_host);
|
std::tuple<u8*, u64, bool> Reserve(u64 size);
|
||||||
|
|
||||||
/// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy.
|
/// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy.
|
||||||
[[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx, u64 size);
|
[[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx, u64 size);
|
||||||
|
|
||||||
|
vk::Buffer GetBuffer() const {
|
||||||
|
return *buffer;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Creates Vulkan buffer handles committing the required the required memory.
|
/// Creates Vulkan buffer handles committing the required the required memory.
|
||||||
void CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage);
|
void CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage);
|
||||||
|
@ -50,19 +53,15 @@ private:
|
||||||
const VKDevice& device; ///< Vulkan device manager.
|
const VKDevice& device; ///< Vulkan device manager.
|
||||||
VKScheduler& scheduler; ///< Command scheduler.
|
VKScheduler& scheduler; ///< Command scheduler.
|
||||||
const u64 buffer_size; ///< Total size of the stream buffer.
|
const u64 buffer_size; ///< Total size of the stream buffer.
|
||||||
const bool has_device_exclusive_memory; ///< True if the streaming buffer will use VRAM.
|
|
||||||
const vk::AccessFlags access; ///< Access usage of this stream buffer.
|
const vk::AccessFlags access; ///< Access usage of this stream buffer.
|
||||||
const vk::PipelineStageFlags pipeline_stage; ///< Pipeline usage of this stream buffer.
|
const vk::PipelineStageFlags pipeline_stage; ///< Pipeline usage of this stream buffer.
|
||||||
|
|
||||||
UniqueBuffer mappable_buffer; ///< Mapped buffer.
|
UniqueBuffer buffer; ///< Mapped buffer.
|
||||||
UniqueBuffer device_buffer; ///< Buffer exclusive to the GPU.
|
VKMemoryCommit commit; ///< Memory commit.
|
||||||
VKMemoryCommit mappable_commit; ///< Commit visible from the CPU.
|
u8* mapped_pointer{}; ///< Pointer to the host visible commit
|
||||||
VKMemoryCommit device_commit; ///< Commit stored in VRAM.
|
|
||||||
u8* mapped_pointer{}; ///< Pointer to the host visible commit
|
|
||||||
|
|
||||||
u64 offset{}; ///< Buffer iterator.
|
u64 offset{}; ///< Buffer iterator.
|
||||||
u64 mapped_size{}; ///< Size reserved for the current copy.
|
u64 mapped_size{}; ///< Size reserved for the current copy.
|
||||||
bool use_device{}; ///< True if the current uses VRAM.
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<VKFenceWatch>> watches; ///< Total watches
|
std::vector<std::unique_ptr<VKFenceWatch>> watches; ///< Total watches
|
||||||
std::size_t used_watches{}; ///< Count of watches, reset on invalidation.
|
std::size_t used_watches{}; ///< Count of watches, reset on invalidation.
|
||||||
|
|
Loading…
Reference in a new issue