mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-01 21:44:17 +01:00
use texture views for surface copies
This commit is contained in:
parent
366be049a4
commit
163eeea102
@ -1,6 +1,6 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalHybridComputePipeline.h"
|
||||||
|
|
||||||
MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const char* vertexFunctionName, const char* kernelFunctionName)
|
MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const std::string& vertexFunctionName/*, const std::string& kernelFunctionName*/)
|
||||||
{
|
{
|
||||||
// Render pipeline state
|
// Render pipeline state
|
||||||
MTL::Function* vertexFunction = library->newFunction(ToNSString(vertexFunctionName));
|
MTL::Function* vertexFunction = library->newFunction(ToNSString(vertexFunctionName));
|
||||||
@ -20,12 +20,10 @@ MetalHybridComputePipeline::MetalHybridComputePipeline(class MetalRenderer* mtlR
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute pipeline state
|
// Compute pipeline state
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalHybridComputePipeline::~MetalHybridComputePipeline()
|
MetalHybridComputePipeline::~MetalHybridComputePipeline()
|
||||||
{
|
{
|
||||||
m_renderPipelineState->release();
|
m_renderPipelineState->release();
|
||||||
// TODO: uncomment
|
|
||||||
//m_computePipelineState->release();
|
//m_computePipelineState->release();
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,18 @@
|
|||||||
#include "Metal/MTLLibrary.hpp"
|
#include "Metal/MTLLibrary.hpp"
|
||||||
#include "Metal/MTLRenderPipeline.hpp"
|
#include "Metal/MTLRenderPipeline.hpp"
|
||||||
|
|
||||||
|
// TODO: rename to MetalVoidVertexPipeline
|
||||||
class MetalHybridComputePipeline
|
class MetalHybridComputePipeline
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const char* vertexFunctionName, const char* kernelFunctionName);
|
MetalHybridComputePipeline(class MetalRenderer* mtlRenderer, MTL::Library* library, const std::string& vertexFunctionName/*, const std::string& kernelFunctionName*/);
|
||||||
~MetalHybridComputePipeline();
|
~MetalHybridComputePipeline();
|
||||||
|
|
||||||
MTL::RenderPipelineState* GetRenderPipelineState() const { return m_renderPipelineState; }
|
MTL::RenderPipelineState* GetRenderPipelineState() const { return m_renderPipelineState; }
|
||||||
|
|
||||||
MTL::RenderPipelineState* GetComputePipelineState() const { return m_computePipelineState; }
|
//MTL::RenderPipelineState* GetComputePipelineState() const { return m_computePipelineState; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MTL::RenderPipelineState* m_renderPipelineState;
|
MTL::RenderPipelineState* m_renderPipelineState;
|
||||||
MTL::RenderPipelineState* m_computePipelineState;
|
//MTL::RenderPipelineState* m_computePipelineState;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||||
|
#include "Foundation/NSTypes.hpp"
|
||||||
#include "HW/Latte/Core/LatteConst.h"
|
#include "HW/Latte/Core/LatteConst.h"
|
||||||
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
|
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
#include "HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
#include "HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
||||||
@ -23,7 +24,9 @@
|
|||||||
#include "Metal/MTLCommandBuffer.hpp"
|
#include "Metal/MTLCommandBuffer.hpp"
|
||||||
#include "Metal/MTLDevice.hpp"
|
#include "Metal/MTLDevice.hpp"
|
||||||
#include "Metal/MTLRenderPass.hpp"
|
#include "Metal/MTLRenderPass.hpp"
|
||||||
|
#include "Metal/MTLRenderPipeline.hpp"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#define IMGUI_IMPL_METAL_CPP
|
#define IMGUI_IMPL_METAL_CPP
|
||||||
#include "imgui/imgui_extension.h"
|
#include "imgui/imgui_extension.h"
|
||||||
@ -117,13 +120,13 @@ MetalRenderer::MetalRenderer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Present pipeline
|
// Present pipeline
|
||||||
MTL::Function* presentVertexFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen"));
|
MTL::Function* fullscreenVertexFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen"));
|
||||||
MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(ToNSString("fragmentPresent"));
|
MTL::Function* presentFragmentFunction = utilityLibrary->newFunction(ToNSString("fragmentPresent"));
|
||||||
|
|
||||||
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
MTL::RenderPipelineDescriptor* renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
renderPipelineDescriptor->setVertexFunction(presentVertexFunction);
|
renderPipelineDescriptor->setVertexFunction(fullscreenVertexFunction);
|
||||||
renderPipelineDescriptor->setFragmentFunction(presentFragmentFunction);
|
renderPipelineDescriptor->setFragmentFunction(presentFragmentFunction);
|
||||||
presentVertexFunction->release();
|
fullscreenVertexFunction->release();
|
||||||
presentFragmentFunction->release();
|
presentFragmentFunction->release();
|
||||||
|
|
||||||
error = nullptr;
|
error = nullptr;
|
||||||
@ -151,9 +154,12 @@ MetalRenderer::MetalRenderer()
|
|||||||
error->release();
|
error->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy texture pipelines
|
||||||
|
auto copyTextureToColorPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
|
|
||||||
// Hybrid pipelines
|
// Hybrid pipelines
|
||||||
m_copyTextureToTexturePipeline = new MetalHybridComputePipeline(this, utilityLibrary, "vertexCopyTextureToTexture", "kernelCopyTextureToTexture");
|
m_copyTextureToTexturePipeline = new MetalHybridComputePipeline(this, utilityLibrary, "vertexCopyTextureToTexture");
|
||||||
m_restrideBufferPipeline = new MetalHybridComputePipeline(this, utilityLibrary, "vertexRestrideBuffer", "kernelRestrideBuffer");
|
m_restrideBufferPipeline = new MetalHybridComputePipeline(this, utilityLibrary, "vertexRestrideBuffer");
|
||||||
utilityLibrary->release();
|
utilityLibrary->release();
|
||||||
|
|
||||||
m_memoryManager->SetRestrideBufferPipeline(m_restrideBufferPipeline);
|
m_memoryManager->SetRestrideBufferPipeline(m_restrideBufferPipeline);
|
||||||
@ -674,8 +680,6 @@ LatteTextureReadbackInfo* MetalRenderer::texture_createReadback(LatteTextureView
|
|||||||
|
|
||||||
void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height)
|
void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height)
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
|
|
||||||
// scale copy size to effective size
|
// scale copy size to effective size
|
||||||
sint32 effectiveCopyWidth = width;
|
sint32 effectiveCopyWidth = width;
|
||||||
sint32 effectiveCopyHeight = height;
|
sint32 effectiveCopyHeight = height;
|
||||||
@ -688,33 +692,25 @@ void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* so
|
|||||||
sint32 texDstMip = dstMip;
|
sint32 texDstMip = dstMip;
|
||||||
sint32 texDstSlice = dstSlice;
|
sint32 texDstSlice = dstSlice;
|
||||||
|
|
||||||
LatteTextureMtl* srcTextureMtl = static_cast<LatteTextureMtl*>(sourceTexture);
|
// Create texture views
|
||||||
LatteTextureMtl* dstTextureMtl = static_cast<LatteTextureMtl*>(destinationTexture);
|
LatteTextureViewMtl* srcTextureMtl = static_cast<LatteTextureViewMtl*>(sourceTexture->GetOrCreateView(srcMip, 1, srcSlice, 1));
|
||||||
|
LatteTextureViewMtl* dstTextureMtl = static_cast<LatteTextureViewMtl*>(destinationTexture->GetOrCreateView(dstMip, 1, dstSlice, 1));
|
||||||
|
|
||||||
// check if texture rescale ratios match
|
// check if texture rescale ratios match
|
||||||
// todo - if not, we have to use drawcall based copying
|
// todo - if not, we have to use drawcall based copying
|
||||||
if (!LatteTexture_doesEffectiveRescaleRatioMatch(srcTextureMtl, texSrcMip, dstTextureMtl, texDstMip))
|
if (!LatteTexture_doesEffectiveRescaleRatioMatch(sourceTexture, texSrcMip, destinationTexture, texDstMip))
|
||||||
{
|
{
|
||||||
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching dimensions");
|
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching dimensions");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if bpp size matches
|
// check if bpp size matches
|
||||||
if (srcTextureMtl->GetBPP() != dstTextureMtl->GetBPP())
|
if (sourceTexture->GetBPP() != destinationTexture->GetBPP())
|
||||||
{
|
{
|
||||||
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching BPP");
|
cemuLog_logDebug(LogType::Force, "surfaceCopy_copySurfaceWithFormatConversion(): Mismatching BPP");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CopyParams
|
|
||||||
{
|
|
||||||
uint32 width;
|
|
||||||
uint32 srcMip;
|
|
||||||
uint32 srcSlice;
|
|
||||||
uint32 dstMip;
|
|
||||||
uint32 dstSlice;
|
|
||||||
} params{(uint32)effectiveCopyWidth, (uint32)texSrcMip, (uint32)texSrcSlice, (uint32)texDstMip, (uint32)texDstSlice};
|
|
||||||
|
|
||||||
if (m_encoderType == MetalEncoderType::Render)
|
if (m_encoderType == MetalEncoderType::Render)
|
||||||
{
|
{
|
||||||
auto renderCommandEncoder = static_cast<MTL::RenderCommandEncoder*>(m_commandEncoder);
|
auto renderCommandEncoder = static_cast<MTL::RenderCommandEncoder*>(m_commandEncoder);
|
||||||
@ -722,17 +718,42 @@ void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* so
|
|||||||
renderCommandEncoder->setRenderPipelineState(m_copyTextureToTexturePipeline->GetRenderPipelineState());
|
renderCommandEncoder->setRenderPipelineState(m_copyTextureToTexturePipeline->GetRenderPipelineState());
|
||||||
m_state.m_encoderState.m_renderPipelineState = m_copyTextureToTexturePipeline->GetRenderPipelineState();
|
m_state.m_encoderState.m_renderPipelineState = m_copyTextureToTexturePipeline->GetRenderPipelineState();
|
||||||
|
|
||||||
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_VERTEX, srcTextureMtl->GetTexture(), GET_HELPER_TEXTURE_BINDING(0));
|
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_VERTEX, srcTextureMtl->GetRGBAView(), GET_HELPER_TEXTURE_BINDING(0));
|
||||||
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_VERTEX, dstTextureMtl->GetTexture(), GET_HELPER_TEXTURE_BINDING(1));
|
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_VERTEX, dstTextureMtl->GetRGBAView(), GET_HELPER_TEXTURE_BINDING(1));
|
||||||
renderCommandEncoder->setVertexBytes(¶ms, sizeof(params), GET_HELPER_BUFFER_BINDING(0));
|
renderCommandEncoder->setVertexBytes(&effectiveCopyWidth, sizeof(effectiveCopyWidth), GET_HELPER_BUFFER_BINDING(0));
|
||||||
m_state.m_encoderState.m_buffers[METAL_SHADER_TYPE_VERTEX][GET_HELPER_BUFFER_BINDING(0)] = {nullptr};
|
m_state.m_encoderState.m_buffers[METAL_SHADER_TYPE_VERTEX][GET_HELPER_BUFFER_BINDING(0)] = {nullptr};
|
||||||
|
|
||||||
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: do the copy in a compute shader
|
// TODO: uncomment
|
||||||
debug_printf("surfaceCopy_copySurfaceWithFormatConversion: no active render command encoder, skipping copy\n");
|
/*
|
||||||
|
bool copyingToWholeRegion = ((effectiveCopyWidth == dstTextureMtl->GetMipWidth(dstMip) && effectiveCopyHeight == dstTextureMtl->GetMipHeight(dstMip)));
|
||||||
|
|
||||||
|
auto renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
||||||
|
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
|
||||||
|
colorAttachment->setTexture(dstTextureMtl->GetTexture());
|
||||||
|
// We don't care about previous contents if we are about to overwrite the whole region
|
||||||
|
colorAttachment->setLoadAction(copyingToWholeRegion ? MTL::LoadActionDontCare : MTL::LoadActionLoad);
|
||||||
|
colorAttachment->setStoreAction(MTL::StoreActionStore);
|
||||||
|
colorAttachment->setSlice(dstSlice);
|
||||||
|
colorAttachment->setLevel(dstMip);
|
||||||
|
|
||||||
|
auto renderCommandEncoder = GetTemporaryRenderCommandEncoder(renderPassDescriptor);
|
||||||
|
|
||||||
|
auto pipeline = (srcTextureMtl->IsDepth() ? m_copyTextureToColorPipeline : m_copyTextureToDepthPipeline);
|
||||||
|
renderCommandEncoder->setRenderPipelineState(pipeline);
|
||||||
|
|
||||||
|
renderCommandEncoder->setFragmentTexture(srcTextureMtl->GetTexture(), GET_HELPER_TEXTURE_BINDING(0));
|
||||||
|
renderCommandEncoder->setFragmentBytes(&effectiveCopyWidth, offsetof(effectiveCopyWidth), GET_HELPER_BUFFER_BINDING(0));
|
||||||
|
|
||||||
|
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
|
||||||
|
|
||||||
|
EndEncoding();
|
||||||
|
*/
|
||||||
|
|
||||||
|
debug_printf("surface copy with no render command encoder, skipping copy\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,17 +31,9 @@ fragment float4 fragmentPresent(VertexOut in [[stage_in]], texture2d<float> tex
|
|||||||
return tex.sample(samplr, in.texCoord);
|
return tex.sample(samplr, in.texCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CopyParams {
|
vertex void vertexCopyTextureToTexture(uint vid [[vertex_id]], texture2d<float, access::read> src [[texture(GET_TEXTURE_BINDING(0))]], texture2d<float, access::write> dst [[texture(GET_TEXTURE_BINDING(1))]], constant uint32_t& width [[buffer(GET_BUFFER_BINDING(0))]]) {
|
||||||
uint width;
|
uint2 coord = uint2(vid % width, vid / width);
|
||||||
uint srcMip;
|
return dst.write(float4(src.read(coord).r, 0.0, 0.0, 0.0), coord);
|
||||||
uint srcSlice;
|
|
||||||
uint dstMip;
|
|
||||||
uint dstSlice;
|
|
||||||
};
|
|
||||||
|
|
||||||
vertex void vertexCopyTextureToTexture(uint vid [[vertex_id]], texture2d_array<float, access::read> src [[texture(GET_TEXTURE_BINDING(0))]], texture2d_array<float, access::write> dst [[texture(GET_TEXTURE_BINDING(1))]], constant CopyParams& params [[buffer(GET_BUFFER_BINDING(0))]]) {
|
|
||||||
uint2 coord = uint2(vid % params.width, vid / params.width);
|
|
||||||
return dst.write(float4(src.read(coord, params.srcSlice, params.srcMip).r, 0.0, 0.0, 0.0), coord, params.dstSlice, params.dstMip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RestrideParams {
|
struct RestrideParams {
|
||||||
|
Loading…
Reference in New Issue
Block a user