168 lines
5.7 KiB
C++
168 lines
5.7 KiB
C++
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include "video_core/buffer_cache/buffer_cache_base.h"
|
|
#include "video_core/buffer_cache/memory_tracker_base.h"
|
|
#include "video_core/engines/maxwell_3d.h"
|
|
#include "video_core/renderer_vulkan/vk_compute_pass.h"
|
|
#include "video_core/renderer_vulkan/vk_staging_buffer_pool.h"
|
|
#include "video_core/renderer_vulkan/vk_update_descriptor.h"
|
|
#include "video_core/surface.h"
|
|
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
|
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
|
|
|
namespace Vulkan {
|
|
|
|
class Device;
|
|
class DescriptorPool;
|
|
class Scheduler;
|
|
struct HostVertexBinding;
|
|
|
|
class BufferCacheRuntime;
|
|
|
|
class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> {
|
|
public:
|
|
explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params);
|
|
explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_,
|
|
VAddr cpu_addr_, u64 size_bytes_);
|
|
|
|
[[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
|
|
|
|
[[nodiscard]] VkBuffer Handle() const noexcept {
|
|
return *buffer;
|
|
}
|
|
|
|
operator VkBuffer() const noexcept {
|
|
return *buffer;
|
|
}
|
|
|
|
private:
|
|
struct BufferView {
|
|
u32 offset;
|
|
u32 size;
|
|
VideoCore::Surface::PixelFormat format;
|
|
vk::BufferView handle;
|
|
};
|
|
|
|
const Device* device{};
|
|
vk::Buffer buffer;
|
|
std::vector<BufferView> views;
|
|
};
|
|
|
|
class QuadArrayIndexBuffer;
|
|
class QuadStripIndexBuffer;
|
|
|
|
class BufferCacheRuntime {
|
|
friend Buffer;
|
|
|
|
using PrimitiveTopology = Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology;
|
|
using IndexFormat = Tegra::Engines::Maxwell3D::Regs::IndexFormat;
|
|
|
|
public:
|
|
explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_,
|
|
Scheduler& scheduler_, StagingBufferPool& staging_pool_,
|
|
GuestDescriptorQueue& guest_descriptor_queue,
|
|
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
|
|
DescriptorPool& descriptor_pool);
|
|
|
|
void Finish();
|
|
|
|
u64 GetDeviceLocalMemory() const;
|
|
|
|
u64 GetDeviceMemoryUsage() const;
|
|
|
|
bool CanReportMemoryUsage() const;
|
|
|
|
[[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size);
|
|
|
|
[[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size, bool deferred = false);
|
|
|
|
void FreeDeferredStagingBuffer(StagingBufferRef& ref);
|
|
|
|
void PreCopyBarrier();
|
|
|
|
void CopyBuffer(VkBuffer src_buffer, VkBuffer dst_buffer,
|
|
std::span<const VideoCommon::BufferCopy> copies, bool barrier = true);
|
|
|
|
void PostCopyBarrier();
|
|
|
|
void ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t size, u32 value);
|
|
|
|
void BindIndexBuffer(PrimitiveTopology topology, IndexFormat index_format, u32 num_indices,
|
|
u32 base_vertex, VkBuffer buffer, u32 offset, u32 size);
|
|
|
|
void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count);
|
|
|
|
void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride);
|
|
|
|
void BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings);
|
|
|
|
void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
|
|
|
|
void BindTransformFeedbackBuffers(VideoCommon::HostBindings<Buffer>& bindings);
|
|
|
|
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);
|
|
BindBuffer(ref.buffer, static_cast<u32>(ref.offset), size);
|
|
return ref.mapped_span;
|
|
}
|
|
|
|
void BindUniformBuffer(VkBuffer buffer, u32 offset, u32 size) {
|
|
BindBuffer(buffer, offset, size);
|
|
}
|
|
|
|
void BindStorageBuffer(VkBuffer buffer, u32 offset, u32 size,
|
|
[[maybe_unused]] bool is_written) {
|
|
BindBuffer(buffer, offset, size);
|
|
}
|
|
|
|
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
|
|
VideoCore::Surface::PixelFormat format) {
|
|
guest_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format));
|
|
}
|
|
|
|
private:
|
|
void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
|
|
guest_descriptor_queue.AddBuffer(buffer, offset, size);
|
|
}
|
|
|
|
void ReserveNullBuffer();
|
|
|
|
const Device& device;
|
|
MemoryAllocator& memory_allocator;
|
|
Scheduler& scheduler;
|
|
StagingBufferPool& staging_pool;
|
|
GuestDescriptorQueue& guest_descriptor_queue;
|
|
|
|
std::shared_ptr<QuadArrayIndexBuffer> quad_array_index_buffer;
|
|
std::shared_ptr<QuadStripIndexBuffer> quad_strip_index_buffer;
|
|
|
|
vk::Buffer null_buffer;
|
|
|
|
std::unique_ptr<Uint8Pass> uint8_pass;
|
|
QuadIndexedPass quad_index_pass;
|
|
};
|
|
|
|
struct BufferCacheParams {
|
|
using Runtime = Vulkan::BufferCacheRuntime;
|
|
using Buffer = Vulkan::Buffer;
|
|
using Async_Buffer = Vulkan::StagingBufferRef;
|
|
using MemoryTracker = VideoCommon::MemoryTrackerBase<VideoCore::RasterizerInterface>;
|
|
|
|
static constexpr bool IS_OPENGL = false;
|
|
static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = false;
|
|
static constexpr bool HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT = false;
|
|
static constexpr bool NEEDS_BIND_UNIFORM_INDEX = false;
|
|
static constexpr bool NEEDS_BIND_STORAGE_INDEX = false;
|
|
static constexpr bool USE_MEMORY_MAPS = true;
|
|
static constexpr bool SEPARATE_IMAGE_BUFFER_BINDINGS = false;
|
|
static constexpr bool IMPLEMENTS_ASYNC_DOWNLOADS = true;
|
|
static constexpr bool USE_MEMORY_MAPS_FOR_UPLOADS = true;
|
|
};
|
|
|
|
using BufferCache = VideoCommon::BufferCache<BufferCacheParams>;
|
|
|
|
} // namespace Vulkan
|