mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-10 01:24:41 -06:00
Latte: fix shader-cache hang, redundant vertex rebind, and latent UB
- Fix an infinite loop when removing a shader from the middle of a cache chain (the list traversal never advanced). - Vulkan direct-access path: record the bound vertex-buffer offset so the redundant-bind check works; previously one vkCmdBindVertexBuffers per buffer group was issued on every draw. - Fix an out-of-bounds __m256i lane read in the clang texture-hash path. - Fix a use-after-free read in the texture-readback queue and an inverted fetch-shader cache assertion. - Initialize MetalRenderer commit-threshold fields; avoid re-strlen'ing the shader source when assigning it.
This commit is contained in:
parent
855e51f3f8
commit
44c19af7db
@ -170,10 +170,13 @@ void LatteFetchShader::CalculateFetchShaderVkHash()
|
||||
EVP_DigestFinal_ex(ctx, shaDigest, NULL);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
|
||||
// fold SHA1 hash into a 64bit value
|
||||
uint64 h = *(uint64*)(shaDigest + 0);
|
||||
h += *(uint64*)(shaDigest + 8);
|
||||
h += (uint64)*(uint32*)(shaDigest + 16);
|
||||
// fold SHA1 hash into a 64bit value (use memcpy to avoid unaligned/strict-aliasing UB)
|
||||
uint64 shaLow, shaMid;
|
||||
uint32 shaHigh;
|
||||
std::memcpy(&shaLow, shaDigest + 0, sizeof(shaLow));
|
||||
std::memcpy(&shaMid, shaDigest + 8, sizeof(shaMid));
|
||||
std::memcpy(&shaHigh, shaDigest + 16, sizeof(shaHigh));
|
||||
uint64 h = shaLow + shaMid + (uint64)shaHigh;
|
||||
this->vkPipelineHashFragment = h;
|
||||
}
|
||||
|
||||
@ -604,7 +607,7 @@ void LatteFetchShader::UnregisterInCache()
|
||||
return;
|
||||
s_spinlockFetchShaderCache.lock();
|
||||
auto itr = s_fetchShaderByHash.find(m_cacheHash);
|
||||
cemu_assert(itr == s_fetchShaderByHash.end());
|
||||
cemu_assert(itr != s_fetchShaderByHash.end());
|
||||
s_fetchShaderByHash.erase(itr);
|
||||
s_spinlockFetchShaderCache.unlock();
|
||||
}
|
||||
|
||||
@ -187,6 +187,7 @@ void LatteSHRC_RemoveFromCaches(LatteDecompilerShader* shader)
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
shaderChain = shaderChain->next;
|
||||
}
|
||||
}
|
||||
cemu_assert(removed);
|
||||
@ -355,7 +356,7 @@ void LatteShader_CreateRendererShader(LatteDecompilerShader* shader, bool compil
|
||||
shader->isCustomShader = true;
|
||||
}
|
||||
else
|
||||
shaderSrc.assign(shader->strBuf_shaderSource->c_str());
|
||||
shaderSrc.assign(shader->strBuf_shaderSource->c_str(), shader->strBuf_shaderSource->getLen());
|
||||
|
||||
if (shaderType == RendererShader::ShaderType::kVertex &&
|
||||
(shader->baseHash == 0x15bc7edf9de2ed30 || shader->baseHash == 0x83a697d61a3b9202 ||
|
||||
|
||||
@ -159,7 +159,7 @@ uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture)
|
||||
h256 = _mm256_xor_si256(h256, temp);
|
||||
}
|
||||
#ifdef __clang__
|
||||
hashVal = h256[0] + h256[1] + h256[2] + h256[3] + h256[4] + h256[5] + h256[6] + h256[7];
|
||||
hashVal = (uint32)h256[0] + (uint32)(h256[0] >> 32) + (uint32)h256[1] + (uint32)(h256[1] >> 32) + (uint32)h256[2] + (uint32)(h256[2] >> 32) + (uint32)h256[3] + (uint32)(h256[3] >> 32);
|
||||
#else
|
||||
hashVal = h256.m256i_u32[0] + h256.m256i_u32[1] + h256.m256i_u32[2] + h256.m256i_u32[3] + h256.m256i_u32[4] + h256.m256i_u32[5] + h256.m256i_u32[6] + h256.m256i_u32[7];
|
||||
#endif
|
||||
|
||||
@ -151,11 +151,11 @@ void LatteTextureReadback_UpdateFinishedTransfers(bool forceFinish)
|
||||
LatteTextureView* origTexView = LatteTextureViewLookupCache::lookupSlice(readbackInfo->hostTextureCopy.physAddress, readbackInfo->hostTextureCopy.width, readbackInfo->hostTextureCopy.height, readbackInfo->hostTextureCopy.pitch, 0, 0, readbackInfo->hostTextureCopy.format);
|
||||
if (origTexView)
|
||||
LatteTC_ResetTextureChangeTracker(origTexView->baseTexture, true);
|
||||
delete readbackInfo;
|
||||
// remove from queue
|
||||
cemu_assert_debug(!sTextureActiveReadbackQueue.empty());
|
||||
cemu_assert_debug(readbackInfo == sTextureActiveReadbackQueue.front());
|
||||
sTextureActiveReadbackQueue.pop();
|
||||
delete readbackInfo;
|
||||
}
|
||||
performanceMonitor.gpuTime_waitForAsync.endMeasuring();
|
||||
}
|
||||
|
||||
@ -535,9 +535,9 @@ private:
|
||||
MetalEncoderType m_encoderType = MetalEncoderType::None;
|
||||
MTL::CommandEncoder* m_commandEncoder = nullptr;
|
||||
|
||||
uint32 m_recordedDrawcalls;
|
||||
uint32 m_defaultCommitTreshlod;
|
||||
uint32 m_commitTreshold;
|
||||
uint32 m_recordedDrawcalls = 0;
|
||||
uint32 m_defaultCommitTreshlod = 0;
|
||||
uint32 m_commitTreshold = 0;
|
||||
|
||||
// State
|
||||
MetalState m_state;
|
||||
|
||||
@ -1772,6 +1772,7 @@ void VulkanRenderer::draw_updateVertexBuffersDirectAccess()
|
||||
VkBuffer attrBuffer = m_importedMem;
|
||||
VkDeviceSize attrOffset = bufferAddress - m_importedMemBaseAddress;
|
||||
vkCmdBindVertexBuffers(m_state.currentCommandBuffer, bufferIndex, 1, &attrBuffer, &attrOffset);
|
||||
m_state.currentVertexBinding[bufferIndex].offset = bufferAddress;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user