Set default floating-point environment at compiler boundaries (#1703)
Restore floating-point environment at compiler boundaries, and add a test for this.
This commit is contained in:
Родитель
9bcb3a5b81
Коммит
7a18290e77
|
@ -0,0 +1,7 @@
|
|||
// RUN: %dxc -E main -T ps_6_0 %s
|
||||
|
||||
float3 main() : SV_Target
|
||||
{
|
||||
// Some calls known to cause floating point exceptions when evaluated
|
||||
return float3(pow(0.0f, 0.0f), pow(-1.0f, 0.5f), pow(0.0f, -1.0f));
|
||||
}
|
|
@ -46,6 +46,7 @@
|
|||
#endif
|
||||
#include "dxillib.h"
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
|
||||
// SPIRV change starts
|
||||
#ifdef ENABLE_SPIRV_CODEGEN
|
||||
|
@ -100,6 +101,28 @@ static void CreateOperationResultFromOutputs(
|
|||
ppResult);
|
||||
}
|
||||
|
||||
struct DefaultFPEnvScope
|
||||
{
|
||||
// _controlfp_s is non-standard and <cfenv>.feholdexceptions doesn't work on windows...?
|
||||
#ifdef _WIN32
|
||||
unsigned int previousValue;
|
||||
DefaultFPEnvScope() {
|
||||
// No exceptions, preserve denormals & round to nearest.
|
||||
errno_t error = _controlfp_s(&previousValue, _MCW_EM | _DN_SAVE | _RC_NEAR, _MCW_EM | _MCW_DN | _MCW_RC);
|
||||
IFT(error == 0 ? S_OK : E_FAIL);
|
||||
}
|
||||
~DefaultFPEnvScope() {
|
||||
unsigned int newValue;
|
||||
errno_t error = _controlfp_s(&newValue, previousValue, _MCW_EM | _MCW_DN | _MCW_RC);
|
||||
// During cleanup we can't throw as we might already be handling another one.
|
||||
DXASSERT(error == 0, "Failed to restore floating-point environment.");
|
||||
(void)error;
|
||||
}
|
||||
#else
|
||||
DefaultFPEnvScope() {} // Dummy ctor to avoid unused local warning
|
||||
#endif
|
||||
};
|
||||
|
||||
class HLSLExtensionsCodegenHelperImpl : public HLSLExtensionsCodegenHelper {
|
||||
private:
|
||||
CompilerInstance &m_CI;
|
||||
|
@ -311,6 +334,8 @@ public:
|
|||
DxcThreadMalloc TM(m_pMalloc);
|
||||
|
||||
try {
|
||||
DefaultFPEnvScope fpEnvScope;
|
||||
|
||||
IFT(CreateMemoryStream(m_pMalloc, &pOutputStream));
|
||||
|
||||
// Parse command-line options into DxcOpts
|
||||
|
@ -649,6 +674,8 @@ public:
|
|||
IFC(hlsl::DxcGetBlobAsUtf8(pSource, &utf8Source));
|
||||
|
||||
try {
|
||||
DefaultFPEnvScope fpEnvScope;
|
||||
|
||||
CComPtr<AbstractMemoryStream> pOutputStream;
|
||||
dxcutil::DxcArgsFileSystem *msfPtr = dxcutil::CreateDxcArgsFileSystem(utf8Source, pSourceName, pIncludeHandler);
|
||||
std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
|
||||
|
@ -756,6 +783,8 @@ public:
|
|||
DxcEtw_DXCompilerDisassemble_Start();
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
try {
|
||||
DefaultFPEnvScope fpEnvScope;
|
||||
|
||||
::llvm::sys::fs::MSFileSystem *msfPtr;
|
||||
IFT(CreateMSFileSystemForDisk(&msfPtr));
|
||||
std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include "dxc/DxilContainer/DxilContainer.h"
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
#include "dxc/dxcapi.h"
|
||||
|
@ -374,6 +375,7 @@ public:
|
|||
TEST_METHOD(CodeGenExternRes)
|
||||
TEST_METHOD(CodeGenExpandTrig)
|
||||
TEST_METHOD(CodeGenFloatCast)
|
||||
TEST_METHOD(CodeGenFloatingPointEnvironment)
|
||||
TEST_METHOD(CodeGenFloatToBool)
|
||||
TEST_METHOD(CodeGenFirstbitHi)
|
||||
TEST_METHOD(CodeGenFirstbitLo)
|
||||
|
@ -3452,6 +3454,28 @@ TEST_F(CompilerTest, CodeGenFloatCast) {
|
|||
CodeGenTestCheck(L"..\\CodeGenHLSL\\float_cast.hlsl");
|
||||
}
|
||||
|
||||
struct FPEnableExceptionsScope
|
||||
{
|
||||
// _controlfp_s is non-standard and <cfenv> doesn't have a function to enable exceptions
|
||||
#ifdef _WIN32
|
||||
unsigned int previousValue;
|
||||
FPEnableExceptionsScope() {
|
||||
VERIFY_IS_TRUE(_controlfp_s(&previousValue, 0, _MCW_EM) == 0); // _MCW_EM == 0 means enable all exceptions
|
||||
}
|
||||
~FPEnableExceptionsScope() {
|
||||
unsigned int newValue;
|
||||
errno_t error = _controlfp_s(&newValue, previousValue, _MCW_EM);
|
||||
DXASSERT(error == 0, "Failed to restore floating-point environment.");
|
||||
(void)error;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
TEST_F(CompilerTest, CodeGenFloatingPointEnvironment) {
|
||||
FPEnableExceptionsScope fpEnableExceptions;
|
||||
CodeGenTestCheck(L"..\\CodeGenHLSL\\fpexcept.hlsl");
|
||||
}
|
||||
|
||||
TEST_F(CompilerTest, CodeGenFloatToBool) {
|
||||
CodeGenTestCheck(L"..\\CodeGenHLSL\\float_to_bool.hlsl");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче