From e142fadfcdebb25cab7acf0d30e9e3cb9cc42c0f Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Sun, 21 Jun 2026 12:38:36 +0200 Subject: [PATCH] Latte: Remove calculation of unused minIndex --- src/Cafe/HW/Latte/Core/Latte.h | 2 +- src/Cafe/HW/Latte/Core/LatteBufferData.cpp | 2 +- src/Cafe/HW/Latte/Core/LatteIndices.cpp | 181 +++++------------- src/Cafe/HW/Latte/Core/LatteIndices.h | 2 +- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 5 +- .../Renderer/OpenGL/OpenGLRendererCore.cpp | 2 +- .../HW/Latte/Renderer/Vulkan/VulkanAPI.cpp | 8 + .../Renderer/Vulkan/VulkanRendererCore.cpp | 10 +- 8 files changed, 70 insertions(+), 142 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/Latte.h b/src/Cafe/HW/Latte/Core/Latte.h index fae9e51f..711bb087 100644 --- a/src/Cafe/HW/Latte/Core/Latte.h +++ b/src/Cafe/HW/Latte/Core/Latte.h @@ -168,7 +168,7 @@ void LatteCP_ProcessRingbuffer(); // buffer cache -void LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance, uint32 instanceCount, uint32 attribBufferDirtyMask, uint32 vsUniformBufferDirtyMask, uint32 psUniformBufferDirtyMask, uint32 gsUniformBufferDirtyMask, uint8& stageUniformModifiedMask, bool isIncremental = false); +void LatteBufferCache_Sync(uint32 maxIndex, uint32 baseInstance, uint32 instanceCount, uint32 attribBufferDirtyMask, uint32 vsUniformBufferDirtyMask, uint32 psUniformBufferDirtyMask, uint32 gsUniformBufferDirtyMask, uint8& stageUniformModifiedMask, bool isIncremental = false); bool LatteBufferCache_LoadRemappedUniforms(struct LatteDecompilerShader* shader, float* uniformData, bool aluConstDirty, uint32 uniformBufferDirtyMask); void LatteRenderTarget_updateViewport(); diff --git a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp index 17a781d5..e7fb4893 100644 --- a/src/Cafe/HW/Latte/Core/LatteBufferData.cpp +++ b/src/Cafe/HW/Latte/Core/LatteBufferData.cpp @@ -185,7 +185,7 @@ void LatteBufferCache_ProcessQueues() } // upload vertex and uniform buffers and update bindings -void LatteBufferCache_Sync(uint32 minIndex, uint32 maxIndex, uint32 baseInstance, uint32 instanceCount, uint32 attribBufferDirtyMask, uint32 vsUniformBufferDirtyMask, uint32 psUniformBufferDirtyMask, uint32 gsUniformBufferDirtyMask, uint8& stageUniformModifiedMask, bool isIncremental) +void LatteBufferCache_Sync(uint32 maxIndex, uint32 baseInstance, uint32 instanceCount, uint32 attribBufferDirtyMask, uint32 vsUniformBufferDirtyMask, uint32 psUniformBufferDirtyMask, uint32 gsUniformBufferDirtyMask, uint8& stageUniformModifiedMask, bool isIncremental) { LatteFetchShader* parsedFetchShader = LatteSHRC_GetActiveFetchShader(); cemu_assert_debug(parsedFetchShader); diff --git a/src/Cafe/HW/Latte/Core/LatteIndices.cpp b/src/Cafe/HW/Latte/Core/LatteIndices.cpp index 260c6cd6..a2376443 100644 --- a/src/Cafe/HW/Latte/Core/LatteIndices.cpp +++ b/src/Cafe/HW/Latte/Core/LatteIndices.cpp @@ -21,7 +21,6 @@ struct LatteIndexType lastIndexType; uint64 lastUsed; // output - uint32 indexMin; uint32 indexMax; Renderer::INDEX_TYPE renderIndexType; uint32 outputCount; @@ -140,7 +139,7 @@ uint32 LatteIndices_calculateIndexOutputSize(LattePrimitiveMode primitiveMode, L } template -void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const betype* src = (betype*)indexDataInput; T* dst = (T*)indexDataOutput; @@ -148,7 +147,6 @@ void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, u { T v = *src; *dst = v; - indexMin = std::min(indexMin, (uint32)v); indexMax = std::max(indexMax, (uint32)v); dst++; src++; @@ -156,7 +154,7 @@ void LatteIndices_convertBE(const void* indexDataInput, void* indexDataOutput, u } template -void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const T* src = (T*)indexDataInput; T* dst = (T*)indexDataOutput; @@ -164,7 +162,6 @@ void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, u { T v = *src; *dst = v; - indexMin = std::min(indexMin, (uint32)v); indexMax = std::max(indexMax, (uint32)v); dst++; src++; @@ -172,7 +169,7 @@ void LatteIndices_convertLE(const void* indexDataInput, void* indexDataOutput, u } template -void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { sint32 numQuads = count / 4; const betype* src = (betype*)indexDataInput; @@ -183,13 +180,9 @@ void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexD T idx1 = src[1]; T idx2 = src[2]; T idx3 = src[3]; - indexMin = std::min(indexMin, (uint32)idx0); indexMax = std::max(indexMax, (uint32)idx0); - indexMin = std::min(indexMin, (uint32)idx1); indexMax = std::max(indexMax, (uint32)idx1); - indexMin = std::min(indexMin, (uint32)idx2); indexMax = std::max(indexMax, (uint32)idx2); - indexMin = std::min(indexMin, (uint32)idx3); indexMax = std::max(indexMax, (uint32)idx3); dst[0] = idx0; dst[1] = idx1; @@ -203,7 +196,7 @@ void LatteIndices_unpackQuadsAndConvert(const void* indexDataInput, void* indexD } template -void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { sint32 numQuads = count / 4; const betype* src = (betype*)indexDataInput; @@ -223,12 +216,11 @@ void LatteIndices_generateAutoQuadIndices(const void* indexDataInput, void* inde src += 4; dst += 6; } - indexMin = 0; indexMax = std::max(count, 1u) - 1; } template -void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { if (count <= 3) return; @@ -241,13 +233,9 @@ void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* in T idx1 = src[1]; T idx2 = src[2]; T idx3 = src[3]; - indexMin = std::min(indexMin, (uint32)idx0); indexMax = std::max(indexMax, (uint32)idx0); - indexMin = std::min(indexMin, (uint32)idx1); indexMax = std::max(indexMax, (uint32)idx1); - indexMin = std::min(indexMin, (uint32)idx2); indexMax = std::max(indexMax, (uint32)idx2); - indexMin = std::min(indexMin, (uint32)idx3); indexMax = std::max(indexMax, (uint32)idx3); dst[0] = idx0; dst[1] = idx1; @@ -261,7 +249,7 @@ void LatteIndices_unpackQuadStripAndConvert(const void* indexDataInput, void* in } template -void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { if (count <= 0) return; @@ -271,7 +259,6 @@ void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* ind for (sint32 i = 0; i < (sint32)count; i++) { T idx = *src; - indexMin = std::min(indexMin, (uint32)idx); indexMax = std::max(indexMax, (uint32)idx); *dst = idx; src++; @@ -281,7 +268,7 @@ void LatteIndices_unpackLineLoopAndConvert(const void* indexDataInput, void* ind } template -void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 count, uint32& indexMax) { if (count <= 3) return; @@ -301,13 +288,12 @@ void LatteIndices_generateAutoQuadStripIndices(void* indexDataOutput, uint32 cou dst[5] = idx3; dst += 6; } - indexMin = 0; indexMax = std::max(count, 1u) - 1; } template -void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 count, uint32& indexMax) { if (count == 0) return; @@ -319,12 +305,11 @@ void LatteIndices_generateAutoLineLoopIndices(void* indexDataOutput, uint32 coun } *dst = 0; dst++; - indexMin = 0; indexMax = std::max(count, 1u) - 1; } template -void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const betype* src = (betype*)indexDataInput; T* dst = (T*)indexDataOutput; @@ -337,14 +322,13 @@ void LatteIndices_unpackTriangleFanAndConvert(const void* indexDataInput, void* 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; } } template -void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const betype* src = (betype*)indexDataInput; T* dst = (T*)indexDataOutput; @@ -357,13 +341,12 @@ void LatteIndices_generateAutoTriangleFanIndices(const void* indexDataInput, voi idx = count - 1 - idx / 2; dst[i] = idx; } - indexMin = 0; indexMax = std::max(count, 1u) - 1; } #if defined(ARCH_X86_64) ATTRIBUTE_AVX2 -void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { // using AVX + AVX2 we can process 16 indices at a time const uint16* indicesU16BE = (const uint16*)indexDataInput; @@ -385,33 +368,23 @@ void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDat // endian swap mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle16Swap); _mm256_store_si256((__m256i*)indexOutput, mIndexData); - mMin = _mm256_min_epu16(mIndexData, mMin); mMax = _mm256_max_epu16(mIndexData, mMax); indexOutput += 16; } while (--count16); // fold 32 to 16 byte - mMin = _mm256_min_epu16(mMin, _mm256_permute2x128_si256(mMin, mMin, 1)); mMax = _mm256_max_epu16(mMax, _mm256_permute2x128_si256(mMax, mMax, 1)); // fold 16 to 8 byte - mMin = _mm256_min_epu16(mMin, _mm256_shuffle_epi32(mMin, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6))); mMax = _mm256_max_epu16(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6))); - uint16* mMinU16 = (uint16*)&mMin; uint16* mMaxU16 = (uint16*)&mMax; - indexMin = std::min(indexMin, (uint32)mMinU16[0]); - indexMin = std::min(indexMin, (uint32)mMinU16[1]); - indexMin = std::min(indexMin, (uint32)mMinU16[2]); - indexMin = std::min(indexMin, (uint32)mMinU16[3]); - indexMax = std::max(indexMax, (uint32)mMaxU16[0]); indexMax = std::max(indexMax, (uint32)mMaxU16[1]); indexMax = std::max(indexMax, (uint32)mMaxU16[2]); indexMax = std::max(indexMax, (uint32)mMaxU16[3]); } // process remaining indices - uint32 _minIndex = 0xFFFFFFFF; uint32 _maxIndex = 0; for (sint32 i = countRemaining; (--i) >= 0;) { @@ -420,15 +393,13 @@ void LatteIndices_fastConvertU16_AVX2(const void* indexDataInput, void* indexDat indexOutput++; indicesU16BE++; _maxIndex = std::max(_maxIndex, (uint32)idx); - _minIndex = std::min(_minIndex, (uint32)idx); } - // update min/max + // update max indexMax = std::max(indexMax, _maxIndex); - indexMin = std::min(indexMin, _minIndex); } ATTRIBUTE_SSE41 -void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { // SSSE3 & SSE4.1 optimized decoding const uint16* indicesU16BE = (const uint16*)indexDataInput; @@ -437,7 +408,6 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa sint32 countRemaining = count & 7; if (count8) { - __m128i mMin = _mm_set_epi16((short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF, (short)0xFFFF); __m128i mMax = _mm_set_epi16(0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); __m128i mTemp; __m128i* mRawIndices = (__m128i*)indicesU16BE; @@ -450,14 +420,12 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa mTemp = _mm_loadu_si128(mRawIndices); mRawIndices++; mTemp = _mm_shuffle_epi8(mTemp, shufmask); - mMin = _mm_min_epu16(mMin, mTemp); mMax = _mm_max_epu16(mMax, mTemp); _mm_store_si128(mOutputIndices, mTemp); mOutputIndices++; } uint16* mMaxU16 = (uint16*)&mMax; - uint16* mMinU16 = (uint16*)&mMin; indexMax = std::max(indexMax, (uint32)mMaxU16[0]); indexMax = std::max(indexMax, (uint32)mMaxU16[1]); @@ -467,16 +435,7 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa indexMax = std::max(indexMax, (uint32)mMaxU16[5]); indexMax = std::max(indexMax, (uint32)mMaxU16[6]); indexMax = std::max(indexMax, (uint32)mMaxU16[7]); - indexMin = std::min(indexMin, (uint32)mMinU16[0]); - indexMin = std::min(indexMin, (uint32)mMinU16[1]); - indexMin = std::min(indexMin, (uint32)mMinU16[2]); - indexMin = std::min(indexMin, (uint32)mMinU16[3]); - indexMin = std::min(indexMin, (uint32)mMinU16[4]); - indexMin = std::min(indexMin, (uint32)mMinU16[5]); - indexMin = std::min(indexMin, (uint32)mMinU16[6]); - indexMin = std::min(indexMin, (uint32)mMinU16[7]); } - uint32 _minIndex = 0xFFFFFFFF; uint32 _maxIndex = 0; for (sint32 i = countRemaining; (--i) >= 0;) { @@ -485,14 +444,12 @@ void LatteIndices_fastConvertU16_SSE41(const void* indexDataInput, void* indexDa indexOutput++; indicesU16BE++; _maxIndex = std::max(_maxIndex, (uint32)idx); - _minIndex = std::min(_minIndex, (uint32)idx); } indexMax = std::max(indexMax, _maxIndex); - indexMin = std::min(indexMin, _minIndex); } ATTRIBUTE_AVX2 -void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { // using AVX + AVX2 we can process 8 indices at a time const uint32* indicesU32BE = (const uint32*)indexDataInput; @@ -501,7 +458,6 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat sint32 countRemaining = count & 7; if (count8) { - __m256i mMin = _mm256_set_epi32((sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF, (sint32)0xFFFFFFFF); __m256i mMax = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0); __m256i mShuffle32Swap = _mm256_set_epi8(28,29,30,31, 24,25,26,27, @@ -520,29 +476,20 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat // endian swap mIndexData = _mm256_shuffle_epi8(mIndexData, mShuffle32Swap); _mm256_store_si256((__m256i*)indexOutput, mIndexData); - mMin = _mm256_min_epu32(mIndexData, mMin); mMax = _mm256_max_epu32(mIndexData, mMax); indexOutput += 8; } while (--count8); // fold 32 to 16 byte - mMin = _mm256_min_epu32(mMin, _mm256_permute2x128_si256(mMin, mMin, 1)); mMax = _mm256_max_epu32(mMax, _mm256_permute2x128_si256(mMax, mMax, 1)); // fold 16 to 8 byte - mMin = _mm256_min_epu32(mMin, _mm256_shuffle_epi32(mMin, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6))); mMax = _mm256_max_epu32(mMax, _mm256_shuffle_epi32(mMax, (2 << 0) | (3 << 2) | (2 << 4) | (3 << 6))); - uint32* mMinU32 = (uint32*)&mMin; uint32* mMaxU32 = (uint32*)&mMax; - - indexMin = std::min(indexMin, (uint32)mMinU32[0]); - indexMin = std::min(indexMin, (uint32)mMinU32[1]); - indexMax = std::max(indexMax, (uint32)mMaxU32[0]); indexMax = std::max(indexMax, (uint32)mMaxU32[1]); } // process remaining indices - uint32 _minIndex = 0xFFFFFFFF; uint32 _maxIndex = 0; for (sint32 i = countRemaining; (--i) >= 0;) { @@ -551,15 +498,13 @@ void LatteIndices_fastConvertU32_AVX2(const void* indexDataInput, void* indexDat indexOutput++; indicesU32BE++; _maxIndex = std::max(_maxIndex, (uint32)idx); - _minIndex = std::min(_minIndex, (uint32)idx); } // update min/max indexMax = std::max(indexMax, _maxIndex); - indexMin = std::min(indexMin, _minIndex); } #elif defined(__aarch64__) -void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const uint16* indicesU16BE = (const uint16*)indexDataInput; uint16* indexOutput = (uint16*)indexDataOutput; @@ -568,7 +513,6 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat if (count8) { - uint16x8_t mMin = vdupq_n_u16(0xFFFF); uint16x8_t mMax = vdupq_n_u16(0x0000); uint16x8_t mTemp; uint16x8_t* mRawIndices = (uint16x8_t*) indicesU16BE; @@ -581,22 +525,18 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat mTemp = vld1q_u16((uint16*)mRawIndices); mRawIndices++; mTemp = vrev16q_u8(mTemp); - mMin = vminq_u16(mMin, mTemp); mMax = vmaxq_u16(mMax, mTemp); vst1q_u16((uint16*)mOutputIndices, mTemp); mOutputIndices++; } uint16* mMaxU16 = (uint16*)&mMax; - uint16* mMinU16 = (uint16*)&mMin; for (int i = 0; i < 8; ++i) { indexMax = std::max(indexMax, (uint32)mMaxU16[i]); - indexMin = std::min(indexMin, (uint32)mMinU16[i]); } } // process remaining indices - uint32 _minIndex = 0xFFFFFFFF; uint32 _maxIndex = 0; for (sint32 i = countRemaining; (--i) >= 0;) { @@ -605,14 +545,12 @@ void LatteIndices_fastConvertU16_NEON(const void* indexDataInput, void* indexDat indexOutput++; indicesU16BE++; _maxIndex = std::max(_maxIndex, (uint32)idx); - _minIndex = std::min(_minIndex, (uint32)idx); } // update min/max indexMax = std::max(indexMax, _maxIndex); - indexMin = std::min(indexMin, _minIndex); } -void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDataOutput, uint32 count, uint32& indexMax) { const uint32* indicesU32BE = (const uint32*)indexDataInput; uint32* indexOutput = (uint32*)indexDataOutput; @@ -621,7 +559,6 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat if (count8) { - uint32x4_t mMin = vdupq_n_u32(0xFFFFFFFF); uint32x4_t mMax = vdupq_n_u32(0x00000000); uint32x4_t mTemp; uint32x4_t* mRawIndices = (uint32x4_t*) indicesU32BE; @@ -634,22 +571,18 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat mTemp = vld1q_u32((uint32*)mRawIndices); mRawIndices++; mTemp = vrev32q_u8(mTemp); - mMin = vminq_u32(mMin, mTemp); mMax = vmaxq_u32(mMax, mTemp); vst1q_u32((uint32*)mOutputIndices, mTemp); mOutputIndices++; } uint32* mMaxU32 = (uint32*)&mMax; - uint32* mMinU32 = (uint32*)&mMin; for (int i = 0; i < 4; ++i) { indexMax = std::max(indexMax, mMaxU32[i]); - indexMin = std::min(indexMin, mMinU32[i]); } } // process remaining indices - uint32 _minIndex = 0xFFFFFFFF; uint32 _maxIndex = 0; for (sint32 i = countRemaining; (--i) >= 0;) { @@ -658,21 +591,18 @@ void LatteIndices_fastConvertU32_NEON(const void* indexDataInput, void* indexDat indexOutput++; indicesU32BE++; _maxIndex = std::max(_maxIndex, idx); - _minIndex = std::min(_minIndex, idx); } // update min/max indexMax = std::max(indexMax, _maxIndex); - indexMin = std::min(indexMin, _minIndex); } #endif template -void _LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, uint32 count, uint32 primitiveRestartIndex, uint32& indexMin, uint32& indexMax) +void _LatteIndices_alternativeCalculateIndexMax(const void* indexData, uint32 count, uint32 primitiveRestartIndex, uint32& indexMax) { cemu_assert_debug(count != 0); const betype* idxPtrT = (betype*)indexData; - T _indexMin = *idxPtrT; T _indexMax = *idxPtrT; cemu_assert_debug(primitiveRestartIndex <= std::numeric_limits::max()); T restartIndexT = (T)primitiveRestartIndex; @@ -681,23 +611,20 @@ void _LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, uint32 T idx = *idxPtrT; if (idx != restartIndexT) { - _indexMin = std::min(_indexMin, idx); _indexMax = std::max(_indexMax, idx); } idxPtrT++; count--; } - indexMin = _indexMin; indexMax = _indexMax; } // calculate min and max index while taking primitive restart into account // fallback implementation in case the fast path gives us invalid results -void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIndexType indexType, uint32 count, uint32& indexMin, uint32& indexMax) +void LatteIndices_alternativeCalculateIndexMax(const void* indexData, LatteIndexType indexType, uint32 count, uint32& indexMax) { if (count == 0) { - indexMin = 0; indexMax = 0; return; } @@ -705,11 +632,11 @@ void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIn if (indexType == LatteIndexType::U16_BE) { - _LatteIndices_alternativeCalculateIndexMinMax(indexData, count, primitiveRestartIndex, indexMin, indexMax); + _LatteIndices_alternativeCalculateIndexMax(indexData, count, primitiveRestartIndex, indexMax); } else if (indexType == LatteIndexType::U32_BE) { - _LatteIndices_alternativeCalculateIndexMinMax(indexData, count, primitiveRestartIndex, indexMin, indexMax); + _LatteIndices_alternativeCalculateIndexMax(indexData, count, primitiveRestartIndex, indexMax); } else { @@ -717,7 +644,7 @@ void LatteIndices_alternativeCalculateIndexMinMax(const void* indexData, LatteIn } } -void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation) +void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation) { // what this should do: // [x] use fast SIMD-based index decoding @@ -733,7 +660,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 }); if (cacheEntry != LatteIndexCache.entry.end()) { - indexMin = cacheEntry->indexMin; indexMax = cacheEntry->indexMax; renderIndexType = cacheEntry->renderIndexType; outputCount = cacheEntry->outputCount; @@ -759,7 +685,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 if (indexOutputSize == 0) { outputCount = count; - indexMin = 0; indexMax = std::max(count, 1u)-1; renderIndexType = Renderer::INDEX_TYPE::NONE; indexAllocation = {}; @@ -770,7 +695,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 void* indexOutputPtr = indexAllocation.mem; // decode indices - indexMin = std::numeric_limits::max(); indexMax = std::numeric_limits::min(); if (primitiveMode == LattePrimitiveMode::QUADS) { @@ -779,19 +703,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 { if (count <= 0xFFFF) { - LatteIndices_generateAutoQuadIndices(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoQuadIndices(indexData, indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U16; } else { - LatteIndices_generateAutoQuadIndices(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoQuadIndices(indexData, indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U32; } } else if (indexType == LatteIndexType::U16_BE) - LatteIndices_unpackQuadsAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackQuadsAndConvert(indexData, indexOutputPtr, count, indexMax); else if (indexType == LatteIndexType::U32_BE) - LatteIndices_unpackQuadsAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackQuadsAndConvert(indexData, indexOutputPtr, count, indexMax); else cemu_assert_debug(false); outputCount = count / 4 * 6; @@ -803,19 +727,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 { if (count <= 0xFFFF) { - LatteIndices_generateAutoQuadStripIndices(indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoQuadStripIndices(indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U16; } else { - LatteIndices_generateAutoQuadStripIndices(indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoQuadStripIndices(indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U32; } } else if (indexType == LatteIndexType::U16_BE) - LatteIndices_unpackQuadStripAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackQuadStripAndConvert(indexData, indexOutputPtr, count, indexMax); else if (indexType == LatteIndexType::U32_BE) - LatteIndices_unpackQuadStripAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackQuadStripAndConvert(indexData, indexOutputPtr, count, indexMax); else cemu_assert_debug(false); if (count >= 2) @@ -830,19 +754,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 { if (count <= 0xFFFF) { - LatteIndices_generateAutoLineLoopIndices(indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoLineLoopIndices(indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U16; } else { - LatteIndices_generateAutoLineLoopIndices(indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoLineLoopIndices(indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U32; } } else if (indexType == LatteIndexType::U16_BE) - LatteIndices_unpackLineLoopAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackLineLoopAndConvert(indexData, indexOutputPtr, count, indexMax); else if (indexType == LatteIndexType::U32_BE) - LatteIndices_unpackLineLoopAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackLineLoopAndConvert(indexData, indexOutputPtr, count, indexMax); else cemu_assert_debug(false); outputCount = count + 1; @@ -853,19 +777,19 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 { if (count <= 0xFFFF) { - LatteIndices_generateAutoTriangleFanIndices(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoTriangleFanIndices(indexData, indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U16; } else { - LatteIndices_generateAutoTriangleFanIndices(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_generateAutoTriangleFanIndices(indexData, indexOutputPtr, count, indexMax); renderIndexType = Renderer::INDEX_TYPE::U32; } } else if (indexType == LatteIndexType::U16_BE) - LatteIndices_unpackTriangleFanAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackTriangleFanAndConvert(indexData, indexOutputPtr, count, indexMax); else if (indexType == LatteIndexType::U32_BE) - LatteIndices_unpackTriangleFanAndConvert(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_unpackTriangleFanAndConvert(indexData, indexOutputPtr, count, indexMax); else cemu_assert_debug(false); outputCount = count; @@ -876,48 +800,48 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 { #if defined(ARCH_X86_64) if (g_CPUFeatures.x86.avx2) - LatteIndices_fastConvertU16_AVX2(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_fastConvertU16_AVX2(indexData, indexOutputPtr, count, indexMax); else if (g_CPUFeatures.x86.sse4_1 && g_CPUFeatures.x86.ssse3) - LatteIndices_fastConvertU16_SSE41(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_fastConvertU16_SSE41(indexData, indexOutputPtr, count, indexMax); else - LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMax); #elif defined(__aarch64__) - LatteIndices_fastConvertU16_NEON(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_fastConvertU16_NEON(indexData, indexOutputPtr, count, indexMax); #else - LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMax); #endif } else if (indexType == LatteIndexType::U32_BE) { #if defined(ARCH_X86_64) if (g_CPUFeatures.x86.avx2) - LatteIndices_fastConvertU32_AVX2(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_fastConvertU32_AVX2(indexData, indexOutputPtr, count, indexMax); else - LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMax); #elif defined(__aarch64__) - LatteIndices_fastConvertU32_NEON(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_fastConvertU32_NEON(indexData, indexOutputPtr, count, indexMax); #else - LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertBE(indexData, indexOutputPtr, count, indexMax); #endif } else if (indexType == LatteIndexType::U16_LE) { - LatteIndices_convertLE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertLE(indexData, indexOutputPtr, count, indexMax); } else if (indexType == LatteIndexType::U32_LE) { - LatteIndices_convertLE(indexData, indexOutputPtr, count, indexMin, indexMax); + LatteIndices_convertLE(indexData, indexOutputPtr, count, indexMax); } else cemu_assert_debug(false); outputCount = count; } - // the above algorithms use a simplistic approach to get indexMin/indexMax - // here we make sure primitive restart indices dont influence the index range - if (primitiveRestartIndex == indexMin || primitiveRestartIndex == indexMax) + // the above algorithms use a fast approach to get indexMax which does not filter out indices matching primitiveRestartIndex + // here we use a fallback in case the determined index equals the primitive restart index + if (primitiveRestartIndex == indexMax) { // recalculate index range but filter out primitive restart index - LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax); + LatteIndices_alternativeCalculateIndexMax(indexData, indexType, count, indexMax); } g_renderer->indexData_uploadIndexMemory(indexAllocation); performanceMonitor.cycle[performanceMonitor.cycleIndex].indexDataUploaded += indexOutputSize; @@ -934,7 +858,6 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 lruEntry->lastCount = count; lruEntry->lastPrimitiveMode = primitiveMode; lruEntry->lastIndexType = indexType; - lruEntry->indexMin = indexMin; lruEntry->indexMax = indexMax; lruEntry->renderIndexType = renderIndexType; lruEntry->outputCount = outputCount; diff --git a/src/Cafe/HW/Latte/Core/LatteIndices.h b/src/Cafe/HW/Latte/Core/LatteIndices.h index 8aace24e..26ddb062 100644 --- a/src/Cafe/HW/Latte/Core/LatteIndices.h +++ b/src/Cafe/HW/Latte/Core/LatteIndices.h @@ -4,4 +4,4 @@ void LatteIndices_invalidate(const void* memPtr, uint32 size); void LatteIndices_invalidateAll(); -void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMin, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation); \ No newline at end of file +void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32 count, LattePrimitiveMode primitiveMode, uint32& indexMax, Renderer::INDEX_TYPE& renderIndexType, uint32& outputCount, Renderer::IndexAllocation& indexAllocation); \ No newline at end of file diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 50e60cc2..a694411b 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -1142,10 +1142,9 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 // Index buffer Renderer::INDEX_TYPE hostIndexType; uint32 hostIndexCount; - uint32 indexMin = 0; uint32 indexMax = 0; Renderer::IndexAllocation indexAllocation; - LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation); + LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMax, hostIndexType, hostIndexCount, indexAllocation); auto indexAllocationMtl = static_cast(indexAllocation.rendererInternal); // Buffer cache @@ -1165,7 +1164,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 // synchronize vertex and uniform cache and update buffer bindings // We need to call this before getting the render command encoder, since it can cause buffer copies uint8 stageUniformModifiedMask = 0; - LatteBufferCache_Sync(indexMin + baseVertex, indexMax + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); + LatteBufferCache_Sync(indexMax + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); } // Render pass diff --git a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp index 56d7a8aa..a67306b3 100644 --- a/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/OpenGL/OpenGLRendererCore.cpp @@ -976,7 +976,7 @@ void OpenGLRenderer::draw_genericDrawHandler(uint32 baseVertex, uint32 baseInsta // synchronize vertex and uniform buffers uint8 stageUniformModifiedMask = 0; - LatteBufferCache_Sync(indexState.minIndex + baseVertex, indexState.maxIndex + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); + LatteBufferCache_Sync(indexState.maxIndex + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); _setupVertexAttributes(); diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp index e09ebcd1..b7dc5001 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.cpp @@ -58,6 +58,14 @@ void VulkanBenchmarkPrintResults() cemuLog_log(LogType::Force, "--- Vulkan API CPU benchmark ---"); cemuLog_log(LogType::Force, "Elapsed cycles this frame: {:} | Current cycle {:} | NumFunc {:}", elapsedCycles, currentCycle, s_vulkanBenchmarkFuncs.size()); + // sum up total time of Vulkan calls + uint64 totalVkCycles = 0; + for (auto& it : s_vulkanBenchmarkFuncs) + { + totalVkCycles += it->cycles; + } + cemuLog_log(LogType::Force, "Total Vulkan time: {:.4}%", ((double)totalVkCycles / elapsedCyclesDbl) * 100.0); + std::vector sortedIndices(s_vulkanBenchmarkFuncs.size()); std::iota(sortedIndices.begin(), sortedIndices.end(), 0); std::sort(sortedIndices.begin(), sortedIndices.end(), diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp index 11314581..01295a4d 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRendererCore.cpp @@ -1368,10 +1368,9 @@ void VulkanRenderer::draw_execute_first(uint32 baseVertex, uint32 baseInstance, Renderer::INDEX_TYPE hostIndexType; uint32 hostIndexCount; - uint32 indexMin = 0; uint32 indexMax = 0; Renderer::IndexAllocation indexAllocation; - LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation); + LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMax, hostIndexType, hostIndexCount, indexAllocation); VKRSynchronizedHeapAllocator::AllocatorReservation* indexReservation = (VKRSynchronizedHeapAllocator::AllocatorReservation*)indexAllocation.rendererInternal; // update index binding if (hostIndexType != INDEX_TYPE::NONE) @@ -1412,7 +1411,7 @@ void VulkanRenderer::draw_execute_first(uint32 baseVertex, uint32 baseInstance, { // synchronize vertex and uniform cache and update buffer bindings uint8 stageUniformModifiedMask = 0; - LatteBufferCache_Sync(indexMin + baseVertex, indexMax + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); + LatteBufferCache_Sync(indexMax + baseVertex, baseInstance, instanceCount, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, stageUniformModifiedMask); } PipelineInfo* pipeline_info = draw_getOrCreateGraphicsPipeline(count); @@ -1537,10 +1536,9 @@ void VulkanRenderer::draw_execute_continued(uint32 baseVertex, uint32 baseInstan Renderer::INDEX_TYPE hostIndexType; uint32 hostIndexCount; - uint32 indexMin = 0; uint32 indexMax = 0; Renderer::IndexAllocation indexAllocation; - LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMin, indexMax, hostIndexType, hostIndexCount, indexAllocation); + LatteIndices_decode(memory_getPointerFromVirtualOffset(indexDataMPTR), indexType, count, primitiveMode, indexMax, hostIndexType, hostIndexCount, indexAllocation); VKRSynchronizedHeapAllocator::AllocatorReservation* indexReservation = (VKRSynchronizedHeapAllocator::AllocatorReservation*)indexAllocation.rendererInternal; // update index binding if (hostIndexType != INDEX_TYPE::NONE) @@ -1580,7 +1578,7 @@ void VulkanRenderer::draw_execute_continued(uint32 baseVertex, uint32 baseInstan else { // synchronize vertex and uniform cache and update buffer bindings - LatteBufferCache_Sync(indexMin + baseVertex, indexMax + baseVertex, baseInstance, instanceCount, drawcallContext.vertexBufferDirtyMask, drawcallContext.vsUniformBufferDirtyMask, drawcallContext.psUniformBufferDirtyMask, drawcallContext.gsUniformBufferDirtyMask, stageUniformModifiedMask, true); + LatteBufferCache_Sync(indexMax + baseVertex, baseInstance, instanceCount, drawcallContext.vertexBufferDirtyMask, drawcallContext.vsUniformBufferDirtyMask, drawcallContext.psUniformBufferDirtyMask, drawcallContext.gsUniformBufferDirtyMask, stageUniformModifiedMask, true); } m_state.descriptorSetsChanged = false;