implement state 5 through a draw call

This commit is contained in:
Samuliak 2024-11-22 19:44:49 +01:00
parent 732e3be63d
commit 66ad59db92
No known key found for this signature in database
3 changed files with 75 additions and 38 deletions

View file

@ -21,6 +21,9 @@
#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Core/LatteConst.h"
#include "HW/Latte/Renderer/Metal/MetalCommon.h"
#include "Metal/MTLPixelFormat.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp"
#include "Metal/MTLRenderPipeline.hpp"
#include "config/CemuConfig.h"
#include "gui/guiWrapper.h"
@ -125,7 +128,26 @@ MetalRenderer::MetalRenderer()
if (error)
{
cemuLog_log(LogType::Force, "failed to create utility library (error: {})", error->localizedDescription()->utf8String());
return;
}
// Pipelines
MTL::Function* vertexFullscreenFunction = utilityLibrary->newFunction(ToNSString("vertexFullscreen"));
MTL::Function* fragmentCopyDepthToColorFunction = utilityLibrary->newFunction(ToNSString("fragmentCopyDepthToColor"));
MTL::RenderPipelineDescriptor* rpd = MTL::RenderPipelineDescriptor::alloc()->init();
rpd->setVertexFunction(vertexFullscreenFunction);
rpd->setFragmentFunction(fragmentCopyDepthToColorFunction);
// TODO: don't hardcode the format
rpd->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatR16Unorm);
vertexFullscreenFunction->release();
fragmentCopyDepthToColorFunction->release();
error = nullptr;
m_copyDepthToColorPipeline = m_device->newRenderPipelineState(rpd, &error);
if (error)
{
cemuLog_log(LogType::Force, "failed to create copy depth to color pipeline (error: {})", error->localizedDescription()->utf8String());
}
// Void vertex pipelines
@ -142,8 +164,7 @@ MetalRenderer::~MetalRenderer()
//delete m_copyTextureToTexturePipeline;
//delete m_restrideBufferPipeline;
//m_presentPipelineLinear->release();
//m_presentPipelineSRGB->release();
m_copyDepthToColorPipeline->release();
delete m_outputShaderCache;
delete m_pipelineCache;
@ -1348,14 +1369,27 @@ void MetalRenderer::draw_handleSpecialState5()
LatteTextureView* colorBuffer = LatteMRT::GetColorAttachment(0);
LatteTextureView* depthBuffer = LatteMRT::GetDepthAttachment();
auto mtlDepthTexture = static_cast<LatteTextureViewMtl*>(depthBuffer)->GetRGBAView();
sint32 vpWidth, vpHeight;
LatteMRT::GetVirtualViewportDimensions(vpWidth, vpHeight);
surfaceCopy_copySurfaceWithFormatConversion(
depthBuffer->baseTexture, depthBuffer->firstMip, depthBuffer->firstSlice,
colorBuffer->baseTexture, colorBuffer->firstMip, colorBuffer->firstSlice,
vpWidth, vpHeight);
// Sadly, we need to end encoding to ensure that the depth data is up-to-date
// Copy depth to color
auto renderCommandEncoder = GetRenderCommandEncoder();
auto& encoderState = m_state.m_encoderState;
renderCommandEncoder->setRenderPipelineState(m_copyDepthToColorPipeline);
// TODO: make a helper function for this
encoderState.m_renderPipelineState = m_copyDepthToColorPipeline;
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_FRAGMENT, mtlDepthTexture, GET_HELPER_TEXTURE_BINDING(0));
// TODO: make a helper function for this
renderCommandEncoder->setFragmentBytes(&vpWidth, sizeof(sint32), GET_HELPER_BUFFER_BINDING(0));
encoderState.m_buffers[METAL_SHADER_TYPE_FRAGMENT][GET_HELPER_BUFFER_BINDING(0)] = {nullptr};
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(3));
}
void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex)

View file

