diff --git a/src/Cafe/HW/Latte/Core/LatteIndices.cpp b/src/Cafe/HW/Latte/Core/LatteIndices.cpp index 260c6cd6..77f66581 100644 --- a/src/Cafe/HW/Latte/Core/LatteIndices.cpp +++ b/src/Cafe/HW/Latte/Core/LatteIndices.cpp @@ -117,16 +117,22 @@ uint32 LatteIndices_calculateIndexOutputSize(LattePrimitiveMode primitiveMode, L } else if (primitiveMode == LattePrimitiveMode::TRIANGLE_FAN && g_renderer->GetType() == RendererAPI::Metal) { + // Metal doesn't support triangle fan -> convert to triangle list + if (count <= 2) + { + return 0; + } + uint32 numTriangles = count - 2; if (indexType == LatteIndexType::AUTO) { if (count <= 0xFFFF) - return count * sizeof(uint16); - return count * sizeof(uint32); + return numTriangles * 3 * sizeof(uint16); + return numTriangles * 3 * sizeof(uint32); } if (indexType == LatteIndexType::U16_BE || indexType == LatteIndexType::U16_LE) - return count * sizeof(uint16); + return numTriangles * 3 * sizeof(uint16); if (indexType == LatteIndexType::U32_BE || indexType == LatteIndexType::U32_LE) - return count * sizeof(uint32); + return numTriangles * 3 * sizeof(uint32); cemu_assert_suspicious(); return 0; } @@ -326,36 +332,46 @@ void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 coun template void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) { + if (count <= 2) + return; + sint32 numTriangles = count - 2; const betype* src = (betype*)indexDataInput; + T idx0 = src[0]; + indexMin = std::min(indexMin, (uint32)idx0); + indexMax = std::max(indexMax, (uint32)idx0); T* dst = (T*)indexDataOutput; - // TODO: check this - for (sint32 i = 0; i < count; i++) + for (sint32 i = 0; i < numTriangles; i++) { - uint32 i0; - if (i % 2 == 0) - i0 = i / 2; - else - i0 = count - 1 - i / 2; - T idx = src[i0]; - indexMin = std::min(indexMin, (uint32)idx); - indexMax = std::max(indexMax, (uint32)idx); - dst[i] = idx; + T idx1 = src[1]; + T idx2 = src[2]; + indexMin = std::min(indexMin, (uint32)idx1); + indexMax = std::max(indexMax, (uint32)idx1); + indexMin = std::min(indexMin, (uint32)idx2); + indexMax = std::max(indexMax, (uint32)idx2); + dst[0] = idx0; + dst[1] = idx1; + dst[2] = idx2; + src += 1; + dst += 3; } } template void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) { - const betype* src = (betype*)indexDataInput; + if (count <= 2) + return; + sint32 numTriangles = count - 2; T* dst = (T*)indexDataOutput; - for (sint32 i = 0; i < count; i++) + for (sint32 i = 0; i < numTriangles; i++) { - T idx = i; - if (idx % 2 == 0) - idx = idx / 2; - else - idx = count - 1 - idx / 2; - dst[i] = idx; + T idx0 = 0; + T idx1 = i + 1; + T idx2 = i + 2; + dst[0] = idx0; + dst[1] = idx1; + dst[2] = idx2; + dst += 3; } indexMin = 0; indexMax = std::max(count, 1u) - 1; @@ -868,7 +884,10 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 LatteIndices_unpackTriangleFanAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); else cemu_assert_debug(false); - outputCount = count; + if (count >= 2) + outputCount = (count - 2) * 3; + else + outputCount = 0; } else { diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp index a06b11f0..10178c5c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp @@ -104,17 +104,17 @@ MTL::Texture* LatteTextureViewMtl::GetSwizzledView(uint32 gpuSamplerSwizzle) } // Fallback cache - auto& fallbackEntry = m_fallbackViewCache[gpuSamplerSwizzle]; - if (fallbackEntry) + auto it = m_fallbackViewCache.find(gpuSamplerSwizzle); + if (it != m_fallbackViewCache.end()) { - return fallbackEntry; + return it->second; } MTL::Texture* texture = CreateSwizzledView(gpuSamplerSwizzle); if (freeIndex != -1) m_viewCache[freeIndex] = {gpuSamplerSwizzle, texture}; else - fallbackEntry = texture; + m_fallbackViewCache[gpuSamplerSwizzle] = texture; return texture; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index 7bf295df..28404ba6 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -244,7 +244,7 @@ MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode primitiveMode) case Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::TRIANGLES: return MTL::PrimitiveTypeTriangle; case Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::TRIANGLE_FAN: - return MTL::PrimitiveTypeTriangleStrip; + return MTL::PrimitiveTypeTriangle; // triangle fans are emulated as a triangle list case Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::TRIANGLE_STRIP: return MTL::PrimitiveTypeTriangleStrip; case Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::QUADS: diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h index 270c2db7..46188ce3 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h @@ -31,9 +31,9 @@ private: std::map m_pipelineCache; FSpinlock m_pipelineCacheLock; - std::thread* m_pipelineCacheStoreThread; + std::thread* m_pipelineCacheStoreThread = nullptr; - class FileCache* s_cache; + class FileCache* s_cache = nullptr; std::atomic_uint32_t m_numCompilationThreads{ 0 }; ConcurrentQueue> m_compilationQueue; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 7ceaf74d..562ad674 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -236,7 +236,7 @@ MetalRenderer::MetalRenderer() for (uint32 i = 0; i < MAX_MTL_VERTEX_BUFFERS; i++) m_state.m_vertexBufferOffsets[i] = INVALID_OFFSET; - for (uint32 i = 0; i < METAL_SHADER_TYPE_TOTAL; i++) + for (uint32 i = 0; i < METAL_GENERAL_SHADER_TYPE_TOTAL; i++) { for (uint32 j = 0; j < MAX_MTL_BUFFERS; j++) m_state.m_uniformBufferOffsets[i][j] = INVALID_OFFSET;