mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-07 07:21:18 +12:00
Merge pull request #12 from SamoZ256/metal-state5
Accurate special state 5
This commit is contained in:
commit
4c54f4b11d
4 changed files with 90 additions and 48 deletions
|
@ -2,7 +2,6 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
#include "Metal/MTLTexture.hpp"
|
|
||||||
|
|
||||||
uint32 LatteTextureMtl_AdjustTextureCompSel(Latte::E_GX2SURFFMT format, uint32 compSel)
|
uint32 LatteTextureMtl_AdjustTextureCompSel(Latte::E_GX2SURFFMT format, uint32 compSel)
|
||||||
{
|
{
|
||||||
|
@ -159,17 +158,17 @@ MTL::Texture* LatteTextureViewMtl::CreateSwizzledView(uint32 gpuSamplerSwizzle)
|
||||||
|
|
||||||
uint32 baseLevel = firstMip;
|
uint32 baseLevel = firstMip;
|
||||||
uint32 levelCount = this->numMip;
|
uint32 levelCount = this->numMip;
|
||||||
uint32 baseLayer = 0;
|
uint32 baseLayer;
|
||||||
uint32 layerCount = 1;
|
uint32 layerCount;
|
||||||
|
// TODO: check if base texture is 3D texture as well
|
||||||
// TODO: check if base texture is 3D texture as well?
|
|
||||||
if (textureType == MTL::TextureType3D)
|
if (textureType == MTL::TextureType3D)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(firstMip == 0);
|
cemu_assert_debug(firstMip == 0);
|
||||||
cemu_assert_debug(this->numSlice == baseTexture->depth);
|
cemu_assert_debug(this->numSlice == baseTexture->depth);
|
||||||
|
baseLayer = 0;
|
||||||
|
layerCount = 1;
|
||||||
}
|
}
|
||||||
// Cube array needs to have layer count multiple of 6 as opposed to when creating a texture
|
else
|
||||||
else if (textureType == MTL::TextureTypeCubeArray || textureType == MTL::TextureType2DArray)
|
|
||||||
{
|
{
|
||||||
baseLayer = firstSlice;
|
baseLayer = firstSlice;
|
||||||
layerCount = this->numSlice;
|
layerCount = this->numSlice;
|
||||||
|
|
|
@ -125,9 +125,18 @@ MetalRenderer::MetalRenderer()
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
cemuLog_log(LogType::Force, "failed to create utility library (error: {})", error->localizedDescription()->utf8String());
|
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"));
|
||||||
|
|
||||||
|
m_copyDepthToColorDesc = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
|
m_copyDepthToColorDesc->setVertexFunction(vertexFullscreenFunction);
|
||||||
|
m_copyDepthToColorDesc->setFragmentFunction(fragmentCopyDepthToColorFunction);
|
||||||
|
vertexFullscreenFunction->release();
|
||||||
|
fragmentCopyDepthToColorFunction->release();
|
||||||
|
|
||||||
// Void vertex pipelines
|
// Void vertex pipelines
|
||||||
if (m_isAppleGPU)
|
if (m_isAppleGPU)
|
||||||
m_copyBufferToBufferPipeline = new MetalVoidVertexPipeline(this, utilityLibrary, "vertexCopyBufferToBuffer");
|
m_copyBufferToBufferPipeline = new MetalVoidVertexPipeline(this, utilityLibrary, "vertexCopyBufferToBuffer");
|
||||||
|
@ -142,8 +151,9 @@ MetalRenderer::~MetalRenderer()
|
||||||
//delete m_copyTextureToTexturePipeline;
|
//delete m_copyTextureToTexturePipeline;
|
||||||
//delete m_restrideBufferPipeline;
|
//delete m_restrideBufferPipeline;
|
||||||
|
|
||||||
//m_presentPipelineLinear->release();
|
m_copyDepthToColorDesc->release();
|
||||||
//m_presentPipelineSRGB->release();
|
for (const auto [pixelFormat, pipeline] : m_copyDepthToColorPipelines)
|
||||||
|
pipeline->release();
|
||||||
|
|
||||||
delete m_outputShaderCache;
|
delete m_outputShaderCache;
|
||||||
delete m_pipelineCache;
|
delete m_pipelineCache;
|
||||||
|
@ -1348,14 +1358,44 @@ void MetalRenderer::draw_handleSpecialState5()
|
||||||
|
|
||||||
LatteTextureView* colorBuffer = LatteMRT::GetColorAttachment(0);
|
LatteTextureView* colorBuffer = LatteMRT::GetColorAttachment(0);
|
||||||
LatteTextureView* depthBuffer = LatteMRT::GetDepthAttachment();
|
LatteTextureView* depthBuffer = LatteMRT::GetDepthAttachment();
|
||||||
|
auto colorTextureMtl = static_cast<LatteTextureViewMtl*>(colorBuffer);
|
||||||
|
auto depthTextureMtl = static_cast<LatteTextureViewMtl*>(depthBuffer);
|
||||||
|
|
||||||
sint32 vpWidth, vpHeight;
|
sint32 vpWidth, vpHeight;
|
||||||
LatteMRT::GetVirtualViewportDimensions(vpWidth, vpHeight);
|
LatteMRT::GetVirtualViewportDimensions(vpWidth, vpHeight);
|
||||||
|
|
||||||
surfaceCopy_copySurfaceWithFormatConversion(
|
// Get the pipeline
|
||||||
depthBuffer->baseTexture, depthBuffer->firstMip, depthBuffer->firstSlice,
|
MTL::PixelFormat colorPixelFormat = colorTextureMtl->GetRGBAView()->pixelFormat();
|
||||||
colorBuffer->baseTexture, colorBuffer->firstMip, colorBuffer->firstSlice,
|
auto& pipeline = m_copyDepthToColorPipelines[colorPixelFormat];
|
||||||
vpWidth, vpHeight);
|
if (!pipeline)
|
||||||
|
{
|
||||||
|
m_copyDepthToColorDesc->colorAttachments()->object(0)->setPixelFormat(colorPixelFormat);
|
||||||
|
|
||||||
|
NS::Error* error = nullptr;
|
||||||
|
pipeline = m_device->newRenderPipelineState(m_copyDepthToColorDesc, &error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
cemuLog_log(LogType::Force, "failed to create copy depth to color pipeline (error: {})", error->localizedDescription()->utf8String());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sadly, we need to end encoding to ensure that the depth data is up-to-date
|
||||||
|
EndEncoding();
|
||||||
|
|
||||||
|
// Copy depth to color
|
||||||
|
auto renderCommandEncoder = GetRenderCommandEncoder();
|
||||||
|
|
||||||
|
auto& encoderState = m_state.m_encoderState;
|
||||||
|
|
||||||
|
renderCommandEncoder->setRenderPipelineState(pipeline);
|
||||||
|
// TODO: make a helper function for this
|
||||||
|
encoderState.m_renderPipelineState = pipeline;
|
||||||
|
SetTexture(renderCommandEncoder, METAL_SHADER_TYPE_FRAGMENT, depthTextureMtl->GetRGBAView(), 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)
|
void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex)
|
||||||
|
|
|
@ -471,6 +471,10 @@ private:
|
||||||
class MetalDepthStencilCache* m_depthStencilCache;
|
class MetalDepthStencilCache* m_depthStencilCache;
|
||||||
class MetalSamplerCache* m_samplerCache;
|
class MetalSamplerCache* m_samplerCache;
|
||||||
|
|
||||||
|
// Pipelines
|
||||||
|
MTL::RenderPipelineDescriptor* m_copyDepthToColorDesc;
|
||||||
|
std::map<MTL::PixelFormat, MTL::RenderPipelineState*> m_copyDepthToColorPipelines;
|
||||||
|
|
||||||
// Void vertex pipelines
|
// Void vertex pipelines
|
||||||
class MetalVoidVertexPipeline* m_copyBufferToBufferPipeline;
|
class MetalVoidVertexPipeline* m_copyBufferToBufferPipeline;
|
||||||
|
|
||||||
|
|
|
@ -8,24 +8,24 @@ using namespace metal;
|
||||||
|
|
||||||
#define GET_BUFFER_BINDING(index) (28 + index)
|
#define GET_BUFFER_BINDING(index) (28 + index)
|
||||||
#define GET_TEXTURE_BINDING(index) (29 + 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)]]) {
|
//fragment float4 fragmentPresent(VertexOut in [[stage_in]], texture2d<float> tex [[texture(0)]], //sampler samplr [[sampler(0)]]) {
|
||||||
// return tex.sample(samplr, in.texCoord);
|
// 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];
|
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))]]) {
|
fragment float4 fragmentCopyDepthToColor(VertexOut in [[stage_in]], texture2d<float, access::read> src [[texture(GET_TEXTURE_BINDING(0))]]) {
|
||||||
// uint2 coord = uint2(vid % width, vid / width);
|
return float4(src.read(uint2(in.position.xy)).r, 0.0, 0.0, 0.0);
|
||||||
// return dst.write(float4(src.read(coord).r, 0.0, 0.0, 0.0), coord);
|
}
|
||||||
|
|
||||||
|
//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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)";
|
)";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue