From be0a69a5e268644a06faf58b3076f04cb4ae80ae Mon Sep 17 00:00:00 2001 From: Samuliak Date: Sun, 18 Aug 2024 14:49:25 +0200 Subject: [PATCH] do texture load on GPU if no unified memory --- .../Latte/Renderer/Metal/LatteTextureMtl.cpp | 3 ++- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 22 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp index c1508085..9bc5b63b 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp @@ -3,13 +3,14 @@ #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #include "Common/precompiled.h" +#include "Metal/MTLResource.hpp" LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) : LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer), m_format(format), m_isDepth(isDepth) { MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init(); - desc->setStorageMode(m_mtlr->GetOptimalStorageMode()); + desc->setStorageMode(m_mtlr->HasUnifiedMemory() ? MTL::StorageModeShared : MTL::StorageModePrivate); sint32 effectiveBaseWidth = width; sint32 effectiveBaseHeight = height; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 7c6c6a2d..21ee47eb 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -378,6 +378,7 @@ void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIn } } +// TODO: do a GPU blit even on unified memory? That would mean we could use private storage mode for all textures void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) { auto textureMtl = (LatteTextureMtl*)hostTexture; @@ -390,9 +391,26 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s } size_t bytesPerRow = GetMtlTextureBytesPerRow(textureMtl->GetFormat(), textureMtl->IsDepth(), width); - // No need to calculate bytesPerImage for 3D textures, since we always load just one slice + // No need to set bytesPerImage for 3D textures, since we always load just one slice //size_t bytesPerImage = GetMtlTextureBytesPerImage(textureMtl->GetFormat(), textureMtl->IsDepth(), height, bytesPerRow); - textureMtl->GetTexture()->replaceRegion(MTL::Region(0, 0, offsetZ, width, height, 1), mipIndex, sliceIndex, pixelData, bytesPerRow, 0); + if (HasUnifiedMemory()) + { + textureMtl->GetTexture()->replaceRegion(MTL::Region(0, 0, offsetZ, width, height, 1), mipIndex, sliceIndex, pixelData, bytesPerRow, 0); + } + else + { + auto blitCommandEncoder = GetBlitCommandEncoder(); + + // Allocate a temporary buffer + auto allocation = m_memoryManager->GetTemporaryBufferAllocator().GetBufferAllocation(compressedImageSize); + auto buffer = m_memoryManager->GetTemporaryBufferAllocator().GetBuffer(allocation.bufferIndex); + + // Copy the data to the temporary buffer + memcpy(allocation.data, pixelData, compressedImageSize); + + // Copy the data from the temporary buffer to the texture + blitCommandEncoder->copyFromBuffer(buffer, allocation.offset, bytesPerRow, 0, MTL::Size(width, height, 1), textureMtl->GetTexture(), sliceIndex, mipIndex, MTL::Origin(0, 0, offsetZ)); + } } void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a)