1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-13 19:29:14 +01:00

[dxbc] Handle 0 divisors in UDiv

UDiv is defined as having 0xffffffff as both the quotient and remainder value when the divisor is 0

This fixes vertex corruption on the water bottles in Half-Life: Alyx
https://github.com/ValveSoftware/Proton/issues/3681

https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/udiv--sm4---asm-
This commit is contained in:
Joshua Ashton 2020-03-26 07:08:31 +00:00 committed by Philip Rebohle
parent 649c3805d9
commit 62c2c9cd15

View File

@ -2054,6 +2054,14 @@ namespace dxvk {
emitRegisterLoad(ins.src[1], srcMask),
};
// Division by zero will return 0xffffffff for both results
auto bvecId = getVectorTypeId({ DxbcScalarType::Bool, ins.dst[0].mask.popCount() });
DxbcRegisterValue const0 = emitBuildConstVecu32( 0u, 0u, 0u, 0u, ins.dst[0].mask);
DxbcRegisterValue constff = emitBuildConstVecu32(~0u, ~0u, ~0u, ~0u, ins.dst[0].mask);
uint32_t cmpValue = m_module.opINotEqual(bvecId, src.at(1).id, const0.id);
// Compute results only if the destination
// operands are not NULL.
if (ins.dst[0].type != DxbcOperandType::Null) {
@ -2064,6 +2072,10 @@ namespace dxvk {
quotient.id = m_module.opUDiv(
getVectorTypeId(quotient.type),
src.at(0).id, src.at(1).id);
quotient.id = m_module.opSelect(
getVectorTypeId(quotient.type),
cmpValue, quotient.id, constff.id);
quotient = emitDstOperandModifiers(quotient, ins.modifiers);
emitRegisterStore(ins.dst[0], quotient);
@ -2077,6 +2089,10 @@ namespace dxvk {
remainder.id = m_module.opUMod(
getVectorTypeId(remainder.type),
src.at(0).id, src.at(1).id);
remainder.id = m_module.opSelect(
getVectorTypeId(remainder.type),
cmpValue, remainder.id, constff.id);
remainder = emitDstOperandModifiers(remainder, ins.modifiers);
emitRegisterStore(ins.dst[1], remainder);