[dxbc] Implemented round instructions

Also fixed potential numerical stability issues in with min/max
instructions and saturation when an operand is NaN.
This commit is contained in:
Philip Rebohle 2017-12-29 19:26:59 +01:00
parent 2e215e24e5
commit 298eeedcc4
5 changed files with 174 additions and 19 deletions

View File

@ -963,6 +963,11 @@ namespace dxvk {
typeId, src.at(0).id);
break;
case DxbcOpcode::Frc:
dst.id = m_module.opFract(
typeId, src.at(0).id);
break;
case DxbcOpcode::Log:
dst.id = m_module.opLog2(
typeId, src.at(0).id);
@ -974,12 +979,12 @@ namespace dxvk {
break;
case DxbcOpcode::Max:
dst.id = m_module.opFMax(typeId,
dst.id = m_module.opNMax(typeId,
src.at(0).id, src.at(1).id);
break;
case DxbcOpcode::Min:
dst.id = m_module.opFMin(typeId,
dst.id = m_module.opNMin(typeId,
src.at(0).id, src.at(1).id);
break;
@ -988,8 +993,23 @@ namespace dxvk {
src.at(0).id, src.at(1).id);
break;
case DxbcOpcode::Sqrt:
dst.id = m_module.opSqrt(
case DxbcOpcode::RoundNe:
dst.id = m_module.opRoundEven(
typeId, src.at(0).id);
break;
case DxbcOpcode::RoundNi:
dst.id = m_module.opFloor(
typeId, src.at(0).id);
break;
case DxbcOpcode::RoundPi:
dst.id = m_module.opCeil(
typeId, src.at(0).id);
break;
case DxbcOpcode::RoundZ:
dst.id = m_module.opTrunc(
typeId, src.at(0).id);
break;
@ -998,6 +1018,11 @@ namespace dxvk {
typeId, src.at(0).id);
break;
case DxbcOpcode::Sqrt:
dst.id = m_module.opSqrt(
typeId, src.at(0).id);
break;
/////////////////////////////////////
// ALU operations on signed integers
case DxbcOpcode::IAdd:
@ -2419,7 +2444,7 @@ namespace dxvk {
if (value.type.ctype == DxbcScalarType::Float32) {
// Saturating only makes sense on floats
if (modifiers.saturate) {
value.id = m_module.opFClamp(
value.id = m_module.opNClamp(
typeId, value.id,
m_module.constf32(0.0f),
m_module.constf32(1.0f));

View File

@ -103,7 +103,10 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* Frc */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* FtoI */
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
@ -296,13 +299,25 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* RoundNe */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* RoundNi */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* RoundPi */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* RoundZ */
{ },
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* Rsq */
{ 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },

View File

@ -66,6 +66,7 @@ namespace dxvk {
TRACE(this);
// We do not release the SDL window handle here since
// that would destroy the underlying window as well.
SDL_DestroyWindow(m_window);
}

View File

@ -1151,7 +1151,7 @@ namespace dxvk {
}
uint32_t SpirvModule::opFMax(
uint32_t SpirvModule::opNMax(
uint32_t resultType,
uint32_t a,
uint32_t b) {
@ -1161,14 +1161,14 @@ namespace dxvk {
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450FMax);
m_code.putWord(spv::GLSLstd450NMax);
m_code.putWord(a);
m_code.putWord(b);
return resultId;
}
uint32_t SpirvModule::opFMin(
uint32_t SpirvModule::opNMin(
uint32_t resultType,
uint32_t a,
uint32_t b) {
@ -1178,7 +1178,7 @@ namespace dxvk {
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450FMin);
m_code.putWord(spv::GLSLstd450NMin);
m_code.putWord(a);
m_code.putWord(b);
return resultId;
@ -1253,7 +1253,7 @@ namespace dxvk {
}
uint32_t SpirvModule::opFClamp(
uint32_t SpirvModule::opNClamp(
uint32_t resultType,
uint32_t x,
uint32_t minVal,
@ -1264,7 +1264,7 @@ namespace dxvk {
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450FClamp);
m_code.putWord(spv::GLSLstd450NClamp);
m_code.putWord(x);
m_code.putWord(minVal);
m_code.putWord(maxVal);
@ -1617,6 +1617,96 @@ namespace dxvk {
}
uint32_t SpirvModule::opFract(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450Fract);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opCeil(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450Ceil);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opFloor(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450Floor);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opRound(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450Round);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opRoundEven(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450RoundEven);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opTrunc(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpExtInst, 6);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(m_instExtGlsl450);
m_code.putWord(spv::GLSLstd450Trunc);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opSelect(
uint32_t resultType,
uint32_t condition,

View File

@ -413,12 +413,12 @@ namespace dxvk {
uint32_t b,
uint32_t c);
uint32_t opFMax(
uint32_t opNMax(
uint32_t resultType,
uint32_t a,
uint32_t b);
uint32_t opFMin(
uint32_t opNMin(
uint32_t resultType,
uint32_t a,
uint32_t b);
@ -443,7 +443,7 @@ namespace dxvk {
uint32_t a,
uint32_t b);
uint32_t opFClamp(
uint32_t opNClamp(
uint32_t resultType,
uint32_t x,
uint32_t minVal,
@ -558,6 +558,30 @@ namespace dxvk {
uint32_t resultType,
uint32_t operand);
uint32_t opFract(
uint32_t resultType,
uint32_t operand);
uint32_t opCeil(
uint32_t resultType,
uint32_t operand);
uint32_t opFloor(
uint32_t resultType,
uint32_t operand);
uint32_t opRound(
uint32_t resultType,
uint32_t operand);
uint32_t opRoundEven(
uint32_t resultType,
uint32_t operand);
uint32_t opTrunc(
uint32_t resultType,
uint32_t operand);
uint32_t opSelect(
uint32_t resultType,
uint32_t condition,