From 82b3fcca18ab20764036de8b8d2eaf84416ddb55 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Sat, 6 Apr 2024 09:55:26 +0200 Subject: [PATCH] metal: create texture cache in rasterizer --- .../renderer_metal/mtl_rasterizer.h | 14 +- .../renderer_metal/mtl_rasterizer.mm | 13 +- .../renderer_metal/mtl_staging_buffer_pool.mm | 4 +- .../renderer_metal/mtl_texture_cache.h | 79 +++++--- .../renderer_metal/mtl_texture_cache.mm | 171 ++++++++++++------ .../renderer_metal/renderer_metal.mm | 2 +- 6 files changed, 198 insertions(+), 85 deletions(-) diff --git a/src/video_core/renderer_metal/mtl_rasterizer.h b/src/video_core/renderer_metal/mtl_rasterizer.h index 95263566af..9ea17af354 100644 --- a/src/video_core/renderer_metal/mtl_rasterizer.h +++ b/src/video_core/renderer_metal/mtl_rasterizer.h @@ -3,10 +3,11 @@ #pragma once #include "common/common_types.h" +#include "mtl_texture_cache.h" #include "video_core/control/channel_state_cache.h" #include "video_core/engines/maxwell_dma.h" #include "video_core/rasterizer_interface.h" -#include "video_core/renderer_metal/objc_bridge.h" +#include "video_core/renderer_metal/mtl_texture_cache.h" namespace Core { class System; @@ -17,6 +18,7 @@ namespace Metal { class Device; class CommandRecorder; class SwapChain; +class TextureCacheRuntime; class RasterizerMetal; @@ -38,8 +40,9 @@ public: class RasterizerMetal final : public VideoCore::RasterizerInterface, protected VideoCommon::ChannelSetupCaches { public: - explicit RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, - CommandRecorder& command_recorder_, const SwapChain& swap_chain_); + explicit RasterizerMetal(Tegra::GPU& gpu_, Tegra::MaxwellDeviceMemoryManager& device_memory_, + const Device& device_, CommandRecorder& command_recorder_, + const SwapChain& swap_chain_); ~RasterizerMetal() override; void Draw(bool is_indexed, u32 instance_count) override; @@ -91,10 +94,15 @@ public: private: Tegra::GPU& gpu; AccelerateDMA accelerate_dma; + Tegra::MaxwellDeviceMemoryManager& device_memory; const Device& device; CommandRecorder& command_recorder; const SwapChain& swap_chain; + + StagingBufferPool staging_buffer_pool; + TextureCacheRuntime texture_cache_runtime; + TextureCache texture_cache; }; } // namespace Metal diff --git a/src/video_core/renderer_metal/mtl_rasterizer.mm b/src/video_core/renderer_metal/mtl_rasterizer.mm index 3554670cbd..ce93692547 100644 --- a/src/video_core/renderer_metal/mtl_rasterizer.mm +++ b/src/video_core/renderer_metal/mtl_rasterizer.mm @@ -11,6 +11,7 @@ #include "video_core/renderer_metal/mtl_command_recorder.h" #include "video_core/renderer_metal/mtl_device.h" #include "video_core/renderer_metal/mtl_rasterizer.h" +#include "video_core/texture_cache/texture_cache_base.h" #include @@ -25,9 +26,15 @@ bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { return true; } -RasterizerMetal::RasterizerMetal(Tegra::GPU& gpu_, const Device& device_, - CommandRecorder& command_recorder_, const SwapChain& swap_chain_) - : gpu{gpu_}, device{device_}, command_recorder{command_recorder_}, swap_chain{swap_chain_} {} +RasterizerMetal::RasterizerMetal(Tegra::GPU& gpu_, + Tegra::MaxwellDeviceMemoryManager& device_memory_, + const Device& device_, CommandRecorder& command_recorder_, + const SwapChain& swap_chain_) + : gpu{gpu_}, device_memory{device_memory_}, device{device_}, + command_recorder{command_recorder_}, swap_chain{swap_chain_}, + staging_buffer_pool(device, command_recorder), + texture_cache_runtime(device, command_recorder, staging_buffer_pool), + texture_cache(texture_cache_runtime, device_memory) {} RasterizerMetal::~RasterizerMetal() = default; void RasterizerMetal::Draw(bool is_indexed, u32 instance_count) { diff --git a/src/video_core/renderer_metal/mtl_staging_buffer_pool.mm b/src/video_core/renderer_metal/mtl_staging_buffer_pool.mm index b69720a44e..7f420c64a5 100644 --- a/src/video_core/renderer_metal/mtl_staging_buffer_pool.mm +++ b/src/video_core/renderer_metal/mtl_staging_buffer_pool.mm @@ -42,7 +42,7 @@ constexpr size_t REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS StagingBufferPool::StagingBufferPool(const Device& device_, CommandRecorder& command_recorder_) : device{device_}, command_recorder{command_recorder_} { stream_buffer = [device.GetDevice() newBufferWithLength:STREAM_BUFFER_SIZE - options:MTLResourceStorageModePrivate]; + options:MTLResourceStorageModeShared]; } StagingBufferPool::~StagingBufferPool() = default; @@ -83,7 +83,7 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage bool deferred) { const u32 log2 = Common::Log2Ceil64(size); MTLBuffer_t buffer = [device.GetDevice() newBufferWithLength:size - options:MTLResourceStorageModePrivate]; + options:MTLResourceStorageModeShared]; // TODO: check if the mapped span is correct std::span mapped_span(static_cast([buffer contents]), size); auto& entry = GetCache(usage)[log2].entries.emplace_back(buffer, mapped_span); diff --git a/src/video_core/renderer_metal/mtl_texture_cache.h b/src/video_core/renderer_metal/mtl_texture_cache.h index a866bf731e..328a074263 100644 --- a/src/video_core/renderer_metal/mtl_texture_cache.h +++ b/src/video_core/renderer_metal/mtl_texture_cache.h @@ -4,6 +4,7 @@ #include +#include "mtl_staging_buffer_pool.h" #include "video_core/texture_cache/texture_cache_base.h" #include "shader_recompiler/shader_info.h" @@ -24,6 +25,7 @@ using VideoCommon::Region2D; using VideoCommon::RenderTargets; using VideoCore::Surface::PixelFormat; +class CommandRecorder; class Device; class Image; class ImageView; @@ -31,9 +33,13 @@ class Framebuffer; class TextureCacheRuntime { public: - explicit TextureCacheRuntime(const Device& device_); + explicit TextureCacheRuntime(const Device& device_, CommandRecorder& command_recorder_, + StagingBufferPool& staging_buffer_pool_); - void Finish(); + // TODO: implement + void Finish() {} + + void TickFrame(); StagingBufferRef UploadStagingBuffer(size_t size); @@ -45,35 +51,49 @@ public: return true; } - void TickFrame(); + u64 GetDeviceLocalMemory() const { + return 0; + } - u64 GetDeviceLocalMemory() const; + u64 GetDeviceMemoryUsage() const { + return 0; + } - u64 GetDeviceMemoryUsage() const; - - bool CanReportMemoryUsage() const; + bool CanReportMemoryUsage() const { + return false; + } + // TODO: implement void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, const Region2D& dst_region, const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, - Tegra::Engines::Fermi2D::Operation operation); + Tegra::Engines::Fermi2D::Operation operation) {} - void CopyImage(Image& dst, Image& src, std::span copies); + // TODO: implement + void CopyImage(Image& dst, Image& src, std::span copies) {} - void CopyImageMSAA(Image& dst, Image& src, std::span copies); + // TODO: implement + void CopyImageMSAA(Image& dst, Image& src, std::span copies) {} - bool ShouldReinterpret(Image& dst, Image& src); + bool ShouldReinterpret(Image& dst, Image& src) { + // HACK + return false; + } - void ReinterpretImage(Image& dst, Image& src, std::span copies); + // TODO: implement + void ReinterpretImage(Image& dst, Image& src, std::span copies) {} - void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view); + // TODO: implement + void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {} - void InsertUploadMemoryBarrier(); + // TODO: implement + void InsertUploadMemoryBarrier() {} void TransitionImageLayout(Image& image) {} + // TODO: implement void AccelerateImageUpload(Image&, const StagingBufferRef&, - std::span); + std::span) {} bool HasNativeBgr() const noexcept { return true; @@ -83,9 +103,12 @@ public: return false; } - void BarrierFeedbackLoop(); + // TODO: implement + void BarrierFeedbackLoop() {} const Device& device; + CommandRecorder& command_recorder; + StagingBufferPool& staging_buffer_pool; const Settings::ResolutionScalingInfo& resolution; }; @@ -112,25 +135,39 @@ public: void DownloadMemory(MTLBuffer_t buffer, size_t offset, std::span copies); + // For some reason, this function cannot be defined in the .mm file since it would report + // undefined symbols void DownloadMemory(std::span buffers, std::span offsets, - std::span copies); + std::span copies) { + // TODO: implement + } void DownloadMemory(const StagingBufferRef& map, std::span copies); - bool IsRescaled() const; + bool IsRescaled() const { + return rescaled; + } - bool ScaleUp(bool ignore = false); + bool ScaleUp(bool ignore = false) { + // HACK + return true; + } - bool ScaleDown(bool ignore = false); + bool ScaleDown(bool ignore = false) { + // HACK + return true; + } MTLTexture_t GetHandle() const noexcept { return texture; } private: - MTLTexture_t texture; + MTLTexture_t texture = nil; bool initialized = false; + + bool rescaled = false; }; class ImageView : public VideoCommon::ImageViewBase { diff --git a/src/video_core/renderer_metal/mtl_texture_cache.mm b/src/video_core/renderer_metal/mtl_texture_cache.mm index ac9de037d1..6bc65929f3 100644 --- a/src/video_core/renderer_metal/mtl_texture_cache.mm +++ b/src/video_core/renderer_metal/mtl_texture_cache.mm @@ -33,91 +33,152 @@ using VideoCore::Surface::IsPixelFormatASTC; using VideoCore::Surface::IsPixelFormatInteger; using VideoCore::Surface::SurfaceType; -TextureCacheRuntime::TextureCacheRuntime(const Device &device_) - : device{device_}, resolution{Settings::values.resolution_info} {} +TextureCacheRuntime::TextureCacheRuntime(const Device& device_, CommandRecorder& command_recorder_, + StagingBufferPool& staging_buffer_pool_) + : device{device_}, command_recorder{command_recorder_}, + staging_buffer_pool{staging_buffer_pool_}, + resolution{Settings::values.resolution_info} {} void TextureCacheRuntime::TickFrame() {} -Image::Image(TextureCacheRuntime &runtime, const ImageInfo &info, +StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size) { + return staging_buffer_pool.Request(size, MemoryUsage::Upload); +} + +StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { + return staging_buffer_pool.Request(size, MemoryUsage::Download, deferred); +} + +void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) { + staging_buffer_pool.FreeDeferred(ref); +} + +Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info, GPUVAddr gpu_addr_, VAddr cpu_addr_) : VideoCommon::ImageBase(info, gpu_addr_, cpu_addr_) { - MTLTextureDescriptor *texture_descriptor = - [[MTLTextureDescriptor alloc] init]; - // TODO: don't hardcode the format - texture_descriptor.pixelFormat = MTLPixelFormatRGBA8Unorm; - texture_descriptor.width = info.size.width; - texture_descriptor.height = info.size.height; + MTLTextureDescriptor *texture_descriptor = + [[MTLTextureDescriptor alloc] init]; + // TODO: don't hardcode the format + texture_descriptor.pixelFormat = MTLPixelFormatRGBA8Unorm; + texture_descriptor.width = info.size.width; + texture_descriptor.height = info.size.height; - texture = - [runtime.device.GetDevice() newTextureWithDescriptor:texture_descriptor]; + texture = + [runtime.device.GetDevice() newTextureWithDescriptor:texture_descriptor]; } -Image::~Image() { [texture release]; } +Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} -ImageView::ImageView(TextureCacheRuntime &runtime, - const VideoCommon::ImageViewInfo &info, ImageId image_id_, - Image &image) +Image::~Image() { + if (texture) { + [texture release]; + } +} + +// TODO: implement these +void Image::UploadMemory(MTLBuffer_t buffer, size_t offset, + std::span copies) { + ; +} + +void Image::UploadMemory(const StagingBufferRef& map, + std::span copies) { + ; +} + +void Image::DownloadMemory(MTLBuffer_t buffer, size_t offset, + std::span copies) { + ; +} + +// TODO: uncomment +/* +void Image::DownloadMemory(std::span buffers, std::span offsets, + std::span copies) { + ; +} +*/ + +void Image::DownloadMemory(const StagingBufferRef& map, + std::span copies) { + ; +} + +ImageView::ImageView(TextureCacheRuntime& runtime, + const VideoCommon::ImageViewInfo& info, ImageId image_id_, + Image& image) : VideoCommon::ImageViewBase{info, image.info, image_id_, image.gpu_addr} { - using Shader::TextureType; + using Shader::TextureType; - texture = [image.GetHandle() retain]; + texture = [image.GetHandle() retain]; - // TODO: create texture view + // TODO: create texture view } -ImageView::ImageView(TextureCacheRuntime &runtime, - const VideoCommon::ImageViewInfo &info, ImageId image_id_, - Image &image, const SlotVector& slot_imgs) +ImageView::ImageView(TextureCacheRuntime& runtime, + const VideoCommon::ImageViewInfo& info, ImageId image_id_, + Image& image, const SlotVector& slot_imgs) : ImageView(runtime, info, image_id_, image) { - // TODO: save slot images + // TODO: save slot images +} + +ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, + const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) + : VideoCommon::ImageViewBase{info, view_info, gpu_addr_} { + // TODO: implement +} + +ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params) + : VideoCommon::ImageViewBase{params} { + // TODO: implement } ImageView::~ImageView() { [texture release]; } -Sampler::Sampler(TextureCacheRuntime &runtime, - const Tegra::Texture::TSCEntry &tsc) { - MTLSamplerDescriptor *sampler_descriptor = - [[MTLSamplerDescriptor alloc] init]; +Sampler::Sampler(TextureCacheRuntime& runtime, + const Tegra::Texture::TSCEntry& tsc) { + MTLSamplerDescriptor* sampler_descriptor = + [[MTLSamplerDescriptor alloc] init]; - // TODO: configure the descriptor + // TODO: configure the descriptor - sampler_state = [runtime.device.GetDevice() - newSamplerStateWithDescriptor:sampler_descriptor]; + sampler_state = [runtime.device.GetDevice() + newSamplerStateWithDescriptor:sampler_descriptor]; } -Framebuffer::Framebuffer(TextureCacheRuntime &runtime, - std::span color_buffers, - ImageView *depth_buffer, - const VideoCommon::RenderTargets &key) { - CreateRenderPassDescriptor(runtime, color_buffers, depth_buffer, - key.is_rescaled, key.size.width, key.size.height); +Framebuffer::Framebuffer(TextureCacheRuntime& runtime, + std::span color_buffers, + ImageView* depth_buffer, + const VideoCommon::RenderTargets& key) { + CreateRenderPassDescriptor(runtime, color_buffers, depth_buffer, + key.is_rescaled, key.size.width, key.size.height); } Framebuffer::~Framebuffer() = default; void Framebuffer::CreateRenderPassDescriptor( - TextureCacheRuntime &runtime, std::span color_buffers, - ImageView *depth_buffer, bool is_rescaled, size_t width, size_t height) { - render_pass = [MTLRenderPassDescriptor renderPassDescriptor]; + TextureCacheRuntime& runtime, std::span color_buffers, + ImageView* depth_buffer, bool is_rescaled, size_t width, size_t height) { + render_pass = [MTLRenderPassDescriptor renderPassDescriptor]; - for (size_t index = 0; index < NUM_RT; ++index) { - const ImageView *const color_buffer = color_buffers[index]; - if (!color_buffer) { - continue; + for (size_t index = 0; index < NUM_RT; ++index) { + const ImageView* const color_buffer = color_buffers[index]; + if (!color_buffer) { + continue; + } + // TODO: don't use index as attachment index + render_pass.colorAttachments[index].clearColor = + MTLClearColorMake(0.5, 1.0, 0.0, 1.0); + render_pass.colorAttachments[index].loadAction = MTLLoadActionClear; + render_pass.colorAttachments[index].storeAction = MTLStoreActionStore; + render_pass.colorAttachments[index].texture = color_buffer->GetHandle(); + } + if (depth_buffer) { + render_pass.depthAttachment.clearDepth = 1.0; + render_pass.depthAttachment.loadAction = MTLLoadActionClear; + render_pass.depthAttachment.storeAction = MTLStoreActionStore; + render_pass.depthAttachment.texture = depth_buffer->GetHandle(); } - // TODO: don't use index as attachment index - render_pass.colorAttachments[index].clearColor = - MTLClearColorMake(0.5, 1.0, 0.0, 1.0); - render_pass.colorAttachments[index].loadAction = MTLLoadActionClear; - render_pass.colorAttachments[index].storeAction = MTLStoreActionStore; - render_pass.colorAttachments[index].texture = color_buffer->GetHandle(); - } - if (depth_buffer) { - render_pass.depthAttachment.clearDepth = 1.0; - render_pass.depthAttachment.loadAction = MTLLoadActionClear; - render_pass.depthAttachment.storeAction = MTLStoreActionStore; - render_pass.depthAttachment.texture = depth_buffer->GetHandle(); - } } } // namespace Vulkan diff --git a/src/video_core/renderer_metal/renderer_metal.mm b/src/video_core/renderer_metal/renderer_metal.mm index add0f11eaf..8911f0e1b2 100644 --- a/src/video_core/renderer_metal/renderer_metal.mm +++ b/src/video_core/renderer_metal/renderer_metal.mm @@ -16,7 +16,7 @@ RendererMetal::RendererMetal(Core::Frontend::EmuWindow& emu_window, command_recorder(device), swap_chain(device, command_recorder, static_cast(render_window.GetWindowInfo().render_surface)), - rasterizer(gpu_, device, command_recorder, swap_chain) {} + rasterizer(gpu_, device_memory, device, command_recorder, swap_chain) {} RendererMetal::~RendererMetal() = default;