Skip to content

Commit 5bc9913

Browse files
committed
implement surface copy
1 parent 8316cee commit 5bc9913

File tree

1 file changed

+63
-9
lines changed

1 file changed

+63
-9
lines changed

src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,7 @@
1515
#include "Cafe/HW/Latte/Core/LatteShader.h"
1616
#include "Cafe/HW/Latte/Core/LatteIndices.h"
1717
#include "Cemu/Logging/CemuDebugLogging.h"
18-
#include "Foundation/NSError.hpp"
19-
#include "HW/Latte/Core/Latte.h"
20-
#include "HW/Latte/ISA/LatteReg.h"
21-
#include "Metal/MTLPixelFormat.hpp"
22-
#include "Metal/MTLRenderCommandEncoder.hpp"
23-
#include "Metal/MTLResource.hpp"
24-
#include "Metal/MTLTypes.hpp"
2518
#include "gui/guiWrapper.h"
26-
#include <stdexcept>
2719

2820
extern bool hasValidFramebufferAttached;
2921

@@ -452,7 +444,68 @@ LatteTextureReadbackInfo* MetalRenderer::texture_createReadback(LatteTextureView
452444

453445
void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height)
454446
{
455-
debug_printf("MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion not implemented\n");
447+
EnsureCommandBuffer();
448+
449+
// scale copy size to effective size
450+
sint32 effectiveCopyWidth = width;
451+
sint32 effectiveCopyHeight = height;
452+
LatteTexture_scaleToEffectiveSize(sourceTexture, &effectiveCopyWidth, &effectiveCopyHeight, 0);
453+
sint32 sourceEffectiveWidth, sourceEffectiveHeight;
454+
sourceTexture->GetEffectiveSize(sourceEffectiveWidth, sourceEffectiveHeight, srcMip);
455+
456+
sint32 texSrcMip = srcMip;
457+
sint32 texSrcSlice = srcSlice;
458+
sint32 texDstMip = dstMip;
459+
sint32 texDstSlice = dstSlice;
460+
461+
LatteTextureMtl* srcTextureMtl = static_cast<LatteTextureMtl*>(sourceTexture);
462+
LatteTextureMtl* dstTextureMtl = static_cast<LatteTextureMtl*>(destinationTexture);
463+
464+
// check if texture rescale ratios match
465+
// todo - if not, we have to use drawcall based copying
466+
if (!LatteTexture_doesEffectiveRescaleRatioMatch(srcTextureMtl, texSrcMip, dstTextureMtl, texDstMip))
467+
{
468+
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching dimensions");
469+
return;
470+
}
471+
472+
// check if bpp size matches
473+
if (srcTextureMtl->GetBPP() != dstTextureMtl->GetBPP())
474+
{
475+
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching BPP");
476+
return;
477+
}
478+
479+
MetalHybridComputePipeline* copyPipeline;
480+
if (srcTextureMtl->IsDepth())
481+
copyPipeline = m_copyDepthToColorPipeline;
482+
else
483+
copyPipeline = m_copyColorToDepthPipeline;
484+
485+
MTL::Texture* textures[] = {srcTextureMtl->GetTexture(), dstTextureMtl->GetTexture()};
486+
487+
if (m_encoderType == MetalEncoderType::Render)
488+
{
489+
auto renderCommandEncoder = static_cast<MTL::RenderCommandEncoder*>(m_commandEncoder);
490+
491+
renderCommandEncoder->setRenderPipelineState(copyPipeline->GetRenderPipelineState());
492+
493+
renderCommandEncoder->setViewport(MTL::Viewport{0.0, 0.0, (double)effectiveCopyWidth, (double)effectiveCopyHeight, 0.0, 1.0});
494+
renderCommandEncoder->setScissorRect(MTL::ScissorRect{0, 0, (uint32)effectiveCopyWidth, (uint32)effectiveCopyHeight});
495+
496+
renderCommandEncoder->setVertexTextures(textures, NS::Range(0, 2));
497+
renderCommandEncoder->setVertexBytes(&effectiveCopyWidth, sizeof(uint32), 0);
498+
// TODO: set slices and mips
499+
500+
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
501+
}
502+
else
503+
{
504+
// TODO: do the copy in a compute shader
505+
debug_printf("surfaceCopy_copySurfaceWithFormatConversion: no active render command encoder, skipping copy\n");
506+
}
507+
508+
// TODO: restore state
456509
}
457510

458511
void MetalRenderer::bufferCache_init(const sint32 bufferSize)
@@ -884,6 +937,7 @@ void MetalRenderer::EndEncoding()
884937
m_commandEncoder->endEncoding();
885938
m_commandEncoder->release();
886939
m_commandEncoder = nullptr;
940+
m_encoderType = MetalEncoderType::None;
887941
}
888942
}
889943

0 commit comments

Comments
 (0)