|
15 | 15 | #include "Cafe/HW/Latte/Core/LatteShader.h"
|
16 | 16 | #include "Cafe/HW/Latte/Core/LatteIndices.h"
|
17 | 17 | #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" |
25 | 18 | #include "gui/guiWrapper.h"
|
26 |
| -#include <stdexcept> |
27 | 19 |
|
28 | 20 | extern bool hasValidFramebufferAttached;
|
29 | 21 |
|
@@ -452,7 +444,68 @@ LatteTextureReadbackInfo* MetalRenderer::texture_createReadback(LatteTextureView
|
452 | 444 |
|
453 | 445 | void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height)
|
454 | 446 | {
|
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 |
456 | 509 | }
|
457 | 510 |
|
458 | 511 | void MetalRenderer::bufferCache_init(const sint32 bufferSize)
|
@@ -884,6 +937,7 @@ void MetalRenderer::EndEncoding()
|
884 | 937 | m_commandEncoder->endEncoding();
|
885 | 938 | m_commandEncoder->release();
|
886 | 939 | m_commandEncoder = nullptr;
|
| 940 | + m_encoderType = MetalEncoderType::None; |
887 | 941 | }
|
888 | 942 | }
|
889 | 943 |
|
|
0 commit comments