From 786cd8a7084fff0568d6305819a698154dd650eb Mon Sep 17 00:00:00 2001 From: Samuliak Date: Tue, 9 Apr 2024 15:49:12 +0200 Subject: [PATCH] metal: implement buffer to texture copy --- .../renderer_metal/mtl_graphics_pipeline.cpp | 27 ++++++++++--------- .../renderer_metal/mtl_texture_cache.cpp | 21 +++++++++++---- .../renderer_metal/mtl_texture_cache.h | 6 +++-- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/video_core/renderer_metal/mtl_graphics_pipeline.cpp b/src/video_core/renderer_metal/mtl_graphics_pipeline.cpp index 819e327897..cfe827c100 100644 --- a/src/video_core/renderer_metal/mtl_graphics_pipeline.cpp +++ b/src/video_core/renderer_metal/mtl_graphics_pipeline.cpp @@ -63,18 +63,7 @@ void GraphicsPipeline::Configure(bool is_indexed) { texture_cache.SynchronizeGraphicsDescriptors(); - texture_cache.UpdateRenderTargets(false); - const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); - if (!framebuffer) { - return; - } - command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle()); - - command_recorder.GetRenderCommandEncoder()->setRenderPipelineState(pipeline_state); - - // Bind resources - - // HACK: try to find a texture that we can bind + // Find resources size_t stage = 4; // const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers}; const auto read_handle{[&](const auto& desc, u32 index) { @@ -116,6 +105,20 @@ void GraphicsPipeline::Configure(bool is_indexed) { } } texture_cache.FillGraphicsImageViews(std::span(views.data(), view_index)); + + // Begin render pass + texture_cache.UpdateRenderTargets(false); + const Framebuffer* const framebuffer = texture_cache.GetFramebuffer(); + if (!framebuffer) { + return; + } + command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle()); + + command_recorder.GetRenderCommandEncoder()->setRenderPipelineState(pipeline_state); + + // Bind resources + + // HACK: try to find a texture that we can bind VideoCommon::ImageViewInOut* texture_buffer_it{views.data()}; ImageView& image_view{texture_cache.GetImageView(texture_buffer_it->id)}; diff --git a/src/video_core/renderer_metal/mtl_texture_cache.cpp b/src/video_core/renderer_metal/mtl_texture_cache.cpp index 9d87a23df2..cf37577595 100644 --- a/src/video_core/renderer_metal/mtl_texture_cache.cpp +++ b/src/video_core/renderer_metal/mtl_texture_cache.cpp @@ -11,6 +11,7 @@ #include "common/bit_util.h" #include "common/settings.h" +#include "video_core/renderer_metal/mtl_command_recorder.h" #include "video_core/renderer_metal/mtl_device.h" #include "video_core/renderer_metal/mtl_texture_cache.h" @@ -53,16 +54,16 @@ void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) { staging_buffer_pool.FreeDeferred(ref); } -Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info, GPUVAddr gpu_addr_, +Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info, GPUVAddr gpu_addr_, VAddr cpu_addr_) - : VideoCommon::ImageBase(info, gpu_addr_, cpu_addr_) { + : VideoCommon::ImageBase(info, gpu_addr_, cpu_addr_), runtime{&runtime_} { MTL::TextureDescriptor* texture_descriptor = MTL::TextureDescriptor::alloc()->init(); // TODO: don't hardcode the format texture_descriptor->setPixelFormat(MTL::PixelFormatRGBA8Unorm); texture_descriptor->setWidth(info.size.width); texture_descriptor->setHeight(info.size.height); - texture = runtime.device.GetDevice()->newTexture(texture_descriptor); + texture = runtime->device.GetDevice()->newTexture(texture_descriptor); } Image::Image(const VideoCommon::NullImageParams& params) : VideoCommon::ImageBase{params} {} @@ -76,12 +77,22 @@ Image::~Image() { // TODO: implement these void Image::UploadMemory(MTL::Buffer* buffer, size_t offset, std::span copies) { - ; + for (const VideoCommon::BufferImageCopy& copy : copies) { + // TODO: query this from texture format + size_t bytes_per_pixel = 4; + size_t bytes_per_row = info.size.width * bytes_per_pixel; + size_t bytes_per_image = info.size.height * bytes_per_row; + MTL::Size size = MTL::Size::Make(info.size.width, info.size.height, 1); + MTL::Origin origin = MTL::Origin::Make(copy.image_offset.x, copy.image_offset.y, + copy.image_subresource.base_layer); + runtime->command_recorder.GetBlitCommandEncoder()->copyFromBuffer( + buffer, offset, bytes_per_row, bytes_per_image, size, texture, 0, 0, origin); + } } void Image::UploadMemory(const StagingBufferRef& map, std::span copies) { - ; + UploadMemory(map.buffer, map.offset, copies); } void Image::DownloadMemory(MTL::Buffer* buffer, size_t offset, diff --git a/src/video_core/renderer_metal/mtl_texture_cache.h b/src/video_core/renderer_metal/mtl_texture_cache.h index 509c5561fd..799a993e5d 100644 --- a/src/video_core/renderer_metal/mtl_texture_cache.h +++ b/src/video_core/renderer_metal/mtl_texture_cache.h @@ -116,7 +116,7 @@ public: class Image : public VideoCommon::ImageBase { public: - explicit Image(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info, + explicit Image(TextureCacheRuntime& runtime_, const VideoCommon::ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); explicit Image(const VideoCommon::NullImageParams&); @@ -162,7 +162,9 @@ public: } private: - MTL::Texture* texture = nil; + TextureCacheRuntime* runtime; + + MTL::Texture* texture{nullptr}; bool initialized = false; bool rescaled = false;