fix: shader errors

This commit is contained in:
Samuliak 2024-08-02 17:48:25 +02:00
parent e4abb305ac
commit a2d15858ad
8 changed files with 106 additions and 80 deletions

View File

@ -672,7 +672,7 @@ static void _emitUniformAccessCode(LatteDecompilerShaderContext* shaderContext,
uniformBufferIndex = aluInstruction->cfInstruction->cBank1Index; uniformBufferIndex = aluInstruction->cfInstruction->cBank1Index;
} }
_emitTypeConversionPrefixMSL(shaderContext, LATTE_DECOMPILER_DTYPE_FLOAT, requiredType); _emitTypeConversionPrefixMSL(shaderContext, LATTE_DECOMPILER_DTYPE_FLOAT, requiredType);
src->addFmt("ubuff{}[", uniformBufferIndex); src->addFmt("ubuff{}.d[", uniformBufferIndex);
_emitUniformAccessIndexCode(shaderContext, aluInstruction, operandIndex); _emitUniformAccessIndexCode(shaderContext, aluInstruction, operandIndex);
src->addFmt("]"); src->addFmt("]");
@ -2404,7 +2404,8 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex
cemu_assert_debug(texInstruction->textureFetch.srcSel[1] < 4); 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)); 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); _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 ) 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) if( texOpcode == GPU7_TEX_INST_SAMPLE_L || texOpcode == GPU7_TEX_INST_SAMPLE_LB || texOpcode == GPU7_TEX_INST_SAMPLE_C_L)
{ {
src->add(","); src->add(",");
if(texOpcode == GPU7_TEX_INST_SAMPLE_LB) if (texOpcode == GPU7_TEX_INST_SAMPLE_LB)
src->add(_FormatFloatAsConstant((float)texInstruction->textureFetch.lodBias / 16.0f)); {
src->addFmt("bias({})", _FormatFloatAsConstant((float)texInstruction->textureFetch.lodBias / 16.0f));
}
else else
{
// TODO: is this correct
src->add("level(");
_emitTEXSampleCoordInputComponent(shaderContext, texInstruction, 3, LATTE_DECOMPILER_DTYPE_FLOAT); _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 ) 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 else
src->add("("); 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 ) if( shaderContext->typeTracker.defaultDataType == LATTE_DECOMPILER_DTYPE_SIGNED_INT )
src->addFmt("{}.{}", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[texInstruction->textureFetch.srcSel[0]]); src->addFmt("{}.{}", _getRegisterVarName(shaderContext, texInstruction->srcGpr), resultElemTable[texInstruction->textureFetch.srcSel[0]]);
@ -3611,7 +3619,7 @@ void LatteDecompiler_emitHelperFunctions(LatteDecompilerShaderContext* shaderCon
{ {
if( shaderContext->analyzer.hasRedcCUBE ) 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" "{\r\n"
"// stm -> x .. s, y .. t, z .. MajorAxis*2.0\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" "return round(x / 2.0) * 2.0;\r\n"
"}\r\n"); "}\r\n");
// unpackHalf2x16
fCStr_shaderSource->add(""
"float2 unpackHalf2x16(float x) {\r\n"
"return float2(as_type<half>(ushort(as_type<uint>(x) & 0x00FF)), as_type<half>(ushort((as_type<uint>(x) & 0xFF00) >> 16)));\r\n"
"}\r\n");
// mul non-ieee way (0*NaN/INF => 0.0) // mul non-ieee way (0*NaN/INF => 0.0)
if (shaderContext->options->strictMul) if (shaderContext->options->strictMul)
{ {

View File

@ -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("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("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); shaderSrc->add("};" _CRLF _CRLF);
} }
} }
@ -348,8 +348,11 @@ namespace LatteDecompiler
cemu_assert_unimplemented(); cemu_assert_unimplemented();
} }
src->addFmt(" tex{} [[texture({})]]", i, shaderContext->output->resourceMappingGL.textureUnitToBindingPoint[i]); // HACK
src->addFmt(", sampler samplr{} [[sampler({})]]", i, shaderContext->output->resourceMappingGL.textureUnitToBindingPoint[i]); 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);
} }
} }

View File

