// 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 { 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; MemoryCommit commit; std::vector 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 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& bindings); void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings); std::span 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(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 quad_array_index_buffer; std::shared_ptr quad_strip_index_buffer; vk::Buffer null_buffer; MemoryCommit null_buffer_commit; std::unique_ptr 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; 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; } // namespace Vulkan