@ -6,6 +6,7 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
#include "Metal/MTLRenderPipeline.hpp"
#include <cstdint>
struct MetalBufferAllocation
@ -471,6 +472,9 @@ private:
class MetalDepthStencilCache* m_depthStencilCache;
class MetalSamplerCache* m_samplerCache;
// Pipelines
MTL::RenderPipelineState* m_copyDepthToColorPipeline;
// Void vertex pipelines
class MetalVoidVertexPipeline* m_copyBufferToBufferPipeline;

View file

@ -8,24 +8,24 @@ using namespace metal;
#define GET_BUFFER_BINDING(index) (28 + index)
#define GET_TEXTURE_BINDING(index) (29 + index)
#define GET_SAMPLER_BINDING(index) (14 + index)\n
#define GET_SAMPLER_BINDING(index) (14 + index)
constant float2 positions[] = {float2(-1.0, -3.0), float2(-1.0, 1.0), float2(3.0, 1.0)};
struct VertexOut {
float4 position [[position]];
float2 texCoord;
};
vertex VertexOut vertexFullscreen(ushort vid [[vertex_id]]) {
VertexOut out;
out.position = float4(positions[vid], 0.0, 1.0);
out.texCoord = positions[vid] * 0.5 + 0.5;
out.texCoord.y = 1.0 - out.texCoord.y;
return out;
}
//constant float2 positions[] = {float2(-1.0, -3.0), float2(-1.0, 1.0), float2(3.0, 1.0)};
//
//struct VertexOut {
// float4 position [[position]];
// float2 texCoord;
//};
//
//vertex VertexOut vertexFullscreen(ushort vid [[vertex_id]]) {
// VertexOut out;
// out.position = float4(positions[vid], 0.0, 1.0);
// out.texCoord = positions[vid] * 0.5 + 0.5;
// out.texCoord.y = 1.0 - out.texCoord.y;
//
// return out;
//}
//
//fragment float4 fragmentPresent(VertexOut in [[stage_in]], texture2d<float> tex [[texture(0)]], //sampler samplr [[sampler(0)]]) {
// return tex.sample(samplr, in.texCoord);
//}
@ -34,19 +34,18 @@ vertex void vertexCopyBufferToBuffer(uint vid [[vertex_id]], device uint8_t* src
dst[vid] = src[vid];
}
//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))]]) {
// uint2 coord = uint2(vid % width, vid / width);
// return dst.write(float4(src.read(coord).r, 0.0, 0.0, 0.0), coord);
fragment float4 fragmentCopyDepthToColor(VertexOut in [[stage_in]], texture2d<float, access::read> src [[texture(GET_TEXTURE_BINDING(0))]]) {
return float4(src.read(uint2(in.position.xy)).r, 0.0, 0.0, 0.0);
}
//struct RestrideParams {
// uint oldStride;
// uint newStride;
//};
//vertex void vertexRestrideBuffer(uint vid [[vertex_id]], device uint8_t* src [[buffer//(GET_BUFFER_BINDING(0))]], device uint8_t* dst [[buffer(GET_BUFFER_BINDING(1))]], constant //RestrideParams& params [[buffer(GET_BUFFER_BINDING(2))]]) {
// for (uint32_t i = 0; i < params.oldStride; i++) {
// dst[vid * params.newStride + i] = src[vid * params.oldStride + i];
// }
//}
struct RestrideParams {
uint oldStride;
uint newStride;
};
vertex void vertexRestrideBuffer(uint vid [[vertex_id]], device uint8_t* src [[buffer(GET_BUFFER_BINDING(0))]], device uint8_t* dst [[buffer(GET_BUFFER_BINDING(1))]], constant RestrideParams& params [[buffer(GET_BUFFER_BINDING(2))]]) {
for (uint32_t i = 0; i < params.oldStride; i++) {
dst[vid * params.newStride + i] = src[vid * params.oldStride + i];
}
}
)";