@ -25,10 +25,40 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
desc->setHeight(effectiveBaseHeight); desc->setHeight(effectiveBaseHeight);
desc->setMipmapLevelCount(mipLevels); 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); desc->setDepth(effectiveBaseDepth);
} }
else if (textureType == MTL::TextureTypeCube || textureType == MTL::TextureTypeCubeArray)
{
desc->setArrayLength(effectiveBaseDepth / 6);
}
else else
{ {
desc->setArrayLength(effectiveBaseDepth); desc->setArrayLength(effectiveBaseDepth);
@ -46,30 +76,6 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
} }
desc->setUsage(usage); 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); m_texture = mtlRenderer->GetDevice()->newTexture(desc);
desc->release(); desc->release();

View File

@ -2,6 +2,7 @@
#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"
LatteTextureViewMtl::LatteTextureViewMtl(MetalRenderer* mtlRenderer, LatteTextureMtl* texture, Latte::E_DIM dim, Latte::E_GX2SURFFMT format, sint32 firstMip, sint32 mipCount, sint32 firstSlice, sint32 sliceCount) 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) : 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) if (textureType == MTL::TextureType3D)
{ {
cemu_assert_debug(firstMip == 0); cemu_assert_debug(firstMip == 0);
// TODO: uncomment cemu_assert_debug(this->numSlice == baseTexture->depth);
//cemu_assert_debug(this->numSlice == baseTexture->depth);
baseLayer = 0; baseLayer = 0;
layerCount = 1; layerCount = 1;
} }

View File

