From 2de2b094ecb9e7764fd78233d126819cdb66e7d6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 4 Jul 2010 21:11:25 +0000 Subject: [PATCH] ZDBSP: - Add headers to generated CMake projects. - Made SSELevel global so that ClassifyLineBackpatch can see it without being part of FNodeBuilder. With backpatching enabled, it's rather pointless to have a different one per nodebuilder instance, anyway. - Change ClassifyLineBackpatch so it doesn't need any inline assembly to do its magic. - Change the ClassifyLine functions to be extern "C" linkage. SVN r2410 (trunk) --- CMakeLists.txt | 392 ++++++++++++++++--------------- main.cpp | 1 + nodebuild.cpp | 53 ++--- nodebuild.h | 51 ++-- nodebuild_classify_nosse2.cpp | 39 ++- nodebuild_classify_sse1.cpp | 39 ++- nodebuild_classify_sse2.cpp | 39 ++- nodebuild_classify_sse2_vect.cpp | 100 +++----- processor.cpp | 12 +- zdbsp.h | 1 + zlib/CMakeLists.txt | 8 +- 11 files changed, 358 insertions(+), 377 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae469e1..2b8d563 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,189 +1,203 @@ -cmake_minimum_required( VERSION 2.4 ) -if( COMMAND cmake_policy ) - cmake_policy( SET CMP0003 NEW ) -endif( COMMAND cmake_policy ) - - -include( CheckFunctionExists ) -include( CheckCXXCompilerFlag ) - -IF( NOT CMAKE_BUILD_TYPE ) - SET( CMAKE_BUILD_TYPE Debug CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE ) -ENDIF( NOT CMAKE_BUILD_TYPE ) - -set( SSE_MATTERS NO ) - -# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. -if( CMAKE_SIZEOF_VOID_P MATCHES "4" ) - CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) - CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) - if( CAN_DO_MFPMATH ) - set( SSE1_ENABLE "-msse -mfpmath=sse" ) - set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) - set( SSE_MATTERS YES ) - elseif( CAN_DO_ARCHSSE2 ) - set( SSE1_ENABLE -arch:SSE ) - set( SSE2_ENABLE -arch:SSE2 ) - set( SSE_MATTERS YES ) - endif( CAN_DO_MFPMATH ) -endif( CMAKE_SIZEOF_VOID_P MATCHES "4" ) - -if( SSE_MATTERS ) - if( CMAKE_COMPILER_IS_GNUCXX AND WIN32 ) - set( BACKPATCH 1 CACHE BOOL "Enable backpatching." ) - endif( CMAKE_COMPILER_IS_GNUCXX AND WIN32 ) - set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." ) - set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." ) -endif( SSE_MATTERS ) - -if( CMAKE_COMPILER_IS_GNUCXX ) - set( GPROF 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." ) -endif( CMAKE_COMPILER_IS_GNUCXX ) - -find_package( ZLIB ) - -if( MSVC ) - # Eliminate unreferenced functions and data - # Perform identical COMDAT folding - set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt" ) - - # String pooling - # Function-level linking - # Disable run-time type information - set( ALL_C_FLAGS "/GF /Gy /GR-" ) - - # Avoid CRT DLL dependancies in release builds - set( REL_C_FLAGS "/MT" ) - - # Disable warnings for unsecure CRT functions from VC8+ - if( MSVC_VERSION GREATER 1399 ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} /wd4996" ) - endif( MSVC_VERSION GREATER 1399 ) - - # The CMake configurations set /GR and /MD by default, which conflict with our settings. - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} ) - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} ) - string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} ) - string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) - string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) -endif( MSVC ) - -if( CMAKE_COMPILER_IS_GNUCXX ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -ffast-math -pipe" ) - if( GPROF ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -pg -g" ) - else( GPROF ) - set( REL_C_FLAGS "${REL_C_FLAGS} -fomit-frame-pointer" ) - endif( GPROF ) - if( PROFILE EQUAL 1 ) - message( STATUS "Generating profile coverage information" ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-generate" ) - set( PROF_LIB "gcov" ) - elseif( PROFILE EQUAL 2 ) - message( STATUS "Using profile coverage information" ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-use" ) - endif( PROFILE EQUAL 1 ) -endif( CMAKE_COMPILER_IS_GNUCXX ) - -if( ZLIB_FOUND ) - message( STATUS "Using system zlib" ) -else( ZLIB_FOUND ) - message( STATUS "Using internal zlib" ) - add_subdirectory( zlib ) - set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib ) - set( ZLIB_LIBRARIES z ) - set( ZLIB_LIBRARY z ) -endif( ZLIB_FOUND ) - -CHECK_FUNCTION_EXISTS( stricmp STRICMP_EXISTS ) -if( NOT STRICMP_EXISTS ) - add_definitions( -Dstricmp=strcasecmp ) -endif( NOT STRICMP_EXISTS ) - -CHECK_FUNCTION_EXISTS( strnicmp STRNICMP_EXISTS ) -if( NOT STRNICMP_EXISTS ) - add_definitions( -Dstrnicmp=strncasecmp ) -endif( NOT STRNICMP_EXISTS ) - -set( ZDBSP_LIBS "${ZLIB_LIBRARIES}" ) -set( SOURCES - main.cpp - getopt.c - getopt1.c - blockmapbuilder.cpp - processor.cpp - processor_udmf.cpp - sc_man.cpp - wad.cpp - nodebuild.cpp - nodebuild_events.cpp - nodebuild_extract.cpp - nodebuild_gl.cpp - nodebuild_utility.cpp - nodebuild_classify_nosse2.cpp -) -if( WIN32 ) - set( SOURCES "${SOURCES} view.cpp" ) -else( WIN32 ) - add_definitions( -DNO_MAP_VIEWER ) -endif( WIN32 ) - -if( SSE_MATTERS ) - if( FULL_SSE2 ) - message( STATUS "Using SSE2 math everywhere." ) - # Building everything with SSE2 is much like disabling it, in that we - # need not check for its existance while running. - set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE ${SSE2_ENABLE}" ) - else( FULL_SSE2 ) - if( SSE ) - message( STATUS "Using SSE math for ClassifyLine only." ) - set( SOURCES ${SOURCES} nodebuild_classify_sse1.cpp nodebuild_classify_sse2.cpp ) - set_source_files_properties( nodebuild_classify_sse1.cpp PROPERTIES COMPILE_FLAGS "${SSE1_ENABLE}" ) - set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "${SSE2_ENABLE}" ) - else( SSE ) - message( STATUS "SSE math is completely disabled." ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" ) - endif( SSE ) - endif( FULL_SSE2 ) -else( SSE_MATTERS ) - set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" ) -endif( SSE_MATTERS ) - -if( WIN32 ) - set( ZDBSP_LIBS ${ZDBSP_LIBS} user32 gdi32 ) - - if( CMAKE_COMPILER_IS_GNUCXX ) - # CMake is not set up to compile and link rc files with GCC. :( - add_custom_command( OUTPUT zdbsp-rc.o - COMMAND windres -o zdbsp-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc - DEPENDS resource.rc ) - set( SOURCES ${SOURCES} zdbsp-rc.o ) - else( CMAKE_COMPILER_IS_GNUCXX ) - set( SOURCES ${SOURCES} resource.rc ) - endif( CMAKE_COMPILER_IS_GNUCXX ) -endif( WIN32 ) - - -set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" ) -set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} ${REL_LINKER_FLAGS}" ) -set( CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${REL_LINKER_FLAGS}" ) - -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ALL_C_FLAGS}" ) -set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${REL_C_FLAGS}" ) -set( CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" ) -set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) -set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) - -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALL_C_FLAGS}" ) -set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${REL_C_FLAGS}" ) -set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" ) -set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) -set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) - -add_executable( zdbsp ${SOURCES} ) -target_link_libraries( zdbsp ${ZDBSP_LIBS} ${PROF_LIB} ) -include_directories( "${ZLIB_INCLUDE_DIR}" ) +cmake_minimum_required( VERSION 2.4 ) +if( COMMAND cmake_policy ) + cmake_policy( SET CMP0003 NEW ) +endif( COMMAND cmake_policy ) + + +include( CheckFunctionExists ) +include( CheckCXXCompilerFlag ) + +IF( NOT CMAKE_BUILD_TYPE ) + SET( CMAKE_BUILD_TYPE Debug CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE ) +ENDIF( NOT CMAKE_BUILD_TYPE ) + +set( SSE_MATTERS NO ) + +# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it. +if( CMAKE_SIZEOF_VOID_P MATCHES "4" ) + CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH ) + CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 ) + if( CAN_DO_MFPMATH ) + set( SSE1_ENABLE "-msse -mfpmath=sse" ) + set( SSE2_ENABLE "-msse2 -mfpmath=sse" ) + set( SSE_MATTERS YES ) + elseif( CAN_DO_ARCHSSE2 ) + set( SSE1_ENABLE -arch:SSE ) + set( SSE2_ENABLE -arch:SSE2 ) + set( SSE_MATTERS YES ) + endif( CAN_DO_MFPMATH ) +endif( CMAKE_SIZEOF_VOID_P MATCHES "4" ) + +if( SSE_MATTERS ) + if( CMAKE_COMPILER_IS_GNUCXX AND WIN32 ) + set( BACKPATCH 1 CACHE BOOL "Enable backpatching." ) + endif( CMAKE_COMPILER_IS_GNUCXX AND WIN32 ) + set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." ) + set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." ) +endif( SSE_MATTERS ) + +if( CMAKE_COMPILER_IS_GNUCXX ) + set( GPROF 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." ) +endif( CMAKE_COMPILER_IS_GNUCXX ) + +find_package( ZLIB ) + +if( MSVC ) + # Eliminate unreferenced functions and data + # Perform identical COMDAT folding + set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt" ) + + # String pooling + # Function-level linking + # Disable run-time type information + set( ALL_C_FLAGS "/GF /Gy /GR-" ) + + # Avoid CRT DLL dependancies in release builds + set( REL_C_FLAGS "/MT" ) + + # Disable warnings for unsecure CRT functions from VC8+ + if( MSVC_VERSION GREATER 1399 ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} /wd4996" ) + endif( MSVC_VERSION GREATER 1399 ) + + # The CMake configurations set /GR and /MD by default, which conflict with our settings. + string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} ) + string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} ) + string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ) + string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) + string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} ) + string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) + string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ) +endif( MSVC ) + +if( CMAKE_COMPILER_IS_GNUCXX ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -ffast-math -pipe" ) + if( GPROF ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -pg -g" ) + else( GPROF ) + set( REL_C_FLAGS "${REL_C_FLAGS} -fomit-frame-pointer" ) + endif( GPROF ) + if( PROFILE EQUAL 1 ) + message( STATUS "Generating profile coverage information" ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-generate" ) + set( PROF_LIB "gcov" ) + elseif( PROFILE EQUAL 2 ) + message( STATUS "Using profile coverage information" ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-use" ) + endif( PROFILE EQUAL 1 ) +endif( CMAKE_COMPILER_IS_GNUCXX ) + +if( ZLIB_FOUND ) + message( STATUS "Using system zlib" ) +else( ZLIB_FOUND ) + message( STATUS "Using internal zlib" ) + add_subdirectory( zlib ) + set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib ) + set( ZLIB_LIBRARIES z ) + set( ZLIB_LIBRARY z ) +endif( ZLIB_FOUND ) + +CHECK_FUNCTION_EXISTS( stricmp STRICMP_EXISTS ) +if( NOT STRICMP_EXISTS ) + add_definitions( -Dstricmp=strcasecmp ) +endif( NOT STRICMP_EXISTS ) + +CHECK_FUNCTION_EXISTS( strnicmp STRNICMP_EXISTS ) +if( NOT STRNICMP_EXISTS ) + add_definitions( -Dstrnicmp=strncasecmp ) +endif( NOT STRNICMP_EXISTS ) + +set( ZDBSP_LIBS "${ZLIB_LIBRARIES}" ) +set( SOURCES + main.cpp + getopt.c + getopt1.c + blockmapbuilder.cpp + processor.cpp + processor_udmf.cpp + sc_man.cpp + wad.cpp + nodebuild.cpp + nodebuild_events.cpp + nodebuild_extract.cpp + nodebuild_gl.cpp + nodebuild_utility.cpp + nodebuild_classify_nosse2.cpp +) +if( WIN32 ) + set( SOURCES "${SOURCES}" view.cpp ) +else( WIN32 ) + add_definitions( -DNO_MAP_VIEWER ) +endif( WIN32 ) + +set( HEADERS + blockmapbuilder.h + doomdata.h + getopt.h + nodebuild.h + processor.h + resource.h + sc_man.h + tarray.h + templates.h + wad.h + workdata.h + zdbsp.h ) + +if( SSE_MATTERS ) + if( FULL_SSE2 ) + message( STATUS "Using SSE2 math everywhere." ) + # Building everything with SSE2 is much like disabling it, in that we + # need not check for its existance while running. + set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE ${SSE2_ENABLE}" ) + else( FULL_SSE2 ) + if( SSE ) + message( STATUS "Using SSE math for ClassifyLine only." ) + set( SOURCES ${SOURCES} nodebuild_classify_sse1.cpp nodebuild_classify_sse2.cpp ) + set_source_files_properties( nodebuild_classify_sse1.cpp PROPERTIES COMPILE_FLAGS "${SSE1_ENABLE}" ) + set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "${SSE2_ENABLE}" ) + else( SSE ) + message( STATUS "SSE math is completely disabled." ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" ) + endif( SSE ) + endif( FULL_SSE2 ) +else( SSE_MATTERS ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" ) +endif( SSE_MATTERS ) + +if( WIN32 ) + set( ZDBSP_LIBS ${ZDBSP_LIBS} user32 gdi32 ) + + if( CMAKE_COMPILER_IS_GNUCXX ) + # CMake is not set up to compile and link rc files with GCC. :( + add_custom_command( OUTPUT zdbsp-rc.o + COMMAND windres -o zdbsp-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/resource.rc + DEPENDS resource.rc ) + set( SOURCES ${SOURCES} zdbsp-rc.o ) + else( CMAKE_COMPILER_IS_GNUCXX ) + set( SOURCES ${SOURCES} resource.rc ) + endif( CMAKE_COMPILER_IS_GNUCXX ) +endif( WIN32 ) + + +set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} ${REL_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${REL_LINKER_FLAGS}" ) + +set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ALL_C_FLAGS}" ) +set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${REL_C_FLAGS}" ) +set( CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" ) +set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) +set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) + +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALL_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${REL_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" ) + +add_executable( zdbsp ${SOURCES} ${HEADERS} ) +target_link_libraries( zdbsp ${ZDBSP_LIBS} ${PROF_LIB} ) +include_directories( "${ZLIB_INCLUDE_DIR}" ) diff --git a/main.cpp b/main.cpp index 1b319db..191abd0 100644 --- a/main.cpp +++ b/main.cpp @@ -113,6 +113,7 @@ bool ForceCompression = false; bool GLOnly = false; bool V5GLNodes = false; bool HaveSSE1, HaveSSE2; +int SSELevel; // PRIVATE DATA DEFINITIONS ------------------------------------------------ diff --git a/nodebuild.cpp b/nodebuild.cpp index d7cfdfa..9f34290 100644 --- a/nodebuild.cpp +++ b/nodebuild.cpp @@ -40,12 +40,11 @@ FNodeBuilder::FNodeBuilder (FLevel &level, TArray &polyspots, TArray &anchors, - const char *name, bool makeGLnodes, BYTE sselevel) + const char *name, bool makeGLnodes) : Level(level), SegsStuffed(0), MapName(name) { VertexMap = new FVertexMap (*this, Level.MinX, Level.MinY, Level.MaxX, Level.MaxY); GLNodes = makeGLnodes; - SSELevel = sselevel; FindUsedVertices (Level.Vertices, Level.NumVertices); MakeSegsFromSides (); FindPolyContainers (polyspots, anchors); @@ -508,7 +507,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) int realSegs[2] = { 0, 0 }; int specialSegs[2] = { 0, 0 }; DWORD i = set; - int sidev1, sidev2; + int sidev[2]; int side; bool splitter = false; unsigned int max, m2, p, q; @@ -527,7 +526,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) } else { - side = ClassifyLine (node, test, sidev1, sidev2); + side = ClassifyLine (node, &Vertices[test->v1], &Vertices[test->v2], sidev); } switch (side) @@ -538,9 +537,9 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) // The "right" thing to do in this case is to only reject it if there is // another nosplit seg from the same sector at this vertex. Note that a line // that lies exactly on top of the splitter is okay. - if (test->loopnum && honorNoSplit && (sidev1 == 0 || sidev2 == 0)) + if (test->loopnum && honorNoSplit && (sidev[0] == 0 || sidev[1] == 0)) { - if ((sidev1 | sidev2) != 0) + if ((sidev[0] | sidev[1]) != 0) { max = Touched.Size(); for (p = 0; p < max; ++p) @@ -752,18 +751,18 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou FPrivSeg *seg = &Segs[set]; int next = seg->next; - int sidev1, sidev2, side; + int sidev[2], side; if (HackSeg == set) { HackSeg = DWORD_MAX; side = 1; - sidev1 = sidev2 = 0; + sidev[0] = sidev[1] = 0; hack = true; } else { - side = ClassifyLine (node, seg, sidev1, sidev2); + side = ClassifyLine (node, &Vertices[seg->v1], &Vertices[seg->v2], sidev); hack = false; } @@ -810,7 +809,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou Printf("SelectVertexClose selected endpoint of seg %u\n", (unsigned int)set); } - seg2 = SplitSeg (set, vertnum, sidev1); + seg2 = SplitSeg (set, vertnum, sidev[0]); Segs[seg2].next = outset0; outset0 = seg2; @@ -821,7 +820,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou if (Segs[set].partner != DWORD_MAX) { int partner1 = Segs[set].partner; - int partner2 = SplitSeg (partner1, vertnum, sidev2); + int partner2 = SplitSeg (partner1, vertnum, sidev[1]); // The newly created seg stays in the same set as the // back seg because it has not been considered for splitting // yet. If it had been, then the front seg would have already @@ -847,17 +846,17 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou } if (side >= 0 && GLNodes) { - if (sidev1 == 0) + if (sidev[0] == 0) { double dist1 = AddIntersection (node, seg->v1); - if (sidev2 == 0) + if (sidev[1] == 0) { double dist2 = AddIntersection (node, seg->v2); FSplitSharer share = { dist1, set, dist2 > dist1 }; SplitSharers.Push (share); } } - else if (sidev2 == 0) + else if (sidev[1] == 0) { AddIntersection (node, seg->v2); } @@ -1058,39 +1057,31 @@ void FNodeBuilder::PrintSet (int l, DWORD set) #define WIN32_LEAN_AND_MEAN #include -int FNodeBuilder::ClassifyLineBackpatch (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +extern "C" int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) { // Select the routine based on SSELevel and patch the caller so that // they call that routine directly next time instead of going through here. int *calleroffset = (int *)__builtin_return_address(0) - 1; int diff; - int (*func)(FNodeBuilder *, node_t &, const FNodeBuilder::FPrivSeg *, int &, int &); + int (*func)(node_t &, const FSimpleVert *, const FSimpleVert *, int[2]); DWORD oldprotect; // printf ("Patching for SSE %d\n", SSELevel); - // I wasn't sure how to calculate the difference between the function addresses with C++ - // (or if it's even possible), so here's some asm to do it instead: if (SSELevel == 2) { - __asm ( - "movl $__ZN12FNodeBuilder16ClassifyLineSSE2ER6node_tPKNS_8FPrivSegERiS5_,%1\n\t" - "movl $__ZN12FNodeBuilder16ClassifyLineSSE2ER6node_tPKNS_8FPrivSegERiS5_-__ZN12FNodeBuilder21ClassifyLineBackpatchER6node_tPKNS_8FPrivSegERiS5_,%0\n\t" - : "=r" (diff), "=r" (func)); + func = ClassifyLineSSE2; + diff = (char *)ClassifyLineSSE2 - (char *)ClassifyLineBackpatch; } else if (SSELevel == 1) { - __asm ( - "movl $__ZN12FNodeBuilder16ClassifyLineSSE1ER6node_tPKNS_8FPrivSegERiS5_,%1\n\t" - "movl $__ZN12FNodeBuilder16ClassifyLineSSE1ER6node_tPKNS_8FPrivSegERiS5_-__ZN12FNodeBuilder21ClassifyLineBackpatchER6node_tPKNS_8FPrivSegERiS5_,%0\n\t" - : "=r" (diff), "=r" (func)); + func = ClassifyLineSSE1; + diff = (char *)ClassifyLineSSE1 - (char *)ClassifyLineBackpatch; } else { - __asm ( - "movl $__ZN12FNodeBuilder13ClassifyLine2ER6node_tPKNS_8FPrivSegERiS5_,%1\n\t" - "movl $__ZN12FNodeBuilder13ClassifyLine2ER6node_tPKNS_8FPrivSegERiS5_-__ZN12FNodeBuilder21ClassifyLineBackpatchER6node_tPKNS_8FPrivSegERiS5_,%0\n\t" - : "=r" (diff), "=r" (func)); + func = ClassifyLine2; + diff = (char *)ClassifyLine2 - (char *)ClassifyLineBackpatch; } // Patch the caller. @@ -1101,6 +1092,6 @@ int FNodeBuilder::ClassifyLineBackpatch (node_t &node, const FPrivSeg *seg, int } // And return by calling the real function. - return func (this, node, seg, sidev1, sidev2); + return func (node, v1, v2, sidev); } #endif diff --git a/nodebuild.h b/nodebuild.h index 73a59ec..66d3b1d 100644 --- a/nodebuild.h +++ b/nodebuild.h @@ -45,6 +45,23 @@ private: void PrintTree (const FEvent *event) const; }; +struct FSimpleVert +{ + fixed_t x, y; +}; + +extern "C" +{ + int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); +#ifndef DISABLE_SSE + int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); + int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); +#if defined(_WIN32) && defined(__GNUC__) && !defined(DISABLE_BACKPATCH) + int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) __attribute__((noinline)); +#endif +#endif +} + class FNodeBuilder { struct FPrivSeg @@ -67,9 +84,8 @@ class FNodeBuilder bool planefront; FPrivSeg *hashnext; }; - struct FPrivVert + struct FPrivVert : FSimpleVert { - fixed_t x, y; DWORD segs; // segs that use this vertex as v1 DWORD segs2; // segs that use this vertex as v2 int index; @@ -139,7 +155,7 @@ public: FNodeBuilder (FLevel &level, TArray &polyspots, TArray &anchors, - const char *name, bool makeGLnodes, BYTE sselevel); + const char *name, bool makeGLnodes); ~FNodeBuilder (); void GetVertices (WideVertex *&verts, int &count); @@ -179,7 +195,6 @@ private: DWORD HackMate; // Seg to use in front of hack seg FLevel &Level; bool GLNodes; - int SSELevel; // Progress meter stuff int SegsStuffed; @@ -211,16 +226,7 @@ private: // 1 = seg is in back // -1 = seg cuts the node - inline int ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2); - int ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2); -#ifndef DISABLE_SSE - int ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2); - int ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2); - -#if defined(_WIN32) && defined(__GNUC__) && !defined(DISABLE_BACKPATCH) - int ClassifyLineBackpatch (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) __attribute__((noinline)); -#endif -#endif + inline int ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]); void FixSplitSharers (); double AddIntersection (const node_t &node, int vertex); @@ -281,29 +287,28 @@ inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int return s_num > 0.0 ? -1 : 1; } -inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]) { #ifdef DISABLE_SSE - return ClassifyLine2 (node, seg, sidev1, sidev2); + return ClassifyLine2 (node, v1, v2, sidev); #else #if defined(__SSE2__) || defined(_M_IX64) // If compiling with SSE2 support everywhere, just use the SSE2 version. - return ClassifyLineSSE2 (node, seg, sidev1, sidev2); + return ClassifyLineSSE2 (node, v1, v2, sidev); #elif defined(_MSC_VER) && _MSC_VER < 1300 // VC 6 does not support SSE optimizations. - return ClassifyLine2 (node, seg, sidev1, sidev2); + return ClassifyLine2 (node, v1, v2, sidev); #else // Select the routine based on our flag. #if defined(_WIN32) && defined(__GNUC__) && !defined(DISABLE_BACKPATCH) - return ClassifyLineBackpatch (node, seg, sidev1, sidev2); + return ClassifyLineBackpatch (node, v1, v2, sidev); #else if (SSELevel == 2) - { int foo = ClassifyLineSSE2 (node, seg, sidev1, sidev2); assert(foo == ClassifyLine2(node,seg,sidev1,sidev2)); - return foo; } + return ClassifyLineSSE2 (node, v1, v2, sidev); else if (SSELevel == 1) - return ClassifyLineSSE1 (node, seg, sidev1, sidev2); + return ClassifyLineSSE1 (node, v1, v2, sidev); else - return ClassifyLine2 (node, seg, sidev1, sidev2); + return ClassifyLine2 (node, v1, v2, sidev); #endif #endif #endif diff --git a/nodebuild_classify_nosse2.cpp b/nodebuild_classify_nosse2.cpp index 6288570..0fc733e 100644 --- a/nodebuild_classify_nosse2.cpp +++ b/nodebuild_classify_nosse2.cpp @@ -23,11 +23,8 @@ #define FAR_ENOUGH 17179869184.f // 4<<32 -int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +extern "C" int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) { - const FPrivVert *v1 = &Vertices[seg->v1]; - const FPrivVert *v2 = &Vertices[seg->v2]; - double d_x1 = double(node.x); double d_y1 = double(node.y); double d_dx = double(node.dx); @@ -46,13 +43,13 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, { if (s_num2 <= -FAR_ENOUGH) { - sidev1 = sidev2 = 1; + sidev[0] = sidev[1] = 1; return 1; } if (s_num2 >= FAR_ENOUGH) { - sidev1 = 1; - sidev2 = -1; + sidev[0] = 1; + sidev[1] = -1; return -1; } nears = 1; @@ -61,13 +58,13 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, { if (s_num2 >= FAR_ENOUGH) { - sidev1 = sidev2 = -1; + sidev[0] = sidev[1] = -1; return 0; } if (s_num2 <= -FAR_ENOUGH) { - sidev1 = -1; - sidev2 = 1; + sidev[0] = -1; + sidev[1] = 1; return -1; } nears = 1; @@ -85,41 +82,41 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, double dist = s_num1 * s_num1 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev1 = 0; + sidev[0] = 0; } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } if (nears & 1) { double dist = s_num2 * s_num2 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev2 = 0; + sidev[1] = 0; } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } - if ((sidev1 | sidev2) == 0) + if ((sidev[0] | sidev[1]) == 0) { // seg is coplanar with the splitter, so use its orientation to determine // which child it ends up in. If it faces the same direction as the splitter, // it goes in front. Otherwise, it goes in back. @@ -147,11 +144,11 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, } } } - else if (sidev1 <= 0 && sidev2 <= 0) + else if (sidev[0] <= 0 && sidev[1] <= 0) { return 0; } - else if (sidev1 >= 0 && sidev2 >= 0) + else if (sidev[0] >= 0 && sidev[1] >= 0) { return 1; } diff --git a/nodebuild_classify_sse1.cpp b/nodebuild_classify_sse1.cpp index d9c3003..4104b1d 100644 --- a/nodebuild_classify_sse1.cpp +++ b/nodebuild_classify_sse1.cpp @@ -29,11 +29,8 @@ // The reason it is SSE is because this file is explicitly compiled // with SSE math enabled, but the other files are not. -int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +extern "C" int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) { - const FPrivVert *v1 = &Vertices[seg->v1]; - const FPrivVert *v2 = &Vertices[seg->v2]; - double d_x1 = double(node.x); double d_y1 = double(node.y); double d_dx = double(node.dx); @@ -52,13 +49,13 @@ int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &side { if (s_num2 <= -FAR_ENOUGH) { - sidev1 = sidev2 = 1; + sidev[0] = sidev[1] = 1; return 1; } if (s_num2 >= FAR_ENOUGH) { - sidev1 = 1; - sidev2 = -1; + sidev[0] = 1; + sidev[1] = -1; return -1; } nears = 1; @@ -67,13 +64,13 @@ int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &side { if (s_num2 >= FAR_ENOUGH) { - sidev1 = sidev2 = -1; + sidev[0] = sidev[1] = -1; return 0; } if (s_num2 <= -FAR_ENOUGH) { - sidev1 = -1; - sidev2 = 1; + sidev[0] = -1; + sidev[1] = 1; return -1; } nears = 1; @@ -91,41 +88,41 @@ int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &side double dist = s_num1 * s_num1 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev1 = 0; + sidev[0] = 0; } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } if (nears & 1) { double dist = s_num2 * s_num2 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev2 = 0; + sidev[1] = 0; } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } - if ((sidev1 | sidev2) == 0) + if ((sidev[0] | sidev[1]) == 0) { // seg is coplanar with the splitter, so use its orientation to determine // which child it ends up in. If it faces the same direction as the splitter, // it goes in front. Otherwise, it goes in back. @@ -153,11 +150,11 @@ int FNodeBuilder::ClassifyLineSSE1 (node_t &node, const FPrivSeg *seg, int &side } } } - else if (sidev1 <= 0 && sidev2 <= 0) + else if (sidev[0] <= 0 && sidev[1] <= 0) { return 0; } - else if (sidev1 >= 0 && sidev2 >= 0) + else if (sidev[0] >= 0 && sidev[1] >= 0) { return 1; } diff --git a/nodebuild_classify_sse2.cpp b/nodebuild_classify_sse2.cpp index 9f7f343..f9ade1d 100644 --- a/nodebuild_classify_sse2.cpp +++ b/nodebuild_classify_sse2.cpp @@ -29,11 +29,8 @@ // The reason it is SSE2 is because this file is explicitly compiled // with SSE2 math enabled, but the other files are not. -int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) { - const FPrivVert *v1 = &Vertices[seg->v1]; - const FPrivVert *v2 = &Vertices[seg->v2]; - double d_x1 = double(node.x); double d_y1 = double(node.y); double d_dx = double(node.dx); @@ -52,13 +49,13 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side { if (s_num2 <= -FAR_ENOUGH) { - sidev1 = sidev2 = 1; + sidev[0] = sidev[1] = 1; return 1; } if (s_num2 >= FAR_ENOUGH) { - sidev1 = 1; - sidev2 = -1; + sidev[0] = 1; + sidev[1] = -1; return -1; } nears = 1; @@ -67,13 +64,13 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side { if (s_num2 >= FAR_ENOUGH) { - sidev1 = sidev2 = -1; + sidev[0] = sidev[1] = -1; return 0; } if (s_num2 <= -FAR_ENOUGH) { - sidev1 = -1; - sidev2 = 1; + sidev[0] = -1; + sidev[1] = 1; return -1; } nears = 1; @@ -91,41 +88,41 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side double dist = s_num1 * s_num1 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev1 = 0; + sidev[0] = 0; } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; } if (nears & 1) { double dist = s_num2 * s_num2 * l; if (dist < SIDE_EPSILON*SIDE_EPSILON) { - sidev2 = 0; + sidev[1] = 0; } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } } else { - sidev1 = s_num1 > 0.0 ? -1 : 1; - sidev2 = s_num2 > 0.0 ? -1 : 1; + sidev[0] = s_num1 > 0.0 ? -1 : 1; + sidev[1] = s_num2 > 0.0 ? -1 : 1; } - if ((sidev1 | sidev2) == 0) + if ((sidev[0] | sidev[1]) == 0) { // seg is coplanar with the splitter, so use its orientation to determine // which child it ends up in. If it faces the same direction as the splitter, // it goes in front. Otherwise, it goes in back. @@ -153,11 +150,11 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side } } } - else if (sidev1 <= 0 && sidev2 <= 0) + else if (sidev[0] <= 0 && sidev[1] <= 0) { return 0; } - else if (sidev1 >= 0 && sidev2 >= 0) + else if (sidev[0] >= 0 && sidev[1] >= 0) { return 1; } diff --git a/nodebuild_classify_sse2_vect.cpp b/nodebuild_classify_sse2_vect.cpp index ef3475c..c231d9c 100644 --- a/nodebuild_classify_sse2_vect.cpp +++ b/nodebuild_classify_sse2_vect.cpp @@ -30,20 +30,17 @@ // The reason it is SSE2 is because this file is explicitly compiled // with SSE2 math enabled, but the other files are not. -int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2) +extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) { - const FPrivVert *v1 = &Vertices[seg->v1]; - const FPrivVert *v2 = &Vertices[seg->v2]; - __m128d xy, dxy, xyv1, xyv2; // Why does this intrinsic go through an MMX register, when it can just go through memory? - // That would let it work with x64, too. - xy = _mm_cvtpi32_pd(node.p64); // d_y1 d_x1 - dxy = _mm_cvtpi32_pd(node.d64); // d_dy d_dx - xyv1 = _mm_cvtpi32_pd(v1->p64); // d_yv1 d_xv1 - xyv2 = _mm_cvtpi32_pd(v2->p64); // d_yv2 d_xv2 - _mm_empty(); + // That would let it work with x64, too. (This only applies to VC++. GCC + // is smarter and can load directly from memory without touching the MMX registers.) + xy = _mm_cvtpi32_pd(*(__m64*)&node.x); // d_y1 d_x1 + dxy = _mm_cvtpi32_pd(*(__m64*)&node.dx); // d_dy d_dx + xyv1 = _mm_cvtpi32_pd(*(__m64*)&v1->x); // d_yv1 d_xv1 + xyv2 = _mm_cvtpi32_pd(*(__m64*)&v2->x); // d_yv2 d_xv2 __m128d num1, num2, dyx; @@ -76,54 +73,56 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side }; struct { - __int64 ni[2], pi[2]; + int ni[4], pi[4]; }; - }; + } _; - _mm_storeu_pd(n, neg_check); - _mm_storeu_pd(p, pos_check); + _mm_storeu_pd(_.n, neg_check); + _mm_storeu_pd(_.p, pos_check); int nears = 0; - if (ni[0]) + if (_.ni[0]) { - if (ni[1]) + if (_.ni[2]) { - sidev1 = sidev2 = 1; + sidev[0] = sidev[1] = 1; return 1; } - if (pi[1]) + if (_.pi[2]) { - sidev1 = 1; - sidev2 = -1; + sidev[0] = 1; + sidev[1] = -1; return -1; } nears = 1; } - else if (pi[0]) + else if (_.pi[0]) { - if (pi[1]) + if (_.pi[2]) { - sidev1 = sidev2 = -1; + sidev[0] = sidev[1] = -1; return 0; } - if (ni[1]) + if (_.ni[2]) { - sidev1 = -1; - sidev2 = 1; + sidev[0] = -1; + sidev[1] = 1; return -1; } nears = 1; } else { - nears = 2 | ((ni[1] | pi[1]) ? 0 : 1); + nears = 2 | ((_.ni[2] | _.pi[2]) ? 0 : 1); } __m128d zero = _mm_setzero_pd(); __m128d posi = _mm_cmpgt_pd(num, zero); - _mm_storeu_pd(p, posi); + _mm_storeu_pd(_.p, posi); + int sv1 = _.pi[0] ? _.pi[0] : 1; + int sv2 = _.pi[2] ? _.pi[2] : 1; if (nears) { __m128d sqnum = _mm_mul_pd(num, num); @@ -133,45 +132,20 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side __m128d dist = _mm_div_pd(sqnum, l); __m128d epsilon = _mm_set1_pd(SIDE_EPSILON); __m128d close = _mm_cmplt_pd(dist, epsilon); - _mm_storeu_pd(n, close); - if (nears & 2) + _mm_storeu_pd(_.n, close); + if ((nears & 2) && _.ni[0]) { - if (ni[0]) - { - sidev1 = 0; - } - else - { - sidev1 = pi[0] ? -1 : 1; - } + sv1 = 0; } - else + if ((nears & 1) && _.ni[2]) { - sidev1 = pi[0] ? -1 : 1; - } - if (nears & 1) - { - if (ni[1]) - { - sidev2 = 0; - } - else - { - sidev2 = pi[1] ? -1 : 1; - } - } - else - { - sidev2 = pi[1] ? -1 : 1; + sv2 = 0; } } - else - { - sidev1 = pi[0] ? -1 : 1; - sidev2 = pi[1] ? -1 : 1; - } + sidev[0] = sv1; + sidev[1] = sv2; - if ((sidev1 | sidev2) == 0) + if ((sv1 | sv2) == 0) { // seg is coplanar with the splitter, so use its orientation to determine // which child it ends up in. If it faces the same direction as the splitter, // it goes in front. Otherwise, it goes in back. @@ -199,11 +173,11 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side } } } - else if (sidev1 <= 0 && sidev2 <= 0) + else if (sv1 <= 0 && sv2 <= 0) { return 0; } - else if (sidev1 >= 0 && sidev2 >= 0) + else if (sv1 >= 0 && sv2 >= 0) { return 1; } diff --git a/processor.cpp b/processor.cpp index 15ca6e3..f9803be 100644 --- a/processor.cpp +++ b/processor.cpp @@ -577,21 +577,19 @@ void FProcessor::Write (FWadWriter &out) try { - int ssetype; - if (HaveSSE2) { - ssetype = 2; + SSELevel = 2; } else if (HaveSSE1) { - ssetype = 1; + SSELevel = 1; } else { - ssetype = 0; + SSELevel = 0; } - builder = new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), BuildGLNodes, ssetype); + builder = new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), BuildGLNodes); if (builder == NULL) { throw std::runtime_error(" Not enough memory to build nodes!"); @@ -627,7 +625,7 @@ void FProcessor::Write (FWadWriter &out) { // Now repeat the process to obtain regular nodes delete builder; - builder = new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), false, ssetype); + builder = new FNodeBuilder (Level, PolyStarts, PolyAnchors, Wad.LumpName (Lump), false); if (builder == NULL) { throw std::runtime_error(" Not enough memory to build regular nodes!"); diff --git a/zdbsp.h b/zdbsp.h index c801b38..727bf9d 100644 --- a/zdbsp.h +++ b/zdbsp.h @@ -46,6 +46,7 @@ extern bool CheckPolyobjs; extern bool ShowMap; extern bool CompressNodes, CompressGLNodes, ForceCompression, V5GLNodes; extern bool HaveSSE1, HaveSSE2; +extern int SSELevel; #define FIXED_MAX INT_MAX diff --git a/zlib/CMakeLists.txt b/zlib/CMakeLists.txt index 7d8fe56..768cf4a 100644 --- a/zlib/CMakeLists.txt +++ b/zlib/CMakeLists.txt @@ -10,5 +10,11 @@ add_library( z crc32.c deflate.c trees.c - zutil.c ) + zutil.c + crc32.h + deflate.h + trees.h + zconf.h + zlib.h + zutil.h ) target_link_libraries( z )