From a2d15858ad09da2ee5236f60e6f8ea05eb54ba9f Mon Sep 17 00:00:00 2001 From: Samuliak Date: Fri, 2 Aug 2024 17:48:25 +0200 Subject: [PATCH] fix: shader errors --- .../LatteDecompilerEmitMSL.cpp | 26 ++++-- .../LatteDecompilerEmitMSLHeader.hpp | 9 +- .../Latte/Renderer/Metal/LatteTextureMtl.cpp | 56 +++++++------ .../Renderer/Metal/LatteTextureViewMtl.cpp | 4 +- .../HW/Latte/Renderer/Metal/LatteToMtl.cpp | 4 - src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h | 1 - .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 82 ++++++++++--------- .../HW/Latte/Renderer/Metal/MetalRenderer.h | 4 +- 8 files changed, 106 insertions(+), 80 deletions(-) diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp index 21587437..ae6ca8f3 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp @@ -672,7 +672,7 @@ static void _emitUniformAccessCode(LatteDecompilerShaderContext* shaderContext, uniformBufferIndex = aluInstruction->cfInstruction->cBank1Index; } _emitTypeConversionPrefixMSL(shaderContext, LATTE_DECOMPILER_DTYPE_FLOAT, requiredType); - src->addFmt("ubuff{}[", uniformBufferIndex); + src->addFmt("ubuff{}.d[", uniformBufferIndex); _emitUniformAccessIndexCode(shaderContext, aluInstruction, operandIndex); src->addFmt("]"); @@ -2404,7 +2404,8 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex cemu_assert_debug(texInstruction->textureFetch.srcSel[1] < 4); src->addFmt("redcCUBEReverse({},", _getTexGPRAccess(shaderContext, texInstruction->srcGpr, LATTE_DECOMPILER_DTYPE_FLOAT, texInstruction->textureFetch.srcSel[0], texInstruction->textureFetch.srcSel[1], -1, -1, tempBuffer0)); _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 2, LATTE_DECOMPILER_DTYPE_SIGNED_INT); - src->addFmt(", cubeMapArrayIndex{})", texInstruction->textureFetch.textureIndex); // cubemap index + src->add(")"); + src->addFmt(", cubeMapArrayIndex{}", texInstruction->textureFetch.textureIndex); // cubemap index } else if( texDim == Latte::E_DIM::DIM_1D ) { @@ -2427,10 +2428,17 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L) { src->add(","); - if(texOpcode == GPU7_TEX_INST_SAMPLE_LB) - src->add(_FormatFloatAsConstant((float)texInstruction->textureFetch.lodBias / 16.0f)); + if (texOpcode == GPU7_TEX_INST_SAMPLE_LB) + { + src->addFmt("bias({})", _FormatFloatAsConstant((float)texInstruction->textureFetch.lodBias / 16.0f)); + } else + { + // TODO: is this correct + src->add("level("); _emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT); + src->add(")"); + } } else if( texOpcode == GPU7_TEX_INST_SAMPLE_LZ || texOpcode == GPU7_TEX_INST_SAMPLE_C_LZ ) { @@ -2876,7 +2884,7 @@ static void _emitTEXVFetchCode(LatteDecompilerShaderContext* shaderContext, Latt else src->add("("); - src->addFmt("ubuff{}[", texInstruction->textureFetch.textureIndex - 0x80); + src->addFmt("ubuff{}.d[", texInstruction->textureFetch.textureIndex - 0x80); if( shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_SIGNED_INT ) src->addFmt("{}.{}", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[texInstruction->textureFetch.srcSel[0]]); @@ -3611,7 +3619,7 @@ void LatteDecompiler_emitHelperFunctions(LatteDecompilerShaderContext* shaderCon { if( shaderContext->analyzer.hasRedcCUBE ) { - fCStr_shaderSource->add("void redcCUBE(float4 src0, float4 src1, out float3 stm, out int faceId)\r\n" + fCStr_shaderSource->add("void redcCUBE(float4 src0, float4 src1, thread float3& stm, thread int& faceId)\r\n" "{\r\n" "// stm -> x .. s, y .. t, z .. MajorAxis*2.0\r\n" @@ -3721,6 +3729,12 @@ void LatteDecompiler_emitHelperFunctions(LatteDecompilerShaderContext* shaderCon "return round(x / 2.0) * 2.0;\r\n" "}\r\n"); + // unpackHalf2x16 + fCStr_shaderSource->add("" + "float2 unpackHalf2x16(float x) {\r\n" + "return float2(as_type(ushort(as_type(x) & 0x00FF)), as_type(ushort((as_type(x) & 0xFF00) >> 16)));\r\n" + "}\r\n"); + // mul non-ieee way (0*NaN/INF => 0.0) if (shaderContext->options->strictMul) { diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp index 38b15384..e62a7d1c 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp @@ -135,7 +135,7 @@ namespace LatteDecompiler //shaderSrc->addFmt("UNIFORM_BUFFER_LAYOUT({}, {}, {}) ", (sint32)decompilerContext->output->resourceMappingGL.uniformBuffersBindingPoint[i], (sint32)decompilerContext->output->resourceMappingVK.setIndex, (sint32)decompilerContext->output->resourceMappingVK.uniformBuffersBindingPoint[i]); shaderSrc->addFmt("struct UBuff{} {{" _CRLF, i); - shaderSrc->addFmt("float4 d{}[{}];" _CRLF, i, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(decompilerContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE)); + shaderSrc->addFmt("float4 d[{}];" _CRLF, decompilerContext->analyzer.uniformBufferAccessTracker[i].DetermineSize(decompilerContext->shaderBaseHash, LATTE_GLSL_DYNAMIC_UNIFORM_BLOCK_SIZE)); shaderSrc->add("};" _CRLF _CRLF); } } @@ -348,8 +348,11 @@ namespace LatteDecompiler cemu_assert_unimplemented(); } - src->addFmt(" tex{} [[texture({})]]", i, shaderContext->output->resourceMappingGL.textureUnitToBindingPoint[i]); - src->addFmt(", sampler samplr{} [[sampler({})]]", i, shaderContext->output->resourceMappingGL.textureUnitToBindingPoint[i]); + // HACK + uint32 textureBinding = shaderContext->output->resourceMappingGL.textureUnitToBindingPoint[i] % 31; + uint32 samplerBinding = textureBinding % 16; + src->addFmt(" tex{} [[texture({})]]", i, textureBinding); + src->addFmt(", sampler samplr{} [[sampler({})]]", i, samplerBinding); } } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp index 9a8a3927..933752eb 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp @@ -25,10 +25,40 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM desc->setHeight(effectiveBaseHeight); desc->setMipmapLevelCount(mipLevels); - if (dim == Latte::E_DIM::DIM_3D) + MTL::TextureType textureType; + switch (dim) + { + case Latte::E_DIM::DIM_1D: + textureType = MTL::TextureType1D; + break; + case Latte::E_DIM::DIM_2D: + case Latte::E_DIM::DIM_2D_MSAA: + textureType = MTL::TextureType2D; + break; + case Latte::E_DIM::DIM_2D_ARRAY: + textureType = MTL::TextureType2DArray; + break; + case Latte::E_DIM::DIM_3D: + textureType = MTL::TextureType3D; + break; + case Latte::E_DIM::DIM_CUBEMAP: + textureType = MTL::TextureTypeCube; // TODO: check this + break; + default: + cemu_assert_unimplemented(); + textureType = MTL::TextureType2D; + break; + } + desc->setTextureType(textureType); + + if (textureType == MTL::TextureType3D) { desc->setDepth(effectiveBaseDepth); } + else if (textureType == MTL::TextureTypeCube || textureType == MTL::TextureTypeCubeArray) + { + desc->setArrayLength(effectiveBaseDepth / 6); + } else { desc->setArrayLength(effectiveBaseDepth); @@ -46,30 +76,6 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM } desc->setUsage(usage); - switch (dim) - { - case Latte::E_DIM::DIM_1D: - desc->setTextureType(MTL::TextureType1D); - break; - case Latte::E_DIM::DIM_2D: - case Latte::E_DIM::DIM_2D_MSAA: - desc->setTextureType(MTL::TextureType2D); - break; - case Latte::E_DIM::DIM_2D_ARRAY: - desc->setTextureType(MTL::TextureType2DArray); - break; - case Latte::E_DIM::DIM_3D: - desc->setTextureType(MTL::TextureType3D); - break; - case Latte::E_DIM::DIM_CUBEMAP: - desc->setTextureType(MTL::TextureTypeCube); // TODO: check this - break; - default: - cemu_assert_unimplemented(); - desc->setTextureType(MTL::TextureType2D); - break; - } - m_texture = mtlRenderer->GetDevice()->newTexture(desc); desc->release(); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp index 34dd6f9f..2e7a3309 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp @@ -2,6 +2,7 @@ #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" +#include "Metal/MTLTexture.hpp" LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) : LatteTextureView(texture, firstMip, mipCount, firstSlice, sliceCount, dim, format), m_mtlr(mtlRenderer), m_format(format) @@ -39,8 +40,7 @@ LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextur if (textureType == MTL::TextureType3D) { cemu_assert_debug(firstMip == 0); - // TODO: uncomment - //cemu_assert_debug(this->numSlice == baseTexture->depth); + cemu_assert_debug(this->numSlice == baseTexture->depth); baseLayer = 0; layerCount = 1; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index a7d5598c..049482c6 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -1,8 +1,4 @@ #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" -#include "Common/precompiled.h" -#include "Metal/MTLPixelFormat.hpp" -#include "Metal/MTLRenderPipeline.hpp" -#include "Metal/MTLVertexDescriptor.hpp" std::map MTL_COLOR_FORMAT_TABLE = { {Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct? diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h index 922d536c..54e0de32 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h @@ -6,7 +6,6 @@ #include "Cafe/HW/Latte/Core/LatteConst.h" //#include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" -#include "Metal/MTLRenderPipeline.hpp" struct Uvec2 { uint32 x; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 00207d65..54bf1fee 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -61,7 +61,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow) MTL::Library* presentLibrary = m_device->newLibrary(NS::String::string(presentLibrarySource, NS::ASCIIStringEncoding), nullptr, &error); if (error) { - printf("failed to create present library (error: %s)\n", error->localizedDescription()->utf8String()); + debug_printf("failed to create present library (error: %s)\n", error->localizedDescription()->utf8String()); error->release(); throw; return; @@ -79,7 +79,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow) presentFragmentFunction->release(); if (error) { - printf("failed to create present pipeline (error: %s)\n", error->localizedDescription()->utf8String()); + debug_printf("failed to create present pipeline (error: %s)\n", error->localizedDescription()->utf8String()); error->release(); throw; return; @@ -92,19 +92,19 @@ void MetalRenderer::Initialize() void MetalRenderer::Shutdown() { - printf("MetalRenderer::Shutdown not implemented\n"); + debug_printf("MetalRenderer::Shutdown not implemented\n"); } bool MetalRenderer::IsPadWindowActive() { - printf("MetalRenderer::IsPadWindowActive not implemented\n"); + debug_printf("MetalRenderer::IsPadWindowActive not implemented\n"); return false; } bool MetalRenderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const { - printf("MetalRenderer::GetVRAMInfo not implemented\n"); + debug_printf("MetalRenderer::GetVRAMInfo not implemented\n"); usageInMB = 1024; totalInMB = 1024; @@ -114,12 +114,12 @@ bool MetalRenderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const void MetalRenderer::ClearColorbuffer(bool padView) { - printf("MetalRenderer::ClearColorbuffer not implemented\n"); + debug_printf("MetalRenderer::ClearColorbuffer not implemented\n"); } void MetalRenderer::DrawEmptyFrame(bool mainWindow) { - printf("MetalRenderer::DrawEmptyFrame not implemented\n"); + debug_printf("MetalRenderer::DrawEmptyFrame not implemented\n"); } void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC) @@ -132,7 +132,7 @@ void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC) m_commandBuffer->presentDrawable(m_drawable); } else { - printf("skipped present!\n"); + debug_printf("skipped present!\n"); } m_drawable = nullptr; @@ -177,7 +177,7 @@ bool MetalRenderer::BeginFrame(bool mainWindow) void MetalRenderer::Flush(bool waitIdle) { - printf("MetalRenderer::Flush not implemented\n"); + debug_printf("MetalRenderer::Flush not implemented\n"); } void MetalRenderer::NotifyLatteCommandProcessorIdle() @@ -188,7 +188,7 @@ void MetalRenderer::NotifyLatteCommandProcessorIdle() void MetalRenderer::AppendOverlayDebugInfo() { - printf("MetalRenderer::AppendOverlayDebugInfo not implemented\n"); + debug_printf("MetalRenderer::AppendOverlayDebugInfo not implemented\n"); } void MetalRenderer::renderTarget_setViewport(float x, float y, float width, float height, float nearZ, float farZ, bool halfZ) @@ -232,7 +232,7 @@ void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size) void MetalRenderer::texture_releaseTextureUploadBuffer(uint8* mem) { - printf("MetalRenderer::texture_releaseTextureUploadBuffer not implemented\n"); + debug_printf("MetalRenderer::texture_releaseTextureUploadBuffer not implemented\n"); } TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, uint32 width, uint32 height) @@ -253,7 +253,7 @@ TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT f case Latte::E_GX2SURFFMT::D32_S8_FLOAT: return TextureDecoder_D32_S8_UINT_X24::getInstance(); default: - printf("invalid depth texture format %u\n", (uint32)format); + debug_printf("invalid depth texture format %u\n", (uint32)format); cemu_assert_debug(false); return nullptr; } @@ -356,7 +356,7 @@ TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT f case Latte::E_GX2SURFFMT::X24_G8_UINT: return TextureDecoder_X24_G8_UINT::getInstance(); // todo - verify default: - printf("invalid color texture format %u\n", (uint32)format); + debug_printf("invalid color texture format %u\n", (uint32)format); cemu_assert_debug(false); return nullptr; } @@ -365,7 +365,7 @@ TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT f void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) { - printf("MetalRenderer::texture_clearSlice not implemented\n"); + debug_printf("MetalRenderer::texture_clearSlice not implemented\n"); } void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, sint32 height, sint32 depth, void* pixelData, sint32 sliceIndex, sint32 mipIndex, uint32 compressedImageSize) @@ -379,12 +379,12 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) { - printf("MetalRenderer::texture_clearColorSlice not implemented\n"); + debug_printf("MetalRenderer::texture_clearColorSlice not implemented\n"); } void MetalRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) { - printf("MetalRenderer::texture_clearDepthSlice not implemented\n"); + debug_printf("MetalRenderer::texture_clearDepthSlice not implemented\n"); } LatteTexture* MetalRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) @@ -399,19 +399,19 @@ void MetalRenderer::texture_setLatteTexture(LatteTextureView* textureView, uint3 void MetalRenderer::texture_copyImageSubData(LatteTexture* src, sint32 srcMip, sint32 effectiveSrcX, sint32 effectiveSrcY, sint32 srcSlice, LatteTexture* dst, sint32 dstMip, sint32 effectiveDstX, sint32 effectiveDstY, sint32 dstSlice, sint32 effectiveCopyWidth, sint32 effectiveCopyHeight, sint32 srcDepth) { - printf("MetalRenderer::texture_copyImageSubData not implemented\n"); + debug_printf("MetalRenderer::texture_copyImageSubData not implemented\n"); } LatteTextureReadbackInfo* MetalRenderer::texture_createReadback(LatteTextureView* textureView) { - printf("MetalRenderer::texture_createReadback not implemented\n"); + debug_printf("MetalRenderer::texture_createReadback not implemented\n"); return nullptr; } void MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion(LatteTexture* sourceTexture, sint32 srcMip, sint32 srcSlice, LatteTexture* destinationTexture, sint32 dstMip, sint32 dstSlice, sint32 width, sint32 height) { - printf("MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion not implemented\n"); + debug_printf("MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion not implemented\n"); } void MetalRenderer::bufferCache_init(const sint32 bufferSize) @@ -431,7 +431,7 @@ void MetalRenderer::bufferCache_copy(uint32 srcOffset, uint32 dstOffset, uint32 void MetalRenderer::bufferCache_copyStreamoutToMainBuffer(uint32 srcOffset, uint32 dstOffset, uint32 size) { - printf("MetalRenderer::bufferCache_copyStreamoutToMainBuffer not implemented\n"); + debug_printf("MetalRenderer::bufferCache_copyStreamoutToMainBuffer not implemented\n"); } void MetalRenderer::buffer_bindVertexBuffer(uint32 bufferIndex, uint32 offset, uint32 size) @@ -455,17 +455,17 @@ RendererShader* MetalRenderer::shader_create(RendererShader::ShaderType type, ui void MetalRenderer::streamout_setupXfbBuffer(uint32 bufferIndex, sint32 ringBufferOffset, uint32 rangeAddr, uint32 rangeSize) { - printf("MetalRenderer::streamout_setupXfbBuffer not implemented\n"); + debug_printf("MetalRenderer::streamout_setupXfbBuffer not implemented\n"); } void MetalRenderer::streamout_begin() { - printf("MetalRenderer::streamout_begin not implemented\n"); + debug_printf("MetalRenderer::streamout_begin not implemented\n"); } void MetalRenderer::streamout_rendererFinishDrawcall() { - printf("MetalRenderer::streamout_rendererFinishDrawcall not implemented\n"); + debug_printf("MetalRenderer::streamout_rendererFinishDrawcall not implemented\n"); } void MetalRenderer::draw_beginSequence() @@ -476,7 +476,7 @@ void MetalRenderer::draw_beginSequence() LatteSHRC_UpdateActiveShaders(); if (LatteGPUState.activeShaderHasError) { - printf("Skipping drawcalls due to shader error\n"); + debug_printf("Skipping drawcalls due to shader error\n"); m_state.skipDrawSequence = true; cemu_assert_debug(false); return; @@ -489,14 +489,14 @@ void MetalRenderer::draw_beginSequence() LatteGPUState.repeatTextureInitialization = false; if (!LatteMRT::UpdateCurrentFBO()) { - printf("Rendertarget invalid\n"); + debug_printf("Rendertarget invalid\n"); m_state.skipDrawSequence = true; return; // no render target } if (!hasValidFramebufferAttached) { - printf("Drawcall with no color buffer or depth buffer attached\n"); + debug_printf("Drawcall with no color buffer or depth buffer attached\n"); m_state.skipDrawSequence = true; return; // no render target } @@ -534,7 +534,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 // Render pass if (!m_state.activeFBO) { - printf("no active FBO, skipping draw\n"); + debug_printf("no active FBO, skipping draw\n"); return; } @@ -562,7 +562,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader(); if (!vertexShader || !static_cast(vertexShader->shader)->GetFunction()) { - printf("no vertex function, skipping draw\n"); + debug_printf("no vertex function, skipping draw\n"); return; } @@ -612,7 +612,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 layout->setStepFunction(MTL::VertexStepFunctionPerInstance); else { - printf("unimplemented vertex fetch type %u\n", (uint32)fetchType.value()); + debug_printf("unimplemented vertex fetch type %u\n", (uint32)fetchType.value()); cemu_assert(false); } } @@ -678,7 +678,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error); if (error) { - printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String()); + debug_printf("error creating render pipeline state: %s\n", error->localizedDescription()->utf8String()); return; } renderCommandEncoder->setRenderPipelineState(renderPipelineState); @@ -744,7 +744,7 @@ void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, u void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size) { - printf("MetalRenderer::indexData_uploadIndexMemory not implemented\n"); + debug_printf("MetalRenderer::indexData_uploadIndexMemory not implemented\n"); } void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader) @@ -759,6 +759,11 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE auto texUnitRegIndex = hostTextureUnit * 7; auto textureView = m_state.textures[hostTextureUnit]; + if (!textureView) + { + debug_printf("invalid bound texture view %u\n", hostTextureUnit); + continue; + } //LatteTexture* baseTexture = textureView->baseTexture; // get texture register word 0 @@ -768,10 +773,11 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE //auto imageViewObj = textureView->GetSamplerView(word4); //info.imageView = imageViewObj->m_textureImageView; - uint32 binding = shader->resourceMapping.getTextureBaseBindingPoint() + i; + // HACK + uint32 textureBinding = (shader->resourceMapping.getTextureBaseBindingPoint() + i) % MAX_MTL_TEXTURES; + uint32 samplerBinding = textureBinding % MAX_MTL_SAMPLERS; uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit]; - // TODO: uncomment if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE) { // TODO: bind the actual sampler @@ -780,12 +786,12 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE { case LatteConst::ShaderType::Vertex: { - renderCommandEncoder->setVertexSamplerState(sampler, binding); + renderCommandEncoder->setVertexSamplerState(sampler, samplerBinding); break; } case LatteConst::ShaderType::Pixel: { - renderCommandEncoder->setFragmentSamplerState(sampler, binding); + renderCommandEncoder->setFragmentSamplerState(sampler, samplerBinding); break; } default: @@ -797,12 +803,12 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE { case LatteConst::ShaderType::Vertex: { - renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding); + renderCommandEncoder->setVertexTexture(textureView->GetTexture(), textureBinding); break; } case LatteConst::ShaderType::Pixel: { - renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding); + renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), textureBinding); break; } default: @@ -919,7 +925,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i]; if (binding >= MAX_MTL_BUFFERS) { - printf("too big buffer index (%u), skipping binding\n", binding); + debug_printf("too big buffer index (%u), skipping binding\n", binding); continue; } size_t offset = m_state.uniformBufferOffsets[(uint32)shader->shaderType][binding]; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index fff6c6c2..5e6d6995 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -17,6 +17,7 @@ #define MTL_SUPPORT_BUFFER_BINDING 30 #define MAX_MTL_TEXTURES 31 +#define MAX_MTL_SAMPLERS 16 constexpr size_t INVALID_OFFSET = std::numeric_limits::max(); @@ -31,7 +32,8 @@ struct MetalState bool skipDrawSequence = false; class CachedFBOMtl* activeFBO = nullptr; MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}}; - class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr}; + // TODO: find out what is the max number of bound textures on the Wii U + class LatteTextureViewMtl* textures[64] = {nullptr}; size_t uniformBufferOffsets[(uint32)LatteConst::ShaderType::TotalCount][MAX_MTL_BUFFERS]; MTL::Texture* colorRenderTargets[8] = {nullptr}; MTL::Texture* depthRenderTarget = nullptr;