From 298eeedcc46e3ddeafebe5e8879f051b91d877fd Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 29 Dec 2017 19:26:59 +0100 Subject: [PATCH] [dxbc] Implemented round instructions Also fixed potential numerical stability issues in with min/max instructions and saturation when an operand is NaN. --- src/dxbc/dxbc_compiler.cpp | 35 +++++++++++-- src/dxbc/dxbc_defs.cpp | 25 +++++++-- src/dxgi/dxgi_swapchain.cpp | 1 + src/spirv/spirv_module.cpp | 102 +++++++++++++++++++++++++++++++++--- src/spirv/spirv_module.h | 30 +++++++++-- 5 files changed, 174 insertions(+), 19 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index f05887ccb..61fa04a35 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -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)); diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 0745e91d1..bdf0cc6d0 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -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 }, diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index 272f4c3f6..5a1520f31 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -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); } diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 8cc102cec..289055ca1 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -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, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 538539b32..c3a613341 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -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,