@ -1,8 +1,4 @@
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #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<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = { std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = {
{Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct? {Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct?

View File

@ -6,7 +6,6 @@
#include "Cafe/HW/Latte/Core/LatteConst.h" #include "Cafe/HW/Latte/Core/LatteConst.h"
//#include "Cafe/HW/Latte/Core/FetchShader.h" //#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Metal/MTLRenderPipeline.hpp"
struct Uvec2 { struct Uvec2 {
uint32 x; uint32 x;

View File

@ -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); MTL::Library* presentLibrary = m_device->newLibrary(NS::String::string(presentLibrarySource, NS::ASCIIStringEncoding), nullptr, &error);
if (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(); error->release();
throw; throw;
return; return;
@ -79,7 +79,7 @@ void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow)
presentFragmentFunction->release(); presentFragmentFunction->release();
if (error) 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(); error->release();
throw; throw;
return; return;
@ -92,19 +92,19 @@ void MetalRenderer::Initialize()
void MetalRenderer::Shutdown() void MetalRenderer::Shutdown()
{ {
printf("MetalRenderer::Shutdown not implemented\n"); debug_printf("MetalRenderer::Shutdown not implemented\n");
} }
bool MetalRenderer::IsPadWindowActive() bool MetalRenderer::IsPadWindowActive()
{ {
printf("MetalRenderer::IsPadWindowActive not implemented\n"); debug_printf("MetalRenderer::IsPadWindowActive not implemented\n");
return false; return false;
} }
bool MetalRenderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const bool MetalRenderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const
{ {
printf("MetalRenderer::GetVRAMInfo not implemented\n"); debug_printf("MetalRenderer::GetVRAMInfo not implemented\n");
usageInMB = 1024; usageInMB = 1024;
totalInMB = 1024; totalInMB = 1024;
@ -114,12 +114,12 @@ bool MetalRenderer::GetVRAMInfo(int& usageInMB, int& totalInMB) const
void MetalRenderer::ClearColorbuffer(bool padView) void MetalRenderer::ClearColorbuffer(bool padView)
{ {
printf("MetalRenderer::ClearColorbuffer not implemented\n"); debug_printf("MetalRenderer::ClearColorbuffer not implemented\n");
} }
void MetalRenderer::DrawEmptyFrame(bool mainWindow) 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) void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
@ -132,7 +132,7 @@ void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
m_commandBuffer->presentDrawable(m_drawable); m_commandBuffer->presentDrawable(m_drawable);
} else } else
{ {
printf("skipped present!\n"); debug_printf("skipped present!\n");
} }
m_drawable = nullptr; m_drawable = nullptr;
@ -177,7 +177,7 @@ bool MetalRenderer::BeginFrame(bool mainWindow)
void MetalRenderer::Flush(bool waitIdle) void MetalRenderer::Flush(bool waitIdle)
{ {
printf("MetalRenderer::Flush not implemented\n"); debug_printf("MetalRenderer::Flush not implemented\n");
} }
void MetalRenderer::NotifyLatteCommandProcessorIdle() void MetalRenderer::NotifyLatteCommandProcessorIdle()
@ -188,7 +188,7 @@ void MetalRenderer::NotifyLatteCommandProcessorIdle()
void MetalRenderer::AppendOverlayDebugInfo() 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) 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) 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) 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: case Latte::E_GX2SURFFMT::D32_S8_FLOAT:
return TextureDecoder_D32_S8_UINT_X24::getInstance(); return TextureDecoder_D32_S8_UINT_X24::getInstance();
default: default:
printf("invalid depth texture format %u\n", (uint32)format); debug_printf("invalid depth texture format %u\n", (uint32)format);
cemu_assert_debug(false); cemu_assert_debug(false);
return nullptr; return nullptr;
} }
@ -356,7 +356,7 @@ TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT f
case Latte::E_GX2SURFFMT::X24_G8_UINT: case Latte::E_GX2SURFFMT::X24_G8_UINT:
return TextureDecoder_X24_G8_UINT::getInstance(); // todo - verify return TextureDecoder_X24_G8_UINT::getInstance(); // todo - verify
default: default:
printf("invalid color texture format %u\n", (uint32)format); debug_printf("invalid color texture format %u\n", (uint32)format);
cemu_assert_debug(false); cemu_assert_debug(false);
return nullptr; return nullptr;
} }
@ -365,7 +365,7 @@ TextureDecoder* MetalRenderer::texture_chooseDecodedFormat(Latte::E_GX2SURFFMT f
void MetalRenderer::texture_clearSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex) 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) 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) 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) 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) 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) 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) LatteTextureReadbackInfo* MetalRenderer::texture_createReadback(LatteTextureView* textureView)
{ {
printf("MetalRenderer::texture_createReadback not implemented\n"); debug_printf("MetalRenderer::texture_createReadback not implemented\n");
return nullptr; return nullptr;
} }
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)
{ {
printf("MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion not implemented\n"); debug_printf("MetalRenderer::surfaceCopy_copySurfaceWithFormatConversion not implemented\n");
} }
void MetalRenderer::bufferCache_init(const sint32 bufferSize) 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) 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) 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) 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() void MetalRenderer::streamout_begin()
{ {
printf("MetalRenderer::streamout_begin not implemented\n"); debug_printf("MetalRenderer::streamout_begin not implemented\n");
} }
void MetalRenderer::streamout_rendererFinishDrawcall() void MetalRenderer::streamout_rendererFinishDrawcall()
{ {
printf("MetalRenderer::streamout_rendererFinishDrawcall not implemented\n"); debug_printf("MetalRenderer::streamout_rendererFinishDrawcall not implemented\n");
} }
void MetalRenderer::draw_beginSequence() void MetalRenderer::draw_beginSequence()
@ -476,7 +476,7 @@ void MetalRenderer::draw_beginSequence()
LatteSHRC_UpdateActiveShaders(); LatteSHRC_UpdateActiveShaders();
if (LatteGPUState.activeShaderHasError) if (LatteGPUState.activeShaderHasError)
{ {
printf("Skipping drawcalls due to shader error\n"); debug_printf("Skipping drawcalls due to shader error\n");
m_state.skipDrawSequence = true; m_state.skipDrawSequence = true;
cemu_assert_debug(false); cemu_assert_debug(false);
return; return;
@ -489,14 +489,14 @@ void MetalRenderer::draw_beginSequence()
LatteGPUState.repeatTextureInitialization = false; LatteGPUState.repeatTextureInitialization = false;
if (!LatteMRT::UpdateCurrentFBO()) if (!LatteMRT::UpdateCurrentFBO())
{ {
printf("Rendertarget invalid\n"); debug_printf("Rendertarget invalid\n");
m_state.skipDrawSequence = true; m_state.skipDrawSequence = true;
return; // no render target return; // no render target
} }
if (!hasValidFramebufferAttached) 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; m_state.skipDrawSequence = true;
return; // no render target return; // no render target
} }
@ -534,7 +534,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
// Render pass // Render pass
if (!m_state.activeFBO) if (!m_state.activeFBO)
{ {
printf("no active FBO, skipping draw\n"); debug_printf("no active FBO, skipping draw\n");
return; return;
} }
@ -562,7 +562,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader(); LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader();
if (!vertexShader || !static_cast<RendererShaderMtl*>(vertexShader->shader)->GetFunction()) if (!vertexShader || !static_cast<RendererShaderMtl*>(vertexShader->shader)->GetFunction())
{ {
printf("no vertex function, skipping draw\n"); debug_printf("no vertex function, skipping draw\n");
return; return;
} }
@ -612,7 +612,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
layout->setStepFunction(MTL::VertexStepFunctionPerInstance); layout->setStepFunction(MTL::VertexStepFunctionPerInstance);
else 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); cemu_assert(false);
} }
} }
@ -678,7 +678,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error); MTL::RenderPipelineState* renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
if (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; return;
} }
renderCommandEncoder->setRenderPipelineState(renderPipelineState); renderCommandEncoder->setRenderPipelineState(renderPipelineState);
@ -744,7 +744,7 @@ void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, u
void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size) 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) void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandEncoder, LatteDecompilerShader* shader)
@ -759,6 +759,11 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
auto texUnitRegIndex = hostTextureUnit * 7; auto texUnitRegIndex = hostTextureUnit * 7;
auto textureView = m_state.textures[hostTextureUnit]; auto textureView = m_state.textures[hostTextureUnit];
if (!textureView)
{
debug_printf("invalid bound texture view %u\n", hostTextureUnit);
continue;
}
//LatteTexture* baseTexture = textureView->baseTexture; //LatteTexture* baseTexture = textureView->baseTexture;
// get texture register word 0 // get texture register word 0
@ -768,10 +773,11 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
//auto imageViewObj = textureView->GetSamplerView(word4); //auto imageViewObj = textureView->GetSamplerView(word4);
//info.imageView = imageViewObj->m_textureImageView; //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]; uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit];
// TODO: uncomment
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE) if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
{ {
// TODO: bind the actual sampler // TODO: bind the actual sampler
@ -780,12 +786,12 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
renderCommandEncoder->setVertexSamplerState(sampler, binding); renderCommandEncoder->setVertexSamplerState(sampler, samplerBinding);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
renderCommandEncoder->setFragmentSamplerState(sampler, binding); renderCommandEncoder->setFragmentSamplerState(sampler, samplerBinding);
break; break;
} }
default: default:
@ -797,12 +803,12 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
{ {
case LatteConst::ShaderType::Vertex: case LatteConst::ShaderType::Vertex:
{ {
renderCommandEncoder->setVertexTexture(textureView->GetTexture(), binding); renderCommandEncoder->setVertexTexture(textureView->GetTexture(), textureBinding);
break; break;
} }
case LatteConst::ShaderType::Pixel: case LatteConst::ShaderType::Pixel:
{ {
renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), binding); renderCommandEncoder->setFragmentTexture(textureView->GetTexture(), textureBinding);
break; break;
} }
default: default:
@ -919,7 +925,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i]; uint32 binding = shader->resourceMapping.uniformBuffersBindingPoint[i];
if (binding >= MAX_MTL_BUFFERS) 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; continue;
} }
size_t offset = m_state.uniformBufferOffsets[(uint32)shader->shaderType][binding]; size_t offset = m_state.uniformBufferOffsets[(uint32)shader->shaderType][binding];

View File

@ -17,6 +17,7 @@
#define MTL_SUPPORT_BUFFER_BINDING 30 #define MTL_SUPPORT_BUFFER_BINDING 30
#define MAX_MTL_TEXTURES 31 #define MAX_MTL_TEXTURES 31
#define MAX_MTL_SAMPLERS 16
constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max(); constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max();
@ -31,7 +32,8 @@ struct MetalState
bool skipDrawSequence = false; bool skipDrawSequence = false;
class CachedFBOMtl* activeFBO = nullptr; class CachedFBOMtl* activeFBO = nullptr;
MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}}; 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]; size_t uniformBufferOffsets[(uint32)LatteConst::ShaderType::TotalCount][MAX_MTL_BUFFERS];
MTL::Texture* colorRenderTargets[8] = {nullptr}; MTL::Texture* colorRenderTargets[8] = {nullptr};
MTL::Texture* depthRenderTarget = nullptr; MTL::Texture* depthRenderTarget = nullptr;