diff options
| author | 2019-02-26 02:09:43 -0300 | |
|---|---|---|
| committer | 2019-02-26 02:09:43 -0300 | |
| commit | 730eb1dad74756256a3f839215f6dc4f97181928 (patch) | |
| tree | 497ed0a321578fe19ec60efba4df4c13b6cf0205 /src | |
| parent | vk_stream_buffer: Implement a stream buffer (diff) | |
| download | yuzu-730eb1dad74756256a3f839215f6dc4f97181928.tar.gz yuzu-730eb1dad74756256a3f839215f6dc4f97181928.tar.xz yuzu-730eb1dad74756256a3f839215f6dc4f97181928.zip | |
vk_stream_buffer: Remove copy code path
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_stream_buffer.cpp | 52 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_stream_buffer.h | 19 |
2 files changed, 18 insertions, 53 deletions
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp index 1c5aefaec..58ffa42f2 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp | |||
| @@ -23,16 +23,15 @@ constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000; | |||
| 23 | VKStreamBuffer::VKStreamBuffer(const VKDevice& device, VKMemoryManager& memory_manager, | 23 | VKStreamBuffer::VKStreamBuffer(const VKDevice& device, VKMemoryManager& memory_manager, |
| 24 | VKScheduler& scheduler, u64 size, vk::BufferUsageFlags usage, | 24 | VKScheduler& scheduler, u64 size, vk::BufferUsageFlags usage, |
| 25 | vk::AccessFlags access, vk::PipelineStageFlags pipeline_stage) | 25 | vk::AccessFlags access, vk::PipelineStageFlags pipeline_stage) |
| 26 | : device{device}, scheduler{scheduler}, | 26 | : device{device}, scheduler{scheduler}, buffer_size{size}, access{access}, pipeline_stage{ |
| 27 | has_device_exclusive_memory{!memory_manager.IsMemoryUnified()}, | 27 | pipeline_stage} { |
| 28 | buffer_size{size}, access{access}, pipeline_stage{pipeline_stage} { | ||
| 29 | CreateBuffers(memory_manager, usage); | 28 | CreateBuffers(memory_manager, usage); |
| 30 | ReserveWatches(WATCHES_INITIAL_RESERVE); | 29 | ReserveWatches(WATCHES_INITIAL_RESERVE); |
| 31 | } | 30 | } |
| 32 | 31 | ||
| 33 | VKStreamBuffer::~VKStreamBuffer() = default; | 32 | VKStreamBuffer::~VKStreamBuffer() = default; |
| 34 | 33 | ||
| 35 | std::tuple<u8*, u64, vk::Buffer, bool> VKStreamBuffer::Reserve(u64 size, bool keep_in_host) { | 34 | std::tuple<u8*, u64, bool> VKStreamBuffer::Reserve(u64 size) { |
| 36 | ASSERT(size <= buffer_size); | 35 | ASSERT(size <= buffer_size); |
| 37 | mapped_size = size; | 36 | mapped_size = size; |
| 38 | 37 | ||
| @@ -44,10 +43,7 @@ std::tuple<u8*, u64, vk::Buffer, bool> VKStreamBuffer::Reserve(u64 size, bool ke | |||
| 44 | offset = 0; | 43 | offset = 0; |
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | use_device = has_device_exclusive_memory && !keep_in_host; | 46 | return {mapped_pointer + offset, offset, invalidation_mark.has_value()}; |
| 48 | |||
| 49 | const vk::Buffer buffer = use_device ? *device_buffer : *mappable_buffer; | ||
| 50 | return {mapped_pointer + offset, offset, buffer, invalidation_mark.has_value()}; | ||
| 51 | } | 47 | } |
| 52 | 48 | ||
| 53 | VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { | 49 | VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { |
| @@ -61,24 +57,6 @@ VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { | |||
| 61 | invalidation_mark = std::nullopt; | 57 | invalidation_mark = std::nullopt; |
| 62 | } | 58 | } |
| 63 | 59 | ||
| 64 | // Only copy to VRAM when requested. | ||
| 65 | if (use_device) { | ||
| 66 | const auto& dld = device.GetDispatchLoader(); | ||
| 67 | const u32 graphics_family = device.GetGraphicsFamily(); | ||
| 68 | const auto cmdbuf = exctx.GetCommandBuffer(); | ||
| 69 | |||
| 70 | // Buffers are mirrored, that's why the copy is done with the same offset on both buffers. | ||
| 71 | const vk::BufferCopy copy_region(offset, offset, size); | ||
| 72 | cmdbuf.copyBuffer(*mappable_buffer, *device_buffer, {copy_region}, dld); | ||
| 73 | |||
| 74 | // Protect the buffer from GPU usage until the copy has finished. | ||
| 75 | const vk::BufferMemoryBarrier barrier(vk::AccessFlagBits::eTransferWrite, access, | ||
| 76 | graphics_family, graphics_family, *device_buffer, | ||
| 77 | offset, size); | ||
| 78 | cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, pipeline_stage, {}, {}, | ||
| 79 | {barrier}, {}, dld); | ||
| 80 | } | ||
| 81 | |||
| 82 | if (used_watches + 1 >= watches.size()) { | 60 | if (used_watches + 1 >= watches.size()) { |
| 83 | // Ensure that there are enough watches. | 61 | // Ensure that there are enough watches. |
| 84 | ReserveWatches(WATCHES_RESERVE_CHUNK); | 62 | ReserveWatches(WATCHES_RESERVE_CHUNK); |
| @@ -92,26 +70,14 @@ VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { | |||
| 92 | } | 70 | } |
| 93 | 71 | ||
| 94 | void VKStreamBuffer::CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage) { | 72 | void VKStreamBuffer::CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage) { |
| 95 | vk::BufferUsageFlags mappable_usage = usage; | 73 | const vk::BufferCreateInfo buffer_ci({}, buffer_size, usage, vk::SharingMode::eExclusive, 0, |
| 96 | if (has_device_exclusive_memory) { | 74 | nullptr); |
| 97 | mappable_usage |= vk::BufferUsageFlagBits::eTransferSrc; | ||
| 98 | } | ||
| 99 | const vk::BufferCreateInfo buffer_ci({}, buffer_size, mappable_usage, | ||
| 100 | vk::SharingMode::eExclusive, 0, nullptr); | ||
| 101 | 75 | ||
| 102 | const auto dev = device.GetLogical(); | 76 | const auto dev = device.GetLogical(); |
| 103 | const auto& dld = device.GetDispatchLoader(); | 77 | const auto& dld = device.GetDispatchLoader(); |
| 104 | mappable_buffer = dev.createBufferUnique(buffer_ci, nullptr, dld); | 78 | buffer = dev.createBufferUnique(buffer_ci, nullptr, dld); |
| 105 | mappable_commit = memory_manager.Commit(*mappable_buffer, true); | 79 | commit = memory_manager.Commit(*buffer, true); |
| 106 | mapped_pointer = mappable_commit->GetData(); | 80 | mapped_pointer = commit->GetData(); |
| 107 | |||
| 108 | if (has_device_exclusive_memory) { | ||
| 109 | const vk::BufferCreateInfo buffer_ci({}, buffer_size, | ||
| 110 | usage | vk::BufferUsageFlagBits::eTransferDst, | ||
| 111 | vk::SharingMode::eExclusive, 0, nullptr); | ||
| 112 | device_buffer = dev.createBufferUnique(buffer_ci, nullptr, dld); | ||
| 113 | device_commit = memory_manager.Commit(*device_buffer, false); | ||
| 114 | } | ||
| 115 | } | 81 | } |
| 116 | 82 | ||
| 117 | void VKStreamBuffer::ReserveWatches(std::size_t grow_size) { | 83 | void VKStreamBuffer::ReserveWatches(std::size_t grow_size) { |
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h index 8c00d383a..69d036ccd 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h | |||
| @@ -31,15 +31,18 @@ public: | |||
| 31 | /** | 31 | /** |
| 32 | * Reserves a region of memory from the stream buffer. | 32 | * Reserves a region of memory from the stream buffer. |
| 33 | * @param size Size to reserve. | 33 | * @param size Size to reserve. |
| 34 | * @param keep_in_host Mapped buffer will be in host memory, skipping the copy to device local. | ||
| 35 | * @returns A tuple in the following order: Raw memory pointer (with offset added), buffer | 34 | * @returns A tuple in the following order: Raw memory pointer (with offset added), buffer |
| 36 | * offset, Vulkan buffer handle, buffer has been invalited. | 35 | * offset and a boolean that's true when buffer has been invalidated. |
| 37 | */ | 36 | */ |
| 38 | std::tuple<u8*, u64, vk::Buffer, bool> Reserve(u64 size, bool keep_in_host); | 37 | std::tuple<u8*, u64, bool> Reserve(u64 size); |
| 39 | 38 | ||
| 40 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. | 39 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. |
| 41 | [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx, u64 size); | 40 | [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx, u64 size); |
| 42 | 41 | ||
| 42 | vk::Buffer GetBuffer() const { | ||
| 43 | return *buffer; | ||
| 44 | } | ||
| 45 | |||
| 43 | private: | 46 | private: |
| 44 | /// Creates Vulkan buffer handles committing the required the required memory. | 47 | /// Creates Vulkan buffer handles committing the required the required memory. |
| 45 | void CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage); | 48 | void CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage); |
| @@ -50,19 +53,15 @@ private: | |||
| 50 | const VKDevice& device; ///< Vulkan device manager. | 53 | const VKDevice& device; ///< Vulkan device manager. |
| 51 | VKScheduler& scheduler; ///< Command scheduler. | 54 | VKScheduler& scheduler; ///< Command scheduler. |
| 52 | const u64 buffer_size; ///< Total size of the stream buffer. | 55 | const u64 buffer_size; ///< Total size of the stream buffer. |
| 53 | const bool has_device_exclusive_memory; ///< True if the streaming buffer will use VRAM. | ||
| 54 | const vk::AccessFlags access; ///< Access usage of this stream buffer. | 56 | const vk::AccessFlags access; ///< Access usage of this stream buffer. |
| 55 | const vk::PipelineStageFlags pipeline_stage; ///< Pipeline usage of this stream buffer. | 57 | const vk::PipelineStageFlags pipeline_stage; ///< Pipeline usage of this stream buffer. |
| 56 | 58 | ||
| 57 | UniqueBuffer mappable_buffer; ///< Mapped buffer. | 59 | UniqueBuffer buffer; ///< Mapped buffer. |
| 58 | UniqueBuffer device_buffer; ///< Buffer exclusive to the GPU. | 60 | VKMemoryCommit commit; ///< Memory commit. |
| 59 | VKMemoryCommit mappable_commit; ///< Commit visible from the CPU. | 61 | u8* mapped_pointer{}; ///< Pointer to the host visible commit |
| 60 | VKMemoryCommit device_commit; ///< Commit stored in VRAM. | ||
| 61 | u8* mapped_pointer{}; ///< Pointer to the host visible commit | ||
| 62 | 62 | ||
| 63 | u64 offset{}; ///< Buffer iterator. | 63 | u64 offset{}; ///< Buffer iterator. |
| 64 | u64 mapped_size{}; ///< Size reserved for the current copy. | 64 | u64 mapped_size{}; ///< Size reserved for the current copy. |
| 65 | bool use_device{}; ///< True if the current uses VRAM. | ||
| 66 | 65 | ||
| 67 | std::vector<std::unique_ptr<VKFenceWatch>> watches; ///< Total watches | 66 | std::vector<std::unique_ptr<VKFenceWatch>> watches; ///< Total watches |
| 68 | std::size_t used_watches{}; ///< Count of watches, reset on invalidation. | 67 | std::size_t used_watches{}; ///< Count of watches, reset on invalidation. |