Compare commits

..
6 Commits
849 changed files with 104827 additions and 101754 deletions
+29 -290
View File
@@ -1,290 +1,6 @@
Version History
---------------
### New Features in Embree 2.16.5
- Bugfix in the robust triangle intersector that rarely caused NaNs.
- Fixed bug in hybrid traversal kernel when BVH leaf was entered with no
active rays. This rarely caused crashes when used with instancing.
- Fixed bug introduced in Embree 2.16.2 which caused instancing not to
work properly when a smaller than the native SIMD width was
used in ray packet mode.
- Fixed bug in the curve geometry intersector that caused rendering
artefacts for Bézier curves with p0=p1 and/or p2=p3.
- Fixed bug in the curve geometry intersector that caused hit results
with NaNs to be reported.
- Fixed masking bug that caused rare cracks in curve geometry.
- Enabled support for SSE2 in precompiled binaries again.
### New Features in Embree 2.16.4
- Bugfix in the ribbon intersector for hair primitives. Non-normalized
rays caused wrong intersection distance to be reported.
### New Features in Embree 2.16.3
- Increased accuracy for handling subdivision surfaces. This fixes
cracks when using displacement mapping but reduces performance
at irregular vertices.
- Fixed a bug where subdivision geometry was not properly updated
when modifying only the tesselation rate and vertex array.
### New Features in Embree 2.16.2
- Fixed bug that caused NULL intersection context in intersection
filter when instancing was used.
- Fixed an issue where uv's where outside the triangle (or quad) for
very small triangles (or quads). In robust mode we improved the uv
calculation to avoid that issue, in fast mode we accept that
inconsistency for better performance.
- Changed UV encoding for non-quad subdivision patches to
allow a subpatch UV range of `[-0.5,1.5[`. Using this new encoding
one can use finite differences to calculate derivatives if required.
Please adjust your code in case you rely on the old encoding.
### New Features in Embree 2.16.1
- Workaround for compile issues with Visual Studio 2017
- Fixed bug in subdiv code for static scenes when using tessellation
levels larger than 50.
- Fixed low performance when adding many geometries to a scene.
- Fixed high memory consumption issue when using instances in
dynamic scene (by disabling two level builder for user geometries
and instances).
### New Features in Embree 2.16.0
- Improved multi-segment motion blur support for scenes with
different number of time steps per mesh.
- New top level BVH builder that improves build times and BVH quality
of two-level BVHs.
- Added support to enable only a single ISA. Previously code was
always compiled for SSE2.
- Improved single ray tracing performance for incoherent rays on
AVX-512 architectures by 5-10%.
- Improved packet/hybrid ray tracing performance for incoherent rays
on AVX-512 architectures by 10-30%.
- Improved stream ray tracing performance for coherent rays in
structure-of-pointers layout by 40-70%.
- BVH builder for compact scenes of triangles and quads needs
essentially no temporary memory anymore. This doubles the
maximal scene size that can be rendered in compact mode.
- Triangles no longer store the geometry normal in fast/default mode
which reduces memory consumption by up to 20%.
- Compact mode uses BVH4 now consistently which reduces memory
consumption by up to 10%.
- Reduced memory consumption for small scenes (of 10k-100k primitives)
and dynamic scenes.
- Improved performance of user geometries and instances through BVH8
support.
- The API supports now specifying the geometry ID of a geometry at
construction time. This way matching the geometry ID used by
Embree and the application is simplified.
- Fixed a bug that would have caused a failure of the BVH builder
for dynamic scenes when run on a machine with more then 1000 threads.
- Fixed a bug that could have been triggered when reaching the maximal
number of mappings under Linux (`vm.max_map_count`). This could have
happened when creating a large number of small static scenes.
- Added huge page support for Windows and MacOSX (experimental).
- Added support for Visual Studio 2017.
- Removed support for Visual Studio 2012.
- Precompiled binaries now require a CPU supporting at least the
SSE4.2 ISA.
- We no longer provide precompiled binaries for 32 bit on Windows.
- Under Windows one now has to use the platform toolset option in
CMake to switch to Clang or the Intel® Compiler.
- Fixed a bug for subdivision meshes when using the incoherent scene
flag.
- Fixed a bug in the line geometry intersection, that caused reporting
an invalid line segment intersection with primID -1.
- Buffer stride for vertex buffers of different time steps of triangle
and quad meshes have to be identical now.
- Fixed a bug in the curve geometry intersection code when passed a
perfect cylinder.
### New Features in Embree 2.15.0
- Added `rtcCommitJoin` mode that allows thread to join a build
operation. When using the internal tasking system this allows
Embree to solely use the threads that called `rtcCommitJoin` to
build the scene, while previously also normal worker threads
participated in the build. You should no longer use `rtcCommit`
to join a build.
- Added `rtcDeviceSetErrorFunction2` API call, which sets an error
callback function which additionally gets passed a user provided
pointer (`rtcDeviceSetErrorFunction` is now deprecated).
- Added `rtcDeviceSetMemoryMonitorFunction2` API call, which sets a
memory monitor callback function which additionally get passed a
user provided pointer. (`rtcDeviceSetMemoryMonitorFunction` is now
deprecated).
- Build performance for hair geometry improved by up to 2×.
- Standard BVH build performance increased by 5%.
- Added API extension to use internal Morton-code based builder, the
standard binned-SAH builder, and the spatial split-based SAH builder.
- Added support for BSpline hair and curves. Embree uses
either the Bézier or BSpline basis internally, and converts other
curves, which requires more memory during rendering. For reduced
memory consumption set the `EMBREE_NATIVE_SPLINE_BASIS` to the basis
your application uses (which is set to `BEZIER` by default).
- Setting the number of threads through `tbb::taskscheduler_init`
object on the application side is now working properly.
- Windows and Linux releases are build using AVX-512 support.
- Implemented hybrid traversal for hair and line segments for
improved ray packet performance.
- AVX-512 code compiles with Clang 4.0.0
- Fixed crash when ray packets were disabled in CMake.
### New Features in Embree 2.14.0
- Added `ignore_config_files` option to init flags that allows the
application to ignore Embree configuration files.
- Face-varying interpolation is now supported for subdivision surfaces.
- Up to 16 user vertex buffers are supported for vertex
attribute interpolation.
- Deprecated `rtcSetBoundaryMode` function, please use the new
`rtcSetSubdivisionMode` function.
- Added `RTC_SUBDIV_PIN_BOUNDARY` mode for handling boundaries of
subdivision meshes.
- Added `RTC_SUBDIV_PIN_ALL` mode to enforce linear interpolation
for subdivision meshes.
- Optimized object generation performance for dynamic scenes.
- Reduced memory consumption when using lots of small dynamic objects.
- Fixed bug for subdivision surfaces using low tessellation rates.
- Hair geometry now uses a new ribbon intersector that intersects with
ray-facing quads. The new intersector also returns the v-coordinate
of the hair intersection, and fixes artefacts at junction points
between segments, at the cost of a small performance hit.
- Added `rtcSetBuffer2` function, that additionally gets the number of
elements of a buffer. In dynamic scenes, this function allows to
quickly change buffer sizes, making it possible to change the number
of primitives of a mesh or the number of crease features for
subdivision surfaces.
- Added simple 'viewer_anim' tutorial for rendering key
frame animations and 'buildbench' for measuring BVH (re-)build
performance for static and dynamic scenes.
- Added more AVX-512 optimizations for future architectures.
### New Features in Embree 2.13.0
- Improved performance for compact (but not robust) scenes.
- Added robust mode for motion blurred triangles and quads.
- Added fast dynamic mode for user geometries.
- Up to 20% faster BVH build performance on the second generation
Intel® Xeon Phi™ processor codenamed Knights Landing.
- Improved quality of the spatial split builder.
- Improved performance for coherent streams of ray packets (SOA
layout), e.g. for fast primary visibility.
- Various bug fixes in tessellation cache, quad-based spatial
split builder, etc.
### New Features in Embree 2.12.0
- Added support for multi-segment motion blur for all primitive types.
- API support for stream of pointers to single rays (`rtcIntersect1Mp`
and `rtcOccluded1Mp`)
- Improved BVH refitting performance for dynamic scenes.
- Improved high-quality mode for quads (added spatial split builder
for quads)
- Faster dynamic scenes for triangle and quad-based meshes on AVX2
enabled machines.
- Performance and correctness bugfix in optimization for streams of
coherent (single) rays.
- Fixed large memory consumption (issue introduced in Embree v2.11.0).
If you use Embree v2.11.0 please upgrade to Embree v2.12.0.
- Reduced memory consumption for dynamic scenes containing small
meshes.
- Added support to start and affinitize TBB worker threads by passing
"`start_threads=1,set_affinity=1`" to `rtcNewDevice`. These settings
are recommended on systems with a high thread count.
- `rtcInterpolate2` can now be called within a displacement shader.
- Added initial support for Microsoft's Parallel Pattern Library (PPL)
as tasking system alternative (for optimal performance TBB is
highly recommended).
- Updated to TBB 2017 which is released under the Apache v2.0 license.
- Dropped support for Visual Studio 2012 Win32 compiler. Visual Studio
2012 x64 is still supported.
### New Features in Embree 2.11.0
- Improved performance for streams of coherent (single) rays flagged
with `RTC_INTERSECT_COHERENT`. For such coherent ray streams, e.g.
primary rays, the performance typically improves by 1.3-2×.
- New spatial split BVH builder for triangles, which is 2-6× faster
than the previous version and more memory conservative.
- Improved performance and scalability of all standard BVH builders on
systems with large core counts.
- Fixed `rtcGetBounds` for motion blur scenes.
- Thread affinity is now on by default when running on the latest
Intel® Xeon Phi™ processor.
- Added AVX-512 support for future Intel® Xeon processors.
### New Features in Embree 2.10.0
- Added a new curve geometry which renders the sweep surface of a
circle along a Bézier curve.
- Intersection filters can update the `tfar` ray distance.
- Geometry types can get disabled at compile time.
- Modified and extended the ray stream API.
- Added new callback mechanism for the ray stream API.
- Improved ray stream performance (up to 5-10%).
- Up to 20% faster morton builder on machines with large core counts.
- Lots of optimizations for the second generation Intel® Xeon Phi™
processor codenamed Knights Landing.
- Added experimental support for compressed BVH nodes (reduces node
size to 56-62% of uncompressed size). Compression introduces a
typical performance overhead of ~10%.
- Bugfix in backface culling mode. We do now properly cull the
backfaces and not the frontfaces.
- Feature freeze for the first generation Intel® Xeon Phi™ coprocessor
codenamed Knights Corner. We will still maintain and add bug fixes
to Embree v2.9.0, but Embree 2.10 and future versions will no longer
support it.
### New Features in Embree 2.9.0
- Improved shadow ray performance (10-100% depending on the scene).
- Added initial support for ray streams (10-30% higher performance
depending on ray coherence in the stream).
- Added support to calculate second order derivatives using the
`rtcInterpolate2` function.
- Changed the parametrization for triangular subdivision faces to
the same scheme used for pentagons.
- Added support to query the Embree configuration using the
`rtcDeviceGetParameter` function.
### New Features in Embree 2.8.1
- Added support for setting per geometry tessellation rate (supported
for subdivision and Bézier geometries).
- Added support for motion blurred instances.
### New Features in Embree 2.8.0
- Added support for line segment geometry.
- Added support for quad geometry (replaces triangle-pairs feature).
- Added support for linear motion blur of user geometries.
- Improved performance through AVX-512 optimizations.
- Improved performance of lazy scene build (when using TBB 4.4 update
2).
- Improved performance through huge page support under linux.
### New Features in Embree 2.7.1
- Internal tasking system supports cancellation of build operations.
- ISPC mode for robust and compact scenes got significantly faster
(implemented hybrid traversal for bvh4.triangle4v and
bvh4.triangle4i).
- Hair rendering got faster as we fixed some issues with the SAH
heuristic cost factors.
- BVH8 got slight faster for single ray traversal (improved sorting
when hitting more than 4 boxes).
- BVH build performance got up to 30% faster on CPUs with high core
counts (improved parallel partition code).
- High quality build mode again working properly (spatial splits had
been deactivated in v2.7.0 due to some bug).
- Support for merging two adjacent triangles sharing a common edge
into a triangle-pair primitive (can reduce memory consumption and
BVH build times by up to 50% for mostly quad-based input meshes).
- Internal cleanups (reduced number of traversal kernels by more
templating).
- Reduced stack size requirements of BVH builders.
- Fixed crash for dynamic scenes, triggered by deleting all
geometries from the scene.
### New Features in Embree 2.7.0
- Added device concept to Embree to allow different components of an
@@ -293,7 +9,7 @@ Version History
- Fixed bug in tesselation cache that caused crashes for subdivision
surfaces.
- Fixed bug in internal task scheduler that caused deadlocks when
using `rtcCommitThread`.
using rtcCommitThread.
- Improved hit-distance accuracy for thin triangles in robust mode.
- Added support to disable ray packet support in cmake.
@@ -306,17 +22,17 @@ Version History
- Added ray packet intersectors for subdivision geometry, resulting in
improved performance for coherent rays.
- Reduced virtual address space usage for static geometries.
- Fixed some AVX2 code paths when compiling with GCC or Clang.
- Fixed some AVX2 code paths when compiling with GCC or CLANG.
- Bugfix for subdiv patches with non-matching winding order.
- Bugfix in ISA detection of AVX-512.
- Bugfix in ISA detection of AVX512.
### New Features in Embree 2.6.1
- Major performance improvements for ray tracing subdivision surfaces,
e.g. up to 2× faster for scenes where only the tessellation levels
are changing per frame, and up to 3× faster for scenes with lots of
crease features
- Initial support for architectures supporting the new 16-wide AVX-512
- Initial support for architectures supporting the new 16-wide AVX512
ISA
- Implemented intersection filter callback support for subdivision
surfaces
@@ -394,7 +110,7 @@ Version History
- Improved mixed AABB/OBB-BVH for hair geometry (Xeon Phi)
- Reduced amount of pre-allocated memory for BVH builders (Xeon Phi)
- New 64 bit Morton code-based BVH builder (Xeon Phi)
- New 64\ bit Morton code-based BVH builder (Xeon Phi)
- (Enhanced) Morton code-based BVH builders use now tree rotations to
improve BVH quality (Xeon Phi)
- Bug fixes (Xeon and Xeon Phi)
@@ -450,6 +166,29 @@ Version History
- New variant of the SAH-based builder using triangle pre-splits
(Xeon Phi)
### Example Performance Numbers for Embree 2.1
BVH rebuild performance (including triangle accel generation, excluding
memory allocation) for scenes with 2--12 million triangles:
- Intel® Core™ i7 (Haswell-based CPU, 4 cores @ 3.0\ GHz)
- 7--8 million triangles/s for the SAH-based BVH builder
- 30--36 million triangles/s for the Morton code-based BVH builder
- Intel® Xeon Phi™ 7120
- 37--40 million triangles/s for the SAH-based BVH builder
- 140--160 million triangles/s for the Morton code-based BVH
builder
Rendering of the Crown model (`crown.ecs`) with 4\ samples per pixel
(`-spp 4`):
- Intel® Core™ i7 (Haswell-based CPU, 4 cores CPU @ 3.0\ GHz)
- 1024×1024 resolution: 7.8 million rays per sec
- 1920×1080 resolution: 9.9 million rays per sec
- Intel® Xeon Phi™ 7120
- 1024×1024 resolution: 47.1 million rays per sec
- 1920×1080 resolution: 61.1 million rays per sec
### New Features in Embree 2.0
- Support for the Intel® Xeon Phi™ coprocessor platform
+143 -249
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -15,9 +15,9 @@
## ======================================================================== ##
SET(EMBREE_VERSION_MAJOR 2)
SET(EMBREE_VERSION_MINOR 17)
SET(EMBREE_VERSION_MINOR 7)
SET(EMBREE_VERSION_PATCH 0)
SET(EMBREE_VERSION_NOTE "-alpha.0")
SET(EMBREE_VERSION_NOTE "")
SET(EMBREE_VERSION ${EMBREE_VERSION_MAJOR}.${EMBREE_VERSION_MINOR}.${EMBREE_VERSION_PATCH})
MATH(EXPR EMBREE_VERSION_NUMBER "10000*${EMBREE_VERSION_MAJOR} + 100*${EMBREE_VERSION_MINOR} + ${EMBREE_VERSION_PATCH}")
SET(CPACK_RPM_PACKAGE_RELEASE 1)
@@ -26,30 +26,11 @@ PROJECT(embree${EMBREE_VERSION_MAJOR})
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
# find git version
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
FIND_PACKAGE(Git)
IF(GIT_FOUND)
EXECUTE_PROCESS(
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE "EMBREE_HASH"
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
ELSE()
SET(EMBREE_HASH 0)
ENDIF()
ENDIF()
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/kernels/rtcore_version.h.in"
"${PROJECT_SOURCE_DIR}/include/embree2/rtcore_version.h"
"${PROJECT_SOURCE_DIR}/kernels/version.h.in"
"${PROJECT_BINARY_DIR}/version.h"
)
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/kernels/hash.h.in"
"${PROJECT_BINARY_DIR}/hash.h"
)
FILE(WRITE "${PROJECT_BINARY_DIR}/hash" "${EMBREE_HASH}")
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}")
IF(COMMAND cmake_policy)
if (POLICY CMP0003)
@@ -67,88 +48,60 @@ MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH)
MARK_AS_ADVANCED(CMAKE_OSX_ARCHITECTURES)
MARK_AS_ADVANCED(CMAKE_OSX_DEPLOYMENT_TARGET)
MARK_AS_ADVANCED(CMAKE_OSX_SYSROOT)
MARK_AS_ADVANCED(CLEAR CMAKE_CXX_COMPILER)
MARK_AS_ADVANCED(GLUT_cocoa_LIBRARY)
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/common/cmake ${CMAKE_MODULE_PATH})
INCLUDE(test)
##############################################################
# Create Binary Packages
##############################################################
include(package)
##############################################################
# Embree configuration
##############################################################
GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
IF(SHARED_LIBS_SUPPORTED)
OPTION(EMBREE_STATIC_LIB "Build Embree as a static library.")
MARK_AS_ADVANCED(CLEAR EMBREE_STATIC_LIB)
ELSE()
SET(EMBREE_STATIC_LIB ON CACHE BOOL "Build Embree as a static library." FORCE)
MARK_AS_ADVANCED(EMBREE_STATIC_LIB)
ENDIF()
IF (EMBREE_STATIC_LIB)
OPTION(ENABLE_STATIC_LIB "Build Embree as a static library." OFF)
IF (ENABLE_STATIC_LIB)
SET(EMBREE_LIB_TYPE STATIC)
ADD_DEFINITIONS(-DEMBREE_STATIC_LIB)
ADD_DEFINITIONS(-DENABLE_STATIC_LIB)
ELSE()
SET(EMBREE_LIB_TYPE SHARED)
ENDIF()
OPTION(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON)
OPTION(EMBREE_TUTORIALS "Enable to build Embree tutorials" ON)
OPTION(ENABLE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON)
OPTION(ENABLE_TUTORIALS "Enable to build Embree tutorials" ON)
##############################################################################
# Configurations (add configurations also to common/cmake/embree-config-default.cmake)
OPTION(EMBREE_STAT_COUNTERS "Enables statistic counters.")
OPTION(EMBREE_STACK_PROTECTOR "When enabled Embree compiles with stack protection against return address overrides." OFF)
OPTION(EMBREE_RAY_MASK "Enables ray mask support.")
OPTION(EMBREE_BACKFACE_CULLING "Enables backface culling.")
OPTION(EMBREE_INTERSECTION_FILTER "Enables intersection filter callback." ON)
OPTION(EMBREE_INTERSECTION_FILTER_RESTORE "Restores previous hit when hit is filtered out." ON)
OPTION(EMBREE_IGNORE_INVALID_RAYS "Ignores invalid rays." OFF) # FIXME: enable by default?
OPTION(EMBREE_GEOMETRY_TRIANGLES "Enables support for triangle geometries." ON)
OPTION(EMBREE_GEOMETRY_QUADS "Enables support for quad geometries." ON)
OPTION(EMBREE_GEOMETRY_LINES "Enables support for line geometries." ON)
OPTION(EMBREE_GEOMETRY_HAIR "Enables support for hair geometries." ON)
OPTION(EMBREE_GEOMETRY_SUBDIV "Enables support for subdiv geometries." ON)
OPTION(EMBREE_GEOMETRY_USER "Enables support for user geometries." ON)
OPTION(EMBREE_RAY_PACKETS "Enabled support for ray packets." ON)
SET(EMBREE_NATIVE_SPLINE_BASIS BEZIER CACHE STRING "Sets the basis for curves which Embree uses internally. Other types are converted and need more memory.")
SET_PROPERTY(CACHE EMBREE_NATIVE_SPLINE_BASIS PROPERTY STRINGS BSPLINE BEZIER)
IF (EMBREE_NATIVE_SPLINE_BASIS STREQUAL "BSPLINE")
SET(EMBREE_NATIVE_CURVE_BSPLINE ON)
# only support Xeon Phi on Linux
IF (NOT WIN32 AND NOT APPLE)
OPTION(ENABLE_XEON_PHI_SUPPORT "Generates code path for Xeon Phi.")
ELSE()
SET(EMBREE_NATIVE_CURVE_BSPLINE OFF)
SET(ENABLE_XEON_PHI_SUPPORT OFF CACHE INTERNAL "Xeon Phi only supported on Linux.")
ENDIF()
SET(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system")
IF (WIN32)
SET_PROPERTY(CACHE EMBREE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL PPL)
ELSE()
SET_PROPERTY(CACHE EMBREE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL)
ENDIF()
IF (ENABLE_XEON_PHI_SUPPORT)
SET(ENABLE_ISPC_SUPPORT ON CACHE BOOL "Build Embree with support for ISPC applications." FORCE)
ENDIF ()
IF (EMBREE_TASKING_SYSTEM STREQUAL "TBB")
SET(TASKING_TBB ON )
SET(TASKING_INTERNAL OFF)
SET(TASKING_PPL OFF )
ADD_DEFINITIONS(-DTASKING_TBB)
LIST(APPEND ISPC_DEFINITIONS -DTASKING_TBB)
ELSEIF (EMBREE_TASKING_SYSTEM STREQUAL "PPL")
SET(TASKING_PPL ON )
SET(TASKING_TBB OFF )
SET(TASKING_INTERNAL OFF)
ADD_DEFINITIONS(-DTASKING_PPL)
LIST(APPEND ISPC_DEFINITIONS -DTASKING_PPL)
OPTION(RTCORE_RAY_MASK "Enables ray mask support.")
OPTION(RTCORE_STAT_COUNTERS "Enables statistic counters.")
OPTION(RTCORE_BACKFACE_CULLING "Enables backface culling.")
OPTION(RTCORE_INTERSECTION_FILTER "Enables intersection filter callback." ON)
OPTION(RTCORE_BUFFER_STRIDE "Enables buffer strides." ON)
OPTION(RTCORE_EXPORT_ALL_SYMBOLS "Lets Embree library export all symbols.")
OPTION(RTCORE_ENABLE_RAYSTREAM_LOGGER "Enables ray stream logger.")
OPTION(RTCORE_IGNORE_INVALID_RAYS "Ignores invalid rays." OFF) # FIXME: enable by default?
OPTION(RTCORE_RAY_PACKETS "Enabled support for ray packets." ON)
SET(RTCORE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system")
SET_PROPERTY(CACHE RTCORE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL)
IF (RTCORE_TASKING_SYSTEM STREQUAL "TBB")
SET(TASKING_TBB ON)
FIND_PACKAGE(TBB REQUIRED)
INCLUDE_DIRECTORIES(${TBB_INCLUDE_DIRS})
ELSE()
SET(TASKING_INTERNAL ON )
SET(TASKING_TBB OFF)
SET(TASKING_PPL OFF )
ADD_DEFINITIONS(-DTASKING_INTERNAL)
LIST(APPEND ISPC_DEFINITIONS -DTASKING_INTERNAL)
SET(TASKING_INTERNAL ON)
ENDIF()
CONFIGURE_FILE(
@@ -156,83 +109,6 @@ CONFIGURE_FILE(
"${PROJECT_BINARY_DIR}/config.h"
)
##############################################################
# ISA configuration
##############################################################
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
SET(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.")
ELSE()
SET(EMBREE_MAX_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
ENDIF()
SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE SSE2 SSE4.2 AVX AVX2 AVX512KNL AVX512SKX)
IF (EMBREE_MAX_ISA STREQUAL "NONE")
OPTION(EMBREE_ISA_SSE2 "Enables SSE2 ISA.")
OPTION(EMBREE_ISA_SSE42 "Enables SSE4.2 ISA.")
OPTION(EMBREE_ISA_AVX "Enables AVX ISA.")
OPTION(EMBREE_ISA_AVX2 "Enables AVX2 ISA.")
OPTION(EMBREE_ISA_AVX512KNL "Enables AVX512 ISA for Knights Landing.")
OPTION(EMBREE_ISA_AVX512SKX "Enables AVX512 ISA for Skylake.")
IF(NOT (EMBREE_ISA_SSE2 OR EMBREE_ISA_SSE42 OR EMBREE_ISA_AVX OR
EMBREE_ISA_AVX2 OR EMBREE_ISA_AVX512KNL OR EMBREE_ISA_AVX512SKX))
MESSAGE(STATUS "Detecting default ISA:")
INCLUDE(check_isa_default)
CHECK_ISA_DEFAULT(EMBREE_ISA_DEFAULT)
MESSAGE(STATUS "Detecting default ISA: ${EMBREE_ISA_DEFAULT}")
SET(EMBREE_ISA_${EMBREE_ISA_DEFAULT} ON)
ENDIF()
ELSE()
UNSET(EMBREE_ISA_SSE2 CACHE)
UNSET(EMBREE_ISA_SSE42 CACHE)
UNSET(EMBREE_ISA_AVX CACHE)
UNSET(EMBREE_ISA_AVX2 CACHE)
UNSET(EMBREE_ISA_AVX512KNL CACHE)
UNSET(EMBREE_ISA_AVX512SKX CACHE)
IF(EMBREE_MAX_ISA STREQUAL "SSE2")
SET(ISA 1)
ELSEIF(EMBREE_MAX_ISA STREQUAL "SSE4.2")
SET(ISA 2)
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX")
SET(ISA 3)
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX2")
SET(ISA 4)
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512KNL")
SET(ISA 5)
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512SKX")
SET(ISA 6)
ELSE()
MESSAGE(FATAL_ERROR "Unsupported ISA specified: " ${EMBREE_MAX_ISA})
ENDIF()
SET(EMBREE_ISA_SSE2 OFF)
SET(EMBREE_ISA_SSE42 OFF)
SET(EMBREE_ISA_AVX OFF)
SET(EMBREE_ISA_AVX2 OFF)
SET(EMBREE_ISA_AVX512KNL OFF)
SET(EMBREE_ISA_AVX512SKX OFF)
IF (ISA GREATER 0)
SET(EMBREE_ISA_SSE2 ON)
ENDIF ()
IF (ISA GREATER 1)
SET(EMBREE_ISA_SSE42 ON)
ENDIF ()
IF (ISA GREATER 2)
SET(EMBREE_ISA_AVX ON)
ENDIF ()
IF (ISA GREATER 3)
SET(EMBREE_ISA_AVX2 ON)
ENDIF ()
IF (ISA GREATER 4)
SET(EMBREE_ISA_AVX512KNL ON)
ENDIF ()
IF (ISA GREATER 5)
SET(EMBREE_ISA_AVX512SKX ON)
ENDIF ()
ENDIF()
##############################################################
# Compiler
##############################################################
@@ -245,31 +121,20 @@ IF (WIN32)
SET(DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON CACHE INTERNAL "Default CMake configuration types set.")
ENDIF()
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
IF (${CMAKE_GENERATOR_TOOLSET} MATCHES "^LLVM" )
MESSAGE("CLANG detected")
INCLUDE(clang)
ELSEIF(${CMAKE_GENERATOR_TOOLSET} MATCHES "^Intel")
MESSAGE("Intel Compiler detected")
INCLUDE (icc)
ELSE()
IF (EMBREE_ISA_AVX512KNL OR EMBREE_ISA_AVX512SKX)
MESSAGE(FATAL_ERROR "Microsoft Visual C++ Compiler does not support AVX512. Please use Intel Compiler or Clang.")
ENDIF()
INCLUDE (msvc)
ENDIF()
INCLUDE (msvc)
ELSE (WIN32)
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
INCLUDE(crayprgenv)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
SET(COMPILER "GCC" CACHE STRING "Selects compiler to use.")
SET_PROPERTY(CACHE COMPILER PROPERTY STRINGS GCC CLANG ICC)
IF (COMPILER STREQUAL "GCC")
INCLUDE (gcc)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
ELSEIF (COMPILER STREQUAL "CLANG")
INCLUDE (clang)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
ELSEIF (COMPILER STREQUAL "ICC")
INCLUDE (icc)
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler: " ${CMAKE_CXX_COMPILER_ID})
MESSAGE(FATAL_ERROR "Unknown compiler specified: " ${COMPILER})
ENDIF ()
IF(NOT CMAKE_BUILD_TYPE)
@@ -283,96 +148,119 @@ ELSE (WIN32)
ENDIF (WIN32)
##############################################################
# ISA configuration continued
# ISA configuration
##############################################################
SET(SSE2 0)
SET(SSE42 1)
SET(AVX 2)
SET(AVX2 3)
SET(AVX512KNL 4)
SET(AVX512SKX 5)
IF(APPLE)
SET(XEON_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
ELSEIF(NOT COMPILER STREQUAL "ICC")
SET(XEON_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
ELSE()
SET(XEON_ISA "AVX512" CACHE STRING "Selects highest ISA to support.")
ENDIF ()
UNSET(FLAGS_LOWEST)
SET_PROPERTY(CACHE XEON_ISA PROPERTY STRINGS SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 AVX AVX-I AVX2 AVX512)
IF (EMBREE_ISA_SSE2)
ADD_DEFINITIONS(-DEMBREE_TARGET_SSE2)
LIST(APPEND ISPC_TARGETS "sse2")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${SSE2})
SET(FLAGS_LOWEST ${FLAGS_SSE2})
ENDIF()
ENDIF()
IF (XEON_ISA STREQUAL "SSE2")
SET(ISA 1)
ENDIF ()
IF (EMBREE_ISA_SSE42)
ADD_DEFINITIONS(-DEMBREE_TARGET_SSE42)
IF (XEON_ISA STREQUAL "SSE3")
SET(ISA 2)
ENDIF ()
IF (XEON_ISA STREQUAL "SSSE3")
SET(ISA 3)
ENDIF ()
IF (XEON_ISA STREQUAL "SSE4.1")
SET(ISA 4)
ENDIF ()
IF (XEON_ISA STREQUAL "SSE4.2")
SET(ISA 5)
ENDIF ()
IF (XEON_ISA STREQUAL "AVX")
SET(ISA 6)
ENDIF ()
IF (XEON_ISA STREQUAL "AVX-I")
SET(ISA 7)
ENDIF ()
IF (XEON_ISA STREQUAL "AVX2")
SET(ISA 8)
ENDIF ()
IF (XEON_ISA STREQUAL "AVX512")
SET(ISA 9)
ENDIF ()
SET(TARGET_SSE2 OFF)
SET(TARGET_SSE3 OFF)
SET(TARGET_SSSE3 OFF)
SET(TARGET_SSE41 OFF)
SET(TARGET_SSE42 OFF)
SET(TARGET_AVX OFF)
SET(TARGET_AVXI OFF)
SET(TARGET_AVX2 OFF)
SET(TARGET_AVX512 OFF)
IF (ISA GREATER 0)
SET(TARGET_SSE2 ON)
SET(ISPC_TARGETS "sse2")
ENDIF ()
IF (ISA GREATER 1)
SET(TARGET_SSE3 ON)
ENDIF ()
IF (ISA GREATER 2)
SET(TARGET_SSSE3 ON)
ENDIF ()
IF (ISA GREATER 3)
SET(TARGET_SSE41 ON)
LIST(APPEND ISPC_TARGETS "sse4")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${SSE42})
SET(FLAGS_LOWEST ${FLAGS_SSE42})
ENDIF()
ENDIF ()
IF (EMBREE_ISA_AVX)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX)
IF (ISA GREATER 4)
SET(TARGET_SSE42 ON)
ENDIF ()
IF (ISA GREATER 5)
SET(TARGET_AVX ON)
LIST(APPEND ISPC_TARGETS "avx")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${AVX})
SET(FLAGS_LOWEST ${FLAGS_AVX})
ENDIF()
ENDIF ()
IF (EMBREE_ISA_AVX2)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX2)
IF (ISA GREATER 6)
SET(TARGET_AVXI ON)
ENDIF ()
IF (ISA GREATER 7)
SET(TARGET_AVX2 ON)
LIST(APPEND ISPC_TARGETS "avx2")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${AVX2})
SET(FLAGS_LOWEST ${FLAGS_AVX2})
ENDIF()
ENDIF ()
IF (EMBREE_ISA_AVX512KNL)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512KNL)
IF (ISA GREATER 8)
SET(TARGET_AVX512 ON)
LIST(APPEND ISPC_TARGETS "avx512knl-i32x16")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${AVX512KNL})
SET(FLAGS_LOWEST ${FLAGS_AVX512KNL})
ENDIF()
ENDIF ()
IF (EMBREE_ISA_AVX512SKX)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512SKX)
LIST(APPEND ISPC_TARGETS "avx512skx-i32x16")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${AVX512SKX})
SET(FLAGS_LOWEST ${FLAGS_AVX512SKX})
ENDIF()
ENDIF ()
INCLUDE (ispc)
##############################################################
# Create Binary Packages (uses above config options)
##############################################################
include(package)
##############################################################
# Search paths
##############################################################
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}")
INCLUDE_DIRECTORIES_ISPC("${PROJECT_BINARY_DIR}")
IF (TASKING_TBB)
FIND_PACKAGE(TBB REQUIRED)
INCLUDE_DIRECTORIES(${TBB_INCLUDE_DIRS})
ENDIF()
##############################################################
# Output paths
##############################################################
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
##############################################################
# Directories to compile
@@ -381,8 +269,16 @@ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(kernels)
IF (EMBREE_TUTORIALS)
IF (ENABLE_TUTORIALS)
ADD_SUBDIRECTORY(tutorials)
SET (__XEON__ 1)
ADD_SUBDIRECTORY(tests)
IF (ENABLE_XEON_PHI_SUPPORT)
SET (__XEON__ 0)
ADD_SUBDIRECTORY(tests tests_xeonphi)
ENDIF ()
ENDIF()
##############################################################
@@ -397,8 +293,6 @@ configure_file(
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake)
SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets)
##############################################################
# Has to be last
##############################################################
+671 -1819
View File
File diff suppressed because it is too large Load Diff
+10 -3
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,9 +14,16 @@
## limitations under the License. ##
## ======================================================================== ##
SET(__XEON__ 1)
ADD_SUBDIRECTORY(sys)
ADD_SUBDIRECTORY(math)
ADD_SUBDIRECTORY(simd)
ADD_SUBDIRECTORY(lexers)
ADD_SUBDIRECTORY(tasking)
ADD_SUBDIRECTORY(algorithms)
IF (ENABLE_XEON_PHI_SUPPORT)
SET(__XEON__ 0)
ADD_SUBDIRECTORY(sys sys_xeonphi)
ADD_SUBDIRECTORY(simd simd_xeonphi)
ADD_SUBDIRECTORY(lexers lexers_xeonphi)
ADD_SUBDIRECTORY(tasking tasking_xeonphi)
ENDIF ()
-69
View File
@@ -1,69 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "parallel_filter.h"
#include "../sys/regression.h"
#include <map>
namespace embree
{
struct parallel_filter_regression_test : public RegressionTest
{
parallel_filter_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
auto pred = [&]( uint32_t v ) { return (v & 0x3) == 0; };
for (size_t N=10; N<1000000; N=size_t(2.1*N))
{
size_t N0 = rand() % N;
/* initialize array with random numbers */
std::vector<uint32_t> src(N);
std::map<uint32_t,int> m;
for (size_t i=0; i<N; i++) src[i] = rand();
/* count elements up */
for (size_t i=N0; i<N; i++)
if (pred(src[i]))
m[src[i]] = 0;
for (size_t i=N0; i<N; i++)
if (pred(src[i]))
m[src[i]]++;
/* filter array */
//size_t M = sequential_filter(src.data(),N0,N,pred);
size_t M = parallel_filter(src.data(),N0,N,size_t(1024),pred);
/* check if filtered data is correct */
for (size_t i=N0; i<M; i++) {
passed &= pred(src[i]);
m[src[i]]--;
}
for (size_t i=N0; i<M; i++)
passed &= (m[src[i]] == 0);
}
return passed;
}
};
parallel_filter_regression_test parallel_filter_regression("parallel_filter_regression");
}
-106
View File
@@ -1,106 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "parallel_for.h"
namespace embree
{
template<typename Ty, typename Index, typename Predicate>
inline Index sequential_filter( Ty* data, const Index first, const Index last, const Predicate& predicate)
{
Index j = first;
for (Index i=first; i<last; i++)
if (predicate(data[i]))
data[j++] = data[i];
return j;
}
template<typename Ty, typename Index, typename Predicate>
inline Index parallel_filter( Ty* data, const Index begin, const Index end, const Index minStepSize, const Predicate& predicate)
{
/* sequential fallback */
if (end-begin <= minStepSize)
return sequential_filter(data,begin,end,predicate);
/* calculate number of tasks to use */
enum { MAX_TASKS = 512 };
const Index numThreads = TaskScheduler::threadCount();
const Index numBlocks = (end-begin+minStepSize-1)/minStepSize;
const Index taskCount = min(numThreads,numBlocks,(Index)MAX_TASKS);
/* filter blocks */
Index nused[MAX_TASKS];
Index nfree[MAX_TASKS];
parallel_for(taskCount, [&](const Index taskIndex)
{
const Index i0 = begin+(taskIndex+0)*(end-begin)/taskCount;
const Index i1 = begin+(taskIndex+1)*(end-begin)/taskCount;
const Index i2 = sequential_filter(data,i0,i1,predicate);
nused[taskIndex] = i2-i0;
nfree[taskIndex] = i1-i2;
});
/* calculate offsets */
Index sused=0;
Index sfree=0;
Index pfree[MAX_TASKS];
for (Index i=0; i<taskCount; i++)
{
sused+=nused[i];
Index cfree = nfree[i]; pfree[i] = sfree; sfree+=cfree;
}
/* return if we did not filter out any element */
assert(sfree <= end-begin);
assert(sused <= end-begin);
if (sused == end-begin)
return end;
/* otherwise we have to copy misplaced elements around */
parallel_for(taskCount, [&](const Index taskIndex)
{
/* destination to write elements to */
Index dst = begin+(taskIndex+0)*(end-begin)/taskCount+nused[taskIndex];
Index dst_end = min(dst+nfree[taskIndex],begin+sused);
if (dst_end <= dst) return;
/* range of misplaced elements to copy to destination */
Index r0 = pfree[taskIndex];
Index r1 = r0+dst_end-dst;
/* find range in misplaced elements in back to front order */
Index k0=0;
for (Index i=taskCount-1; i>0; i--)
{
if (k0 > r1) break;
Index k1 = k0+nused[i];
Index src = begin+(i+0)*(end-begin)/taskCount+nused[i];
for (Index i=max(r0,k0); i<min(r1,k1); i++) {
Index isrc = src-i+k0-1;
assert(dst >= begin && dst < end);
assert(isrc >= begin && isrc < end);
data[dst++] = data[isrc];
}
k0 = k1;
}
});
return begin+sused;
}
}
-133
View File
@@ -1,133 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../common/tasking/taskscheduler.h"
#include "../sys/array.h"
#include "../math/math.h"
#include "../common/math/range.h"
namespace embree
{
/* parallel_for without range */
template<typename Index, typename Func>
__forceinline void parallel_for( const Index N, const Func& func)
{
#if defined(TASKING_INTERNAL)
if (N) {
TaskScheduler::spawn(Index(0),N,Index(1),[&] (const range<Index>& r) {
assert(r.size() == 1);
func(r.begin());
});
if (!TaskScheduler::wait())
throw std::runtime_error("task cancelled");
}
#elif defined(TASKING_TBB)
tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
func(i);
});
if (tbb::task::self().is_cancelled())
throw std::runtime_error("task cancelled");
#elif defined(TASKING_PPL)
concurrency::parallel_for(Index(0),N,Index(1),[&](Index i) {
func(i);
});
#else
# error "no tasking system enabled"
#endif
}
/* parallel for with range and granulatity */
template<typename Index, typename Func>
__forceinline void parallel_for( const Index first, const Index last, const Index minStepSize, const Func& func)
{
assert(first <= last);
#if defined(TASKING_INTERNAL)
TaskScheduler::spawn(first,last,minStepSize,func);
if (!TaskScheduler::wait())
throw std::runtime_error("task cancelled");
#elif defined(TASKING_TBB)
tbb::parallel_for(tbb::blocked_range<Index>(first,last,minStepSize),[&](const tbb::blocked_range<Index>& r) {
func(range<Index>(r.begin(),r.end()));
});
if (tbb::task::self().is_cancelled())
throw std::runtime_error("task cancelled");
#elif defined(TASKING_PPL)
concurrency::parallel_for(first, last, Index(1) /*minStepSize*/, [&](Index i) {
func(range<Index>(i,i+1));
});
#else
# error "no tasking system enabled"
#endif
}
/* parallel for with range */
template<typename Index, typename Func>
__forceinline void parallel_for( const Index first, const Index last, const Func& func)
{
assert(first <= last);
parallel_for(first,last,(Index)1,func);
}
#if defined(TASKING_TBB) && (TBB_INTERFACE_VERSION > 4001)
template<typename Index, typename Func>
__forceinline void parallel_for_static( const Index N, const Func& func)
{
tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
func(i);
},tbb::simple_partitioner());
if (tbb::task::self().is_cancelled())
throw std::runtime_error("task cancelled");
}
typedef tbb::affinity_partitioner affinity_partitioner;
template<typename Index, typename Func>
__forceinline void parallel_for_affinity( const Index N, const Func& func, tbb::affinity_partitioner& ap)
{
tbb::parallel_for(Index(0),N,Index(1),[&](Index i) {
func(i);
},ap);
if (tbb::task::self().is_cancelled())
throw std::runtime_error("task cancelled");
}
#else
template<typename Index, typename Func>
__forceinline void parallel_for_static( const Index N, const Func& func)
{
parallel_for(N,func);
}
struct affinity_partitioner {
};
template<typename Index, typename Func>
__forceinline void parallel_for_affinity( const Index N, const Func& func, affinity_partitioner& ap)
{
parallel_for(N,func);
}
#endif
}
-66
View File
@@ -1,66 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "parallel_partition.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_partition_regression_test : public RegressionTest
{
parallel_partition_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
for (size_t i=0; i<100; i++)
{
/* create random permutation */
size_t N = std::rand() % 1000000;
std::vector<unsigned> array(N);
for (unsigned i=0; i<N; i++) array[i] = i;
for (auto& v : array) std::swap(v,array[std::rand()%array.size()]);
size_t split = std::rand() % (N+1);
/* perform parallel partitioning */
size_t left_sum = 0, right_sum = 0;
size_t mid = parallel_partitioning(array.data(),0,array.size(),0,left_sum,right_sum,
[&] ( size_t i ) { return i < split; },
[] ( size_t& sum, unsigned v) { sum += v; },
[] ( size_t& sum, size_t v) { sum += v; },
128);
/*serial_partitioning(array.data(),0,array.size(),left_sum,right_sum,
[&] ( size_t i ) { return i < split; },
[] ( size_t& left_sum, int v) { left_sum += v; });*/
/* verify result */
passed &= mid == split;
passed &= left_sum == split*(split-1)/2;
passed &= right_sum == N*(N-1)/2-left_sum;
for (size_t i=0; i<split; i++) passed &= array[i] < split;
for (size_t i=split; i<N; i++) passed &= array[i] >= split;
}
return passed;
}
};
parallel_partition_regression_test parallel_partition_regression("parallel_partition_regression_test");
}
-278
View File
@@ -1,278 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "parallel_for.h"
#include "../common/math/range.h"
namespace embree
{
/* serial partitioning */
template<typename T, typename V, typename IsLeft, typename Reduction_T>
__forceinline size_t serial_partitioning(T* array,
const size_t begin,
const size_t end,
V& leftReduction,
V& rightReduction,
const IsLeft& is_left,
const Reduction_T& reduction_t)
{
T* l = array + begin;
T* r = array + end - 1;
while(1)
{
/* *l < pivot */
while (likely(l <= r && is_left(*l) ))
{
//prefetchw(l+4); // FIXME: enable?
reduction_t(leftReduction,*l);
++l;
}
/* *r >= pivot) */
while (likely(l <= r && !is_left(*r)))
{
//prefetchw(r-4); FIXME: enable?
reduction_t(rightReduction,*r);
--r;
}
if (r<l) break;
reduction_t(leftReduction ,*r);
reduction_t(rightReduction,*l);
xchg(*l,*r);
l++; r--;
}
return l - array;
}
template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
class __aligned(64) parallel_partition_task
{
ALIGNED_CLASS;
private:
static const size_t MAX_TASKS = 512;
T* array;
size_t N;
const IsLeft& is_left;
const Reduction_T& reduction_t;
const Reduction_V& reduction_v;
const Vi& identity;
size_t numTasks;
__aligned(64) size_t counter_start[MAX_TASKS+1];
__aligned(64) size_t counter_left[MAX_TASKS+1];
__aligned(64) range<ssize_t> leftMisplacedRanges[MAX_TASKS];
__aligned(64) range<ssize_t> rightMisplacedRanges[MAX_TASKS];
__aligned(64) V leftReductions[MAX_TASKS];
__aligned(64) V rightReductions[MAX_TASKS];
public:
__forceinline parallel_partition_task(T* array,
const size_t N,
const Vi& identity,
const IsLeft& is_left,
const Reduction_T& reduction_t,
const Reduction_V& reduction_v,
const size_t BLOCK_SIZE)
: array(array), N(N), is_left(is_left), reduction_t(reduction_t), reduction_v(reduction_v), identity(identity),
numTasks(min((N+BLOCK_SIZE-1)/BLOCK_SIZE,min(TaskScheduler::threadCount(),MAX_TASKS))) {}
__forceinline const range<ssize_t>* findStartRange(size_t& index, const range<ssize_t>* const r, const size_t numRanges)
{
size_t i = 0;
while(index >= (size_t)r[i].size())
{
assert(i < numRanges);
index -= (size_t)r[i].size();
i++;
}
return &r[i];
}
__forceinline void swapItemsInMisplacedRanges(const size_t numLeftMisplacedRanges,
const size_t numRightMisplacedRanges,
const size_t startID,
const size_t endID)
{
size_t leftLocalIndex = startID;
size_t rightLocalIndex = startID;
const range<ssize_t>* l_range = findStartRange(leftLocalIndex,leftMisplacedRanges,numLeftMisplacedRanges);
const range<ssize_t>* r_range = findStartRange(rightLocalIndex,rightMisplacedRanges,numRightMisplacedRanges);
size_t l_left = l_range->size() - leftLocalIndex;
size_t r_left = r_range->size() - rightLocalIndex;
T *__restrict__ l = &array[l_range->begin() + leftLocalIndex];
T *__restrict__ r = &array[r_range->begin() + rightLocalIndex];
size_t size = endID - startID;
size_t items = min(size,min(l_left,r_left));
while (size)
{
if (unlikely(l_left == 0))
{
l_range++;
l_left = l_range->size();
l = &array[l_range->begin()];
items = min(size,min(l_left,r_left));
}
if (unlikely(r_left == 0))
{
r_range++;
r_left = r_range->size();
r = &array[r_range->begin()];
items = min(size,min(l_left,r_left));
}
size -= items;
l_left -= items;
r_left -= items;
while(items) {
items--;
xchg(*l++,*r++);
}
}
}
__forceinline size_t partition(V& leftReduction, V& rightReduction)
{
/* partition the individual ranges for each task */
parallel_for(numTasks,[&] (const size_t taskID) {
const size_t startID = (taskID+0)*N/numTasks;
const size_t endID = (taskID+1)*N/numTasks;
V local_left(identity);
V local_right(identity);
const size_t mid = serial_partitioning(array,startID,endID,local_left,local_right,is_left,reduction_t);
counter_start[taskID] = startID;
counter_left [taskID] = mid-startID;
leftReductions[taskID] = local_left;
rightReductions[taskID] = local_right;
});
counter_start[numTasks] = N;
counter_left[numTasks] = 0;
/* finalize the reductions */
for (size_t i=0; i<numTasks; i++) {
reduction_v(leftReduction,leftReductions[i]);
reduction_v(rightReduction,rightReductions[i]);
}
/* calculate mid point for partitioning */
size_t mid = counter_left[0];
for (size_t i=1; i<numTasks; i++)
mid += counter_left[i];
const range<ssize_t> globalLeft (0,mid);
const range<ssize_t> globalRight(mid,N);
/* calculate all left and right ranges that are on the wrong global side */
size_t numMisplacedRangesLeft = 0;
size_t numMisplacedRangesRight = 0;
size_t numMisplacedItemsLeft = 0;
size_t numMisplacedItemsRight = 0;
for (size_t i=0; i<numTasks; i++)
{
const range<ssize_t> left_range (counter_start[i], counter_start[i] + counter_left[i]);
const range<ssize_t> right_range(counter_start[i] + counter_left[i], counter_start[i+1]);
const range<ssize_t> left_misplaced = globalLeft. intersect(right_range);
const range<ssize_t> right_misplaced = globalRight.intersect(left_range);
if (!left_misplaced.empty())
{
numMisplacedItemsLeft += left_misplaced.size();
leftMisplacedRanges[numMisplacedRangesLeft++] = left_misplaced;
}
if (!right_misplaced.empty())
{
numMisplacedItemsRight += right_misplaced.size();
rightMisplacedRanges[numMisplacedRangesRight++] = right_misplaced;
}
}
assert( numMisplacedItemsLeft == numMisplacedItemsRight );
/* if no items are misplaced we are done */
if (numMisplacedItemsLeft == 0)
return mid;
/* otherwise we copy the items to the right place in parallel */
parallel_for(numTasks,[&] (const size_t taskID) {
const size_t startID = (taskID+0)*numMisplacedItemsLeft/numTasks;
const size_t endID = (taskID+1)*numMisplacedItemsLeft/numTasks;
swapItemsInMisplacedRanges(numMisplacedRangesLeft,numMisplacedRangesRight,startID,endID);
});
return mid;
}
};
template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
__noinline size_t parallel_partitioning(T* array,
const size_t begin,
const size_t end,
const Vi &identity,
V &leftReduction,
V &rightReduction,
const IsLeft& is_left,
const Reduction_T& reduction_t,
const Reduction_V& reduction_v,
size_t BLOCK_SIZE = 128)
{
/* fall back to single threaded partitioning for small N */
if (unlikely(end-begin < BLOCK_SIZE))
return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
/* otherwise use parallel code */
else {
typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
return begin+p->partition(leftReduction,rightReduction);
}
}
template<typename T, typename V, typename Vi, typename IsLeft, typename Reduction_T, typename Reduction_V>
__noinline size_t parallel_partitioning(T* array,
const size_t begin,
const size_t end,
const Vi &identity,
V &leftReduction,
V &rightReduction,
const IsLeft& is_left,
const Reduction_T& reduction_t,
const Reduction_V& reduction_v,
size_t BLOCK_SIZE,
size_t PARALLEL_THRESHOLD)
{
/* fall back to single threaded partitioning for small N */
if (unlikely(end-begin < PARALLEL_THRESHOLD))
return serial_partitioning(array,begin,end,leftReduction,rightReduction,is_left,reduction_t);
/* otherwise use parallel code */
else {
typedef parallel_partition_task<T,V,Vi,IsLeft,Reduction_T,Reduction_V> partition_task;
std::unique_ptr<partition_task> p(new partition_task(&array[begin],end-begin,identity,is_left,reduction_t,reduction_v,BLOCK_SIZE));
return begin+p->partition(leftReduction,rightReduction);
}
}
}
-149
View File
@@ -1,149 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "parallel_for.h"
namespace embree
{
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value sequential_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
{
return func(range<Index>(first,last));
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value sequential_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
{
return func(range<Index>(first,last));
}
template<typename Index, typename Value, typename Func, typename Reduction>
__noinline Value parallel_reduce_internal( Index taskCount, const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
{
const Index maxTasks = 512;
const Index threadCount = (Index) TaskScheduler::threadCount();
taskCount = min(taskCount,threadCount,maxTasks);
/* parallel invokation of all tasks */
dynamic_large_stack_array(Value,values,taskCount,4096); // consumes at most 4096 bytes on the stack
parallel_for(taskCount, [&](const Index taskIndex) {
const Index k0 = first+(taskIndex+0)*(last-first)/taskCount;
const Index k1 = first+(taskIndex+1)*(last-first)/taskCount;
values[taskIndex] = func(range<Index>(k0,k1));
});
/* perform reduction over all tasks */
Value v = identity;
for (Index i=0; i<taskCount; i++) v = reduction(v,values[i]);
return v;
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
{
#if defined(TASKING_INTERNAL)
/* fast path for small number of iterations */
Index taskCount = (last-first+minStepSize-1)/minStepSize;
if (likely(taskCount == 1)) {
return func(range<Index>(first,last));
}
return parallel_reduce_internal(taskCount,first,last,minStepSize,identity,func,reduction);
#elif defined(TASKING_TBB)
const Value v = tbb::parallel_reduce(tbb::blocked_range<Index>(first,last,minStepSize),identity,
[&](const tbb::blocked_range<Index>& r, const Value& start) { return reduction(start,func(range<Index>(r.begin(),r.end()))); },
reduction);
if (tbb::task::self().is_cancelled())
throw std::runtime_error("task cancelled");
return v;
#else // TASKING_PPL
struct AlignedValue
{
char storage[__alignof(Value)+sizeof(Value)];
static uintptr_t alignUp(uintptr_t p, size_t a) { return p + (~(p - 1) % a); };
Value* getValuePtr() { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
const Value* getValuePtr() const { return reinterpret_cast<Value*>(alignUp(uintptr_t(storage), __alignof(Value))); }
AlignedValue(const Value& v) { new(getValuePtr()) Value(v); }
AlignedValue(const AlignedValue& v) { new(getValuePtr()) Value(*v.getValuePtr()); }
AlignedValue(const AlignedValue&& v) { new(getValuePtr()) Value(*v.getValuePtr()); };
AlignedValue& operator = (const AlignedValue& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
AlignedValue& operator = (const AlignedValue&& v) { *getValuePtr() = *v.getValuePtr(); return *this; };
operator Value() const { return *getValuePtr(); }
};
struct Iterator_Index
{
Index v;
typedef std::forward_iterator_tag iterator_category;
typedef AlignedValue value_type;
typedef Index difference_type;
typedef Index distance_type;
typedef AlignedValue* pointer;
typedef AlignedValue& reference;
__forceinline Iterator_Index() {}
__forceinline Iterator_Index(Index v) : v(v) {}
__forceinline bool operator== (Iterator_Index other) { return v == other.v; }
__forceinline bool operator!= (Iterator_Index other) { return v != other.v; }
__forceinline Iterator_Index operator++() { return Iterator_Index(++v); }
__forceinline Iterator_Index operator++(int) { return Iterator_Index(v++); }
};
auto range_reduction = [&](Iterator_Index begin, Iterator_Index end, const AlignedValue& start) {
assert(begin.v < end.v);
return reduction(start, func(range<Index>(begin.v, end.v)));
};
const Value v = concurrency::parallel_reduce(Iterator_Index(first), Iterator_Index(last), AlignedValue(identity), range_reduction, reduction);
return v;
#endif
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_reduce( const Index first, const Index last, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
{
if (likely(last-first < parallel_threshold)) {
return func(range<Index>(first,last));
} else {
return parallel_reduce(first,last,minStepSize,identity,func,reduction);
}
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_reduce( const range<Index> range, const Index minStepSize, const Index parallel_threshold, const Value& identity, const Func& func, const Reduction& reduction )
{
return parallel_reduce(range.begin(),range.end(),minStepSize,parallel_threshold,identity,func,reduction);
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_reduce( const Index first, const Index last, const Value& identity, const Func& func, const Reduction& reduction )
{
auto funcr = [&] ( const range<Index> r ) {
Value v = identity;
for (Index i=r.begin(); i<r.end(); i++)
v = reduction(v,func(i));
return v;
};
return parallel_reduce(first,last,Index(1),identity,funcr,reduction);
}
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_reduce( const range<Index> range, const Value& identity, const Func& func, const Reduction& reduction )
{
return parallel_reduce(range.begin(),range.end(),Index(1),identity,func,reduction);
}
}
-456
View File
@@ -1,456 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../simd/simd.h"
#include "parallel_for.h"
#include <algorithm>
namespace embree
{
template<class T>
__forceinline void insertionsort_ascending(T *__restrict__ array, const size_t length)
{
for(size_t i = 1;i<length;++i)
{
T v = array[i];
size_t j = i;
while(j > 0 && v < array[j-1])
{
array[j] = array[j-1];
--j;
}
array[j] = v;
}
}
template<class T>
__forceinline void insertionsort_decending(T *__restrict__ array, const size_t length)
{
for(size_t i = 1;i<length;++i)
{
T v = array[i];
size_t j = i;
while(j > 0 && v > array[j-1])
{
array[j] = array[j-1];
--j;
}
array[j] = v;
}
}
template<class T>
void quicksort_ascending(T *__restrict__ t,
const ssize_t begin,
const ssize_t end)
{
if (likely(begin < end))
{
const T pivotvalue = t[begin];
ssize_t left = begin - 1;
ssize_t right = end + 1;
while(1)
{
while (t[--right] > pivotvalue);
while (t[++left] < pivotvalue);
if (left >= right) break;
const T temp = t[right];
t[right] = t[left];
t[left] = temp;
}
const int pivot = right;
quicksort_ascending(t, begin, pivot);
quicksort_ascending(t, pivot + 1, end);
}
}
template<class T>
void quicksort_decending(T *__restrict__ t,
const ssize_t begin,
const ssize_t end)
{
if (likely(begin < end))
{
const T pivotvalue = t[begin];
ssize_t left = begin - 1;
ssize_t right = end + 1;
while(1)
{
while (t[--right] < pivotvalue);
while (t[++left] > pivotvalue);
if (left >= right) break;
const T temp = t[right];
t[right] = t[left];
t[left] = temp;
}
const int pivot = right;
quicksort_decending(t, begin, pivot);
quicksort_decending(t, pivot + 1, end);
}
}
template<class T, ssize_t THRESHOLD>
void quicksort_insertionsort_ascending(T *__restrict__ t,
const ssize_t begin,
const ssize_t end)
{
if (likely(begin < end))
{
const ssize_t size = end-begin+1;
if (likely(size <= THRESHOLD))
{
insertionsort_ascending<T>(&t[begin],size);
}
else
{
const T pivotvalue = t[begin];
ssize_t left = begin - 1;
ssize_t right = end + 1;
while(1)
{
while (t[--right] > pivotvalue);
while (t[++left] < pivotvalue);
if (left >= right) break;
const T temp = t[right];
t[right] = t[left];
t[left] = temp;
}
const ssize_t pivot = right;
quicksort_insertionsort_ascending<T,THRESHOLD>(t, begin, pivot);
quicksort_insertionsort_ascending<T,THRESHOLD>(t, pivot + 1, end);
}
}
}
template<class T, ssize_t THRESHOLD>
void quicksort_insertionsort_decending(T *__restrict__ t,
const ssize_t begin,
const ssize_t end)
{
if (likely(begin < end))
{
const ssize_t size = end-begin+1;
if (likely(size <= THRESHOLD))
{
insertionsort_decending<T>(&t[begin],size);
}
else
{
const T pivotvalue = t[begin];
ssize_t left = begin - 1;
ssize_t right = end + 1;
while(1)
{
while (t[--right] < pivotvalue);
while (t[++left] > pivotvalue);
if (left >= right) break;
const T temp = t[right];
t[right] = t[left];
t[left] = temp;
}
const ssize_t pivot = right;
quicksort_insertionsort_decending<T,THRESHOLD>(t, begin, pivot);
quicksort_insertionsort_decending<T,THRESHOLD>(t, pivot + 1, end);
}
}
}
template<typename T>
static void radixsort32(T* const morton, const size_t num, const unsigned int shift = 3*8)
{
static const unsigned int BITS = 8;
static const unsigned int BUCKETS = (1 << BITS);
static const unsigned int CMP_SORT_THRESHOLD = 16;
__aligned(64) unsigned int count[BUCKETS];
/* clear buckets */
for (size_t i=0;i<BUCKETS;i++) count[i] = 0;
/* count buckets */
#if defined(__INTEL_COMPILER)
#pragma nounroll
#endif
for (size_t i=0;i<num;i++)
count[(unsigned(morton[i]) >> shift) & (BUCKETS-1)]++;
/* prefix sums */
__aligned(64) unsigned int head[BUCKETS];
__aligned(64) unsigned int tail[BUCKETS];
head[0] = 0;
for (size_t i=1; i<BUCKETS; i++)
head[i] = head[i-1] + count[i-1];
for (size_t i=0; i<BUCKETS-1; i++)
tail[i] = head[i+1];
tail[BUCKETS-1] = head[BUCKETS-1] + count[BUCKETS-1];
assert(tail[BUCKETS-1] == head[BUCKETS-1] + count[BUCKETS-1]);
assert(tail[BUCKETS-1] == num);
/* in-place swap */
for (size_t i=0;i<BUCKETS;i++)
{
/* process bucket */
while(head[i] < tail[i])
{
T v = morton[head[i]];
while(1)
{
const size_t b = (unsigned(v) >> shift) & (BUCKETS-1);
if (b == i) break;
std::swap(v,morton[head[b]++]);
}
assert((unsigned(v) >> shift & (BUCKETS-1)) == i);
morton[head[i]++] = v;
}
}
if (shift == 0) return;
size_t offset = 0;
for (size_t i=0;i<BUCKETS;i++)
if (count[i])
{
for (size_t j=offset;j<offset+count[i]-1;j++)
assert(((unsigned(morton[j]) >> shift) & (BUCKETS-1)) == i);
if (unlikely(count[i] < CMP_SORT_THRESHOLD))
insertionsort_ascending(morton + offset, count[i]);
else
radixsort32(morton + offset, count[i], shift-BITS);
for (size_t j=offset;j<offset+count[i]-1;j++)
assert(morton[j] <= morton[j+1]);
offset += count[i];
}
}
template<typename Ty, typename Key>
class ParallelRadixSort
{
static const size_t MAX_TASKS = 512;
static const size_t BITS = 8;
static const size_t BUCKETS = (1 << BITS);
typedef unsigned int TyRadixCount[BUCKETS];
template<typename T>
static bool compare(const T& v0, const T& v1) {
return (Key)v0 < (Key)v1;
}
public:
ParallelRadixSort (Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize)
: radixCount(nullptr), src(src), tmp(tmp), N(N)
{
assert(blockSize > 0);
/* perform single threaded sort for small N */
if (N<=blockSize) // handles also special case of 0!
{
/* do inplace sort inside destination array */
std::sort(src,src+N,compare<Ty>);
}
/* perform parallel sort for large N */
else
{
const size_t numThreads = min((N+blockSize-1)/blockSize,TaskScheduler::threadCount(),size_t(MAX_TASKS));
tbbRadixSort(numThreads);
}
}
private:
void tbbRadixIteration0(const Key shift,
const Ty* __restrict const src,
Ty* __restrict const dst,
const size_t threadIndex, const size_t threadCount)
{
const size_t startID = (threadIndex+0)*N/threadCount;
const size_t endID = (threadIndex+1)*N/threadCount;
/* mask to extract some number of bits */
const Key mask = BUCKETS-1;
/* count how many items go into the buckets */
for (size_t i=0; i<BUCKETS; i++)
radixCount[threadIndex][i] = 0;
/* iterate over src array and count buckets */
unsigned int * __restrict const count = radixCount[threadIndex];
#if defined(__INTEL_COMPILER)
#pragma nounroll
#endif
for (size_t i=startID; i<endID; i++) {
#if defined(__X86_64__)
const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
#else
const Key index = ((Key)src[i] >> shift) & mask;
#endif
count[index]++;
}
}
void tbbRadixIteration1(const Key shift,
const Ty* __restrict const src,
Ty* __restrict const dst,
const size_t threadIndex, const size_t threadCount)
{
const size_t startID = (threadIndex+0)*N/threadCount;
const size_t endID = (threadIndex+1)*N/threadCount;
/* mask to extract some number of bits */
const Key mask = BUCKETS-1;
/* calculate total number of items for each bucket */
__aligned(64) unsigned int total[BUCKETS];
/*
for (size_t i=0; i<BUCKETS; i++)
total[i] = 0;
*/
for (size_t i=0; i<BUCKETS; i+=VSIZEX)
vintx::store(&total[i], zero);
for (size_t i=0; i<threadCount; i++)
{
/*
for (size_t j=0; j<BUCKETS; j++)
total[j] += radixCount[i][j];
*/
for (size_t j=0; j<BUCKETS; j+=VSIZEX)
vintx::store(&total[j], vintx::load(&total[j]) + vintx::load(&radixCount[i][j]));
}
/* calculate start offset of each bucket */
__aligned(64) unsigned int offset[BUCKETS];
offset[0] = 0;
for (size_t i=1; i<BUCKETS; i++)
offset[i] = offset[i-1] + total[i-1];
/* calculate start offset of each bucket for this thread */
for (size_t i=0; i<threadIndex; i++)
{
/*
for (size_t j=0; j<BUCKETS; j++)
offset[j] += radixCount[i][j];
*/
for (size_t j=0; j<BUCKETS; j+=VSIZEX)
vintx::store(&offset[j], vintx::load(&offset[j]) + vintx::load(&radixCount[i][j]));
}
/* copy items into their buckets */
#if defined(__INTEL_COMPILER)
#pragma nounroll
#endif
for (size_t i=startID; i<endID; i++) {
const Ty elt = src[i];
#if defined(__X86_64__)
const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
#else
const size_t index = ((Key)src[i] >> shift) & mask;
#endif
dst[offset[index]++] = elt;
}
}
void tbbRadixIteration(const Key shift, const bool last,
const Ty* __restrict src, Ty* __restrict dst,
const size_t numTasks)
{
affinity_partitioner ap;
parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration0(shift,src,dst,taskIndex,numTasks); },ap);
parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration1(shift,src,dst,taskIndex,numTasks); },ap);
}
void tbbRadixSort(const size_t numTasks)
{
radixCount = (TyRadixCount*) alignedMalloc(MAX_TASKS*sizeof(TyRadixCount));
if (sizeof(Key) == sizeof(uint32_t)) {
tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
tbbRadixIteration(3*BITS,1,tmp,src,numTasks);
}
else if (sizeof(Key) == sizeof(uint64_t))
{
tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
tbbRadixIteration(3*BITS,0,tmp,src,numTasks);
tbbRadixIteration(4*BITS,0,src,tmp,numTasks);
tbbRadixIteration(5*BITS,0,tmp,src,numTasks);
tbbRadixIteration(6*BITS,0,src,tmp,numTasks);
tbbRadixIteration(7*BITS,1,tmp,src,numTasks);
}
alignedFree(radixCount);
radixCount = nullptr;
}
private:
TyRadixCount* radixCount;
Ty* const src;
Ty* const tmp;
const size_t N;
};
template<typename Ty>
void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
{
ParallelRadixSort<Ty,Ty>(src,tmp,N,blockSize);
}
template<typename Ty, typename Key>
void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
{
ParallelRadixSort<Ty,Key>(src,tmp,N,blockSize);
}
template<typename Ty>
void radix_sort_u32(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
radix_sort<Ty,uint32_t>(src,tmp,N,blockSize);
}
template<typename Ty>
void radix_sort_u64(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
radix_sort<Ty,uint64_t>(src,tmp,N,blockSize);
}
}
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,20 +14,23 @@
## limitations under the License. ##
## ======================================================================== ##
set(CTEST_PROJECT_NAME "Embree")
set(CTEST_NIGHTLY_START_TIME "22:00:00 UTC")
set(TEST_MODELS_HASH 01ada7ec1ace15ddba73aaab3f53ac6aac6a0309)
FIND_PATH(COI_INCLUDE_PATH source/COIProcess_source.h /opt/intel/mic/coi/include /usr/include/intel-coi)
FIND_PATH(COI_HOST_LIBRARY_DIR libcoi_host.so /opt/intel/mic/coi/host-linux-release/lib/)
FIND_PATH(COI_DEV_LIBRARY_DIR libcoi_device.so /opt/mpss/*/sysroots/k1om-mpss-linux/usr/lib64/)
IF (NOT CTEST_DROP_SITE)
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "cdash")
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Embree")
set(CTEST_DROP_SITE_CDASH TRUE)
endif()
IF (COI_INCLUDE_PATH AND COI_HOST_LIBRARY_DIR AND COI_DEV_LIBRARY_DIR)
SET(COI_FOUND TRUE)
SET(COI_INCLUDE_PATHS ${COI_INCLUDE_PATH})
SET(COI_HOST_LIBRARIES ${COI_HOST_LIBRARY_DIR}/libcoi_host.so)
SET(COI_DEV_LIBRARIES ${COI_DEV_LIBRARY_DIR}/libcoi_device.so)
ELSE ()
MESSAGE(FATAL_ERROR "COI installation not found")
ENDIF ()
list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning #1478") # deprecated function used
#list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning #10237") # -lcilkrts linked in dynamically, static library not available")
list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "-Wextern-initializer")
MARK_AS_ADVANCED(COI_INCLUDE_PATH)
MARK_AS_ADVANCED(COI_HOST_LIBRARY_DIR)
MARK_AS_ADVANCED(COI_DEV_LIBRARY_DIR)
SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 200000)
SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE 800000)
MARK_AS_ADVANCED(COI_INCLUDE_PATHS)
MARK_AS_ADVANCED(COI_HOST_LIBRARIES)
MARK_AS_ADVANCED(COI_DEV_LIBRARIES)
+44
View File
@@ -0,0 +1,44 @@
## ======================================================================== ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
SET(LIBRARY_PATHS
/usr/lib /usr/local/lib /opt/local/lib)
FIND_PATH(OPENEXR_INCLUDE_DIR ImfHeader.h
/usr/include /usr/include/OpenEXR
/usr/local/include /usr/local/include/OpenEXR
/opt/local/include /opt/local/include/OpenEXR)
FIND_LIBRARY(OPENEXR_HALF_LIBRARY NAMES Half PATHS ${LIBRARY_PATHS})
FIND_LIBRARY(OPENEXR_IEX_LIBRARY NAMES Iex PATHS ${LIBRARY_PATHS})
FIND_LIBRARY(OPENEXR_IMATH_LIBRARY NAMES Imath PATHS ${LIBRARY_PATHS})
FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY NAMES IlmImf PATHS ${LIBRARY_PATHS})
FIND_LIBRARY(OPENEXR_ILMTHREAD_LIBRARY NAMES IlmThread PATHS ${LIBRARY_PATHS})
SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR})
SET(OPENEXR_LIBRARIES ${OPENEXR_HALF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENEXR DEFAULT_MSG OPENEXR_INCLUDE_DIR OPENEXR_HALF_LIBRARY OPENEXR_IEX_LIBRARY OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY OPENEXR_ILMTHREAD_LIBRARY)
MARK_AS_ADVANCED(
OPENEXR_INCLUDE_DIR
OPENEXR_HALF_LIBRARY
OPENEXR_IEX_LIBRARY
OPENEXR_IMATH_LIBRARY
OPENEXR_ILMIMF_LIBRARY
OPENEXR_ILMTHREAD_LIBRARY
)
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,16 +14,13 @@
## limitations under the License. ##
## ======================================================================== ##
ADD_LIBRARY(scenegraph STATIC
xml_parser.cpp
xml_loader.cpp
xml_writer.cpp
obj_loader.cpp
ply_loader.cpp
corona_loader.cpp
texture.cpp
scenegraph.cpp
geometry_creation.cpp)
FIND_PATH( OPENSUBDIV_INCLUDE_DIR NAMES opensubdiv/version.h )
FIND_LIBRARY( OPENSUBDIV_LIBRARY NAMES osdCPU)
TARGET_LINK_LIBRARIES(scenegraph sys math lexers image)
SET_PROPERTY(TARGET scenegraph PROPERTY FOLDER tutorials/common)
SET(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARY} )
SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR} )
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENSUBDIV DEFAULT_MSG OPENSUBDIV_INCLUDE_DIR OPENSUBDIV_LIBRARY)
MARK_AS_ADVANCED(OPENSUBDIV_INCLUDE_DIR OPENSUBDIV_LIBRARY)
+2 -1
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -22,3 +22,4 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(PNG DEFAULT_MSG PNG_INCLUDE_DIR PNG_LIBRARIES)
MARK_AS_ADVANCED(PNG_INCLUDE_DIR)
MARK_AS_ADVANCED(PNG_LIBRARIES)
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,19 +14,14 @@
## limitations under the License. ##
## ======================================================================== ##
ADD_LIBRARY(algorithms OBJECT
parallel_for.cpp
parallel_reduce.cpp
parallel_prefix_sum.cpp
parallel_for_for.cpp
parallel_for_for_prefix_sum.cpp
parallel_partition.cpp
parallel_sort.cpp
parallel_set.cpp
parallel_map.cpp
parallel_filter.cpp
)
SET_PROPERTY(TARGET algorithms PROPERTY FOLDER common)
SET(PTEX_ROOT ${PROJECT_SOURCE_DIR}/ptex CACHE STRING "Root of Ptex installation")
FIND_PATH (PTEX_INCLUDE_DIRS Ptexture.h PATHS ${PTEX_ROOT}/include ${PTEX_ROOT}/src/ptex )
FIND_LIBRARY(PTEX_LIBRARIES Ptex PATHS ${PTEX_ROOT}/lib ${PTEX_ROOT}/build/ptex )
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PTEX DEFAULT_MSG PTEX_INCLUDE_DIRS PTEX_LIBRARIES)
MARK_AS_ADVANCED(PTEX_INCLUDE_DIRS)
MARK_AS_ADVANCED(PTEX_LIBRARIES)
+21 -43
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -15,12 +15,10 @@
## ======================================================================== ##
IF (WIN32)
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h
FIND_PATH(TBB_ROOT include/tbb/task_scheduler_init.h
DOC "Root of TBB installation"
PATHS ${PROJECT_SOURCE_DIR}/tbb "C:/Program Files (x86)/Intel/Composer XE/tbb"
NO_DEFAULT_PATH
)
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h)
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(TBB_ARCH intel64)
@@ -36,10 +34,10 @@ IF (WIN32)
SET(TBB_VCVER vc12)
ENDIF()
SET(TBB_LIBDIR ${EMBREE_TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER})
SET(TBB_BINDIR ${EMBREE_TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER})
SET(TBB_LIBDIR ${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER})
SET(TBB_BINDIR ${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER})
IF (EMBREE_TBB_ROOT STREQUAL "")
IF (TBB_ROOT STREQUAL "")
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h)
FIND_LIBRARY(TBB_LIBRARY tbb)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
@@ -47,53 +45,34 @@ IF (WIN32)
SET(TBB_INCLUDE_DIR TBB_INCLUDE_DIR-NOTFOUND)
SET(TBB_LIBRARY TBB_LIBRARY-NOTFOUND)
SET(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND)
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_LIBDIR} NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_LIBDIR} NO_DEFAULT_PATH)
ENDIF()
ELSE ()
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h
FIND_PATH(TBB_ROOT include/tbb/task_scheduler_init.h
DOC "Root of TBB installation"
PATHS ${PROJECT_SOURCE_DIR}/tbb /opt/intel/tbb
NO_DEFAULT_PATH
PATHS ${PROJECT_SOURCE_DIR}/tbb /opt/intel/composerxe/tbb
)
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h)
IF (EMBREE_TBB_ROOT STREQUAL "")
IF (TBB_ROOT STREQUAL "")
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h)
FIND_LIBRARY(TBB_LIBRARY tbb)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
ELSEIF (EXISTS ${EMBREE_TBB_ROOT}/src)
OPTION(EMBREE_TBB_STATIC_LIB "Build TBB as a static library (building TBB as a static library is NOT recommended)")
if (EMBREE_TBB_STATIC_LIB)
include(${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
tbb_build(TBB_ROOT ${EMBREE_TBB_ROOT} CONFIG_DIR TBB_DIR MAKE_ARGS extra_inc=big_iron.inc)
SET(TBB_INCLUDE_DIR ${EMBREE_TBB_ROOT}/include)
SET(TBB_LIBRARY ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbb.a)
SET(TBB_LIBRARY_MALLOC ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbbmalloc.a)
else()
include(${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
tbb_build(TBB_ROOT ${EMBREE_TBB_ROOT} CONFIG_DIR TBB_DIR)
SET(TBB_INCLUDE_DIR ${EMBREE_TBB_ROOT}/include)
SET(TBB_LIBRARY ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbb.so.2)
SET(TBB_LIBRARY_MALLOC ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbbmalloc.so.2)
endif()
ELSE()
SET(TBB_INCLUDE_DIR TBB_INCLUDE_DIR-NOTFOUND)
SET(TBB_LIBRARY TBB_LIBRARY-NOTFOUND)
SET(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND)
IF (APPLE)
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${EMBREE_TBB_ROOT}/lib NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${EMBREE_TBB_ROOT}/lib NO_DEFAULT_PATH)
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
ELSE()
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4 ${EMBREE_TBB_ROOT}/lib ${EMBREE_TBB_ROOT}/lib64 /usr/libx86_64-linux-gnu/ NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4 ${EMBREE_TBB_ROOT}/lib ${EMBREE_TBB_ROOT}/lib64 /usr/libx86_64-linux-gnu/ NO_DEFAULT_PATH)
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 NO_DEFAULT_PATH)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 NO_DEFAULT_PATH)
ENDIF()
ENDIF()
@@ -116,13 +95,12 @@ MARK_AS_ADVANCED(TBB_LIBRARY_MALLOC)
##############################################################
IF (WIN32)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
INSTALL(PROGRAMS ${TBB_LIBDIR}/tbb.lib ${TBB_LIBDIR}/tbbmalloc.lib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
ELSEIF (EMBREE_ZIP_MODE)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION bin COMPONENT examples)
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION lib COMPONENT lib)
ELSEIF (NOT ENABLE_INSTALLER)
IF (APPLE)
INSTALL(PROGRAMS ${EMBREE_TBB_ROOT}/lib/libtbb.dylib ${EMBREE_TBB_ROOT}/lib/libtbbmalloc.dylib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
INSTALL(PROGRAMS ${TBB_ROOT}/lib/libc++/libtbb.dylib ${TBB_ROOT}/lib/libc++/libtbbmalloc.dylib DESTINATION lib COMPONENT lib)
ELSE()
INSTALL(PROGRAMS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4/libtbb.so.2 ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4/libtbbmalloc.so.2 DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
INSTALL(PROGRAMS ${TBB_ROOT}/lib/intel64/gcc4.4/libtbb.so.2 ${TBB_ROOT}/lib/intel64/gcc4.4/libtbbmalloc.so.2 DESTINATION lib COMPONENT lib)
ENDIF()
ENDIF()
-31
View File
@@ -1,31 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
IF (WIN32 OR APPLE)
return()
ENDIF()
execute_process(COMMAND objdump -C -t ${file} OUTPUT_VARIABLE output)
string(REPLACE "\n" ";" output ${output})
foreach (line ${output})
if ("${line}" MATCHES "O .bss")
if (NOT "${line}" MATCHES "std::__ioinit" AND # this is caused by iostream initialization and is likely also ok
NOT "${line}" MATCHES "\\(\\)::") # this matches a static inside a function which is fine
message(WARNING "\nProblematic global variable in non-SSE code:\n" ${line})
endif()
endif()
endforeach()
-40
View File
@@ -1,40 +0,0 @@
// ======================================================================== //
// Copyright 2017 Kitware, Inc. //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#if \
defined(__AVX512F__) && defined(__AVX512CD__) && \
defined(__AVX512DQ__) && defined(__AVX512BW__) && defined(__AVX512VL__)
char const *info_isa = "ISA" ":" "AVX512SKX";
#elif \
defined(__AVX512F__) && defined(__AVX512CD__) && \
defined(__AVX512ER__) && defined(__AVX512PF__)
char const *info_isa = "ISA" ":" "AVX512KNL";
#elif defined(__AVX2__)
char const *info_isa = "ISA" ":" "AVX2";
#elif defined(__AVX__)
char const *info_isa = "ISA" ":" "AVX";
#elif defined(__SSE4_2__)
char const *info_isa = "ISA" ":" "SSE42";
#else // defined(__SSE2__)
char const *info_isa = "ISA" ":" "SSE2";
#endif
int main(int argc, char **argv)
{
int require = 0;
require += info_isa[argc];
return require;
}
-33
View File
@@ -1,33 +0,0 @@
## ======================================================================== ##
## Copyright 2017 Kitware, Inc. ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
SET(CHECK_ISA_DIR ${CMAKE_CURRENT_LIST_DIR})
FUNCTION(CHECK_ISA_DEFAULT OUTVAR)
SET(ISA_DEFAULT_BIN ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/check_isa_default.bin)
SET(SRC ${CHECK_ISA_DIR}/check_isa.cpp)
TRY_COMPILE(ISA_DEFAULT_COMPILE
${CMAKE_BINARY_DIR}
${SRC}
COPY_FILE ${ISA_DEFAULT_BIN}
)
IF(NOT ISA_DEFAULT_COMPILE)
SET(ISA_DEFAULT "SSE2")
RETURN()
ENDIF()
FILE(STRINGS ${ISA_DEFAULT_BIN} ISA_DEFAULT REGEX "^ISA:")
STRING(REPLACE "ISA:" "" ISA_DEFAULT "${ISA_DEFAULT}")
SET(${OUTVAR} ${ISA_DEFAULT} PARENT_SCOPE)
ENDFUNCTION()
-37
View File
@@ -1,37 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
IF (WIN32 OR APPLE)
return()
ENDIF()
execute_process(COMMAND objdump -d ${file} OUTPUT_VARIABLE output)
string(REPLACE "\n" ";" output ${output})
SET(lastfunc "")
foreach (line ${output})
if ("${line}" MATCHES "^.*<([^>]*)>:$")
SET(lastfunc ${CMAKE_MATCH_1})
endif()
if ("${line}" MATCHES ".*sub[ ]+[$]([^,]*),%rsp.*")
set(bytes ${CMAKE_MATCH_1})
if ("${bytes}" GREATER "4096")
if ("${lastfunc}" MATCHES ".*recurse.*")
message(WARNING "Large stack space requirement: ${lastfunc} size: ${bytes}")
endif()
endif()
endif()
endforeach()
+16 -95
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -21,100 +21,21 @@ SET(FLAGS_SSE41 "-msse4.1")
SET(FLAGS_SSE42 "-msse4.2")
SET(FLAGS_AVX "-mavx")
SET(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
SET(FLAGS_AVX512KNL "-march=knl")
SET(FLAGS_AVX512SKX "-march=skx")
SET(FLAGS_AVX512 "-mavx512")
IF (WIN32)
SET(COMMON_CXX_FLAGS "")
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
# SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -Xclang -fcxx-exceptions") # enable C++ exceptions in Clang
IF (EMBREE_STACK_PROTECTOR)
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
ELSE()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-vectorize") # disable auto vectorization
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-vectorize") # disable auto vectorization
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(SECURE_LINKER_FLAGS "")
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
ENDIF()
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
INCLUDE(msvc_post)
ELSE()
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
SET(CMAKE_CXX_FLAGS "")
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
IF (NOT APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer
IF (EMBREE_STACK_PROTECTOR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enable assertions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configure TBB in debug mode
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations
IF (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
ELSE(APPLE)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
ENDIF(APPLE)
SET(CMAKE_CXX_COMPILER "clang++")
SET(CMAKE_C_COMPILER "clang")
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 -fno-strict-aliasing -Wno-narrowing -Wno-deprecated-register")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3")
SET(CMAKE_EXE_LINKER_FLAGS "")
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
ENDIF()
IF (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 ") # we only use MacOSX 10.7 features
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) # link against C++11 stdlib
ENDIF (APPLE)
-22
View File
@@ -1,22 +0,0 @@
## ======================================================================== ##
## Copyright 2017 Kitware, Inc. ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
SET(FLAGS_SSE2 "-target-cpu=xeon")
SET(FLAGS_SSE42 "-target-cpu=interlagos")
SET(FLAGS_AVX "-target-cpu=sandybridge")
SET(FLAGS_AVX2 "-target-cpu=haswell")
SET(FLAGS_AVX512KNL "-target-cpu=mic-knl")
SET(FLAGS_AVX512SKX "-target-cpu=x86-skylake")
-17
View File
@@ -1,17 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
file(WRITE ${dst} "#include \"${src}\"\n")
-23
View File
@@ -1,23 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
# use default install config
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/embree-config-install.cmake)
# and override path variables to match for build directory
SET(EMBREE_INCLUDE_DIRS @PROJECT_SOURCE_DIR@/include)
SET(EMBREE_LIBRARY @PROJECT_BINARY_DIR@/@EMBREE_LIBRARY_NAME@)
SET(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,6 +14,8 @@
## limitations under the License. ##
## ======================================================================== ##
SET(EMBREE_ISPC_SUPPORT OFF)
INCLUDE(tutorial)
ADD_TUTORIAL(buildbench)
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../libembree.so.@EMBREE_CONFIG_VERSION@)
SET(EMBREE_LIBRARY_XEONPHI ${CMAKE_CURRENT_LIST_DIR}/../../libembree_xeonphi.so.@EMBREE_CONFIG_VERSION@)
MARK_AS_ADVANCED(embree_DIR)
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,7 +14,7 @@
## limitations under the License. ##
## ======================================================================== ##
INCLUDE(tutorial)
ADD_TUTORIAL(viewer_stream)
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../libembree.@EMBREE_CONFIG_VERSION@.dylib)
MARK_AS_ADVANCED(embree_DIR)
+1 -1
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,7 +14,7 @@
## limitations under the License. ##
## ======================================================================== ##
INCLUDE(tutorial)
ADD_TUTORIAL(viewer_anim)
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../embree.lib)
MARK_AS_ADVANCED(embree_DIR)
-59
View File
@@ -1,59 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
SET(EMBREE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/@EMBREE_RELATIV_ROOT_DIR@)
GET_FILENAME_COMPONENT(EMBREE_ROOT_DIR "${EMBREE_ROOT_DIR}" ABSOLUTE)
SET(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_INCLUDEDIR@)
SET(EMBREE_LIBRARY ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_LIBDIR@/@EMBREE_LIBRARY_NAME@)
SET(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
MARK_AS_ADVANCED(embree_DIR)
SET(EMBREE_VERSION @EMBREE_VERSION@)
SET(EMBREE_VERSION_MAJOR @EMBREE_VERSION_MAJOR@)
SET(EMBREE_VERSION_MINOR @EMBREE_VERSION_MINOR@)
SET(EMBREE_VERSION_PATCH @EMBREE_VERSION_PATCH@)
SET(EMBREE_VERSION_NOTE "@EMBREE_VERSION_NOTE@")
SET(EMBREE_MAX_ISA @EMBREE_MAX_ISA@)
SET(EMBREE_ISA_SSE2 @EMBREE_ISA_SSE2@)
SET(EMBREE_ISA_SSE42 @EMBREE_ISA_SSE42@)
SET(EMBREE_ISA_AVX @EMBREE_ISA_AVX@)
SET(EMBREE_ISA_AVX2 @EMBREE_ISA_AVX2@)
SET(EMBREE_ISA_AVX512KNL @EMBREE_ISA_AVX512KNL@)
SET(EMBREE_ISA_AVX512SKX @EMBREE_ISA_AVX512SKX@)
SET(EMBREE_BUILD_TYPE @CMAKE_BUILD_TYPE@)
SET(EMBREE_ISPC_SUPPORT @EMBREE_ISPC_SUPPORT@)
SET(EMBREE_STATIC_LIB @EMBREE_STATIC_LIB@)
SET(EMBREE_TUTORIALS @EMBREE_TUTORIALS@)
SET(EMBREE_RAY_MASK @EMBREE_RAY_MASK@)
SET(EMBREE_STAT_COUNTERS @EMBREE_STAT_COUNTERS@)
SET(EMBREE_BACKFACE_CULLING @EMBREE_BACKFACE_CULLING@)
SET(EMBREE_INTERSECTION_FILTER @EMBREE_INTERSECTION_FILTER@)
SET(EMBREE_INTERSECTION_FILTER_RESTORE @EMBREE_INTERSECTION_FILTER_RESTORE@)
SET(EMBREE_IGNORE_INVALID_RAYS @EMBREE_IGNORE_INVALID_RAYS@)
SET(EMBREE_TASKING_SYSTEM @EMBREE_TASKING_SYSTEM@)
SET(EMBREE_GEOMETRY_TRIANGLES @EMBREE_GEOMETRY_TRIANGLES@)
SET(EMBREE_GEOMETRY_QUADS @EMBREE_GEOMETRY_QUADS@)
SET(EMBREE_GEOMETRY_LINES @EMBREE_GEOMETRY_LINES@)
SET(EMBREE_GEOMETRY_HAIR @EMBREE_GEOMETRY_HAIR@)
SET(EMBREE_GEOMETRY_SUBDIV @EMBREE_GEOMETRY_SUBDIV@)
SET(EMBREE_GEOMETRY_USER @EMBREE_GEOMETRY_USER@)
SET(EMBREE_RAY_PACKETS @EMBREE_RAY_PACKETS@)
+18 -48
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -15,58 +15,28 @@
## ======================================================================== ##
SET(FLAGS_SSE2 "-msse2")
SET(FLAGS_SSE3 "-msse3")
SET(FLAGS_SSSE3 "-mssse3")
SET(FLAGS_SSE41 "-msse4.1")
SET(FLAGS_SSE42 "-msse4.2")
SET(FLAGS_AVX "-mavx")
SET(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
SET(FLAGS_AVX512KNL "-mavx512f -mavx512pf -mavx512er -mavx512cd -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
SET(FLAGS_AVX512SKX "-mavx512f -mavx512dq -mavx512cd -mavx512bw -mavx512vl -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
SET(FLAGS_AVX512 "-mavx512f -mavx512pf -mavx512er -mavx512cd")
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
SET(CMAKE_CXX_FLAGS "")
SET(CMAKE_CXX_COMPILER "g++")
SET(CMAKE_C_COMPILER "gcc")
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 -fno-strict-aliasing -Wno-narrowing")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3")
SET(CMAKE_EXE_LINKER_FLAGS "")
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
IF (NOT APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer
IF (EMBREE_STACK_PROTECTOR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enable assertions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configure TBB in debug mode
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations
IF (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
ELSE(APPLE)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
ENDIF(APPLE)
SET (CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} -dynamiclib)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 -stdlib=libc++")
ENDIF (APPLE)
+25 -134
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,139 +14,30 @@
## limitations under the License. ##
## ======================================================================== ##
IF (WIN32)
SET(FLAGS_SSE2 "-xsse2")
SET(FLAGS_SSE3 "-xsse3")
SET(FLAGS_SSSE3 "-xssse3")
SET(FLAGS_SSE41 "-xsse4.1")
SET(FLAGS_SSE42 "-xsse4.2")
SET(FLAGS_AVX "-xAVX")
SET(FLAGS_AVX2 "-xCORE-AVX2")
SET(FLAGS_AVX512 "-xMIC-AVX512")
SET(FLAGS_SSE2 "/QxSSE2")
SET(FLAGS_SSE42 "/QxSSE4.2")
SET(FLAGS_AVX "/arch:AVX")
SET(FLAGS_AVX2 "/QxCORE-AVX2")
SET(FLAGS_AVX512KNL "/QxMIC-AVX512")
SET(FLAGS_AVX512SKX "/QxCORE-AVX512")
SET(COMMON_CXX_FLAGS "")
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qvec-") # disable auto vectorizer
IF (EMBREE_STACK_PROTECTOR)
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
ELSE()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
ENDIF()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11074 ") # remark #11074: Inlining inhibited by limit max-size
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11075 ") # remark #11075: To get full report use -Qopt-report:4 -Qopt-report-phase ipo
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Qinline-max-total-size-") # no size limit when performing inlining
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Qinline-factor=200") # increase default inline factors by 2x
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Qinline-max-total-size-") # no size limit when performing inlining
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Qinline-factor=200") # increase default inline factors by 2x
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(SECURE_LINKER_FLAGS "")
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
ENDIF()
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4217") # locally defined symbol XXX imported in function YYY (happens as the ISPC API layer uses exported library functions)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4049") # warning LNK4049: locally defined symbol _rtcOccluded1M imported
INCLUDE(msvc_post)
ELSE()
IF (APPLE)
SET(FLAGS_SSE2 "-xssse3") # on MacOSX ICC does not support SSE2
ELSE()
SET(FLAGS_SSE2 "-xsse2")
ENDIF()
SET(FLAGS_SSE42 "-xsse4.2")
SET(FLAGS_AVX "-xAVX")
SET(FLAGS_AVX2 "-xCORE-AVX2")
SET(FLAGS_AVX512KNL "-xMIC-AVX512")
SET(FLAGS_AVX512SKX "-xCORE-AVX512")
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
SET(CMAKE_CXX_FLAGS "")
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
IF (NOT APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
ENDIF()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-ansi-alias") # disables strict aliasing rules
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-vec") # disable auto vectorizer
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fasm-blocks") # enable assembly blocks
IF (EMBREE_STACK_PROTECTOR)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
ENDIF()
IF(NOT CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel") # links intel runtime statically
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-intel-extensions") # disables some intel extensions which cause symbols to be exported
ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enables assertions
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configures TBB in debug mode
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable all optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # full optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -restrict") # enable restrict keyword
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-total-size") # no size limit when performing inlining
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-per-compile") # no maximal number of inlinings per compilation unit
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -inline-factor=200") # increase default inline factors limits by 2x
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enables assertions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configures TBB in debug mode
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -restrict") # enable restrict keyword
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -no-inline-max-total-size") # no size limit when performing inlining
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -no-inline-max-per-compile") # no maximal number of inlinings per compilation unit
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -inline-factor=200") # increase default inline factors by 2x
#SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -debug inline-debug-info")
#SET(CMAKE_EXE_LINKER_FLAGS "-g")
IF (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
ELSE(APPLE)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
ENDIF(APPLE)
SET(CMAKE_CXX_COMPILER "icpc")
SET(CMAKE_C_COMPILER "icc")
SET(CMAKE_CXX_FLAGS "-Wall -fPIC -std=c++11 -no-ansi-alias -static-intel -fasm-blocks")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
## SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -restrict -g -debug inline-debug-info")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -restrict")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3 -restrict")
SET(CMAKE_EXE_LINKER_FLAGS "-g")
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
ENDIF()
IF (APPLE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 ") # we only use MacOSX 10.7 features
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) # link against C++11 stdlib
ENDIF (APPLE)
+27
View File
@@ -0,0 +1,27 @@
## ======================================================================== ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
SET (CMAKE_CXX_COMPILER icpc)
SET (CMAKE_CXX_FLAGS "-mmic -restrict -Wall -wd177 -fasm-blocks -fPIC -std=c++11")
SET (CMAKE_CXX_FLAGS_NOOPT "-g -O0 -DDEBUG")
SET (CMAKE_CXX_FLAGS_DEBUG "-g -w1 -O2 -DDEBUG ")
SET (CMAKE_CXX_FLAGS_RELEASE "-O3 -g -DNDEBUG -fp-model fast -fimf-precision=low -fasm-blocks -no-inline-max-total-size -inline-factor=200 -fPIC -fma -restrict -no-prec-div -no-prec-sqrt -mGLOB_default_function_attrs=\"use_vec_for_imul=on;use_fast_math=on;gather_scatter_loop_jknzd=on;gather_scatter_loop_unroll=2;use_gather_scatter_hint=on;c_sch_nop_insertion=on;c_avoid_movz_and_movs=off;c_avoid_integer_ciscization=on;avoid_long_vector_ints=on;avoid_loads_with_extend=on;smart_mem_conflicts=on\" -mP2OPT_hlo_prefetch=F ")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O3 -DDEBUG -fp-model fast -fimf-precision=low -fasm-blocks -no-inline-max-total-size -inline-factor=200 -fPIC -fma -restrict -no-prec-div -no-prec-sqrt -mGLOB_default_function_attrs=\"use_vec_for_imul=on;use_fast_math=on;gather_scatter_loop_jknzd=on;gather_scatter_loop_unroll=2;use_gather_scatter_hint=on;c_sch_nop_insertion=on;c_avoid_movz_and_movs=off;c_avoid_integer_ciscization=on;avoid_long_vector_ints=on;avoid_loads_with_extend=on;smart_mem_conflicts=on\" -mP2OPT_hlo_prefetch=F ")
SET(CMAKE_LINKER icpc)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
+53 -45
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -23,50 +23,44 @@ MACRO (INCLUDE_DIRECTORIES_ISPC)
SET(ISPC_INCLUDE_DIR ${ISPC_INCLUDE_DIR} ${ARGN})
ENDMACRO ()
IF (EMBREE_ISPC_SUPPORT)
IF (ENABLE_ISPC_SUPPORT)
# ISPC versions to look for, in decending order (newest first)
SET(ISPC_VERSION_WORKING "1.9.1" "1.9.0" "1.8.3" "1.8.2")
LIST(GET ISPC_VERSION_WORKING -1 ISPC_VERSION_REQUIRED)
SET(ISPC_VERSION_REQUIRED "1.8.2")
IF (NOT EMBREE_ISPC_EXECUTABLE)
IF (NOT ISPC_EXECUTABLE)
# try sibling folder as hint for path of ISPC
IF (APPLE)
SET(ISPC_DIR_SUFFIX "osx")
ELSEIF(WIN32)
SET(ISPC_DIR_SUFFIX "windows")
IF (MSVC14)
LIST(APPEND ISPC_DIR_SUFFIX "windows-vs2015")
ELSE()
LIST(APPEND ISPC_DIR_SUFFIX "windows-vs2013")
ENDIF()
ELSE()
SET(ISPC_DIR_SUFFIX "linux")
ENDIF()
FOREACH(ver ${ISPC_VERSION_WORKING})
FOREACH(suffix ${ISPC_DIR_SUFFIX})
LIST(APPEND ISPC_DIR_HINT ${PROJECT_SOURCE_DIR}/../ispc-v${ver}-${suffix})
ENDFOREACH()
ENDFOREACH()
SET(ISPC_DIR_HINT ${PROJECT_SOURCE_DIR}/../ispc-v${ISPC_VERSION_REQUIRED}-${ISPC_DIR_SUFFIX})
FIND_PROGRAM(EMBREE_ISPC_EXECUTABLE ispc PATHS ${ISPC_DIR_HINT} DOC "Path to the ISPC executable.")
IF (NOT EMBREE_ISPC_EXECUTABLE)
MESSAGE(FATAL_ERROR "Intel SPMD Compiler (ISPC) not found. Disable EMBREE_ISPC_SUPPORT or install ISPC.")
FIND_PROGRAM(ISPC_EXECUTABLE ispc PATHS ${ISPC_DIR_HINT} DOC "Path to the ISPC executable.")
IF (NOT ISPC_EXECUTABLE)
MESSAGE(FATAL_ERROR "Intel SPMD Compiler (ISPC) not found. Disable ENABLE_ISPC_SUPPORT or install ISPC.")
ELSE()
MESSAGE(STATUS "Found Intel SPMD Compiler (ISPC): ${EMBREE_ISPC_EXECUTABLE}")
MESSAGE(STATUS "Found Intel SPMD Compiler (ISPC): ${ISPC_EXECUTABLE}")
ENDIF()
ENDIF()
# check ISPC version
EXECUTE_PROCESS(COMMAND ${EMBREE_ISPC_EXECUTABLE} --version OUTPUT_VARIABLE ISPC_OUTPUT)
STRING(REGEX MATCH " ([0-9]+[.][0-9]+[.][0-9]+)(dev|knl)? " DUMMY "${ISPC_OUTPUT}")
SET(ISPC_VERSION ${CMAKE_MATCH_1})
IF(NOT ISPC_VERSION)
EXECUTE_PROCESS(COMMAND ${ISPC_EXECUTABLE} --version OUTPUT_VARIABLE ISPC_OUTPUT)
STRING(REGEX MATCH " ([0-9]+[.][0-9]+[.][0-9]+)(dev|knl)? " DUMMY "${ISPC_OUTPUT}")
SET(ISPC_VERSION ${CMAKE_MATCH_1})
IF (ISPC_VERSION VERSION_LESS ISPC_VERSION_REQUIRED)
MESSAGE(FATAL_ERROR "Need at least version ${ISPC_VERSION_REQUIRED} of Intel SPMD Compiler (ISPC).")
IF (ISPC_VERSION VERSION_LESS ISPC_VERSION_REQUIRED)
MESSAGE(FATAL_ERROR "Need at least version ${ISPC_VERSION_REQUIRED} of Intel SPMD Compiler (ISPC).")
ENDIF()
SET(ISPC_VERSION ${ISPC_VERSION} CACHE STRING "ISPC Version")
MARK_AS_ADVANCED(ISPC_VERSION)
MARK_AS_ADVANCED(ISPC_EXECUTABLE)
ENDIF()
GET_FILENAME_COMPONENT(ISPC_DIR ${EMBREE_ISPC_EXECUTABLE} PATH)
GET_FILENAME_COMPONENT(ISPC_DIR ${ISPC_EXECUTABLE} PATH)
SET(EMBREE_ISPC_ADDRESSING 32 CACHE INT "32vs64 bit addressing in ispc")
MARK_AS_ADVANCED(EMBREE_ISPC_ADDRESSING)
@@ -74,8 +68,14 @@ MARK_AS_ADVANCED(EMBREE_ISPC_ADDRESSING)
MACRO (ISPC_COMPILE)
SET(ISPC_ADDITIONAL_ARGS "")
SET(ISPC_TARGET_EXT ${CMAKE_CXX_OUTPUT_EXTENSION})
STRING(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}")
IF (NOT __XEON__)
SET(ISPC_TARGET_EXT .cpp)
SET(ISPC_TARGET_ARGS generic-16)
SET(ISPC_ADDITIONAL_ARGS ${ISPC_ADDITIONAL_ARGS} --opt=force-aligned-memory --emit-c++ --c++-include-file=${ISPC_DIR}/examples/intrinsics/knc.h -D__XEON_PHI__)
ELSE()
SET(ISPC_TARGET_EXT ${CMAKE_CXX_OUTPUT_EXTENSION})
STRING(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}")
ENDIF()
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(ISPC_ARCHITECTURE "x86-64")
@@ -84,6 +84,7 @@ MACRO (ISPC_COMPILE)
ENDIF()
SET(ISPC_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${ISPC_TARGET_DIR})
IF(ISPC_INCLUDE_DIR)
STRING(REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}")
@@ -127,26 +128,21 @@ MACRO (ISPC_COMPILE)
SET(results "${outdir}/${fname}.dev${ISPC_TARGET_EXT}")
# if we have multiple targets add additional object files
LIST(LENGTH ISPC_TARGETS NUM_TARGETS)
IF (NUM_TARGETS GREATER 1)
FOREACH(target ${ISPC_TARGETS})
# in v1.9.0 ISPC changed the ISA suffix of avx512knl-i32x16 to just 'avx512knl'
IF (${target} STREQUAL "avx512knl-i32x16" AND NOT ISPC_VERSION VERSION_LESS "1.9.0")
SET(target "avx512knl")
ELSEIF (${target} STREQUAL "avx512skx-i32x16")
SET(target "avx512skx")
ENDIF()
SET(results ${results} "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}")
ENDFOREACH()
IF (__XEON__)
LIST(LENGTH ISPC_TARGETS NUM_TARGETS)
IF (NUM_TARGETS GREATER 1)
FOREACH(target ${ISPC_TARGETS})
SET(results ${results} "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}")
ENDFOREACH()
ENDIF()
ENDIF()
ADD_CUSTOM_COMMAND(
OUTPUT ${results} ${ISPC_TARGET_DIR}/${fname}_ispc.h
COMMAND ${CMAKE_COMMAND} -E make_directory ${outdir}
COMMAND ${EMBREE_ISPC_EXECUTABLE}
COMMAND ${ISPC_EXECUTABLE}
-I ${CMAKE_CURRENT_SOURCE_DIR}
${ISPC_INCLUDE_DIR_PARMS}
${ISPC_DEFINITIONS}
--arch=${ISPC_ARCHITECTURE}
--addressing=${EMBREE_ISPC_ADDRESSING}
${ISPC_OPT_FLAGS}
@@ -166,7 +162,7 @@ MACRO (ISPC_COMPILE)
ENDFOREACH()
ENDMACRO()
MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
MACRO (ADD_ISPC_EXECUTABLE name)
SET(ISPC_SOURCES "")
SET(OTHER_SOURCES "")
FOREACH(src ${ARGN})
@@ -179,6 +175,12 @@ MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
ENDFOREACH()
ISPC_COMPILE(${ISPC_SOURCES})
ADD_EXECUTABLE(${name} ${ISPC_OBJECTS} ${OTHER_SOURCES})
IF (NOT __XEON__)
FOREACH(src ${ISPC_OBJECTS})
SET_SOURCE_FILES_PROPERTIES( ${src} PROPERTIES COMPILE_FLAGS -std=gnu++98 )
ENDFOREACH()
ENDIF()
ENDMACRO()
MACRO (ADD_ISPC_LIBRARY name type)
@@ -194,9 +196,15 @@ MACRO (ADD_ISPC_LIBRARY name type)
ENDFOREACH()
ISPC_COMPILE(${ISPC_SOURCES})
ADD_LIBRARY(${name} ${type} ${ISPC_OBJECTS} ${OTHER_SOURCES})
IF (NOT __XEON__)
FOREACH(src ${ISPC_OBJECTS})
SET_SOURCE_FILES_PROPERTIES( ${src} PROPERTIES COMPILE_FLAGS -std=gnu++98 )
ENDFOREACH()
ENDIF()
ENDMACRO()
ELSE (EMBREE_ISPC_SUPPORT)
ELSE (ENABLE_ISPC_SUPPORT)
MACRO (ADD_ISPC_LIBRARY name type)
SET(ISPC_SOURCES "")
@@ -212,4 +220,4 @@ MACRO (ADD_ISPC_LIBRARY name type)
ADD_LIBRARY(${name} ${type} ${OTHER_SOURCES})
ENDMACRO()
ENDIF (EMBREE_ISPC_SUPPORT)
ENDIF (ENABLE_ISPC_SUPPORT)
+30 -40
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,49 +14,39 @@
## limitations under the License. ##
## ======================================================================== ##
SET(FLAGS_SSE2 "/D__SSE__ /D__SSE2__")
SET(FLAGS_SSE42 "${FLAGS_SSE2} /D__SSE3__ /D__SSSE3__ /D__SSE4_1__ /D__SSE4_2__")
SET(FLAGS_AVX "${FLAGS_SSE42} /arch:AVX")
SET(FLAGS_AVX2 "${FLAGS_SSE42} /arch:AVX2")
SET(COMMON_CXX_FLAGS "")
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
IF (EMBREE_STACK_PROTECTOR)
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
# the /QxXXX flags are meant for the Intel Compiler, MSVC ignores them
SET(FLAGS_SSE2 "/QxSSE2")
SET(FLAGS_SSE3 "/QxSSE3")
SET(FLAGS_SSSE3 "/QxSSSE3")
SET(FLAGS_SSE41 "/DCONFIG_SSE41 /QxSSE4.1")
SET(FLAGS_SSE42 "/DCONFIG_SSE42 /QxSSE4.2")
SET(FLAGS_AVX "/arch:AVX /DCONFIG_AVX")
# Intel Compiler 15, Update 1 unfortunately cannot handle /arch:AVX2
IF (COMPILER STREQUAL "ICC") # for scripts/regression.py to work with ICC
SET(FLAGS_AVX2 "/DCONFIG_AVX2 /QxCORE-AVX2")
ELSE()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
SET(FLAGS_AVX2 "/arch:AVX2 /DCONFIG_AVX2 /QxCORE-AVX2")
ENDIF()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} ${FLAGS_SSE2}")
SET(FLAGS_AVX512 "")
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
SET(COMMON_CXX_FLAGS "/EHsc /MP /GR ")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
SET(SECURE_LINKER_FLAGS "")
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:4000000")
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /STACK:4000000")
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG")
# optionally use static runtime library
OPTION(USE_STATIC_RUNTIME "Use the static version of the C/C++ runtime library." ON)
IF (USE_STATIC_RUNTIME)
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
ENDIF()
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4217") # locally defined symbol XXX imported in function YYY (happens as the ISPC API layer uses exported library functions)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4049") # warning LNK4049: locally defined symbol _rtcOccluded1M imported
INCLUDE(msvc_post)
# remove define NDEBUG and instead set define DEBUG for config RelWithDebInfo
STRING(REPLACE "NDEBUG" "DEBUG" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
-26
View File
@@ -1,26 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
# optionally use static runtime library
OPTION(EMBREE_STATIC_RUNTIME "Use the static version of the C/C++ runtime library." ON)
IF (EMBREE_STATIC_RUNTIME)
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
ENDIF()
# remove define NDEBUG and instead set define DEBUG for config RelWithDebInfo
STRING(REPLACE "NDEBUG" "DEBUG" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
+82 -95
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,112 +14,113 @@
## limitations under the License. ##
## ======================================================================== ##
INCLUDE(GNUInstallDirs)
OPTION(ENABLE_INSTALLER "Switches between installer or ZIP file creation for 'make package'" ON)
MARK_AS_ADVANCED(ENABLE_INSTALLER)
if (NOT DEFINED EMBREE_ZIP_MODE)
set(EMBREE_ZIP_MODE OFF)
endif()
IF (NOT EMBREE_ZIP_MODE AND NOT WIN32 AND NOT APPLE)
SET(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}/embree${EMBREE_VERSION_MAJOR})
SET(CMAKE_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_FULL_BINDIR}/embree${EMBREE_VERSION_MAJOR})
IF (ENABLE_INSTALLER AND APPLE)
#SET(CMAKE_MACOSX_RPATH ON)
#SET(CMAKE_SKIP_INSTALL_RPATH OFF)
#SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
#SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
#SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
ELSE()
SET(CMAKE_SKIP_INSTALL_RPATH ON)
ENDIF()
# use full absolute path as install name
IF (NOT EMBREE_ZIP_MODE)
SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
IF (NOT ENABLE_INSTALLER)
SET(DOC_INSTALL_DIR doc)
SET(TUTORIALS_INSTALL_DIR bin)
SET(UTILITIES_INSTALL_DIR bin)
ELSEIF (WIN32)
SET(DOC_INSTALL_DIR doc)
SET(TUTORIALS_INSTALL_DIR bin)
SET(UTILITIES_INSTALL_DIR bin)
ELSEIF (APPLE)
SET(DOC_INSTALL_DIR ../../Applications/Embree2/documentation)
SET(APPLICATION_INSTALL_DIR ../../Applications/Embree2)
SET(TUTORIALS_INSTALL_DIR ../../Applications/Embree2/tutorials)
SET(UTILITIES_INSTALL_DIR ../../Applications/Embree2/tutorials)
ELSE()
IF(APPLE)
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib")
ELSE()
SET(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
ENDIF()
SET(DOC_INSTALL_DIR share/doc/embree-${EMBREE_VERSION})
SET(TUTORIALS_INSTALL_DIR bin/embree-${EMBREE_VERSION})
SET(UTILITIES_INSTALL_DIR bin/embree-${EMBREE_VERSION})
ENDIF()
##############################################################
# Install Headers
##############################################################
INSTALL(DIRECTORY include/embree2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel)
INSTALL(DIRECTORY include/embree2 DESTINATION include COMPONENT devel)
CONFIGURE_FILE(include/embree2/rtcore.h rtcore.h @ONLY)
CONFIGURE_FILE(include/embree2/rtcore.isph rtcore.isph @ONLY)
INSTALL(FILES ${PROJECT_BINARY_DIR}/rtcore.h DESTINATION include/embree2 COMPONENT devel)
INSTALL(FILES ${PROJECT_BINARY_DIR}/rtcore.isph DESTINATION include/embree2 COMPONENT devel)
##############################################################
# Install Models
##############################################################
INSTALL(DIRECTORY tutorials/models DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples)
INSTALL(DIRECTORY tutorials/models DESTINATION "${TUTORIALS_INSTALL_DIR}" COMPONENT examples)
##############################################################
# Install Documentation
##############################################################
INSTALL(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
#FILE(GLOB DOC_FILES ${PROJECT_SOURCE_DIR}/embree-doc/docbin/*)
#INSTALL(FILES ${DOC_FILES} OPTIONAL DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/LICENSE.txt" "LICENSE")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/CHANGELOG.txt" "CHANGELOG")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/README.md" "README.md")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/readme.pdf" "readme.pdf")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/LICENSE.txt" "LICENSE")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/CHANGELOG.txt" "CHANGELOG")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/README.md" "README.md")
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/readme.pdf" "readme.pdf")
# currently CMake does not support solution folders without projects
# SOURCE_GROUP("Documentation" FILES README.md CHANGELOG.md LICENSE.txt readme.pdf)
##############################################################
# Install scripts to set embree paths
##############################################################
IF (EMBREE_ZIP_MODE)
IF (NOT ENABLE_INSTALLER)
IF (WIN32)
ELSEIF(APPLE)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh embree-vars.sh @ONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh embree-vars.csh @ONLY)
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh DESTINATION "." COMPONENT lib)
ELSE()
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh embree-vars.sh @ONLY)
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh embree-vars.csh @ONLY)
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh DESTINATION "." COMPONENT lib)
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh DESTINATION "." COMPONENT lib)
ENDIF()
ENDIF()
##############################################################
# Install Embree CMake Configuration
##############################################################
IF (NOT EMBREE_ZIP_MODE)
IF (ENABLE_INSTALLER)
SET(EMBREE_CONFIG_VERSION ${EMBREE_VERSION})
ELSE()
SET(EMBREE_CONFIG_VERSION ${EMBREE_VERSION_MAJOR})
ENDIF()
IF (APPLE AND NOT EMBREE_ZIP_MODE)
CONFIGURE_FILE(scripts/install_macosx/uninstall.command uninstall.command @ONLY)
INSTALL(PROGRAMS "${PROJECT_BINARY_DIR}/uninstall.command" DESTINATION ${CMAKE_INSTALL_BINDIR}/.. COMPONENT lib)
ENDIF()
# why does this have to be so complicated...
IF (WIN32)
SET(EMBREE_LIBRARY_NAME ${CMAKE_IMPORT_LIBRARY_PREFIX}embree${CMAKE_IMPORT_LIBRARY_SUFFIX})
CONFIGURE_FILE(common/cmake/embree-config-windows.cmake embree-config.cmake @ONLY)
ELSEIF (APPLE)
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree.${EMBREE_CONFIG_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX})
CONFIGURE_FILE(common/cmake/embree-config-macosx.cmake embree-config.cmake @ONLY)
IF (ENABLE_INSTALLER)
CONFIGURE_FILE(scripts/install_macosx/uninstall.command uninstall.command @ONLY)
INSTALL(PROGRAMS "${PROJECT_BINARY_DIR}/uninstall.command" DESTINATION ${APPLICATION_INSTALL_DIR} COMPONENT lib)
ENDIF()
ELSE()
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree${CMAKE_SHARED_LIBRARY_SUFFIX}.${EMBREE_CONFIG_VERSION})
CONFIGURE_FILE(common/cmake/embree-config-linux.cmake embree-config.cmake @ONLY)
ENDIF()
IF (WIN32 OR EMBREE_ZIP_MODE)
# for local "installs" and on Windows we want the cmake config files placed
# in the install root, such that users can point the CMake variable
# embree_DIR just to the install folder
SET(EMBREE_CMAKECONFIG_DIR ".")
SET(EMBREE_RELATIV_ROOT_DIR ".")
ELSE()
SET(EMBREE_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}")
SET(EMBREE_RELATIV_ROOT_DIR "../../..")
ENDIF()
CONFIGURE_FILE(common/cmake/embree-config.cmake embree-config-install.cmake @ONLY)
CONFIGURE_FILE(common/cmake/embree-config-version.cmake embree-config-version.cmake @ONLY)
# create a config file for the build directory
CONFIGURE_FILE(common/cmake/embree-config-builddir.cmake embree-config.cmake @ONLY)
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-install.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} RENAME "embree-config.cmake" COMPONENT devel)
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} COMPONENT devel)
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config.cmake" DESTINATION "lib/cmake/embree-${EMBREE_VERSION}" COMPONENT devel)
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION "lib/cmake/embree-${EMBREE_VERSION}" COMPONENT devel)
##############################################################
# CPack specific stuff
@@ -129,7 +130,6 @@ SET(CPACK_PACKAGE_NAME "Embree")
SET(CPACK_PACKAGE_FILE_NAME "embree-${EMBREE_VERSION}")
#SET(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/embree-doc/images/icon.png)
#SET(CPACK_PACKAGE_RELOCATABLE TRUE)
SET(CPACK_STRIP_FILES TRUE)
SET(CPACK_PACKAGE_VERSION_MAJOR ${EMBREE_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${EMBREE_VERSION_MINOR})
@@ -141,16 +141,23 @@ SET(CPACK_PACKAGE_CONTACT embree_support@intel.com)
SET(CPACK_COMPONENT_LIB_DISPLAY_NAME "Library")
SET(CPACK_COMPONENT_LIB_DESCRIPTION "The Embree library including documentation.")
SET(XEONPHI_DESCRIPTION "For The Intel Xeon Phi coprocessor." )
SET(CPACK_COMPONENT_LIB_XEONPHI_NAME "Xeon Phi Library")
SET(CPACK_COMPONENT_LIB_XEONPHI_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION}\n${XEONPHI_DESCRIPTION}")
SET(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "Development")
SET(CPACK_COMPONENT_DEVEL_DESCRIPTION "Header Files for C and ISPC required to develop applications with Embree.")
SET(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Examples")
SET(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Tutorials demonstrating how to use Embree.")
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_NAME "Xeon Phi Examples")
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_DESCRIPTION "${CPACK_COMPONENT_EXAMPLES_DESCRIPTION}\n${XEONPHI_DESCRIPTION}")
# dependencies between components
SET(CPACK_COMPONENT_DEVEL_DEPENDS lib)
SET(CPACK_COMPONENT_LIB_XEONPHI_DEPENDS lib)
SET(CPACK_COMPONENT_EXAMPLES_DEPENDS lib)
SET(CPACK_COMPONENT_LIB_REQUIRED ON) # always install the libs
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_DEPENDS lib_xeonphi)
# point to readme and license files
SET(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
@@ -170,7 +177,7 @@ IF(WIN32)
ENDIF()
# NSIS specific settings
IF (NOT EMBREE_ZIP_MODE)
IF (ENABLE_INSTALLER)
SET(CPACK_GENERATOR NSIS)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}")
SET(CPACK_COMPONENTS_ALL lib devel examples)
@@ -188,16 +195,10 @@ IF(WIN32)
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\documentation\\\"")
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\tutorials\\\"")
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\"\n")
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CPACK_PACKAGE_FILE_NAME}.exe ${CMAKE_BUILD_TYPE})
ENDIF()
ELSE()
SET(CPACK_GENERATOR ZIP)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.windows")
SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CPACK_PACKAGE_FILE_NAME}.zip ${CMAKE_BUILD_TYPE})
ENDIF()
ENDIF()
# MacOSX specific settings
@@ -206,8 +207,7 @@ ELSEIF(APPLE)
CONFIGURE_FILE(README.md README.txt)
SET(CPACK_RESOURCE_FILE_README ${PROJECT_BINARY_DIR}/README.txt)
IF (NOT EMBREE_ZIP_MODE)
SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
IF (ENABLE_INSTALLER)
SET(CPACK_GENERATOR PackageMaker)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64")
#SET(CPACK_COMPONENTS_ALL lib devel examples)
@@ -215,52 +215,39 @@ ELSEIF(APPLE)
SET(CPACK_PACKAGE_NAME embree-${EMBREE_VERSION})
SET(CPACK_PACKAGE_VENDOR "intel") # creates short name com.intel.embree2.xxx in pkgutil
SET(CPACK_OSX_PACKAGE_VERSION 10.7)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.dmg)
ENDIF()
ELSE()
SET(CPACK_GENERATOR TGZ)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macosx")
SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.tgz)
ENDIF()
ENDIF()
# Linux specific settings
ELSE()
IF (NOT EMBREE_ZIP_MODE)
IF (ENABLE_INSTALLER)
SET(CPACK_GENERATOR RPM)
SET(CPACK_COMPONENTS_ALL devel lib examples)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}.x86_64")
SET(CPACK_COMPONENTS_ALL devel lib examples lib_xeonphi examples_xeonphi)
SET(CPACK_RPM_COMPONENT_INSTALL ON)
SET(CPACK_RPM_FILE_NAME RPM-DEFAULT)
SET(CPACK_RPM_devel_PACKAGE_ARCHITECTURE noarch)
SET(CPACK_RPM_PACKAGE_LICENSE "ASL 2.0") # Apache Software License, Version 2.0
SET(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
SET(CPACK_RPM_CHANGELOG_FILE ${CMAKE_BINARY_DIR}/rpm_changelog.txt) # ChangeLog of the RPM
STRING(TIMESTAMP CHANGELOG_DATE "%a %b %d %Y")
SET(RPM_CHANGELOG "* ${CHANGELOG_DATE} Johannes Günther <johannes.guenther@intel.com> - ${EMBREE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n- First package")
FILE(WRITE ${CPACK_RPM_CHANGELOG_FILE} ${RPM_CHANGELOG})
#SET(CPACK_RPM_CHANGELOG_FILE "") # ChangeLog of the RPM; also CHANGELOG.md is not in the required format
SET(CPACK_RPM_PACKAGE_ARCHITECTURE x86_64)
SET(CPACK_RPM_PACKAGE_URL http://embree.github.io/)
SET(CPACK_RPM_DEFAULT_DIR_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # otherwise cmake directory has wrong 775 permissions
# post install and uninstall scripts
SET(CPACK_RPM_lib_POST_INSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
SET(CPACK_RPM_lib_POST_UNINSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_linux.sh ${EMBREE_ZIP_MODE} ${EMBREE_VERSION})
ENDIF()
SET(CPACK_RPM_lib_xeonphi_POST_INSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
SET(CPACK_RPM_lib_xeonphi_POST_UNINSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
ELSE()
SET(CPACK_GENERATOR TGZ)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.linux")
SET(CPACK_MONOLITHIC_INSTALL 1)
IF (EMBREE_TESTING_PACKAGE)
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_linux.sh ${EMBREE_ZIP_MODE} ${EMBREE_VERSION})
ENDIF()
ENDIF()
ENDIF()
-148
View File
@@ -1,148 +0,0 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
## You may obtain a copy of the License at ##
## ##
## http://www.apache.org/licenses/LICENSE-2.0 ##
## ##
## Unless required by applicable law or agreed to in writing, software ##
## distributed under the License is distributed on an "AS IS" BASIS, ##
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
## See the License for the specific language governing permissions and ##
## limitations under the License. ##
## ======================================================================== ##
IF(NOT BUILD_TESTING)
SET(BUILD_TESTING OFF CACHE BOOL "Build the testing tree.")
ENDIF()
INCLUDE(CTest)
IF (BUILD_TESTING)
CMAKE_HOST_SYSTEM_INFORMATION(RESULT memory QUERY TOTAL_PHYSICAL_MEMORY)
SET(EMBREE_TESTING_MODEL_DIR "${PROJECT_SOURCE_DIR}/models" CACHE PATH "Path to the folder containing the Embree models for regression testing.")
SET(EMBREE_TESTING_INTENSIVE OFF CACHE BOOL "Turns intensive testing on.")
SET(EMBREE_TESTING_MEMCHECK OFF CACHE BOOL "Turns on memory checking for some tests.")
SET(EMBREE_TESTING_BENCHMARK OFF CACHE BOOL "Turns benchmarking on.")
SET(EMBREE_TESTING_BENCHMARK_DATABASE "${PROJECT_BINARY_DIR}" CACHE PATH "Path to database for benchmarking.")
SET(EMBREE_TESTING_PACKAGE OFF CACHE BOOL "Packages release as test.")
SET(EMBREE_TESTING_KLOCWORK OFF CACHE BOOL "Runs Kocwork as test.")
SET(EMBREE_TESTING_SDE OFF CACHE STRING "Uses SDE to run tests for specified CPU.")
SET_PROPERTY(CACHE EMBREE_TESTING_SDE PROPERTY STRINGS OFF pnr nhm wsm snb ivb hsw bdw knl skl skx cnl)
IF( NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-subdiv.txt"
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-win32.txt"
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-x64.txt"
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-large.txt")
MESSAGE(FATAL_ERROR "Invalid Embree testing model repository. Either disable BUILD_TESTING or properly set EMBREE_TESTING_MODEL_DIR.")
ENDIF()
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-subdiv.txt" models_subdiv)
STRING(REGEX REPLACE "\n" ";" models_subdiv "${models_subdiv}")
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-win32.txt" models_small_win32)
STRING(REGEX REPLACE "\n" ";" models_small_win32 "${models_small_win32}")
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-x64.txt" models_small_x64)
STRING(REGEX REPLACE "\n" ";" models_small_x64 "${models_small_x64}")
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-large.txt" models_large)
STRING(REGEX REPLACE "\n" ";" models_large "${models_large}")
IF (EMBREE_TESTING_INTENSIVE)
SET(models ${models_small_x64})
IF (${memory} GREATER 10000)
SET(models ${models} ${models_large})
ENDIF()
ELSE()
SET(models ${models_small_win32})
ENDIF()
IF (WIN32)
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
ELSE()
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
ENDIF()
MACRO (ADD_EMBREE_MODEL_TEST name reference executable args model)
ADD_TEST(NAME ${name}
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
COMMAND python ${PROJECT_SOURCE_DIR}/scripts/invoke_test.py
--name ${name}
--modeldir ${EMBREE_TESTING_MODEL_DIR}
--reference ${reference}
--model ${model}
--sde ${EMBREE_TESTING_SDE}
--execute ${MY_PROJECT_BINARY_DIR}/${executable} ${args})
IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
ADD_TEST(NAME ${name}_ispc
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
COMMAND python ${PROJECT_SOURCE_DIR}/scripts/invoke_test.py
--name ${name}_ispc
--modeldir ${EMBREE_TESTING_MODEL_DIR}
--reference ${reference}
--model ${model}
--sde ${EMBREE_TESTING_SDE}
--execute ${MY_PROJECT_BINARY_DIR}/${executable}_ispc ${args})
ENDIF()
ENDMACRO()
MACRO (ADD_EMBREE_MODELS_TEST name reference executable)
FOREACH (model ${models})
STRING(REGEX REPLACE "/" "_" modelname "${model}")
STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}")
ADD_EMBREE_MODEL_TEST(${name}_${modelname} ${reference}_${modelname} ${executable} "${ARGN}" ${model})
ENDFOREACH()
ENDMACRO()
MACRO (ADD_EMBREE_SUBDIV_MODELS_TEST name reference executable)
FOREACH (model ${models_subdiv})
STRING(REGEX REPLACE "/" "_" modelname "${model}")
STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}")
ADD_EMBREE_MODEL_TEST(${name}_${modelname} ${reference}_${modelname} ${executable} "${ARGN}" ${model})
ENDFOREACH()
ENDMACRO()
IF (EMBREE_TESTING_KLOCWORK)
ADD_TEST(NAME Klocwork WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/klocwork.sh)
SET_TESTS_PROPERTIES(Klocwork PROPERTIES TIMEOUT 2400)
ENDIF()
ELSE()
MACRO (ADD_EMBREE_MODEL_TEST name reference executable args model)
ENDMACRO()
MACRO (ADD_EMBREE_SUBDIV_MODELS_TEST name reference executable)
ENDMACRO()
MACRO (ADD_EMBREE_MODELS_TEST name)
ENDMACRO()
ENDIF()
MACRO (ADD_EMBREE_TEST name)
ADD_EMBREE_MODEL_TEST(${name} ${name} ${name} "" "default")
ENDMACRO()
MACRO (ADD_EMBREE_TEST2 name exe args)
ADD_EMBREE_MODEL_TEST(${name} ${exe} ${exe} "${args}" "default")
ENDMACRO()
IF (EMBREE_TESTING_MEMCHECK)
find_program( EMBREE_MEMORYCHECK_COMMAND valgrind )
set( EMBREE_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=1" )
FUNCTION(ADD_MEMCHECK_TEST name binary)
set(memcheck_command "${EMBREE_MEMORYCHECK_COMMAND} ${EMBREE_MEMORYCHECK_COMMAND_OPTIONS}")
separate_arguments(memcheck_command)
add_test(NAME ${name} COMMAND ${memcheck_command} ${MY_PROJECT_BINARY_DIR}/${binary} ${ARGN})
ENDFUNCTION()
ENDIF()
+35 -13
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -19,20 +19,42 @@
MACRO (ADD_TUTORIAL TUTORIAL_NAME)
ADD_EXECUTABLE(${TUTORIAL_NAME} ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.cpp ${ARGN})
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME} embree tutorial image tutorial_device noise ${ADDITIONAL_LIBRARIES})
SET_PROPERTY(TARGET ${TUTORIAL_NAME} PROPERTY FOLDER tutorials/single)
INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_BINDIR}/${TUTORIAL_NAME}" "${TUTORIAL_NAME}")
IF (__XEON__)
IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
ADD_EMBREE_ISPC_EXECUTABLE(${TUTORIAL_NAME}_ispc ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.ispc)
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_ispc embree tutorial image tutorial_device_ispc noise noise_ispc)
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc PROPERTY FOLDER tutorials/ispc)
INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_BINDIR}/${TUTORIAL_NAME}_ispc" "${TUTORIAL_NAME}_ispc")
ADD_EXECUTABLE(${TUTORIAL_NAME} ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.cpp ${ARGN})
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME} embree tutorial image transport tutorial_device ${ADDITIONAL_LIBRARIES})
SET_PROPERTY(TARGET ${TUTORIAL_NAME} PROPERTY FOLDER tutorials/single)
INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples)
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${TUTORIALS_INSTALL_DIR}/${TUTORIAL_NAME}" "${TUTORIAL_NAME}")
IF (ENABLE_ISPC_SUPPORT AND RTCORE_RAY_PACKETS)
ADD_ISPC_EXECUTABLE(${TUTORIAL_NAME}_ispc ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.ispc)
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_ispc embree tutorial image transport tutorial_device_ispc)
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc PROPERTY FOLDER tutorials/ispc)
INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples)
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${TUTORIALS_INSTALL_DIR}/${TUTORIAL_NAME}_ispc" "${TUTORIAL_NAME}_ispc")
ENDIF()
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} PARENT_SCOPE)
ELSE (__XEON__)
IF (ENABLE_XEON_PHI_SUPPORT)
IF (__HOST__)
ADD_EXECUTABLE(${TUTORIAL_NAME}_xeonphi ${TUTORIAL_NAME}.cpp)
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_xeonphi tutorial image transport_host)
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_xeonphi PROPERTY FOLDER tutorials/xeonphi)
INSTALL(TARGETS ${TUTORIAL_NAME}_xeonphi DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples_xeonphi)
ELSE()
INCLUDE (icc_xeonphi)
ADD_ISPC_EXECUTABLE(${TUTORIAL_NAME}_xeonphi_device ${TUTORIAL_NAME}_device.ispc)
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_xeonphi_device embree_xeonphi transport_device tutorial_xeonphi_device_ispc)
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_xeonphi_device PROPERTY FOLDER tutorials/xeonphi)
INSTALL(TARGETS ${TUTORIAL_NAME}_xeonphi_device DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples_xeonphi)
ENDIF()
ENDIF()
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} PARENT_SCOPE)
ENDIF (__XEON__)
ENDMACRO ()
+13 -4
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,9 +14,18 @@
## limitations under the License. ##
## ======================================================================== ##
ADD_LIBRARY(lexers STATIC
IF (__XEON__)
SET(EXT)
ELSE()
INCLUDE(icc_xeonphi)
SET(EXT _xeonphi)
ENDIF()
ADD_LIBRARY(lexers${EXT} STATIC
stringstream.cpp
tokenstream.cpp
)
TARGET_LINK_LIBRARIES(lexers sys math)
SET_PROPERTY(TARGET lexers PROPERTY FOLDER common)
TARGET_LINK_LIBRARIES(lexers${EXT} sys${EXT})
SET_PROPERTY(TARGET lexers${EXT} PROPERTY FOLDER common)
+5 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -21,7 +21,9 @@
#include "../math/vec2.h"
#include "../math/vec3.h"
#include "../math/col3.h"
#if !defined(__MIC__)
#include "../math/color.h"
#endif
namespace embree
{
@@ -101,12 +103,14 @@ namespace embree
return Col3f(x,y,z);
}
#if !defined(__MIC__)
Color getColor() {
float r = (float)atof(get().c_str());
float g = (float)atof(get().c_str());
float b = (float)atof(get().c_str());
return Color(r,g,b);
}
#endif
private:
Ref<Stream<std::string> > cin;
+45 -42
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -28,25 +28,31 @@
namespace embree
{
class String : public RefCount {
public:
String(std::string str) : str(str) {}
std::string str;
};
/*! stores the location of a stream element in the source */
class ParseLocation
{
public:
ParseLocation () : lineNumber(-1), colNumber(-1), charNumber(-1) {}
ParseLocation (std::shared_ptr<std::string> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t charNumber)
ParseLocation () : fileName(nullptr), lineNumber(-1), colNumber(-1), charNumber(-1) {}
ParseLocation (Ref<String> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t charNumber)
: fileName(fileName), lineNumber(lineNumber), colNumber(colNumber), charNumber(charNumber) {}
std::string str() const
{
std::string str = "unknown";
if (fileName) str = *fileName;
if (lineNumber >= 0) str += " line " + toString(lineNumber);
if (lineNumber >= 0 && colNumber >= 0) str += " character " + toString(colNumber);
if (fileName) str = fileName->str;
if (lineNumber >= 0) str += " line " + std::to_string((long long)lineNumber);
if (lineNumber >= 0 && colNumber >= 0) str += " character " + std::to_string((long long)colNumber);
return str;
}
private:
std::shared_ptr<std::string> fileName; /// name of the file (or stream) the token is from
Ref<String> fileName; /// name of the file (or stream) the token is from
ssize_t lineNumber; /// the line number the token is from
ssize_t colNumber; /// the character number in the current line
ssize_t charNumber; /// the character in the file
@@ -56,33 +62,33 @@ namespace embree
template<typename T> class Stream : public RefCount
{
enum { BUF_SIZE = 1024 };
private:
virtual T next() = 0;
virtual ParseLocation location() = 0;
__forceinline std::pair<T,ParseLocation> nextHelper() {
ParseLocation l = location();
T v = next();
return std::pair<T,ParseLocation>(v,l);
}
__forceinline void push_back(const std::pair<T,ParseLocation>& v) {
if (past+future == BUF_SIZE) pop_front();
size_t end = (start+past+future++)%BUF_SIZE;
buffer[end] = v;
}
__forceinline void pop_front() {
if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
start = (start+1)%BUF_SIZE; past--;
}
__forceinline std::pair<T,ParseLocation> nextHelper() {
ParseLocation l = location();
T v = next();
return std::pair<T,ParseLocation>(v,l);
}
__forceinline void push_back(const std::pair<T,ParseLocation>& v) {
if (past+future == BUF_SIZE) pop_front();
int end = (start+past+future++)%BUF_SIZE;
buffer[end] = v;
}
__forceinline void pop_front() {
if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
start = (start+1)%BUF_SIZE; past--;
}
public:
Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
virtual ~Stream() {}
Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
virtual ~Stream() {}
public:
const ParseLocation& loc() {
if (future == 0) push_back(nextHelper());
return buffer[(start+past)%BUF_SIZE].second;
const ParseLocation& loc() {
if (future == 0) push_back(nextHelper());
return buffer[(start+past)%BUF_SIZE].second;
}
T get() {
if (future == 0) push_back(nextHelper());
@@ -107,13 +113,13 @@ namespace embree
size_t start,past,future;
std::vector<std::pair<T,ParseLocation> > buffer;
};
/*! warps an iostream stream */
class StdStream : public Stream<int>
{
public:
StdStream (std::istream& cin, const std::string& name = "std::stream")
: cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
: cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(new String(name)) {}
~StdStream() {}
ParseLocation location() {
return ParseLocation(name,lineNumber,colNumber,charNumber);
@@ -129,7 +135,7 @@ namespace embree
ssize_t lineNumber; /// the line number the token is from
ssize_t colNumber; /// the character number in the current line
ssize_t charNumber; /// the character in the file
std::shared_ptr<std::string> name; /// name of buffer
Ref<String> name; /// name of buffer
};
/*! creates a stream from a file */
@@ -138,10 +144,10 @@ namespace embree
public:
FileStream (FILE* file, const std::string& name = "file")
: file(file), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
: file(file), lineNumber(1), colNumber(0), charNumber(0), name(new String(name)) {}
FileStream (const FileName& fileName)
: lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(fileName.str())))
: lineNumber(1), colNumber(0), charNumber(0), name(new String(fileName.str()))
{
file = fopen(fileName.c_str(),"r");
if (file == nullptr) THROW_RUNTIME_ERROR("cannot open file " + fileName.str());
@@ -165,7 +171,7 @@ namespace embree
ssize_t lineNumber; /// the line number the token is from
ssize_t colNumber; /// the character number in the current line
ssize_t charNumber; /// the character in the file
std::shared_ptr<std::string> name; /// name of buffer
Ref<String> name; /// name of buffer
};
/*! creates a stream from a string */
@@ -178,7 +184,7 @@ namespace embree
public:
ParseLocation location() {
return ParseLocation(std::shared_ptr<std::string>(),lineNumber,colNumber,charNumber);
return ParseLocation(nullptr,lineNumber,colNumber,charNumber);
}
int next() {
@@ -201,12 +207,9 @@ namespace embree
{
public:
CommandLineStream (int argc, char** argv, const std::string& name = "command line")
: i(0), j(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name)))
: i(0), j(0), charNumber(0), name(new String(name))
{
if (argc > 0) {
for (size_t i=0; argv[0][i] && i<1024; i++) charNumber++;
charNumber++;
}
if (argc > 0) charNumber = strlen(argv[0])+1;
for (ssize_t k=1; k<argc; k++) args.push_back(argv[k]);
}
~CommandLineStream() {}
@@ -224,6 +227,6 @@ namespace embree
size_t i,j;
std::vector<std::string> args;
ssize_t charNumber; /// the character in the file
std::shared_ptr<std::string> name; /// name of buffer
Ref<String> name; /// name of buffer
};
}
+1 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
+1 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
+2 -2
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -30,7 +30,7 @@ namespace embree
ParseLocation location() { return cin->loc(); }
std::string next();
private:
__forceinline bool isSeparator(int c) const { return c <= 256 && isSepMap[c]; }
__forceinline bool isSeparator(int c) const { return isSepMap[c]; }
private:
Ref<Stream<int> > cin; /*! source character stream */
bool isSepMap[256]; /*! map for fast classification of separators */
+1 -5
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -86,10 +86,6 @@ namespace embree
{
bool ok = false;
std::string str;
if (trySymbol("nan")) {
token = Token(float(nan));
return true;
}
if (trySymbol("+inf")) {
token = Token(float(pos_inf));
return true;
+9 -9
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -103,12 +103,12 @@ namespace embree
friend std::ostream& operator<<(std::ostream& cout, const Token& t)
{
if (t.ty == TY_EOF) return cout << "eof";
if (t.ty == TY_CHAR) return cout << "Char(" << t.c << ")";
if (t.ty == TY_INT) return cout << "Int(" << t.i << ")";
if (t.ty == TY_FLOAT) return cout << "Float(" << t.f << ")";
if (t.ty == TY_IDENTIFIER) return cout << "Id(" << t.str << ")";
if (t.ty == TY_STRING) return cout << "String(" << t.str << ")";
if (t.ty == TY_SYMBOL) return cout << "Symbol(" << t.str << ")";
if (t.ty == TY_CHAR) return cout << t.c;
if (t.ty == TY_INT) return cout << t.i;
if (t.ty == TY_FLOAT) return cout << t.f;
if (t.ty == TY_IDENTIFIER) return cout << t.str;
if (t.ty == TY_STRING) return cout << "\"" + t.str + "\"";
if (t.ty == TY_SYMBOL) return cout << t.str;
return cout << "unknown";
}
@@ -160,13 +160,13 @@ namespace embree
std::vector<std::string> symbols;
/*! checks if a character is a separator */
__forceinline bool isSeparator(int c) const { return c<256 && isSepMap[c]; }
__forceinline bool isSeparator(int c) const { return isSepMap[c]; }
/*! checks if a character is a number */
__forceinline bool isDigit(int c) const { return c >= '0' && c <= '9';}
/*! checks if a character is legal for an identifier */
__forceinline bool isAlpha(int c) const { return c<256 && isAlphaMap[c]; }
__forceinline bool isAlpha(int c) const { return isAlphaMap[c]; }
__forceinline bool isAlphaNum(int c) const { return isAlpha(c) || isDigit(c); }
};
}
+10 -33
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -16,7 +16,6 @@
#pragma once
#include "linearspace2.h"
#include "linearspace3.h"
#include "quaternion.h"
#include "bbox.h"
@@ -48,7 +47,7 @@ namespace embree
__forceinline AffineSpaceT( const VectorT& vx, const VectorT& vy, const VectorT& vz, const VectorT& p ) : l(vx,vy,vz), p(p) {}
__forceinline AffineSpaceT( const L& l, const VectorT& p ) : l(l), p(p) {}
template<typename L1> __forceinline AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
template<typename L1> __forceinline explicit AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
////////////////////////////////////////////////////////////////////////////////
// Constants
@@ -58,21 +57,18 @@ namespace embree
__forceinline AffineSpaceT( OneTy ) : l(one), p(zero) {}
/*! return matrix for scaling */
static __forceinline AffineSpaceT scale(const VectorT& s) { return L::scale(s); }
static __forceinline AffineSpaceT scale(const VectorT& s) { return AffineSpaceT(L::scale(s),zero); }
/*! return matrix for translation */
static __forceinline AffineSpaceT translate(const VectorT& p) { return AffineSpaceT(one,p); }
/*! return matrix for rotation, only in 2D */
static __forceinline AffineSpaceT rotate(const ScalarT& r) { return L::rotate(r); }
/*! return matrix for rotation around arbitrary axis */
static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return AffineSpaceT(L::rotate(u,r),zero); }
/*! return matrix for rotation around arbitrary point (2D) or axis (3D) */
static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return L::rotate(u,r); }
/*! return matrix for rotation around arbitrary axis and point, only in 3D */
/*! return matrix for rotation around arbitrary axis and point */
static __forceinline AffineSpaceT rotate(const VectorT& p, const VectorT& u, const ScalarT& r) { return translate(+p) * rotate(u,r) * translate(-p); }
/*! return matrix for looking at given point, only in 3D */
/*! return matrix for looking at given point */
static __forceinline AffineSpaceT lookat(const VectorT& eye, const VectorT& point, const VectorT& up) {
VectorT Z = normalize(point-eye);
VectorT U = normalize(cross(up,Z));
@@ -107,9 +103,9 @@ namespace embree
template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a / b; }
template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a / b; }
template<typename L> __forceinline VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
template<typename L> __forceinline VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
template<typename L> __forceinline VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
template<typename L> __forceinline const VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
template<typename L> __forceinline const VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
template<typename L> __forceinline const VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
__forceinline const BBox<Vec3fa> xfmBounds(const AffineSpaceT<LinearSpace3<Vec3fa> >& m, const BBox<Vec3fa>& b)
{
@@ -132,20 +128,6 @@ namespace embree
template<typename L> __forceinline bool operator ==( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l == b.l && a.p == b.p; }
template<typename L> __forceinline bool operator !=( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l != b.l || a.p != b.p; }
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
template<typename L> __forceinline AffineSpaceT<L> select ( const typename L::Vector::Scalar::Bool& s, const AffineSpaceT<L>& t, const AffineSpaceT<L>& f ) {
return AffineSpaceT<L>(select(s,t.l,f.l),select(s,t.p,f.p));
}
/*! blending */
template<typename T>
__forceinline AffineSpaceT<T> lerp(const AffineSpaceT<T>& l0, const AffineSpaceT<T>& l1, const float t) {
return AffineSpaceT<T>(lerp(l0.l,l1.l,t),lerp(l0.p,l1.p,t));
}
////////////////////////////////////////////////////////////////////////////////
// Output Operators
////////////////////////////////////////////////////////////////////////////////
@@ -158,15 +140,10 @@ namespace embree
// Template Instantiations
////////////////////////////////////////////////////////////////////////////////
typedef AffineSpaceT<LinearSpace2f> AffineSpace2f;
typedef AffineSpaceT<LinearSpace3f> AffineSpace3f;
typedef AffineSpaceT<LinearSpace3fa> AffineSpace3fa;
typedef AffineSpaceT<Quaternion3f > OrthonormalSpace3f;
////////////////////////////////////////////////////////////////////////////////
/*! Template Specialization for 2D: return matrix for rotation around point (rotation around arbitrarty vector is not meaningful in 2D) */
template<> __forceinline AffineSpace2f AffineSpace2f::rotate(const Vec2f& p, const float& r) { return translate(+p) * AffineSpace2f(LinearSpace2f::rotate(r)) * translate(-p); }
#undef VectorT
#undef ScalarT
}
+11 -138
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -44,6 +44,15 @@ namespace embree
__forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
__forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
__forceinline void extend_atomic(const BBox& other) {
atomic_min_f32(&lower.x,other.lower.x);
atomic_min_f32(&lower.y,other.lower.y);
atomic_min_f32(&lower.z,other.lower.z);
atomic_max_f32(&upper.x,other.upper.x);
atomic_max_f32(&upper.y,other.upper.y);
atomic_max_f32(&upper.z,other.upper.z);
}
/*! tests if box is empty */
__forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
@@ -56,11 +65,6 @@ namespace embree
/*! computes twice the center of the box */
__forceinline T center2() const { return lower+upper; }
/*! merges two boxes */
__forceinline static const BBox merge (const BBox& a, const BBox& b) {
return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
@@ -73,10 +77,6 @@ namespace embree
__forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
};
template<> __forceinline bool BBox<float>::empty() const {
return lower > upper;
}
#if defined(__SSE__)
template<> __forceinline bool BBox<Vec3fa>::empty() const {
return !all(le_mask(lower,upper));
@@ -97,8 +97,8 @@ namespace embree
__forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
/*! computes the center of the box */
template<typename T> __forceinline const T center (const BBox<T>& box) { return T(.5f)*(box.lower + box.upper); }
template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
template<typename T> __forceinline const T center (const BBox<T>& box) { return T(0.5f)*center2(box); }
/*! computes the volume of a bounding box */
__forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
@@ -118,10 +118,6 @@ namespace embree
template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
return halfArea(box);
}
/*! merges bounding boxes and points */
template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
@@ -155,16 +151,6 @@ namespace embree
/*! intersect bounding boxes */
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
/*! subtract bounds from each other */
template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
{
c.lower = a.lower;
c.upper = min(a.upper,b.lower);
d.lower = max(a.lower,b.upper);
d.upper = a.upper;
}
/*! tests if bounding boxes (and points) are disjoint (empty intersection) */
template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
@@ -184,126 +170,13 @@ namespace embree
return true;
}
/*! blending */
template<typename T>
__forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
}
/*! output operator */
template<typename T> __forceinline std::ostream& operator<<(std::ostream& cout, const BBox<T>& box) {
return cout << "[" << box.lower << "; " << box.upper << "]";
}
/*! default template instantiations */
typedef BBox<float> BBox1f;
typedef BBox<Vec2f> BBox2f;
typedef BBox<Vec3f> BBox3f;
typedef BBox<Vec3fa> BBox3fa;
}
////////////////////////////////////////////////////////////////////////////////
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
#if defined __SSE__
#include "../simd/sse.h"
#endif
#if defined __AVX__
#include "../simd/avx.h"
#endif
#if defined(__AVX512F__)
#include "../simd/avx512.h"
#endif
namespace embree
{
template<int N>
__forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
template<>
__forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
{
BBox<Vec3<vfloat4>> dest;
transpose((vfloat4&)bounds[0].lower,
(vfloat4&)bounds[1].lower,
(vfloat4&)bounds[2].lower,
(vfloat4&)bounds[3].lower,
dest.lower.x,
dest.lower.y,
dest.lower.z);
transpose((vfloat4&)bounds[0].upper,
(vfloat4&)bounds[1].upper,
(vfloat4&)bounds[2].upper,
(vfloat4&)bounds[3].upper,
dest.upper.x,
dest.upper.y,
dest.upper.z);
return dest;
}
#if defined(__AVX__)
template<>
__forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
{
BBox<Vec3<vfloat8>> dest;
transpose((vfloat4&)bounds[0].lower,
(vfloat4&)bounds[1].lower,
(vfloat4&)bounds[2].lower,
(vfloat4&)bounds[3].lower,
(vfloat4&)bounds[4].lower,
(vfloat4&)bounds[5].lower,
(vfloat4&)bounds[6].lower,
(vfloat4&)bounds[7].lower,
dest.lower.x,
dest.lower.y,
dest.lower.z);
transpose((vfloat4&)bounds[0].upper,
(vfloat4&)bounds[1].upper,
(vfloat4&)bounds[2].upper,
(vfloat4&)bounds[3].upper,
(vfloat4&)bounds[4].upper,
(vfloat4&)bounds[5].upper,
(vfloat4&)bounds[6].upper,
(vfloat4&)bounds[7].upper,
dest.upper.x,
dest.upper.y,
dest.upper.z);
return dest;
}
#endif
template<int N>
__forceinline BBox3fa merge(const BBox3fa* bounds);
template<>
__forceinline BBox3fa merge<4>(const BBox3fa* bounds)
{
const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
min(bounds[2].lower,bounds[3].lower));
const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
max(bounds[2].upper,bounds[3].upper));
return BBox3fa(lower,upper);
}
#if defined(__AVX__)
template<>
__forceinline BBox3fa merge<8>(const BBox3fa* bounds)
{
const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
return BBox3fa(lower,upper);
}
#endif
}
+1 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
+1 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
+17 -23
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -53,8 +53,8 @@ namespace embree
__forceinline Color4 ( const Color4& other ) : m128(other.m128) {}
__forceinline Color4& operator=( const Color4& other ) { m128 = other.m128; return *this; }
__forceinline operator const __m128&() const { return m128; }
__forceinline operator __m128&() { return m128; }
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
////////////////////////////////////////////////////////////////////////////////
/// Set
@@ -64,14 +64,14 @@ namespace embree
__forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = a; }
__forceinline void set(Col3uc& d) const
{
vfloat4 s = clamp(vfloat4(m128))*255.0f;
float4 s = clamp(float4(m128))*255.0f;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
}
__forceinline void set(Col4uc& d) const
{
vfloat4 s = clamp(vfloat4(m128))*255.0f;
float4 s = clamp(float4(m128))*255.0f;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
@@ -115,8 +115,8 @@ namespace embree
__forceinline Color ( const Color4& other ) : m128(other.m128) {}
__forceinline Color& operator=( const Color4& other ) { m128 = other.m128; return *this; }
__forceinline operator const __m128&() const { return m128; }
__forceinline operator __m128&() { return m128; }
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
////////////////////////////////////////////////////////////////////////////////
/// Set
@@ -126,18 +126,18 @@ namespace embree
__forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = 1.0f; }
__forceinline void set(Col3uc& d) const
{
vfloat4 s = clamp(vfloat4(m128))*255.0f;
float4 s = clamp(float4(m128))*255.0f;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
}
__forceinline void set(Col4uc& d) const
{
vfloat4 s = clamp(vfloat4(m128))*255.0f;
float4 s = clamp(float4(m128))*255.0f;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
d.a = 255;
d.a = 1.0f;
}
////////////////////////////////////////////////////////////////////////////////
@@ -163,22 +163,12 @@ namespace embree
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
return _mm_and_ps(a.m128, mask);
}
__forceinline const Color rcp ( const Color& a )
{
#if defined(__AVX512VL__)
const Color r = _mm_rcp14_ps(a.m128);
#else
__forceinline const Color rcp ( const Color& a ) {
const Color r = _mm_rcp_ps(a.m128);
#endif
return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
}
__forceinline const Color rsqrt( const Color& a )
{
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ps(a.m128);
#else
__forceinline const Color rsqrt( const Color& a ) {
__m128 r = _mm_rsqrt_ps(a.m128);
#endif
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
}
__forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); }
@@ -245,7 +235,11 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
/*! computes luminance of a color */
__forceinline float luminance (const Color& a) { return madd(0.212671f,a.r,madd(0.715160f,a.g,0.072169f*a.b)); }
__forceinline float luminance (const Color& a) { return 0.212671f*a.r + 0.715160f*a.g + 0.072169f*a.b; }
__forceinline Color exp (const Color& a) { return Color(exp_ps(a.m128)); }
__forceinline Color log (const Color& a) { return Color(log_ps(a.m128)); }
__forceinline Color pow (const Color& a, const float& b) { return Color(select(float4(a)<=float4(zero),float4(zero),float4(exp_ps(log(a)*b)))); }
/*! output operator */
inline std::ostream& operator<<(std::ostream& cout, const Color& a) {
-40
View File
@@ -1,40 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "constants.h"
namespace embree
{
TrueTy True;
FalseTy False;
ZeroTy zero;
OneTy one;
NegInfTy neg_inf;
PosInfTy inf;
PosInfTy pos_inf;
NaNTy nan;
UlpTy ulp;
PiTy pi;
OneOverPiTy one_over_pi;
TwoPiTy two_pi;
OneOverTwoPiTy one_over_two_pi;
FourPiTy four_pi;
OneOverFourPiTy one_over_four_pi;
StepTy step;
ReverseStepTy reverse_step;
EmptyTy empty;
UndefinedTy undefined;
}
+47 -92
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -32,19 +32,15 @@ namespace embree
/* we consider floating point numbers in that range as valid input numbers */
static float FLT_LARGE = 1.844E18f;
struct TrueTy {
static struct TrueTy {
__forceinline operator bool( ) const { return true; }
};
} True MAYBE_UNUSED;
extern MAYBE_UNUSED TrueTy True;
struct FalseTy {
static struct FalseTy {
__forceinline operator bool( ) const { return false; }
};
extern MAYBE_UNUSED FalseTy False;
} False MAYBE_UNUSED;
struct ZeroTy
static struct ZeroTy
{
__forceinline operator double ( ) const { return 0; }
__forceinline operator float ( ) const { return 0; }
@@ -58,11 +54,9 @@ namespace embree
__forceinline operator unsigned short ( ) const { return 0; }
__forceinline operator char ( ) const { return 0; }
__forceinline operator unsigned char ( ) const { return 0; }
};
} zero MAYBE_UNUSED;
extern MAYBE_UNUSED ZeroTy zero;
struct OneTy
static struct OneTy
{
__forceinline operator double ( ) const { return 1; }
__forceinline operator float ( ) const { return 1; }
@@ -76,11 +70,9 @@ namespace embree
__forceinline operator unsigned short ( ) const { return 1; }
__forceinline operator char ( ) const { return 1; }
__forceinline operator unsigned char ( ) const { return 1; }
};
} one MAYBE_UNUSED;
extern MAYBE_UNUSED OneTy one;
struct NegInfTy
static struct NegInfTy
{
__forceinline operator double ( ) const { return -std::numeric_limits<double>::infinity(); }
__forceinline operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
@@ -95,11 +87,9 @@ namespace embree
__forceinline operator char ( ) const { return std::numeric_limits<char>::min(); }
__forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::min(); }
};
} neg_inf MAYBE_UNUSED;
extern MAYBE_UNUSED NegInfTy neg_inf;
struct PosInfTy
static struct PosInfTy
{
__forceinline operator double ( ) const { return std::numeric_limits<double>::infinity(); }
__forceinline operator float ( ) const { return std::numeric_limits<float>::infinity(); }
@@ -113,97 +103,62 @@ namespace embree
__forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::max(); }
__forceinline operator char ( ) const { return std::numeric_limits<char>::max(); }
__forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::max(); }
};
} inf MAYBE_UNUSED, pos_inf MAYBE_UNUSED;
extern MAYBE_UNUSED PosInfTy inf;
extern MAYBE_UNUSED PosInfTy pos_inf;
struct NaNTy
static struct NaNTy
{
__forceinline operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
__forceinline operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
};
} nan MAYBE_UNUSED;
extern MAYBE_UNUSED NaNTy nan;
struct UlpTy
static struct UlpTy
{
__forceinline operator double( ) const { return std::numeric_limits<double>::epsilon(); }
__forceinline operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
};
} ulp MAYBE_UNUSED;
extern MAYBE_UNUSED UlpTy ulp;
struct PiTy
static struct PiTy
{
__forceinline operator double( ) const { return double(M_PI); }
__forceinline operator float ( ) const { return float(M_PI); }
};
__forceinline operator double( ) const { return M_PI; }
__forceinline operator float ( ) const { return M_PI; }
} pi MAYBE_UNUSED;
extern MAYBE_UNUSED PiTy pi;
struct OneOverPiTy
static struct OneOverPiTy
{
__forceinline operator double( ) const { return double(M_1_PI); }
__forceinline operator float ( ) const { return float(M_1_PI); }
};
__forceinline operator double( ) const { return M_1_PI; }
__forceinline operator float ( ) const { return M_1_PI; }
} one_over_pi MAYBE_UNUSED;
extern MAYBE_UNUSED OneOverPiTy one_over_pi;
struct TwoPiTy
static struct TwoPiTy
{
__forceinline operator double( ) const { return double(2.0*M_PI); }
__forceinline operator float ( ) const { return float(2.0*M_PI); }
};
__forceinline operator double( ) const { return 2.0*M_PI; }
__forceinline operator float ( ) const { return 2.0*M_PI; }
} two_pi MAYBE_UNUSED;
extern MAYBE_UNUSED TwoPiTy two_pi;
struct OneOverTwoPiTy
static struct OneOverTwoPiTy
{
__forceinline operator double( ) const { return double(0.5*M_1_PI); }
__forceinline operator float ( ) const { return float(0.5*M_1_PI); }
};
__forceinline operator double( ) const { return 0.5*M_1_PI; }
__forceinline operator float ( ) const { return 0.5*M_1_PI; }
} one_over_two_pi MAYBE_UNUSED;
extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi;
struct FourPiTy
static struct FourPiTy
{
__forceinline operator double( ) const { return double(4.0*M_PI); }
__forceinline operator float ( ) const { return float(4.0*M_PI); }
};
__forceinline operator double( ) const { return 4.0*M_PI; }
__forceinline operator float ( ) const { return 4.0*M_PI; }
} four_pi MAYBE_UNUSED;
extern MAYBE_UNUSED FourPiTy four_pi;
struct OneOverFourPiTy
static struct OneOverFourPiTy
{
__forceinline operator double( ) const { return double(0.25*M_1_PI); }
__forceinline operator float ( ) const { return float(0.25*M_1_PI); }
};
__forceinline operator double( ) const { return 0.25*M_1_PI; }
__forceinline operator float ( ) const { return 0.25*M_1_PI; }
} one_over_four_pi MAYBE_UNUSED;
extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi;
static struct StepTy {
} step MAYBE_UNUSED;
struct StepTy {
};
static struct EmptyTy {
} empty MAYBE_UNUSED;
extern MAYBE_UNUSED StepTy step;
struct ReverseStepTy {
};
extern MAYBE_UNUSED ReverseStepTy reverse_step;
struct EmptyTy {
};
extern MAYBE_UNUSED EmptyTy empty;
struct FullTy {
};
extern MAYBE_UNUSED FullTy full;
struct UndefinedTy {
};
extern MAYBE_UNUSED UndefinedTy undefined;
static struct FullTy {
} full MAYBE_UNUSED;
}
-231
View File
@@ -1,231 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "bbox.h"
#include "range.h"
namespace embree
{
template<typename T>
__forceinline std::pair<T,T> globalLinear(const std::pair<T,T>& v, const BBox1f& dt)
{
const float rcp_dt_size = float(1.0f)/dt.size();
const T g0 = lerp(v.first,v.second,-dt.lower*rcp_dt_size);
const T g1 = lerp(v.first,v.second,(1.0f-dt.lower)*rcp_dt_size);
return std::make_pair(g0,g1);
}
template<typename T>
struct LBBox
{
public:
__forceinline LBBox () {}
__forceinline LBBox ( const LBBox& other ) {
bounds0 = other.bounds0; bounds1 = other.bounds1;
}
__forceinline LBBox& operator= ( const LBBox& other ) {
bounds0 = other.bounds0; bounds1 = other.bounds1; return *this;
}
__forceinline LBBox (EmptyTy)
: bounds0(EmptyTy()), bounds1(EmptyTy()) {}
__forceinline explicit LBBox ( const BBox<T>& bounds)
: bounds0(bounds), bounds1(bounds) { }
__forceinline LBBox ( const BBox<T>& bounds0, const BBox<T>& bounds1)
: bounds0(bounds0), bounds1(bounds1) { }
LBBox ( const avector<BBox<T>>& bounds )
{
assert(bounds.size());
BBox<T> b0 = bounds.front();
BBox<T> b1 = bounds.back();
for (size_t i=1; i<bounds.size()-1; i++) {
const float f = float(i)/float(bounds.size()-1);
const BBox<T> bt = lerp(b0,b1,f);
const T dlower = min(bounds[i].lower-bt.lower,T(zero));
const T dupper = max(bounds[i].upper-bt.upper,T(zero));
b0.lower += dlower; b1.lower += dlower;
b0.upper += dupper; b1.upper += dupper;
}
bounds0 = b0;
bounds1 = b1;
}
/*! calculates the linear bounds of a primitive for the specified time range */
template<typename BoundsFunc>
__forceinline LBBox(const BoundsFunc& bounds, const BBox1f& time_range, float numTimeSegments)
{
const float lower = time_range.lower*numTimeSegments;
const float upper = time_range.upper*numTimeSegments;
const float ilowerf = floor(lower);
const float iupperf = ceil(upper);
const int ilower = (int)ilowerf;
const int iupper = (int)iupperf;
const BBox<T> blower0 = bounds(ilower);
const BBox<T> bupper1 = bounds(iupper);
if (iupper-ilower == 1) {
bounds0 = lerp(blower0, bupper1, lower-ilowerf);
bounds1 = lerp(bupper1, blower0, iupperf-upper);
return;
}
const BBox<T> blower1 = bounds(ilower+1);
const BBox<T> bupper0 = bounds(iupper-1);
BBox<T> b0 = lerp(blower0, blower1, lower-ilowerf);
BBox<T> b1 = lerp(bupper1, bupper0, iupperf-upper);
for (int i = ilower+1; i < iupper; i++)
{
const float f = (float(i)/numTimeSegments - time_range.lower) / time_range.size();
const BBox<T> bt = lerp(b0, b1, f);
const BBox<T> bi = bounds(i);
const T dlower = min(bi.lower-bt.lower, T(zero));
const T dupper = max(bi.upper-bt.upper, T(zero));
b0.lower += dlower; b1.lower += dlower;
b0.upper += dupper; b1.upper += dupper;
}
bounds0 = b0;
bounds1 = b1;
}
/*! calculates the linear bounds of a primitive for the specified time range */
template<typename BoundsFunc>
__forceinline LBBox(const BoundsFunc& bounds, const range<int>& time_range, int numTimeSegments)
{
const int ilower = time_range.begin();
const int iupper = time_range.end();
BBox<T> b0 = bounds(ilower);
BBox<T> b1 = bounds(iupper);
if (iupper-ilower == 1) {
bounds0 = b0;
bounds1 = b1;
return;
}
for (int i = ilower+1; i<iupper; i++)
{
const float f = float(i - time_range.begin()) / float(time_range.size());
const BBox<T> bt = lerp(b0, b1, f);
const BBox<T> bi = bounds(i);
const T dlower = min(bi.lower-bt.lower, T(zero));
const T dupper = max(bi.upper-bt.upper, T(zero));
b0.lower += dlower; b1.lower += dlower;
b0.upper += dupper; b1.upper += dupper;
}
bounds0 = b0;
bounds1 = b1;
}
public:
__forceinline bool empty() const {
return bounds().empty();
}
__forceinline BBox<T> bounds () const {
return merge(bounds0,bounds1);
}
__forceinline BBox<T> interpolate( const float t ) const {
return lerp(bounds0,bounds1,t);
}
__forceinline LBBox<T> interpolate( const BBox1f& dt ) const {
return LBBox<T>(interpolate(dt.lower),interpolate(dt.upper));
}
__forceinline void extend( const LBBox& other ) {
bounds0.extend(other.bounds0);
bounds1.extend(other.bounds1);
}
__forceinline float expectedHalfArea() const;
__forceinline float expectedHalfArea(const BBox1f& dt) const {
return interpolate(dt).expectedHalfArea();
}
__forceinline float expectedApproxHalfArea() const {
return 0.5f*(halfArea(bounds0) + halfArea(bounds1));
}
/* calculates bounds for [0,1] time range from bounds in dt time range */
__forceinline LBBox global(const BBox1f& dt) const
{
const float rcp_dt_size = 1.0f/dt.size();
const BBox<T> b0 = interpolate(-dt.lower*rcp_dt_size);
const BBox<T> b1 = interpolate((1.0f-dt.lower)*rcp_dt_size);
return LBBox(b0,b1);
}
/*! Comparison Operators */
template<typename TT> friend __forceinline bool operator==( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 == b.bounds0 && a.bounds1 == b.bounds1; }
template<typename TT> friend __forceinline bool operator!=( const LBBox<TT>& a, const LBBox<TT>& b ) { return a.bounds0 != b.bounds0 || a.bounds1 != b.bounds1; }
/*! output operator */
friend __forceinline std::ostream& operator<<(std::ostream& cout, const LBBox& box) {
return cout << "LBBox { " << box.bounds0 << "; " << box.bounds1 << " }";
}
public:
BBox<T> bounds0, bounds1;
};
template<typename T>
__forceinline T expectedArea(const T& a0, const T& a1, const T& b0, const T& b1)
{
const T da = a1-a0;
const T db = b1-b0;
return a0*b0+(a0*db+da*b0)*T(0.5f) + da*db*T(1.0f/3.0f);
}
template<> __forceinline float LBBox<Vec3fa>::expectedHalfArea() const
{
const Vec3fa d0 = bounds0.size();
const Vec3fa d1 = bounds1.size();
return reduce_add(expectedArea(Vec3fa(d0.x,d0.y,d0.z),
Vec3fa(d1.x,d1.y,d1.z),
Vec3fa(d0.y,d0.z,d0.x),
Vec3fa(d1.y,d1.z,d1.x)));
}
template<typename T>
__forceinline float expectedApproxHalfArea(const LBBox<T>& box) {
return box.expectedApproxHalfArea();
}
template<typename T>
__forceinline LBBox<T> merge(const LBBox<T>& a, const LBBox<T>& b) {
return LBBox<T>(merge(a.bounds0, b.bounds0), merge(a.bounds1, b.bounds1));
}
/*! default template instantiations */
typedef LBBox<float> LBBox1f;
typedef LBBox<Vec2f> LBBox2f;
typedef LBBox<Vec3f> LBBox3f;
typedef LBBox<Vec3fa> LBBox3fa;
}
+4 -37
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -34,7 +34,7 @@ namespace embree
__forceinline LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
__forceinline LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
template<typename L1> __forceinline LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
template<typename L1> __forceinline explicit LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
/*! matrix construction from column vectors */
__forceinline LinearSpace2(const Vector& vx, const Vector& vy)
@@ -58,10 +58,10 @@ namespace embree
__forceinline const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
/*! returns first row of matrix */
__forceinline Vector row0() const { return Vector(vx.x,vy.x); }
__forceinline const Vector row0() const { return Vector(vx.x,vy.x); }
/*! returns second row of matrix */
__forceinline Vector row1() const { return Vector(vx.y,vy.y); }
__forceinline const Vector row1() const { return Vector(vx.y,vy.y); }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -76,39 +76,6 @@ namespace embree
0 , s.y);
}
/*! return matrix for rotation */
static __forceinline LinearSpace2 rotate(const Scalar& r) {
Scalar s = sin(r), c = cos(r);
return LinearSpace2(c, -s,
s, c);
}
/*! return closest orthogonal matrix (i.e. a general rotation including reflection) */
LinearSpace2 orthogonal() const
{
LinearSpace2 m = *this;
// mirrored?
Scalar mirror(one);
if (m.det() < Scalar(zero)) {
m.vx = -m.vx;
mirror = -mirror;
}
// rotation
for (int i = 0; i < 99; i++) {
const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
const LinearSpace2 d = m_next - m;
m = m_next;
// norm^2 of difference small enough?
if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
break;
}
// rotation * mirror_x
return LinearSpace2(mirror*m.vx, m.vy);
}
public:
/*! the column vectors of the matrix */
+12 -31
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -35,7 +35,7 @@ namespace embree
__forceinline LinearSpace3 ( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; }
__forceinline LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
template<typename L1> __forceinline LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
template<typename L1> __forceinline explicit LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
/*! matrix construction from column vectors */
__forceinline LinearSpace3(const Vector& vx, const Vector& vy, const Vector& vz)
@@ -66,13 +66,13 @@ namespace embree
__forceinline const LinearSpace3 transposed() const { return LinearSpace3(vx.x,vx.y,vx.z,vy.x,vy.y,vy.z,vz.x,vz.y,vz.z); }
/*! returns first row of matrix */
__forceinline Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
__forceinline const Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
/*! returns second row of matrix */
__forceinline Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
__forceinline const Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
/*! returns third row of matrix */
__forceinline Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
__forceinline const Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -104,15 +104,12 @@ namespace embree
};
/*! compute transposed matrix */
#if !defined(__MIC__)
template<> __forceinline const LinearSpace3<Vec3fa> LinearSpace3<Vec3fa>::transposed() const {
vfloat4 rx,ry,rz; transpose((vfloat4&)vx,(vfloat4&)vy,(vfloat4&)vz,vfloat4(zero),rx,ry,rz);
float4 rx,ry,rz; transpose((float4&)vx,(float4&)vy,(float4&)vz,float4(zero),rx,ry,rz);
return LinearSpace3<Vec3fa>(Vec3fa(rx),Vec3fa(ry),Vec3fa(rz));
}
template<typename T>
__forceinline const LinearSpace3<T> transposed(const LinearSpace3<T>& xfm) {
return xfm.transposed();
}
#endif
////////////////////////////////////////////////////////////////////////////////
// Unary Operators
@@ -125,8 +122,8 @@ namespace embree
/* constructs a coordinate frame form a normalized normal */
template<typename T> __forceinline LinearSpace3<T> frame(const T& N)
{
const T dx0(0,N.z,-N.y);
const T dx1(-N.z,0,N.x);
const T dx0 = cross(T(one,zero,zero),N);
const T dx1 = cross(T(zero,one,zero),N);
const T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
const T dy = normalize(cross(N,dx));
return LinearSpace3<T>(dx,dy,N);
@@ -156,7 +153,7 @@ namespace embree
template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx-b.vx,a.vy-b.vy,a.vz-b.vz); }
template<typename T> __forceinline LinearSpace3<T> operator*(const typename T::Scalar & a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return madd(T(b.x),a.vx,madd(T(b.y),a.vy,T(b.z)*a.vz)); }
template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy + b.z*a.vz; }
template<typename T> __forceinline LinearSpace3<T> operator*(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const typename T::Scalar & b) { return LinearSpace3<T>(a.vx/b, a.vy/b, a.vz/b); }
@@ -176,23 +173,6 @@ namespace embree
template<typename T> __forceinline bool operator ==( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx == b.vx && a.vy == b.vy && a.vz == b.vz; }
template<typename T> __forceinline bool operator !=( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx != b.vx || a.vy != b.vy || a.vz != b.vz; }
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline LinearSpace3<T> select ( const typename T::Scalar::Bool& s, const LinearSpace3<T>& t, const LinearSpace3<T>& f ) {
return LinearSpace3<T>(select(s,t.vx,f.vx),select(s,t.vy,f.vy),select(s,t.vz,f.vz));
}
/*! blending */
template<typename T>
__forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0, const LinearSpace3<T>& l1, const float t)
{
return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
lerp(l0.vy,l1.vy,t),
lerp(l0.vz,l1.vz,t));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
@@ -204,4 +184,5 @@ namespace embree
/*! Shortcuts for common linear spaces. */
typedef LinearSpace3<Vec3f> LinearSpace3f;
typedef LinearSpace3<Vec3fa> LinearSpace3fa;
}
+71 -131
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -17,21 +17,19 @@
#pragma once
#include "../sys/platform.h"
#include "../sys/intrinsics.h"
#include "constants.h"
#include <cmath>
#include <emmintrin.h>
#include <xmmintrin.h>
#include <immintrin.h>
#if defined(__WIN32__)
#if (__MSV_VER <= 1700)
namespace std
{
__forceinline bool isinf ( const float x ) { return _finite(x) == 0; }
__forceinline bool isnan ( const float x ) { return _isnan(x) != 0; }
__forceinline bool isfinite (const float x) { return _finite(x) != 0; }
__forceinline bool isinf ( const float x ) { return !_finite(x); }
__forceinline bool isnan ( const float x ) { return _isnan(x); }
__forceinline bool isfinite (const float x) { return _finite(x); }
}
#endif
#endif
@@ -45,7 +43,7 @@ namespace embree
__forceinline int cast_f2i(float f) {
union { float f; int i; } v; v.f = f; return v.i;
}
__forceinline float cast_i2f(int i) {
union { float f; int i; } v; v.i = i; return v.f;
}
@@ -57,54 +55,43 @@ namespace embree
__forceinline float sign ( const float x ) { return x<0?-1.0f:1.0f; }
__forceinline float sqr ( const float x ) { return x*x; }
__forceinline float rcp ( const float x )
#ifndef __MIC__
__forceinline float rcp ( const float x )
{
const __m128 a = _mm_set_ss(x);
#if defined(__AVX512VL__)
const __m128 r = _mm_rcp14_ss(_mm_set_ss(0.0f),a);
#else
const __m128 r = _mm_rcp_ss(a);
#endif
const __m128 r = _mm_rcp_ps(a);
#if defined(__AVX2__)
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_fnmadd_ss(r, a, _mm_set_ss(2.0f))));
return _mm_cvtss_f32(_mm_mul_ps(r,_mm_fnmadd_ps(r, a, _mm_set_ss(2.0f))));
#else
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
return _mm_cvtss_f32(_mm_mul_ps(r,_mm_sub_ps(_mm_set_ss(2.0f), _mm_mul_ps(r, a))));
#endif
}
__forceinline float signmsk ( const float x ) {
__forceinline float signmsk ( const float x ) {
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
}
__forceinline float xorf( const float x, const float y ) {
__forceinline float xorf( const float x, const float y ) {
return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
}
__forceinline float andf( const float x, const unsigned y ) {
__forceinline float andf( const float x, const unsigned y ) {
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
}
__forceinline float rsqrt( const float x )
{
__forceinline float rsqrt( const float x ) {
const __m128 a = _mm_set_ss(x);
#if defined(__AVX512VL__)
const __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a);
#else
const __m128 r = _mm_rsqrt_ss(a);
#endif
const __m128 c = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r),
_mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
const __m128 r = _mm_rsqrt_ps(a);
const __m128 c = _mm_add_ps(_mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r), _mm_mul_ps(r, r)));
return _mm_cvtss_f32(c);
}
#if defined(__WIN32__) && (__MSC_VER <= 1700)
__forceinline float nextafter(float x, float y) { if ((x<y) == (x>0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); }
__forceinline double nextafter(double x, double y) { return _nextafter(x, y); }
__forceinline int roundf(float f) { return (int)(f + 0.5f); }
#else
__forceinline float nextafter(float x, float y) { return ::nextafterf(x, y); }
__forceinline double nextafter(double x, double y) { return ::nextafter(x, y); }
__forceinline float rcp ( const float x ) { return 1.0f/x; }
__forceinline float signmsk ( const float x ) { return cast_i2f(cast_f2i(x)&0x80000000); }
__forceinline float xorf( const float x, const float y ) { return cast_i2f(cast_f2i(x) ^ cast_f2i(y)); }
__forceinline float andf( const float x, const float y ) { return cast_i2f(cast_f2i(x) & cast_f2i(y)); }
__forceinline float rsqrt( const float x ) { return 1.0f/sqrtf(x); }
#endif
#if !defined(__WIN32__)
__forceinline float abs ( const float x ) { return ::fabsf(x); }
__forceinline float acos ( const float x ) { return ::acosf (x); }
__forceinline float asin ( const float x ) { return ::asinf (x); }
@@ -124,6 +111,7 @@ namespace embree
__forceinline float tanh ( const float x ) { return ::tanhf (x); }
__forceinline float floor( const float x ) { return ::floorf (x); }
__forceinline float ceil ( const float x ) { return ::ceilf (x); }
#endif
__forceinline float frac ( const float x ) { return x-floor(x); }
__forceinline double abs ( const double x ) { return ::fabs(x); }
@@ -151,7 +139,7 @@ namespace embree
__forceinline double ceil ( const double x ) { return ::ceil (x); }
#if defined(__SSE4_1__)
__forceinline float mini(float a, float b) {
__forceinline float mini(float a, float b) {
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
const __m128i ci = _mm_min_epi32(ai,bi);
@@ -160,7 +148,7 @@ namespace embree
#endif
#if defined(__SSE4_1__)
__forceinline float maxi(float a, float b) {
__forceinline float maxi(float a, float b) {
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
const __m128i ci = _mm_max_epi32(ai,bi);
@@ -168,60 +156,31 @@ namespace embree
}
#endif
template<typename T>
__forceinline T twice(const T& a) { return a+a; }
__forceinline int min(int a, int b) { return a<b ? a:b; }
__forceinline unsigned min(unsigned a, unsigned b) { return a<b ? a:b; }
__forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
__forceinline float min(float a, float b) { return a<b ? a:b; }
__forceinline double min(double a, double b) { return a<b ? a:b; }
#if defined(__X86_64__)
__forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
#endif
__forceinline int min(int a, int b) { return a<b ? a:b; }
__forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
__forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
__forceinline float min(float a, float b) { return a<b ? a:b; }
__forceinline double min(double a, double b) { return a<b ? a:b; }
template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d, const T& e) { return min(min(min(a,b),min(c,d)),e); }
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c) { return mini(mini(a,b),c); }
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d) { return mini(mini(a,b),mini(c,d)); }
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d, const T& e) { return mini(mini(mini(a,b),mini(c,d)),e); }
__forceinline int max(int a, int b) { return a<b ? b:a; }
__forceinline unsigned max(unsigned a, unsigned b) { return a<b ? b:a; }
__forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
__forceinline float max(float a, float b) { return a<b ? b:a; }
__forceinline double max(double a, double b) { return a<b ? b:a; }
#if defined(__X86_64__)
__forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
#endif
__forceinline int max(int a, int b) { return a<b ? b:a; }
__forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
__forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
__forceinline float max(float a, float b) { return a<b ? b:a; }
__forceinline double max(double a, double b) { return a<b ? b:a; }
template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d, const T& e) { return max(max(max(a,b),max(c,d)),e); }
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c) { return maxi(maxi(a,b),c); }
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d) { return maxi(maxi(a,b),maxi(c,d)); }
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d, const T& e) { return maxi(maxi(maxi(a,b),maxi(c,d)),e); }
#if defined(__MACOSX__)
__forceinline ssize_t min(ssize_t a, ssize_t b) { return a<b ? a:b; }
__forceinline ssize_t max(ssize_t a, ssize_t b) { return a<b ? b:a; }
#endif
#if defined(__MACOSX__) && !defined(__INTEL_COMPILER)
__forceinline void sincosf(float x, float *sin, float *cos) {
__sincosf(x,sin,cos);
}
#endif
#if defined(__WIN32__) || defined(__FreeBSD__)
__forceinline void sincosf(float x, float *s, float *c) {
*s = sinf(x); *c = cosf(x);
}
#endif
template<typename T> __forceinline T clamp(const T& x, const T& lower = T(zero), const T& upper = T(one)) { return max(min(x,upper),lower); }
template<typename T> __forceinline T clampz(const T& x, const T& upper) { return max(T(zero), min(x,upper)); }
@@ -251,8 +210,8 @@ namespace embree
template<> __forceinline int random() { return int(rand()); }
template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 16); }
#endif
template<> __forceinline float random() { return rand()/float(RAND_MAX); }
template<> __forceinline double random() { return rand()/double(RAND_MAX); }
template<> __forceinline float random() { return random<uint32_t>()/float(RAND_MAX); }
template<> __forceinline double random() { return random<uint32_t>()/double(RAND_MAX); }
#if _WIN32
__forceinline double drand48() {
@@ -269,15 +228,9 @@ namespace embree
__forceinline int select(bool s, int t, int f) { return s ? t : f; }
__forceinline float select(bool s, float t, float f) { return s ? t : f; }
template<typename V>
__forceinline V lerp(const V& v0, const V& v1, const float t) {
return madd(V(1.0f-t),v0,t*v1);
}
template<typename T>
__forceinline T lerp2(const float x0, const float x1, const float x2, const float x3, const T& u, const T& v) {
return madd((1.0f-u),madd((1.0f-v),T(x0),v*T(x2)),u*madd((1.0f-v),T(x1),v*T(x3)));
template<typename T>
__forceinline T lerp2(const float x0, const float x1, const float x2, const float x3,const T &u, const T &v) {
return (1.0f-u)*(1.0f-v)*x0 + u*(1.0f-v)*x1 + (1.0f-u)*v*x2 + u*v*x3;
}
/*! exchange */
@@ -301,60 +254,47 @@ namespace embree
__forceinline T bitInterleave(const T& xin, const T& yin, const T& zin)
{
T x = xin, y = yin, z = zin;
x = (x | (x << 16)) & 0x030000FF;
x = (x | (x << 8)) & 0x0300F00F;
x = (x | (x << 4)) & 0x030C30C3;
x = (x | (x << 2)) & 0x09249249;
y = (y | (y << 16)) & 0x030000FF;
y = (y | (y << 8)) & 0x0300F00F;
y = (y | (y << 4)) & 0x030C30C3;
y = (y | (y << 2)) & 0x09249249;
z = (z | (z << 16)) & 0x030000FF;
z = (z | (z << 8)) & 0x0300F00F;
z = (z | (z << 4)) & 0x030C30C3;
z = (z | (z << 2)) & 0x09249249;
x = (x | (x << 16)) & 0x030000FF;
x = (x | (x << 8)) & 0x0300F00F;
x = (x | (x << 4)) & 0x030C30C3;
x = (x | (x << 2)) & 0x09249249;
y = (y | (y << 16)) & 0x030000FF;
y = (y | (y << 8)) & 0x0300F00F;
y = (y | (y << 4)) & 0x030C30C3;
y = (y | (y << 2)) & 0x09249249;
z = (z | (z << 16)) & 0x030000FF;
z = (z | (z << 8)) & 0x0300F00F;
z = (z | (z << 4)) & 0x030C30C3;
z = (z | (z << 2)) & 0x09249249;
return x | (y << 1) | (z << 2);
}
#if defined(__AVX2__)
template<>
__forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi)
{
const unsigned int xx = pdep(xi,0x49249249 /* 0b01001001001001001001001001001001 */ );
const unsigned int yy = pdep(yi,0x92492492 /* 0b10010010010010010010010010010010 */);
const unsigned int zz = pdep(zi,0x24924924 /* 0b00100100100100100100100100100100 */);
return xx | yy | zz;
}
#endif
/*! bit interleave operation for 64bit data types*/
template<class T>
__forceinline T bitInterleave64(const T& xin, const T& yin, const T& zin){
T x = xin & 0x1fffff;
T y = yin & 0x1fffff;
T z = zin & 0x1fffff;
T x = xin & 0x1fffff;
T y = yin & 0x1fffff;
T z = zin & 0x1fffff;
x = (x | x << 32) & 0x1f00000000ffff;
x = (x | x << 16) & 0x1f0000ff0000ff;
x = (x | x << 8) & 0x100f00f00f00f00f;
x = (x | x << 4) & 0x10c30c30c30c30c3;
x = (x | x << 32) & 0x1f00000000ffff;
x = (x | x << 16) & 0x1f0000ff0000ff;
x = (x | x << 8) & 0x100f00f00f00f00f;
x = (x | x << 4) & 0x10c30c30c30c30c3;
x = (x | x << 2) & 0x1249249249249249;
y = (y | y << 32) & 0x1f00000000ffff;
y = (y | y << 16) & 0x1f0000ff0000ff;
y = (y | y << 8) & 0x100f00f00f00f00f;
y = (y | y << 4) & 0x10c30c30c30c30c3;
y = (y | y << 32) & 0x1f00000000ffff;
y = (y | y << 16) & 0x1f0000ff0000ff;
y = (y | y << 8) & 0x100f00f00f00f00f;
y = (y | y << 4) & 0x10c30c30c30c30c3;
y = (y | y << 2) & 0x1249249249249249;
z = (z | z << 32) & 0x1f00000000ffff;
z = (z | z << 16) & 0x1f0000ff0000ff;
z = (z | z << 8) & 0x100f00f00f00f00f;
z = (z | z << 4) & 0x10c30c30c30c30c3;
z = (z | z << 32) & 0x1f00000000ffff;
z = (z | z << 16) & 0x1f0000ff0000ff;
z = (z | z << 8) & 0x100f00f00f00f00f;
z = (z | z << 4) & 0x10c30c30c30c30c3;
z = (z | z << 2) & 0x1249249249249249;
return x | (y << 1) | (z << 2);
+1 -1
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
+6 -6
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -21,7 +21,7 @@
namespace embree
{
////////////////////////////////////////////////////////////////
// Quaternion Struct
// Quaterion Struct
////////////////////////////////////////////////////////////////
template<typename T>
@@ -33,13 +33,13 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__forceinline QuaternionT () { }
__forceinline QuaternionT ( void ) { }
__forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
__forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
__forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
__forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
__forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
__forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
__forceinline QuaternionT( const T& r, const T& i, const T& j , const T& k ) : r(r), i(i), j(j), k(k) {}
__forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
__inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
@@ -58,7 +58,7 @@ namespace embree
}
/*! returns the rotation axis of the quaternion as a vector */
__forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
__forceinline const Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
public:
T r, i, j, k;
-150
View File
@@ -1,150 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../sys/platform.h"
#include "../math/math.h"
namespace embree
{
template<typename Ty>
struct range
{
__forceinline range() {}
__forceinline range(const Ty& begin)
: _begin(begin), _end(begin+1) {}
__forceinline range(const Ty& begin, const Ty& end)
: _begin(begin), _end(end) {}
__forceinline range(const range& other)
: _begin(other._begin), _end(other._end) {}
template<typename T1>
__forceinline range(const range<T1>& other)
: _begin(Ty(other._begin)), _end(Ty(other._end)) {}
template<typename T1>
__forceinline range& operator =(const range<T1>& other) {
_begin = other._begin;
_end = other._end;
return *this;
}
__forceinline Ty begin() const {
return _begin;
}
__forceinline Ty end() const {
return _end;
}
__forceinline range intersect(const range& r) const {
return range (max(_begin,r._begin),min(_end,r._end));
}
__forceinline Ty size() const {
return _end - _begin;
}
__forceinline bool empty() const {
return _end <= _begin;
}
__forceinline Ty center() const {
return (_begin + _end)/2;
}
__forceinline std::pair<range,range> split() const
{
const Ty _center = center();
return std::make_pair(range(_begin,_center),range(_center,_end));
}
__forceinline void split(range& left_o, range& right_o) const
{
const Ty _center = center();
left_o = range(_begin,_center);
right_o = range(_center,_end);
}
__forceinline friend bool operator< (const range& r0, const range& r1) {
return r0.size() < r1.size();
}
friend std::ostream& operator<<(std::ostream& cout, const range& r) {
return cout << "range [" << r.begin() << ", " << r.end() << "]";
}
Ty _begin, _end;
};
template<typename Ty>
range<Ty> make_range(const Ty& begin, const Ty& end) {
return range<Ty>(begin,end);
}
template<typename Ty>
struct extended_range : public range<Ty>
{
__forceinline extended_range () {}
__forceinline extended_range (const Ty& begin)
: range<Ty>(begin), _ext_end(begin+1) {}
__forceinline extended_range (const Ty& begin, const Ty& end)
: range<Ty>(begin,end), _ext_end(end) {}
__forceinline extended_range (const Ty& begin, const Ty& end, const Ty& ext_end)
: range<Ty>(begin,end), _ext_end(ext_end) {}
__forceinline Ty ext_end() const {
return _ext_end;
}
__forceinline Ty ext_size() const {
return _ext_end - range<Ty>::_begin;
}
__forceinline Ty ext_range_size() const {
return _ext_end - range<Ty>::_end;
}
__forceinline bool has_ext_range() const {
assert(_ext_end >= range<Ty>::_end);
return (_ext_end - range<Ty>::_end) > 0;
}
__forceinline void set_ext_range(const size_t ext_end){
assert(ext_end >= range<Ty>::_end);
_ext_end = ext_end;
}
__forceinline void move_right(const size_t plus){
range<Ty>::_begin += plus;
range<Ty>::_end += plus;
_ext_end += plus;
}
friend std::ostream& operator<<(std::ostream& cout, const extended_range& r) {
return cout << "extended_range [" << r.begin() << ", " << r.end() << " (" << r.ext_end() << ")]";
}
Ty _ext_end;
};
}
+16 -27
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -35,14 +35,14 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec2( ) {}
__forceinline Vec2 ( ) { }
__forceinline explicit Vec2( const T& a ) : x(a), y(a) {}
__forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {}
__forceinline explicit Vec2( const T& x, const T& y ) : x(x), y(y) {}
__forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; }
__forceinline Vec2 ( const Vec2& other ) { x = other.x; y = other.y; }
template<typename T1> __forceinline Vec2( const Vec2<T1>& a ) : x(T(a.x)), y(T(a.y)) {}
template<typename T1> __forceinline Vec2& operator =( const Vec2<T1>& other ) { x = other.x; y = other.y; return *this; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
@@ -66,18 +66,13 @@ namespace embree
template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); }
template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); }
template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); }
template<typename T> __forceinline Vec2<T> frac ( const Vec2<T>& a ) { return Vec2<T>(frac (a.x), frac (a.y)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x + b.x, a.y + b.y); }
template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x + b , a.y + b ); }
template<typename T> __forceinline Vec2<T> operator +( const T& a, const Vec2<T>& b ) { return Vec2<T>(a + b.x, a + b.y); }
template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x - b.x, a.y - b.y); }
template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x - b , a.y - b ); }
template<typename T> __forceinline Vec2<T> operator -( const T& a, const Vec2<T>& b ) { return Vec2<T>(a - b.x, a - b.y); }
template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x * b.x, a.y * b.y); }
template<typename T> __forceinline Vec2<T> operator *( const T& a, const Vec2<T>& b ) { return Vec2<T>(a * b.x, a * b.y); }
template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x * b , a.y * b ); }
@@ -87,20 +82,15 @@ namespace embree
template<typename T> __forceinline Vec2<T> min(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(min(a.x, b.x), min(a.y, b.y)); }
template<typename T> __forceinline Vec2<T> max(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(max(a.x, b.x), max(a.y, b.y)); }
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> madd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a,b.x,c.x), madd(a,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> msub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a,b.x,c.x), msub(a,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> nmadd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y) ); }
template<typename T> __forceinline Vec2<T> nmsub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y) ); }
template<typename T> __forceinline const Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
template<typename T> __forceinline const Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
template<typename T> __forceinline const Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
template<typename T> __forceinline const Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
@@ -135,7 +125,7 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); }
template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); }
@@ -143,7 +133,7 @@ namespace embree
template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-b); }
template<typename T> __forceinline T det ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.y - a.y*b.x; }
template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) );
}
@@ -159,14 +149,13 @@ namespace embree
return Vec2<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y));
}
template<typename T> __forceinline Vec2<T> select ( const typename T::Bool& s, const Vec2<T>& t, const Vec2<T>& f ) {
template<typename T> __forceinline Vec2<T> select ( const typename T::Mask& s, const Vec2<T>& t, const Vec2<T>& f ) {
return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
}
template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
{
const Vec2<T> b = abs(a);
if (b.x > b.y) return 0;
template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
{
if (a.x > a.y) return 0;
else return 1;
}
+73 -101
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -37,12 +37,12 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3( ) {}
__forceinline explicit Vec3( const T& a ) : x(a), y(a), z(a) {}
__forceinline Vec3( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
__forceinline Vec3 ( ) {}
__forceinline explicit Vec3 ( const T& a ) : x(a), y(a), z(a) {}
__forceinline explicit Vec3 ( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
__forceinline Vec3( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
__forceinline Vec3( const Vec3fa& other );
__forceinline Vec3 ( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
__forceinline Vec3 ( const Vec3fa& other );
template<typename T1> __forceinline Vec3( const Vec3<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)) {}
template<typename T1> __forceinline Vec3& operator =(const Vec3<T1>& other) { x = other.x; y = other.y; z = other.z; return *this; }
@@ -71,13 +71,13 @@ namespace embree
template<typename T> __forceinline Vec3<T> rsqrt ( const Vec3<T>& a ) { return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z)); }
template<typename T> __forceinline Vec3<T> sqrt ( const Vec3<T>& a ) { return Vec3<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z)); }
template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
{
return Vec3<T>(select(abs(a.x)<min_rcp_input,T(min_rcp_input),a.x),
select(abs(a.y)<min_rcp_input,T(min_rcp_input),a.y),
select(abs(a.z)<min_rcp_input,T(min_rcp_input),a.z));
}
template<typename T> __forceinline Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
template<typename T> __forceinline const Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
@@ -102,25 +102,20 @@ namespace embree
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
template<typename T> __forceinline Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
template<typename T> __forceinline Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
template<typename T> __forceinline Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
template<typename T> __forceinline Vec3<T> madd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z)); }
template<typename T> __forceinline Vec3<T> msub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z)); }
template<typename T> __forceinline Vec3<T> nmadd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z));}
template<typename T> __forceinline Vec3<T> nmsub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z)); }
template<typename T> __forceinline const Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
template<typename T> __forceinline const Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
template<typename T> __forceinline const Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
template<typename T> __forceinline const Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
template<typename T> __forceinline Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
template<typename T> __forceinline Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
template<typename T> __forceinline Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
template<typename T> __forceinline const Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
template<typename T> __forceinline const Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
template<typename T> __forceinline const Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
template<typename T> __forceinline const Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
template<typename T> __forceinline const Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operators
@@ -156,22 +151,16 @@ namespace embree
return Vec3<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z));
}
template<typename T> __forceinline Vec3<T> select ( const typename T::Bool& s, const Vec3<T>& t, const Vec3<T>& f ) {
template<typename T> __forceinline Vec3<T> select ( const typename T::Mask& s, const Vec3<T>& t, const Vec3<T>& f ) {
return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
}
template<typename T>
__forceinline Vec3<T> lerp(const Vec3<T>& v0, const Vec3<T>& v1, const T& t) {
return madd(Vec3<T>(T(1.0f)-t),v0,t*v1);
}
template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
{
const Vec3<T> b = abs(a);
if (b.x > b.y) {
if (b.x > b.z) return 0; else return 2;
template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
{
if (a.x > a.y) {
if (a.x > a.z) return 0; else return 2;
} else {
if (b.y > b.z) return 1; else return 2;
if (a.y > a.z) return 1; else return 2;
}
}
@@ -192,48 +181,34 @@ namespace embree
template<typename T> __forceinline T dot ( const Vec3<T>& a, const Vec3<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,a.z*b.z)); }
template<typename T> __forceinline T length ( const Vec3<T>& a ) { return sqrt(dot(a,a)); }
template<typename T> __forceinline T rcp_length( const Vec3<T>& a ) { return rsqrt(dot(a,a)); }
template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(dot(a,a)); }
template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); }
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
{
const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
const T bc_x = b.z*c.y, bc_y = b.x*c.z, bc_z = b.y*c.x;
const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
const auto sx = abs(ab_x) < abs(bc_x);
const auto sy = abs(ab_y) < abs(bc_y);
const auto sz = abs(ab_z) < abs(bc_z);
return Vec3<T>(select(sx,cross_ab.x,cross_bc.x),
select(sy,cross_ab.y,cross_bc.y),
select(sz,cross_ab.z,cross_bc.z));
select(sx,cross_ab.y,cross_bc.y),
select(sx,cross_ab.z,cross_bc.z));
}
template<typename T> __forceinline T sum ( const Vec3<T>& a ) { return a.x+a.y+a.z; }
template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
template<typename T> __forceinline T area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
template<typename T> __forceinline Vec3<T> reflect ( const Vec3<T>& V, const Vec3fa& N ) { return 2.0f*dot(V,N)*N-V; }
template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
const T d = dot(a,a); return select(d == T( zero ), a , a*rsqrt(d) );
}
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& P, const Vec3<T>& Q0, const Vec3<T>& Q1)
{
const Vec3<T> N = cross(P-Q0,Q1-Q0);
const Vec3<T> D = Q1-Q0;
return dot(N,N)*rcp(dot(D,D));
}
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& PmQ0, const Vec3<T>& Q1mQ0)
{
const Vec3<T> N = cross(PmQ0,Q1mQ0);
const Vec3<T> D = Q1mQ0;
return dot(N,N)*rcp(dot(D,D));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
@@ -247,9 +222,15 @@ namespace embree
typedef Vec3<float> Vec3f;
}
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
#if defined(__MIC__)
#include "vec3ba_mic.h"
#include "vec3ia_mic.h"
#include "vec3fa_mic.h"
#else
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
#endif
////////////////////////////////////////////////////////////////////////////////
/// SSE / AVX / MIC specializations
@@ -263,77 +244,68 @@ namespace embree
#include "../simd/avx.h"
#endif
#if defined(__AVX512F__)
#if defined (__MIC__) || defined(__AVX512F__)
#include "../simd/avx512.h"
#endif
namespace embree
{
namespace embree
{
template<typename Out, typename In>
__forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
return Vec3<Out>(Out(a.x[k]), Out(a.y[k]), Out(a.z[k]));
__forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
return Vec3<Out>(Out(a.x[k]),Out(a.y[k]),Out(a.z[k]));
}
template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
template<> __forceinline Vec3<float>::Vec3( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; }
#if defined(__AVX__)
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
x = a.x; y = a.y; z = a.z;
#if defined (__SSE__)
template<> __forceinline Vec3<float4>::Vec3( const Vec3fa& a ) {
const float4 v = float4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
}
#elif defined(__SSE__)
template<>
__forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
const vfloat4 v = vfloat4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
}
#endif
#if defined(__SSE__)
__forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat4>& a, const size_t k) {
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
__forceinline Vec3<float4> broadcast4f( const Vec3<float4>& a, const size_t k ) {
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
}
template<>
__forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
__forceinline Vec3<float4> broadcast<float4,float4>( const Vec3<float4>& a, const size_t k ) {
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
}
template<int i0, int i1, int i2, int i3>
__forceinline Vec3<vfloat4> shuffle(const Vec3<vfloat4>& b) {
return Vec3<vfloat4>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const Vec3<float4> shuffle( const Vec3<float4>& b ) {
return Vec3<float4>(shuffle<i0,i1,i2,i3>(b.x),shuffle<i0,i1,i2,i3>(b.y),shuffle<i0,i1,i2,i3>(b.z));
}
#endif
#if defined(__AVX__)
template<>
__forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
x = a.x; y = a.y; z = a.z;
template<> __forceinline Vec3<float8>::Vec3( const Vec3fa& a ) {
x = a.x; y = a.y; z = a.z;
}
__forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat8>& a, const size_t k) {
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
__forceinline Vec3<float4> broadcast4f( const Vec3<float8>& a, const size_t k ) {
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
}
__forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat4>& a, const size_t k) {
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
__forceinline Vec3<float8> broadcast8f( const Vec3<float4>& a, const size_t k ) {
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
}
__forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat8>& a, const size_t k) {
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
__forceinline Vec3<float8> broadcast8f( const Vec3<float8>& a, const size_t k ) {
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
}
template<>
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
__forceinline Vec3<float8> broadcast<float8,float4>( const Vec3<float4>& a, const size_t k ) {
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
}
template<>
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat8>(const Vec3<vfloat8>& a, const size_t k) {
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
__forceinline Vec3<float8> broadcast<float8,float8>( const Vec3<float8>& a, const size_t k ) {
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
}
template<int i0, int i1, int i2, int i3>
__forceinline Vec3<vfloat8> shuffle(const Vec3<vfloat8>& b) {
return Vec3<vfloat8>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const Vec3<float8> shuffle( const Vec3<float8>& b ) {
return Vec3<float8>(shuffle<i0,i1,i2,i3>(b.x),shuffle<i0,i1,i2,i3>(b.y),shuffle<i0,i1,i2,i3>(b.z));
}
#endif
#if defined(__AVX512F__)
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
#if defined (__MIC__) || defined(__AVX512F__)
template<> __forceinline Vec3<float16>::Vec3( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z) {}
#endif
}
+12 -15
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -16,7 +16,6 @@
#pragma once
#include "../sys/alloc.h"
#include "math.h"
#include "../simd/sse.h"
@@ -28,8 +27,6 @@ namespace embree
struct __aligned(16) Vec3ba
{
ALIGNED_STRUCT;
union {
__m128 m128;
struct { int x,y,z; int a; };
@@ -47,13 +44,13 @@ namespace embree
__forceinline Vec3ba( const Vec3ba& other ) : m128(other.m128) {}
__forceinline Vec3ba& operator =(const Vec3ba& other) { m128 = other.m128; return *this; }
__forceinline explicit Vec3ba( bool a )
__forceinline explicit Vec3ba ( bool a )
: m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
__forceinline Vec3ba( bool a, bool b, bool c)
__forceinline explicit Vec3ba ( bool a, bool b, bool c)
: m128(_mm_lookupmask_ps[(size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline operator const __m128&() const { return m128; }
__forceinline operator __m128&() { return m128; }
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -75,23 +72,23 @@ namespace embree
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
__forceinline const Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
__forceinline Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
__forceinline Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
__forceinline const Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
__forceinline const Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
__forceinline const Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ba& operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
__forceinline Vec3ba& operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
__forceinline Vec3ba& operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
__forceinline const Vec3ba operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
__forceinline const Vec3ba operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
__forceinline const Vec3ba operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
+118
View File
@@ -0,0 +1,118 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "math.h"
#include "../simd/avx512.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// MIC Vec3ba Type
////////////////////////////////////////////////////////////////////////////////
/*! 3-wide bool type emulated with 16-wide bit vectors. */
struct Vec3ba
{
enum { N = 3 };
__mmask16 v;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ba( ) {}
__forceinline Vec3ba ( const __mmask16 a ) : v(a) {}
__forceinline Vec3ba ( const Vec3ba& a ) : v(a.v) {}
__forceinline Vec3ba& operator =(const Vec3ba& a) { v = a.v; return *this; }
__forceinline explicit Vec3ba ( bool x ) : v(x ? 0xF : 0x0) {}
__forceinline explicit Vec3ba ( bool x, bool y, bool z ) : v(1*__mmask16(x)+2*__mmask16(y)+4*__mmask16(z)) {}
__forceinline operator const __mmask16&( void ) const { return v; }
__forceinline operator __mmask16&( void ) { return v; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ba( FalseTy ) : v(0x0) {}
__forceinline Vec3ba( TrueTy ) : v(0xF) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator []( const size_t index ) const { assert(index < 3); return (v >> index) & 1; }
//__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ba operator !( const Vec3ba& a ) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kand(a.v, b.v); }
__forceinline const Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kor (a.v, b.v); }
__forceinline const Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxor(a.v, b.v); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ba operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
__forceinline const Vec3ba operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
__forceinline const Vec3ba operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator ==( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxnor(a, b); }
__forceinline bool operator !=( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxor (a, b); }
__forceinline bool operator < ( const Vec3ba& a, const Vec3ba& b ) {
if (a[0] != b[0]) return a[0] < b[0];
if (a[1] != b[1]) return a[1] < b[1];
if (a[2] != b[2]) return a[2] < b[2];
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const Vec3ba& a ) { return (a.v & 0x7) == 0x7; }
__forceinline bool reduce_or ( const Vec3ba& a ) { return (a.v & 0x7) != 0x0; }
__forceinline int all(const Vec3ba& a) { return (a.v & 0x7) == 0x7; }
__forceinline int any(const Vec3ba& a) { return (a.v & 0x7) != 0x0; }
__forceinline int none(const Vec3ba& a) { return (a.v & 0x7) == 0x0; }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const Vec3ba& a) {
return cout << "(" << (a[0] ? "1" : "0") << ", " << (a[1] ? "1" : "0") << ", " << (a[2] ? "1" : "0") << ")";
}
}
+81 -115
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -16,7 +16,6 @@
#pragma once
#include "../sys/alloc.h"
#include "math.h"
#include "../simd/sse.h"
@@ -28,8 +27,6 @@ namespace embree
struct __aligned(16) Vec3fa
{
ALIGNED_STRUCT;
typedef float Scalar;
enum { N = 3 };
union {
@@ -52,40 +49,40 @@ namespace embree
__forceinline Vec3fa& operator =( const Vec3fa& other ) { m128 = other.m128; return *this; }
__forceinline explicit Vec3fa( const float a ) : m128(_mm_set1_ps(a)) {}
__forceinline Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(z, z, y, x)) {}
__forceinline explicit Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(z, z, y, x)) {}
__forceinline Vec3fa( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
__forceinline Vec3fa( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
__forceinline Vec3fa( const Vec3fa& other, const float w1) { m128 = other.m128; w = w1; }
//__forceinline Vec3fa( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
//__forceinline Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
__forceinline Vec3fa( const float x, const float y, const float z, const float w) : m128(_mm_set_ps(w, z, y, x)) {}
__forceinline explicit Vec3fa( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
__forceinline explicit Vec3fa( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
__forceinline explicit Vec3fa( const Vec3fa& other, const float w1) { m128 = other.m128; w = w1; }
//__forceinline explicit Vec3fa( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
//__forceinline explicit Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
__forceinline explicit Vec3fa( const float x, const float y, const float z, const float w) : x(x), y(y), z(z), w(w) {}
__forceinline explicit Vec3fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
__forceinline operator const __m128&() const { return m128; }
__forceinline operator __m128&() { return m128; }
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
#if defined (__SSE4_1__)
friend __forceinline Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { return _mm_insert_ps(a, b, (3 << 4) | (3 << 6)); }
friend __forceinline const Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { return _mm_insert_ps(a, b, (3 << 4) | (3 << 6)); }
#else
friend __forceinline Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { Vec3fa c = a; c.a = b.a; return c; }
friend __forceinline const Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { Vec3fa c = a; c.a = b.a; return c; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
static __forceinline Vec3fa load( const void* const a ) {
return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
}
static __forceinline Vec3fa load( const void* const a ) {
return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
}
static __forceinline Vec3fa loadu( const void* const a ) {
return Vec3fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
}
static __forceinline Vec3fa loadu( const void* const a ) {
return Vec3fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
}
static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
_mm_storeu_ps((float*)ptr,v);
static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
_mm_storeu_ps((float*)ptr,v);
}
////////////////////////////////////////////////////////////////////////////////
@@ -104,66 +101,50 @@ namespace embree
__forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
__forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
__forceinline Vec3fa operator -( const Vec3fa& a ) {
__forceinline const Vec3fa operator +( const Vec3fa& a ) { return a; }
__forceinline const Vec3fa operator -( const Vec3fa& a ) {
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
return _mm_xor_ps(a.m128, mask);
}
__forceinline Vec3fa abs ( const Vec3fa& a ) {
__forceinline const Vec3fa abs ( const Vec3fa& a ) {
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
return _mm_and_ps(a.m128, mask);
}
__forceinline Vec3fa sign ( const Vec3fa& a ) {
return blendv_ps(Vec3fa(one), -Vec3fa(one), _mm_cmplt_ps (a,Vec3fa(zero)));
__forceinline const Vec3fa sign ( const Vec3fa& a ) {
return blendv_ps(Vec3fa(one), -Vec3fa(one), _mm_cmplt_ps (a,Vec3fa(zero)));
}
__forceinline Vec3fa rcp ( const Vec3fa& a )
{
#if defined(__AVX512VL__)
const Vec3fa r = _mm_rcp14_ps(a.m128);
#else
__forceinline const Vec3fa rcp ( const Vec3fa& a ) {
const Vec3fa r = _mm_rcp_ps(a.m128);
#endif
#if defined(__AVX2__)
const Vec3fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
const Vec3fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, float4(2.0f)));
#else
const Vec3fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
const Vec3fa res = _mm_mul_ps(r,_mm_sub_ps(float4(2.0f), _mm_mul_ps(r, a)));
//return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
#endif
return res;
}
__forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
__forceinline Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a,a); }
__forceinline Vec3fa rsqrt( const Vec3fa& a )
{
#if defined(__AVX512VL__)
__m128 r = _mm_rsqrt14_ps(a.m128);
#else
__forceinline const Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
__forceinline const Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a,a); }
__forceinline const Vec3fa rsqrt( const Vec3fa& a ) {
__m128 r = _mm_rsqrt_ps(a.m128);
#endif
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
}
__forceinline Vec3fa zero_fix(const Vec3fa& a) {
return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
__forceinline const Vec3fa zero_fix(const Vec3fa& a) {
return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
}
__forceinline Vec3fa rcp_safe(const Vec3fa& a) {
return rcp(zero_fix(a));
__forceinline const Vec3fa rcp_safe(const Vec3fa& a) {
return rcp(zero_fix(a));
}
__forceinline Vec3fa log ( const Vec3fa& a ) {
__forceinline Vec3fa log ( const Vec3fa& a ) {
return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
}
__forceinline Vec3fa exp ( const Vec3fa& a ) {
__forceinline Vec3fa exp ( const Vec3fa& a ) {
return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
}
@@ -171,37 +152,37 @@ namespace embree
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
__forceinline Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
__forceinline Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
__forceinline Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
__forceinline Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
__forceinline Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
__forceinline Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
__forceinline Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
__forceinline const Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
__forceinline const Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
__forceinline const Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
__forceinline const Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
__forceinline const Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
__forceinline const Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
__forceinline const Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
__forceinline const Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
__forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
__forceinline const Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline const Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
#if defined(__SSE4_1__)
__forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_min_epi32(ai,bi);
const int4 ai = _mm_castps_si128(a);
const int4 bi = _mm_castps_si128(b);
const int4 ci = _mm_min_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
#if defined(__SSE4_1__)
__forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
const vint4 ai = _mm_castps_si128(a);
const vint4 bi = _mm_castps_si128(b);
const vint4 ci = _mm_max_epi32(ai,bi);
const int4 ai = _mm_castps_si128(a);
const int4 bi = _mm_castps_si128(b);
const int4 ci = _mm_max_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
__forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
__forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
return Vec3fa(powf(a.x,b),powf(a.y,b),powf(a.z,b));
}
@@ -221,11 +202,6 @@ namespace embree
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
#endif
__forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
__forceinline Vec3fa msub ( const float a, const Vec3fa& b, const Vec3fa& c) { return msub(Vec3fa(a),b,c); }
__forceinline Vec3fa nmadd ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmadd(Vec3fa(a),b,c); }
__forceinline Vec3fa nmsub ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmsub(Vec3fa(a),b,c); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
@@ -264,7 +240,7 @@ namespace embree
return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
}
__forceinline bool is_finite ( const Vec3fa& a ) {
__forceinline bool is_finite ( const Vec3fa& a ) {
return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
}
@@ -282,56 +258,46 @@ namespace embree
}
#endif
__forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
__forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
{
vfloat4 a0 = vfloat4(a);
vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b));
vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a));
vfloat4 b1 = vfloat4(b);
float4 a0 = float4(a);
float4 b0 = shuffle<1,2,0,3>(float4(b));
float4 a1 = shuffle<1,2,0,3>(float4(a));
float4 b1 = float4(b);
return Vec3fa(shuffle<1,2,0,3>(msub(a0,b0,a1*b1)));
}
__forceinline float sqr_length ( const Vec3fa& a ) { return dot(a,a); }
__forceinline float rcp_length ( const Vec3fa& a ) { return rsqrt(dot(a,a)); }
__forceinline float rcp_length2( const Vec3fa& a ) { return rcp(dot(a,a)); }
__forceinline float sqr_length( const Vec3fa& a ) { return dot(a,a); }
__forceinline float length ( const Vec3fa& a ) { return sqrt(dot(a,a)); }
__forceinline Vec3fa normalize( const Vec3fa& a ) { return a*rsqrt(dot(a,a)); }
__forceinline float distance ( const Vec3fa& a, const Vec3fa& b ) { return length(a-b); }
__forceinline float halfArea ( const Vec3fa& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
__forceinline float halfArea ( const Vec3fa& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
__forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
__forceinline Vec3fa reflect ( const Vec3fa& V, const Vec3fa& N ) { return 2.0f*dot(V,N)*N-V; }
__forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
__forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
}
/*! differentiated normalization */
__forceinline Vec3fa dnormalize(const Vec3fa& p, const Vec3fa& dp)
{
const float pp = dot(p,p);
const float pdp = dot(p,dp);
return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
}
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
__forceinline const Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
__m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
return blendv_ps(f, t, mask);
}
__forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
__forceinline const Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
return blendv_ps(f, t, s);
}
__forceinline int maxDim ( const Vec3fa& a )
{
const Vec3fa b = abs(a);
if (b.x > b.y) {
if (b.x > b.z) return 0; else return 2;
__forceinline int maxDim ( const Vec3fa& a )
{
if (a.x > a.y) {
if (a.x > a.z) return 0; else return 2;
} else {
if (b.y > b.z) return 1; else return 2;
if (a.y > a.z) return 1; else return 2;
}
}
@@ -340,13 +306,13 @@ namespace embree
////////////////////////////////////////////////////////////////////////////////
#if defined (__SSE4_1__)
//__forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
__forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
//__forceinline const Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
__forceinline const Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
#else
//__forceinline Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
__forceinline Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
//__forceinline const Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
__forceinline const Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
__forceinline const Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -356,6 +322,6 @@ namespace embree
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa& a) {
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
}
typedef Vec3fa Vec3fa_t;
}
+304
View File
@@ -0,0 +1,304 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "math.h"
#include "../simd/avx512.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// MIC Vec3fa Type
////////////////////////////////////////////////////////////////////////////////
struct Vec3fa_t;
/* 3 aligned floats as memory representation */
struct __aligned(16) Vec3fa
{
typedef float Scalar;
enum { N = 3 };
float x,y,z; union { int a; unsigned u; float w; };
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa () {}
__forceinline Vec3fa ( float x ) : x(x), y(x), z(x), a(0) {}
__forceinline Vec3fa ( float x, float y, float z ) : x(x), y(y), z(z), a(0) {}
__forceinline Vec3fa ( float x, float y, float z, float w ) : x(x), y(y), z(z), w(w) {}
__forceinline Vec3fa ( const Vec3f & o ) : x(o.x), y(o.y), z(o.z), a(0) {}
__forceinline Vec3fa ( const Vec3fa& other, const int other_a ) : x(other.x), y(other.y), z(other.z), a(other_a) {}
__forceinline Vec3fa ( const Vec3ia_t& other );
__forceinline Vec3fa ( const Vec3fa_t& other );
__forceinline Vec3fa& operator=( const Vec3fa_t& other );
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa( ZeroTy ) : x(0.0f), y(0.0f), z(0.0f), a(0) {}
__forceinline Vec3fa( OneTy ) : x(1.0f), y(1.0f), z(1.0f), a(0) {}
__forceinline Vec3fa( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), a(0) {}
__forceinline Vec3fa( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), a(0) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const float& operator []( const size_t index ) const { assert(index <= 3); return (&x)[index]; }
__forceinline float& operator []( const size_t index ) { assert(index <= 3); return (&x)[index]; }
};
/*! 3-wide vectors emulated with 16-wide vectors. */
struct __aligned(64) Vec3fa_t
{
__m512 m512;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa_t( ) { m512 = _mm512_undefined(); }
__forceinline Vec3fa_t( const __m512 a ) : m512(a) {}
__forceinline Vec3fa_t ( const Vec3fa_t& other ) { m512 = other.m512; }
__forceinline Vec3fa_t& operator =( const Vec3fa_t& other ) { m512 = other.m512; return *this; }
__forceinline operator const __m512&( void ) const { return m512; }
__forceinline operator __m512&( void ) { return m512; }
__forceinline operator const float16( void ) const { return float16(m512); }
__forceinline operator float16( void ) { return float16(m512); }
public:
__forceinline explicit Vec3fa_t ( float a )
: m512(_mm512_set1_ps(a)) {}
__forceinline Vec3fa_t( const Vec3fa& other ) {
m512 = _mm512_extload_ps(&other,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Loading
////////////////////////////////////////////////////////////////////////////////
static __forceinline Vec3fa_t loadu( const void* const a ) {
const bool16 m_4f = 0xf;
return (__m512)permute<0,0,0,0>(uload16f(m_4f,(float*)a));
}
static __forceinline void storeu( void* const ptr, const Vec3fa_t& v ) // FIXME: implement fast version
{
((float*)ptr)[0] = ((float*)&v)[0];
((float*)ptr)[1] = ((float*)&v)[1];
((float*)ptr)[2] = ((float*)&v)[2];
((float*)ptr)[3] = ((float*)&v)[3];
}
};
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia::Vec3ia ( const Vec3fa_t& other ) {
__m512i i = _mm512_cvtfxpnt_round_adjustps_epi32(other,_MM_ROUND_MODE_NEAREST,_MM_EXPADJ_NONE);
_mm512_mask_extpackstorelo_epi32(this,0xf,i,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline Vec3fa::Vec3fa( const Vec3ia_t& v ) {
__m512 f = _mm512_cvtfxpnt_round_adjustepi32_ps(v,_MM_ROUND_MODE_NEAREST,_MM_EXPADJ_NONE);
_mm512_mask_extpackstorelo_ps(this,0xf,f,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline Vec3fa::Vec3fa ( const Vec3fa_t& other ) {
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline Vec3fa& Vec3fa::operator=( const Vec3fa_t& other ) {
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3fa_t operator +( const Vec3fa_t& a ) { return a; }
__forceinline const Vec3fa_t operator -( const Vec3fa_t& a ) { return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a.m512), _mm512_set1_epi32(0x80000000))); }
__forceinline const Vec3fa_t abs ( const Vec3fa_t& a ) { return _mm512_gmaxabs_ps(a.m512,a.m512); }
__forceinline const Vec3fa_t sign ( const Vec3fa_t& a ) { return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a,_mm512_setzero_ps(),_MM_CMPINT_LT), _mm512_set1_ps(1.0f), _mm512_set1_ps(-1.0f)); }
__forceinline const Vec3fa_t rcp ( const Vec3fa_t& a ) { return _mm512_rcp23_ps(a); }
__forceinline const Vec3fa_t sqr ( const Vec3fa_t& a ) { return _mm512_mul_ps(a,a); }
__forceinline const Vec3fa_t sqrt ( const Vec3fa_t& a ) { return _mm512_sqrt_ps(a.m512); }
__forceinline const Vec3fa_t rsqrt( const Vec3fa_t& a ) { return _mm512_invsqrt_ps(a.m512); }
__forceinline const Vec3fa_t zero_fix( const Vec3fa_t& a ) { return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a.m512,_mm512_setzero_ps(),_MM_CMPINT_EQ), a, _mm512_set1_ps(1E-10f)); }
__forceinline const Vec3fa_t rcp_safe(const Vec3fa_t& a) { return rcp(zero_fix(a)); }
__forceinline Vec3fa log ( const Vec3fa& a ) {
return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
}
__forceinline Vec3fa exp ( const Vec3fa& a ) {
return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3fa_t operator +( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_add_ps(a.m512, b.m512); }
__forceinline const Vec3fa_t operator -( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_sub_ps(a.m512, b.m512); }
__forceinline const Vec3fa_t operator *( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_mul_ps(a.m512, b.m512); }
__forceinline const Vec3fa_t operator *( const Vec3fa_t& a, const float b ) { return a * Vec3fa_t(b); }
__forceinline const Vec3fa_t operator *( const float a, const Vec3fa_t& b ) { return Vec3fa_t(a) * b; }
__forceinline const Vec3fa_t operator /( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_div_ps(a.m512,b.m512); }
__forceinline const Vec3fa_t operator /( const Vec3fa_t& a, const float b ) { return _mm512_div_ps(a.m512,_mm512_set1_ps(b)); }
__forceinline const Vec3fa_t operator /( const float a, const Vec3fa_t& b ) { return _mm512_div_ps(_mm512_set1_ps(a),b.m512); }
__forceinline const Vec3fa_t min( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_gmin_ps(a.m512,b.m512); }
__forceinline const Vec3fa_t max( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_gmax_ps(a.m512,b.m512); }
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa_t madd ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fmadd_ps(a,b,c); }
__forceinline Vec3fa_t msub ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline Vec3fa_t nmadd ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fnmadd_ps(a,b,c); }
__forceinline Vec3fa_t nmsub ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fnmsub_ps(a,b,c); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3fa& operator +=( Vec3fa& a, const Vec3fa_t& b ) { return a = a + b; }
__forceinline Vec3fa& operator -=( Vec3fa& a, const Vec3fa_t& b ) { return a = a - b; }
__forceinline Vec3fa& operator *=( Vec3fa& a, const float b ) { return a = a * b; }
__forceinline Vec3fa& operator /=( Vec3fa& a, const float b ) { return a = a / b; }
__forceinline Vec3fa_t& operator +=( Vec3fa_t& a, const Vec3fa_t& b ) { return a = a + b; }
__forceinline Vec3fa_t& operator *=( Vec3fa_t& a, const float b ) { return a = a * b; }
__forceinline Vec3fa_t& operator /=( Vec3fa_t& a, const float b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline float reduce_add(const Vec3fa_t& a) {
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(0.0f));
__m512 c = _mm512_add_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
__m512 d = _mm512_add_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
return _mm512_cvtss_f32(d);
}
__forceinline float reduce_mul(const Vec3fa_t& a) {
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(1.0f));
__m512 c = _mm512_mul_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
__m512 d = _mm512_mul_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
return _mm512_cvtss_f32(d);
}
__forceinline float reduce_min(const Vec3fa_t& a) {
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(pos_inf));
__m512 c = _mm512_gmin_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
__m512 d = _mm512_gmin_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
return _mm512_cvtss_f32(d);
}
__forceinline float reduce_max(const Vec3fa_t& a) {
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(neg_inf));
__m512 c = _mm512_gmax_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
__m512 d = _mm512_gmax_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
return _mm512_cvtss_f32(d);
}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator ==( const Vec3fa_t& a, const Vec3fa_t& b ) { return (_mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ) & 7) == 7; }
__forceinline bool operator !=( const Vec3fa_t& a, const Vec3fa_t& b ) { return (_mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE) & 7) != 0; }
__forceinline Vec3ba eq_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline Vec3ba neq_mask(const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline Vec3ba lt_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline Vec3ba le_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline Vec3ba gt_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline Vec3ba ge_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline bool isvalid ( const Vec3fa& v ) {
return all(gt_mask(v,Vec3fa_t(-FLT_LARGE)) & lt_mask(v,Vec3fa_t(+FLT_LARGE)));
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float dot ( const Vec3fa_t& a, const Vec3fa_t& b ) {
return reduce_add(a*b);
}
__forceinline Vec3fa_t cross ( const Vec3fa_t& a, const Vec3fa_t& b )
{
__m512 c = _mm512_mul_ps(b,_mm512_swizzle_ps(a,_MM_SWIZ_REG_DACB));
c = _mm512_fmsub_ps(_mm512_swizzle_ps(b,_MM_SWIZ_REG_DACB),a,c);
c = _mm512_swizzle_ps(c,_MM_SWIZ_REG_DACB);
return c;
}
__forceinline float length ( const Vec3fa_t& a ) { return sqrt(dot(a,a)); }
__forceinline Vec3fa_t normalize( const Vec3fa_t& a ) { return a*rsqrt(dot(a,a)); }
__forceinline float distance ( const Vec3fa_t& a, const Vec3fa_t& b ) { return length(a-b); }
__forceinline float halfArea ( const Vec3fa& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
__forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
__forceinline Vec3fa_t reflect ( const Vec3fa_t& V, const Vec3fa_t& N ) { return 2.0f*dot(V,N)*N-V; }
__forceinline Vec3fa_t normalize_safe( const Vec3fa_t& a ) {
const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
}
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3fa_t select( bool s, const Vec3fa_t& t, const Vec3fa_t& f ) {
return _mm512_mask_blend_ps(s ? 0xF : 0x0, f, t);
}
__forceinline const Vec3fa_t select( const Vec3ba& s, const Vec3fa_t& t, const Vec3fa_t& f ) {
return _mm512_mask_blend_ps(s, f, t);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa& a) {
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ", " << a.w << ")";
}
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa_t& a) {
const float * const f = (float*)&a.m512;
return cout << "(" << f[0] << ", " << f[1] << ", " << f[2] << ", " << f[3] << ")";
}
}
+34 -38
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -16,7 +16,6 @@
#pragma once
#include "../sys/alloc.h"
#include "math.h"
#include "../simd/sse.h"
@@ -28,8 +27,6 @@ namespace embree
struct __aligned(16) Vec3ia
{
ALIGNED_STRUCT;
union {
__m128i m128;
struct { int x,y,z; int a; };
@@ -48,11 +45,11 @@ namespace embree
__forceinline Vec3ia& operator =(const Vec3ia& other) { m128 = other.m128; return *this; }
__forceinline explicit Vec3ia( const int a ) : m128(_mm_set1_epi32(a)) {}
__forceinline Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
__forceinline explicit Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
__forceinline explicit Vec3ia( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
__forceinline operator const __m128i&() const { return m128; }
__forceinline operator __m128i&() { return m128; }
__forceinline operator const __m128i&( void ) const { return m128; }
__forceinline operator __m128i&( void ) { return m128; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -76,48 +73,47 @@ namespace embree
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia operator +( const Vec3ia& a ) { return a; }
__forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
__forceinline const Vec3ia operator +( const Vec3ia& a ) { return a; }
__forceinline const Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
#if defined(__SSSE3__)
__forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
__forceinline const Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
__forceinline Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
__forceinline Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
__forceinline const Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
__forceinline const Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
__forceinline const Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
__forceinline Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
__forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
__forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
__forceinline const Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
__forceinline const Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
__forceinline const Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
#if defined(__SSE4_1__)
__forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
__forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
__forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
__forceinline const Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
__forceinline const Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
__forceinline const Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
#endif
__forceinline Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
__forceinline Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
__forceinline Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
__forceinline const Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
__forceinline const Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
__forceinline const Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
__forceinline Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
__forceinline Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
__forceinline Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
__forceinline const Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
__forceinline const Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
__forceinline const Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
__forceinline Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
__forceinline Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
__forceinline Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
__forceinline const Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
__forceinline const Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
__forceinline const Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
__forceinline Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
__forceinline Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
__forceinline const Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
__forceinline const Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
__forceinline Vec3ia sll ( const Vec3ia& a, const int b ) { return _mm_slli_epi32(a.m128, b); }
__forceinline Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
__forceinline Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
__forceinline const Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
__forceinline const Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
@@ -173,7 +169,7 @@ namespace embree
/// Select
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
__forceinline const Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
#if defined(__SSE4_1__)
return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
#else
@@ -182,11 +178,11 @@ namespace embree
}
#if defined(__SSE4_1__)
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
__forceinline const Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
__forceinline const Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
#else
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
__forceinline const Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
__forceinline const Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
#endif
////////////////////////////////////////////////////////////////////////////////
+230
View File
@@ -0,0 +1,230 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "math.h"
#include "../simd/avx512.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// MIC Vec3ia Type
////////////////////////////////////////////////////////////////////////////////
struct Vec3ia_t;
struct Vec3fa_t;
/* 3 aligned ints as memory representation */
struct __aligned(16) Vec3ia
{
typedef int Scalar;
enum { N = 3 };
struct { int x,y,z; int a; };
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia ( ) {}
__forceinline Vec3ia ( int x ) : x(x), y(x), z(x), a(0) {}
__forceinline Vec3ia ( int x, int y, int z ) : x(x), y(y), z(z), a(0) {}
__forceinline Vec3ia ( const Vec3fa_t& other );
__forceinline Vec3ia ( const Vec3ia_t& other );
__forceinline Vec3ia& operator=( const Vec3ia_t& other );
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia( ZeroTy ) : x(0), y(0), z(0), a(0) {}
__forceinline Vec3ia( OneTy ) : x(1), y(1), z(1), a(1) {}
__forceinline Vec3ia( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), a(pos_inf) {}
__forceinline Vec3ia( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), a(neg_inf) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
};
/*! 3-wide vectors emulated with 16-wide vectors. */
struct __aligned(64) Vec3ia_t
{
__m512i m512;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia_t ( const __m512i a ) : m512(a) {}
__forceinline Vec3ia_t ( const Vec3ia_t& other ) { m512 = other.m512; }
__forceinline Vec3ia_t& operator =( const Vec3ia_t& other ) { m512 = other.m512; return *this; }
__forceinline operator const __m512i&( void ) const { return m512; }
__forceinline operator __m512i&( void ) { return m512; }
public:
__forceinline explicit Vec3ia_t ( int a )
: m512(_mm512_set1_epi32(a)) {}
__forceinline Vec3ia_t( const Vec3ia& other ) {
m512 = _mm512_extload_epi32(&other,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
};
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia::Vec3ia ( const Vec3ia_t& other ) {
_mm512_mask_extpackstorelo_epi32(this,0xf,other.m512,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline Vec3ia& Vec3ia::operator=( const Vec3ia_t& other ) {
_mm512_mask_extpackstorelo_epi32(this,0xf,other.m512,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a ) { return a; }
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a ) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a.m512); }
//__forceinline const Vec3ia_t abs ( const Vec3ia_t& a ) { return _mm512_abs_epi32(a.m512); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_add_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a, const int b ) { return a+Vec3ia_t(b); }
__forceinline const Vec3ia_t operator +( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a)+b; }
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_sub_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a, const int b ) { return a-Vec3ia_t(b); }
__forceinline const Vec3ia_t operator -( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a)-b; }
__forceinline const Vec3ia_t operator *( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_mullo_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator *( const Vec3ia_t& a, const int b ) { return a * Vec3ia_t(b); }
__forceinline const Vec3ia_t operator *( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) * b; }
__forceinline const Vec3ia_t operator &( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_and_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator &( const Vec3ia_t& a, const int b ) { return a & Vec3ia_t(b); }
__forceinline const Vec3ia_t operator &( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) & b; }
__forceinline const Vec3ia_t operator |( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_or_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator |( const Vec3ia_t& a, const int b ) { return a | Vec3ia_t(b); }
__forceinline const Vec3ia_t operator |( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) | b; }
__forceinline const Vec3ia_t operator ^( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_xor_epi32(a.m512, b.m512); }
__forceinline const Vec3ia_t operator ^( const Vec3ia_t& a, const int b ) { return a ^ Vec3ia_t(b); }
__forceinline const Vec3ia_t operator ^( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) ^ b; }
__forceinline const Vec3ia_t operator <<( const Vec3ia_t& a, const int n ) { return _mm512_slli_epi32(a.m512, n); }
__forceinline const Vec3ia_t operator >>( const Vec3ia_t& a, const int n ) { return _mm512_srai_epi32(a.m512, n); }
__forceinline const Vec3ia_t sra ( const Vec3ia_t& a, const int b ) { return _mm512_srai_epi32(a.m512, b); }
__forceinline const Vec3ia_t srl ( const Vec3ia_t& a, const int b ) { return _mm512_srli_epi32(a.m512, b); }
__forceinline const Vec3ia_t min( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_min_epi32(a.m512,b.m512); }
__forceinline const Vec3ia_t max( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_max_epi32(a.m512,b.m512); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia_t& b ) { return a = a + b; }
__forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia_t& b ) { return a = a - b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia_t& b ) { return a = a * b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia_t& b ) { return a = a & b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia_t& b ) { return a = a | b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
__forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline int reduce_add(const Vec3ia_t& a) {
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(0));
__m512i c = _mm512_add_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
__m512i d = _mm512_add_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
return *(int*)&d;
}
__forceinline int reduce_mul(const Vec3ia_t& a) {
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(1));
__m512i c = _mm512_mullo_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
__m512i d = _mm512_mullo_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
return *(int*)&d;
}
__forceinline int reduce_min(const Vec3ia_t& a) {
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(pos_inf));
__m512i c = _mm512_min_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
__m512i d = _mm512_min_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
return *(int*)&d;
}
__forceinline int reduce_max(const Vec3ia_t& a) {
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(neg_inf));
__m512i c = _mm512_max_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
__m512i d = _mm512_max_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
return *(int*)&d;
}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator ==( const Vec3ia_t& a, const Vec3ia_t& b ) { return (_mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ) & 7) == 7; }
__forceinline bool operator !=( const Vec3ia_t& a, const Vec3ia_t& b ) { return (_mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE) & 7) != 0; }
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const Vec3ia_t select( bool s, const Vec3ia_t& t, const Vec3ia_t& f ) {
return _mm512_mask_blend_epi32(s ? 0xF : 0x0, f, t);
}
__forceinline const Vec3ia_t select( const Vec3ba& s, const Vec3ia_t& t, const Vec3ia_t& f ) {
return _mm512_mask_blend_epi32(s, f, t);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const Vec3ia& a) {
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
}
}
+33 -78
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -17,7 +17,6 @@
#pragma once
#include "math.h"
#include "vec3.h"
namespace embree
{
@@ -36,19 +35,16 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec4( ) {}
__forceinline Vec4 ( ) { }
__forceinline explicit Vec4( const T& a ) : x(a), y(a), z(a), w(a) {}
__forceinline Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
__forceinline Vec4( const Vec3<T>& xyz, const T& w ) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
__forceinline explicit Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
__forceinline Vec4( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
__forceinline Vec4( const Vec3fa& other );
__forceinline Vec4 ( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
__forceinline Vec4 ( const Vec3fa& other );
template<typename T1> __forceinline Vec4( const Vec4<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)), w(T(a.w)) {}
template<typename T1> __forceinline Vec4& operator =(const Vec4<T1>& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
__forceinline operator Vec3<T> () const { return Vec3<T>(x,y,z); }
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
@@ -60,12 +56,6 @@ namespace embree
__forceinline const T& operator []( const size_t axis ) const { assert(axis < 4); return (&x)[axis]; }
__forceinline T& operator []( const size_t axis ) { assert(axis < 4); return (&x)[axis]; }
////////////////////////////////////////////////////////////////////////////////
/// Swizzles
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3<T> xyz() const { return Vec3<T>(x, y, z); }
};
////////////////////////////////////////////////////////////////////////////////
@@ -95,20 +85,6 @@ namespace embree
template<typename T> __forceinline Vec4<T> min(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w)); }
template<typename T> __forceinline Vec4<T> max(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); }
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec4<T> madd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z), madd(a.w,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> msub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z), msub(a.w,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> nmadd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z),nmadd(a.w,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> nmsub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z),nmsub(a.w,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> madd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z), madd(a,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> msub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z), msub(a,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> nmadd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z),nmadd(a,b.w,c.w)); }
template<typename T> __forceinline Vec4<T> nmsub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z),nmsub(a,b.w,c.w)); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
@@ -141,14 +117,6 @@ namespace embree
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// Shift Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec4<T> shift_right_1( const Vec4<T>& a ) {
return Vec4<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z),shift_right_1(a.w));
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
@@ -167,19 +135,6 @@ namespace embree
return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
}
template<typename T> __forceinline Vec4<T> select ( const Vec4<bool>& s, const Vec4<T>& t, const Vec4<T>& f ) {
return Vec4<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z),select(s.w,t.w,f.w));
}
template<typename T> __forceinline Vec4<T> select ( const typename T::Bool& s, const Vec4<T>& t, const Vec4<T>& f ) {
return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
}
template<typename T>
__forceinline Vec4<T> lerp(const Vec4<T>& v0, const Vec4<T>& v1, const T& t) {
return madd(Vec4<T>(T(1.0f)-t),v0,t*v1);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
@@ -198,9 +153,15 @@ namespace embree
typedef Vec4<float > Vec4f;
}
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
#if defined(__MIC__)
#include "vec3ba_mic.h"
#include "vec3ia_mic.h"
#include "vec3fa_mic.h"
#else
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
#endif
////////////////////////////////////////////////////////////////////////////////
/// SSE / AVX / MIC specializations
@@ -214,46 +175,40 @@ namespace embree
#include "../simd/avx.h"
#endif
#if defined __AVX512F__
#if defined __MIC__
#include "../simd/avx512.h"
#endif
namespace embree
{
namespace embree
{
template<> __forceinline Vec4<float>::Vec4( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; w = a.w; }
#if defined(__AVX__)
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fa& a ) {
x = a.x; y = a.y; z = a.z; w = a.w;
#if defined (__SSE__)
template<> __forceinline Vec4<float4>::Vec4( const Vec3fa& a ) {
const float4 v = float4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
}
#elif defined(__SSE__)
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fa& a ) {
const vfloat4 v = vfloat4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
}
#endif
#if defined(__SSE__)
__forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat4>& a, const size_t k ) {
return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
__forceinline Vec4<float4> broadcast4f( const Vec4<float4>& a, const size_t k ) {
return Vec4<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]), float4::broadcast(&a.w[k]));
}
#endif
#if defined(__AVX__)
template<> __forceinline Vec4<vfloat8>::Vec4( const Vec3fa& a ) {
x = a.x; y = a.y; z = a.z; w = a.w;
template<> __forceinline Vec4<float8>::Vec4( const Vec3fa& a ) {
x = a.x; y = a.y; z = a.z; w = a.w;
}
__forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat8>& a, const size_t k ) {
return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
__forceinline Vec4<float4> broadcast4f( const Vec4<float8>& a, const size_t k ) {
return Vec4<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]), float4::broadcast(&a.w[k]));
}
__forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat4>& a, const size_t k ) {
return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
__forceinline Vec4<float8> broadcast8f( const Vec4<float4>& a, const size_t k ) {
return Vec4<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]), float8::broadcast(&a.w[k]));
}
__forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat8>& a, const size_t k ) {
return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
__forceinline Vec4<float8> broadcast8f( const Vec4<float8>& a, const size_t k ) {
return Vec4<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]), float8::broadcast(&a.w[k]));
}
#endif
#if defined(__AVX512F__)
template<> __forceinline Vec4<vfloat16>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
#if defined(__MIC__)
//template<> __forceinline Vec4<float4>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
template<> __forceinline Vec4<float16>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
#endif
}
+8 -3
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2015 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -14,6 +14,11 @@
## limitations under the License. ##
## ======================================================================== ##
ADD_LIBRARY(simd STATIC sse.cpp)
SET_PROPERTY(TARGET simd PROPERTY FOLDER common)
IF (__XEON__)
ADD_LIBRARY(simd STATIC sse.cpp)
SET_PROPERTY(TARGET simd PROPERTY FOLDER common)
ELSE ()
INCLUDE(icc_xeonphi)
ADD_LIBRARY(simd_xeonphi STATIC bool16_avx512.cpp)
ENDIF ()
+13 -19
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -18,28 +18,22 @@
#include "sse.h"
#if defined(__AVX512VL__)
#include "vboolf8_avx512.h"
#include "vboold4_avx512.h"
#else
#include "vboolf8_avx.h"
#include "vboold4_avx.h"
#endif
namespace embree
{
struct bool8;
struct int8;
struct float8;
}
#if defined(__AVX2__)
#include "vint8_avx2.h"
#if defined(__X86_64__)
#include "vllong4_avx2.h"
#endif
#include "bool8_avx.h"
#if defined (__AVX2__)
#include "int8_avx2.h"
#else
#include "vint8_avx.h"
#endif
#include "vfloat8_avx.h"
#if defined(__X86_64__)
#include "vdouble4_avx.h"
#include "int8_avx.h"
#endif
#include "float8_avx.h"
#if defined(__AVX512F__)
#if defined (__AVX512F__)
#include "avx512.h"
#endif
+89 -9
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -19,16 +19,25 @@
#include "../sys/platform.h"
#include "../sys/intrinsics.h"
#include "../math/constants.h"
#include "varying.h"
//#include "sse_mic.h"
#include "vboolf16_avx512.h"
#include "vint16_avx512.h"
#include "vfloat16_avx512.h"
#include <zmmintrin.h>
#include "vuint16_avx512.h"
#include "vboold8_avx512.h"
#include "vllong8_avx512.h"
#include "vdouble8_avx512.h"
#define _MM_SHUF_PERM(e3, e2, e1, e0) \
((_MM_PERM_ENUM)((e3)*64 + (e2)*16 + (e1)*4 + (e0)))
#define _MM_SHUF_PERM_NONE _MM_SHUF_PERM(3,2,1,0)
namespace embree
{
class bool16;
class int16;
class float16;
}
#include "bool16_avx512.h"
#include "int16_avx512.h"
#include "float16_avx512.h"
namespace embree
{
@@ -39,6 +48,9 @@ namespace embree
#define PFHINT_L1 0
#define PFHINT_L2 1
#define PFHINT_NT 2
#define PFHINT_L1EX 3
#define PFHINT_L2EX 4
#define PFHINT_NTEX 5
template<const unsigned int mode>
__forceinline void prefetch(const void * __restrict__ const m)
@@ -49,5 +61,73 @@ namespace embree
_mm_prefetch((const char*)m,_MM_HINT_T1);
else if (mode == PFHINT_NT)
_mm_prefetch((const char*)m,_MM_HINT_NTA);
else if (mode == PFHINT_L1EX)
_mm_prefetch((const char*)m,_MM_HINT_ET0);
else if (mode == PFHINT_L2EX)
_mm_prefetch((const char*)m,_MM_HINT_ET2);
else if (mode == PFHINT_NTEX)
_mm_prefetch((const char*)m,_MM_HINT_ENTA);
}
__forceinline void gather_prefetch(const bool16 &m_active,
const void *const ptr,
const int16 index,
const int mode = _MM_HINT_T2,
const _MM_INDEX_SCALE_ENUM scale = _MM_SCALE_4,
const _MM_UPCONV_PS_ENUM up = _MM_UPCONV_PS_NONE)
{
_mm512_mask_prefetch_i32extgather_ps(index,m_active,ptr,up,scale,mode);
}
__forceinline void scatter_prefetch(const bool16 &m_active,
void *const ptr,
const int16 index,
const int mode = _MM_HINT_ET2,
const _MM_INDEX_SCALE_ENUM scale = _MM_SCALE_4,
const _MM_UPCONV_PS_ENUM up = _MM_UPCONV_PS_NONE)
{
_mm512_mask_prefetch_i32extscatter_ps(ptr,m_active,index,up,scale,mode);
}
#if !defined(_MM_SHUF_PERM)
#define _MM_SHUF_PERM(e3, e2, e1, e0) ((_MM_PERM_ENUM)((e3)*64 + (e2)*16 + (e1)*4 + (e0)))
#define _MM_SHUF_PERM_NONE _MM_SHUF_PERM(3,2,1,0)
#endif
template<const int D, const int C, const int B, const int A>
__forceinline float16 lshuf(const float16 &in)
{
return _mm512_permute4f128_ps(in,(_MM_PERM_ENUM)_MM_SHUF_PERM(D,C,B,A));
}
template<const int D, const int C, const int B, const int A>
__forceinline float16 lshuf(const bool16 &mask, float16 &dest, const float16 &in)
{
return _mm512_mask_permute4f128_ps(dest,mask,in,(_MM_PERM_ENUM) _MM_SHUF_PERM(D,C,B,A));
}
template<const int lane>
__forceinline float16 lane_shuffle_gather(const float16 &v0,const float16 &v1,const float16 &v2,const float16 &v3)
{
float16 t = lshuf<lane,lane,lane,lane>(v0);
t = lshuf<lane,lane,lane,lane>(0xf0,t,v1);
t = lshuf<lane,lane,lane,lane>(0xf00,t,v2);
t = lshuf<lane,lane,lane,lane>(0xf000,t,v3);
return t;
}
/* __forceinline float16 convert(const float4 &v) */
/* { */
/* return broadcast4to16f(&v); */
/* } */
__forceinline int16 mul_uint64_t( const int16& a, const int16& b) {
const int16 low = _mm512_mullo_epi32(a, b);
const int16 high = _mm512_mulhi_epu32(a, b);
return select(0x5555,low,high);
}
}
+57
View File
@@ -0,0 +1,57 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#include "avx512.h"
namespace embree
{
__aligned(64) unsigned int bool16::shift1[32] = {
((unsigned int)1 << 0),
((unsigned int)1 << 1),
((unsigned int)1 << 2),
((unsigned int)1 << 3),
((unsigned int)1 << 4),
((unsigned int)1 << 5),
((unsigned int)1 << 6),
((unsigned int)1 << 7),
((unsigned int)1 << 8),
((unsigned int)1 << 9),
((unsigned int)1 << 10),
((unsigned int)1 << 11),
((unsigned int)1 << 12),
((unsigned int)1 << 13),
((unsigned int)1 << 14),
((unsigned int)1 << 15),
((unsigned int)1 << 16),
((unsigned int)1 << 17),
((unsigned int)1 << 18),
((unsigned int)1 << 19),
((unsigned int)1 << 20),
((unsigned int)1 << 21),
((unsigned int)1 << 22),
((unsigned int)1 << 23),
((unsigned int)1 << 24),
((unsigned int)1 << 25),
((unsigned int)1 << 26),
((unsigned int)1 << 27),
((unsigned int)1 << 28),
((unsigned int)1 << 29),
((unsigned int)1 << 30),
((unsigned int)1 << 31)
};
};
+121
View File
@@ -0,0 +1,121 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 16-wide MIC bool type. */
class bool16
{
public:
__mmask v;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool16 () {};
__forceinline bool16 (const bool16 &t) { v = t.v; };
__forceinline bool16& operator=(const bool16 &f) { v = f.v; return *this; };
__forceinline bool16 (const __mmask &t) { v = t; };
__forceinline operator __mmask () const { return v; };
__forceinline bool16(bool b) { v = b ? 0xFFFF : 0x0000; };
__forceinline bool16(int t ) { v = (__mmask)t; };
__forceinline bool16(unsigned int t ) { v = (__mmask)t; };
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline bool16( FalseTy ) : v(0x0000) {}
__forceinline bool16( TrueTy ) : v(0xffff) {}
static unsigned int shift1[32];
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool16 operator!(const bool16 &a) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool16 operator&(const bool16 &a, const bool16 &b) { return _mm512_kand(a,b); };
__forceinline bool16 operator|(const bool16 &a, const bool16 &b) { return _mm512_kor(a,b); };
__forceinline bool16 operator^(const bool16 &a, const bool16 &b) { return _mm512_kxor(a,b); };
__forceinline bool16 andn(const bool16 &a, const bool16 &b) { return _mm512_kandn(b,a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool16 operator &=( bool16& a, const bool16& b ) { return a = a & b; }
__forceinline const bool16 operator |=( bool16& a, const bool16& b ) { return a = a | b; }
__forceinline const bool16 operator ^=( bool16& a, const bool16& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool16 operator !=( const bool16& a, const bool16& b ) { return _mm512_kxor(a, b); }
__forceinline const bool16 operator ==( const bool16& a, const bool16& b ) { return _mm512_kxnor(a, b); }
__forceinline bool16 select (const bool16 &s, const bool16 &a, const bool16 &b) {
return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all(const bool16 &a) { return _mm512_kortestc(a,a) != 0; }
__forceinline int any(const bool16 &a) { return _mm512_kortestz(a,a) == 0; }
__forceinline int none(const bool16 &a) { return _mm512_kortestz(a,a) != 0; }
__forceinline int all ( const bool16& valid, const bool16& b ) { return all(!valid | b); }
__forceinline int any ( const bool16& valid, const bool16& b ) { return any( valid & b); }
__forceinline int none ( const bool16& valid, const bool16& b ) { return none(valid & b); }
__forceinline size_t movemask( const bool16& a ) { return _mm512_kmov(a); }
__forceinline size_t popcnt ( const bool16& a ) { return _mm_countbits_32(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Convertion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt (const bool16 &a) { return _mm512_mask2int(a); };
__forceinline bool16 toMask(const int &a) { return _mm512_int2mask(a); };
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const bool16& a)
{
cout << "<";
for (size_t i=0; i<16; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
+163
View File
@@ -0,0 +1,163 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 4-wide SSE bool type. */
struct bool4
{
typedef bool4 Mask; // mask type
typedef int4 Int; // int type
typedef float4 Float; // float type
enum { size = 4 }; // number of SIMD elements
union { __m128 m128; int v[4]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool4 ( ) {}
__forceinline bool4 ( const bool4& other ) { m128 = other.m128; }
__forceinline bool4& operator=( const bool4& other ) { m128 = other.m128; return *this; }
__forceinline bool4( const __m128 input ) : m128(input) {}
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator const __m128i( void ) const { return _mm_castps_si128(m128); }
__forceinline operator const __m128d( void ) const { return _mm_castps_pd(m128); }
__forceinline bool4 ( bool a )
: m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
__forceinline bool4 ( bool a, bool b)
: m128(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline bool4 ( bool a, bool b, bool c, bool d)
: m128(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline bool4(int mask) {
assert(mask >= 0 && mask < 16);
m128 = _mm_lookupmask_ps[mask];
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline bool4( FalseTy ) : m128(_mm_setzero_ps()) {}
__forceinline bool4( TrueTy ) : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator []( const size_t i ) const { assert(i < 4); return (_mm_movemask_ps(m128) >> i) & 1; }
__forceinline int& operator []( const size_t i ) { assert(i < 4); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator !( const bool4& a ) { return _mm_xor_ps(a, bool4(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator &( const bool4& a, const bool4& b ) { return _mm_and_ps(a, b); }
__forceinline const bool4 operator |( const bool4& a, const bool4& b ) { return _mm_or_ps (a, b); }
__forceinline const bool4 operator ^( const bool4& a, const bool4& b ) { return _mm_xor_ps(a, b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator &=( bool4& a, const bool4& b ) { return a = a & b; }
__forceinline const bool4 operator |=( bool4& a, const bool4& b ) { return a = a | b; }
__forceinline const bool4 operator ^=( bool4& a, const bool4& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator !=( const bool4& a, const bool4& b ) { return _mm_xor_ps(a, b); }
__forceinline const bool4 operator ==( const bool4& a, const bool4& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
__forceinline const bool4 select( const bool4& m, const bool4& t, const bool4& f ) {
#if defined(__SSE4_1__)
return _mm_blendv_ps(f, t, m);
#else
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 unpacklo( const bool4& a, const bool4& b ) { return _mm_unpacklo_ps(a, b); }
__forceinline const bool4 unpackhi( const bool4& a, const bool4& b ) { return _mm_unpackhi_ps(a, b); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool4 shuffle( const bool4& a ) {
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool4 shuffle( const bool4& a, const bool4& b ) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
#if defined(__SSE3__)
template<> __forceinline const bool4 shuffle<0, 0, 2, 2>( const bool4& a ) { return _mm_moveldup_ps(a); }
template<> __forceinline const bool4 shuffle<1, 1, 3, 3>( const bool4& a ) { return _mm_movehdup_ps(a); }
template<> __forceinline const bool4 shuffle<0, 1, 0, 1>( const bool4& a ) { return _mm_castpd_ps(_mm_movedup_pd (a)); }
#endif
#if defined(__SSE4_1__)
template<size_t dst, size_t src, size_t clr> __forceinline const bool4 insert( const bool4& a, const bool4& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<size_t dst, size_t src> __forceinline const bool4 insert( const bool4& a, const bool4& b ) { return insert<dst, src, 0>(a, b); }
template<size_t dst> __forceinline const bool4 insert( const bool4& a, const bool b ) { return insert<dst,0>(a, bool4(b)); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const bool4& a ) { return _mm_movemask_ps(a) == 0xf; }
__forceinline bool reduce_or ( const bool4& a ) { return _mm_movemask_ps(a) != 0x0; }
__forceinline bool all ( const bool4& b ) { return _mm_movemask_ps(b) == 0xf; }
__forceinline bool any ( const bool4& b ) { return _mm_movemask_ps(b) != 0x0; }
__forceinline bool none ( const bool4& b ) { return _mm_movemask_ps(b) == 0x0; }
__forceinline bool all ( const bool4& valid, const bool4& b ) { return all(!valid | b); }
__forceinline bool any ( const bool4& valid, const bool4& b ) { return any( valid & b); }
__forceinline bool none ( const bool4& valid, const bool4& b ) { return none(valid & b); }
__forceinline size_t movemask( const bool4& a ) { return _mm_movemask_ps(a); }
#if defined(__SSE4_2__)
__forceinline size_t popcnt( const bool4& a ) { return __popcnt(_mm_movemask_ps(a)); }
#else
__forceinline size_t popcnt( const bool4& a ) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const bool4& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+172
View File
@@ -0,0 +1,172 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 8-wide AVX bool type. */
struct bool8
{
typedef bool8 Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256 m256;
struct { __m128 l,h; };
int v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline bool8 () {}
__forceinline bool8 ( const bool8& a ) { m256 = a.m256; }
__forceinline bool8& operator=( const bool8& a ) { m256 = a.m256; return *this; }
__forceinline bool8( const __m256 a ) : m256(a) {}
__forceinline operator const __m256&( void ) const { return m256; }
__forceinline operator const __m256i( void ) const { return _mm256_castps_si256(m256); }
__forceinline operator const __m256d( void ) const { return _mm256_castps_pd(m256); }
__forceinline bool8 ( const int a )
{
assert(a >= 0 && a <= 255);
#if defined (__AVX2__)
const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
const __m256i b = _mm256_set1_epi32(a);
const __m256i c = _mm256_and_si256(b,mask);
m256 = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
#else
l = _mm_lookupmask_ps[a & 0xF];
h = _mm_lookupmask_ps[a >> 4];
#endif
}
__forceinline bool8 ( const bool4& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
__forceinline bool8 ( const bool4& a, const bool4& b) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
__forceinline bool8 ( const __m128 a, const __m128 b) : l(a), h(b) {}
__forceinline bool8 ( bool a ) : m256(bool8(bool4(a), bool4(a))) {}
__forceinline bool8 ( bool a, bool b) : m256(bool8(bool4(a), bool4(b))) {}
__forceinline bool8 ( bool a, bool b, bool c, bool d) : m256(bool8(bool4(a,b), bool4(c,d))) {}
__forceinline bool8 ( bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h ) : m256(bool8(bool4(a,b,c,d), bool4(e,f,g,h))) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline bool8( FalseTy ) : m256(_mm256_setzero_ps()) {}
__forceinline bool8( TrueTy ) : m256(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator []( const size_t i ) const { assert(i < 8); return (_mm256_movemask_ps(m256) >> i) & 1; }
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator !( const bool8& a ) { return _mm256_xor_ps(a, bool8(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator &( const bool8& a, const bool8& b ) { return _mm256_and_ps(a, b); }
__forceinline const bool8 operator |( const bool8& a, const bool8& b ) { return _mm256_or_ps (a, b); }
__forceinline const bool8 operator ^( const bool8& a, const bool8& b ) { return _mm256_xor_ps(a, b); }
__forceinline bool8 operator &=( bool8& a, const bool8& b ) { return a = a & b; }
__forceinline bool8 operator |=( bool8& a, const bool8& b ) { return a = a | b; }
__forceinline bool8 operator ^=( bool8& a, const bool8& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator !=( const bool8& a, const bool8& b ) { return _mm256_xor_ps(a, b); }
__forceinline const bool8 operator ==( const bool8& a, const bool8& b ) { return _mm256_xor_ps(_mm256_xor_ps(a,b),bool8(embree::True)); }
__forceinline const bool8 select( const bool8& mask, const bool8& t, const bool8& f ) {
return _mm256_blendv_ps(f, t, mask);
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool8 unpacklo( const bool8& a, const bool8& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
__forceinline bool8 unpackhi( const bool8& a, const bool8& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
template<size_t i> __forceinline const bool8 shuffle( const bool8& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
}
template<size_t i0, size_t i1> __forceinline const bool8 shuffle( const bool8& a ) {
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const bool8 shuffle( const bool8& a, const bool8& b) {
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool8 shuffle( const bool8& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool8 shuffle( const bool8& a, const bool8& b ) {
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<> __forceinline const bool8 shuffle<0, 0, 2, 2>( const bool8& b ) { return _mm256_moveldup_ps(b); }
template<> __forceinline const bool8 shuffle<1, 1, 3, 3>( const bool8& b ) { return _mm256_movehdup_ps(b); }
template<> __forceinline const bool8 shuffle<0, 1, 0, 1>( const bool8& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
template<size_t i> __forceinline const bool8 insert (const bool8& a, const bool4& b) { return _mm256_insertf128_ps (a,b,i); }
template<size_t i> __forceinline const bool4 extract(const bool8& a ) { return _mm256_extractf128_ps(a ,i); }
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const bool8& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool reduce_or ( const bool8& a ) { return !_mm256_testz_ps(a,a); }
__forceinline bool all ( const bool8& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool any ( const bool8& a ) { return !_mm256_testz_ps(a,a); }
__forceinline bool none ( const bool8& a ) { return _mm256_testz_ps(a,a) != 0; }
__forceinline bool all ( const bool8& valid, const bool8& b ) { return all(!valid | b); }
__forceinline bool any ( const bool8& valid, const bool8& b ) { return any( valid & b); }
__forceinline bool none ( const bool8& valid, const bool8& b ) { return none(valid & b); }
__forceinline unsigned int movemask( const bool8& a ) { return _mm256_movemask_ps(a); }
__forceinline size_t popcnt ( const bool8& a ) { return __popcnt(_mm256_movemask_ps(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const bool8& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+971
View File
@@ -0,0 +1,971 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 16-wide MIC float type. */
class float16
{
public:
typedef bool16 Mask; // mask type for us
enum { size = 16 }; // number of SIMD elements
union {
__m512 v;
float f[16];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float16() {}
__forceinline float16(const float16& t) { v = t; };
__forceinline float16& operator=(const float16& f) { v = f.v; return *this; };
__forceinline float16(const __m512& t) { v = t; };
__forceinline operator __m512 () const { return v; };
__forceinline float16(const float& f) {
v = _mm512_set_1to16_ps(f);
}
__forceinline float16(const float& a, const float& b, const float& c, const float& d) {
v = _mm512_set_4to16_ps(a,b,c,d);
}
__forceinline explicit float16(const __m512i& a) {
#if defined(__AVX512F__)
v = _mm512_cvt_roundepi32_ps(a,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
#else
v = _mm512_cvtfxpnt_round_adjustepi32_ps(a, _MM_FROUND_NO_EXC,_MM_EXPADJ_NONE);
#endif
}
static __forceinline void store(void* addr, const float16& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_NONE,0);
}
static __forceinline void store(const bool16& mask, void* addr, const float16& v2) {
_mm512_mask_extstore_ps(addr,mask,v2,_MM_DOWNCONV_PS_NONE,0);
}
static __forceinline void storeu(float* ptr, const float16& f ) {
#if defined(__AVX512F__)
_mm512_storeu_ps(ptr,f);
#else
_mm512_extpackstorelo_ps(ptr+0 ,f, _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps(ptr+16 ,f, _MM_DOWNCONV_PS_NONE , 0);
#endif
}
static __forceinline void storeu(const bool16& mask, float* ptr, const float16& f ) {
#if defined(__AVX512F__)
_mm512_mask_storeu_ps(ptr,mask,f);
#else
float16 r = float16::undefined();
r = _mm512_extloadunpacklo_ps(r, ptr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_extloadunpackhi_ps(r, ptr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_mask_blend_ps(mask,r,f);
_mm512_extpackstorelo_ps(ptr, r, _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps(ptr+16 ,r, _MM_DOWNCONV_PS_NONE , 0);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline float16( ZeroTy ) : v(_mm512_setzero_ps()) {}
__forceinline float16( OneTy ) : v(_mm512_set_1to16_ps(1.0f)) {}
__forceinline float16( PosInfTy ) : v(_mm512_set_1to16_ps(pos_inf)) {}
__forceinline float16( NegInfTy ) : v(_mm512_set_1to16_ps(neg_inf)) {}
__forceinline float16( StepTy ) : v(_mm512_set_16to16_ps(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
__forceinline float16( NaNTy ) : v(_mm512_set_1to16_ps(nan)) {}
__forceinline static float16 undefined() { return _mm512_undefined(); }
__forceinline static float16 zero() { return _mm512_setzero_ps(); }
__forceinline static float16 one () { return _mm512_set_1to16_ps(1.0f); }
__forceinline static float16 ulp () { return _mm512_set_1to16_ps(embree::ulp); }
__forceinline static float16 inf () { return _mm512_set_1to16_ps((float)pos_inf); }
__forceinline static float16 minus_inf () { return _mm512_set_1to16_ps((float)neg_inf); }
static __forceinline float16 loadu(const void* addr)
{
#if defined(__AVX512F__)
return _mm512_loadu_ps(addr);
#else
float16 r = float16::undefined();
r =_mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
return _mm512_extloadunpackhi_ps(r, (float*)addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
#endif
}
static __forceinline float16 load(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline float& operator[](const size_t index) { return f[index]; };
__forceinline const float& operator[](const size_t index) const { return f[index]; };
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float16 cast (const __m512i& a) { return _mm512_castsi512_ps(a); }
__forceinline const float16 operator +( const float16& a ) { return a; }
__forceinline const float16 operator -( const float16& a ) { return _mm512_mul_ps(a,float16(-1)); }
__forceinline const float16 abs ( const float16& a ) {
#if defined(__AVX512F__)
return _mm512_abs_ps(a);
#else
return _mm512_gmaxabs_ps(a,a);
#endif
}
__forceinline const float16 signmsk ( const float16& a ) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
__forceinline const float16 rcp ( const float16& a ) {
#if defined(__AVX512F__)
return _mm512_rcp28_ps(a);
#else
return _mm512_rcp23_ps(a);
#endif
};
__forceinline const float16 sqr ( const float16& a ) { return _mm512_mul_ps(a,a); }
__forceinline const float16 sqrt ( const float16& a ) { return _mm512_sqrt_ps(a); }
__forceinline const float16 rsqrt( const float16& a ) { return _mm512_invsqrt_ps(a); }
__forceinline float16 exp(const float16& a) { return _mm512_exp_ps(a); }
__forceinline float16 exp2(const float16& a) { return _mm512_exp2_ps(a); }
__forceinline float16 pow(const float16& a, float16 b) { return _mm512_pow_ps(a,b); }
__forceinline float16 log(const float16& a) { return _mm512_log_ps(a); }
__forceinline float16 log2(const float16& a) { return _mm512_log2_ps(a); }
__forceinline float16 log10(const float16& a) { return _mm512_log10_ps(a); }
__forceinline float16 sin(const float16& a) { return _mm512_sin_ps(a); }
__forceinline float16 cos(const float16& a) { return _mm512_cos_ps(a); }
__forceinline float16 tan(const float16& a) { return _mm512_tan_ps(a); }
__forceinline float16 asin(const float16& a) { return _mm512_asin_ps(a); }
__forceinline float16 acos(const float16& a) { return _mm512_acos_ps(a); }
__forceinline float16 atan(const float16& a) { return _mm512_atan_ps(a); }
__forceinline float16 atan2(const float16& a, float16 b) { return _mm512_atan2_ps(a,b); }
__forceinline float16 sinh(const float16& a) { return _mm512_sinh_ps(a); }
__forceinline float16 cosh(const float16& a) { return _mm512_cosh_ps(a); }
__forceinline float16 tanh(const float16& a) { return _mm512_tan_ps(a); }
__forceinline float16 asinh(const float16& a) { return _mm512_asinh_ps(a); }
__forceinline float16 acosh(const float16& a) { return _mm512_acosh_ps(a); }
__forceinline float16 atanh(const float16& a) { return _mm512_atanh_ps(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float16 operator +( const float16& a, const float16& b ) { return _mm512_add_ps(a, b); }
__forceinline const float16 operator +( const float16& a, const float& b ) { return a + float16(b); }
__forceinline const float16 operator +( const float& a, const float16& b ) { return float16(a) + b; }
__forceinline const float16 operator -( const float16& a, const float16& b ) { return _mm512_sub_ps(a, b); }
__forceinline const float16 operator -( const float16& a, const float& b ) { return a - float16(b); }
__forceinline const float16 operator -( const float& a, const float16& b ) { return float16(a) - b; }
__forceinline const float16 operator *( const float16& a, const float16& b ) { return _mm512_mul_ps(a, b); }
__forceinline const float16 operator *( const float16& a, const float& b ) { return a * float16(b); }
__forceinline const float16 operator *( const float& a, const float16& b ) { return float16(a) * b; }
__forceinline const float16 operator /( const float16& a, const float16& b ) { return _mm512_div_ps(a,b); }
__forceinline const float16 operator /( const float16& a, const float& b ) { return a/float16(b); }
__forceinline const float16 operator /( const float& a, const float16& b ) { return float16(a)/b; }
__forceinline const float16 operator^(const float16& a, const float16& b) {
return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b)));
}
__forceinline const float16 min( const float16& a, const float16& b ) {
#if defined(__AVX512F__)
return _mm512_min_ps(a,b);
#else
return _mm512_gmin_ps(a,b);
#endif
}
__forceinline const float16 min( const float16& a, const float& b ) {
#if defined(__AVX512F__)
return _mm512_min_ps(a,float16(b));
#else
return _mm512_gmin_ps(a,float16(b));
#endif
}
__forceinline const float16 min( const float& a, const float16& b ) {
#if defined(__AVX512F__)
return _mm512_min_ps(float16(a),b);
#else
return _mm512_gmin_ps(float16(a),b);
#endif
}
__forceinline const float16 max( const float16& a, const float16& b ) {
#if defined(__AVX512F__)
return _mm512_max_ps(a,b);
#else
return _mm512_gmax_ps(a,b);
#endif
}
__forceinline const float16 max( const float16& a, const float& b ) {
#if defined(__AVX512F__)
return _mm512_max_ps(a,float16(b));
#else
return _mm512_gmax_ps(a,float16(b));
#endif
}
__forceinline const float16 max( const float& a, const float16& b ) {
#if defined(__AVX512F__)
return _mm512_max_ps(float16(a),b);
#else
return _mm512_gmax_ps(float16(a),b);
#endif
}
__forceinline float16 mask_add(const bool16& mask, const float16& c, const float16& a, const float16& b) { return _mm512_mask_add_ps (c,mask,a,b); };
__forceinline float16 mask_min(const bool16& mask, const float16& c, const float16& a, const float16& b) {
#if defined(__AVX512F__)
return _mm512_mask_min_ps(c,mask,a,b);
#else
return _mm512_mask_gmin_ps(c,mask,a,b);
#endif
};
__forceinline float16 mask_max(const bool16& mask, const float16& c, const float16& a, const float16& b) {
#if defined(__AVX512F__)
return _mm512_mask_max_ps(c,mask,a,b);
#else
return _mm512_mask_gmax_ps(c,mask,a,b);
#endif
};
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 madd (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_ps(a,b,c); }
__forceinline float16 msub (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline float16 nmadd (const float16& a, const float16& b, const float16& c) { return _mm512_fnmadd_ps(a,b,c); }
__forceinline float16 nmsub (const float16& a, const float16& b, const float16& c) { return _mm512_fnmsub_ps(a,b,c); }
__forceinline float16 mask_msub (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_ps(a,mask,b,c); }
__forceinline float16 madd231 (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_ps(c,b,a); }
__forceinline float16 msub213 (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline float16 msub231 (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(c,b,a); }
__forceinline float16 msubr231(const float16& a, const float16& b, const float16& c) { return _mm512_fnmadd_ps(c,b,a); }
////////////////////////////////////////////////////////////////////////////////
/// Operators with rounding
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 madd_round_down (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 madd_round_up (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_POS_INF); }
__forceinline float16 mul_round_down (const float16& a, const float16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 mul_round_up (const float16& a, const float16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
__forceinline float16 add_round_down (const float16& a, const float16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 add_round_up (const float16& a, const float16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
__forceinline float16 sub_round_down (const float16& a, const float16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 sub_round_up (const float16& a, const float16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
__forceinline float16 div_round_down (const float16& a, const float16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 div_round_up (const float16& a, const float16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
__forceinline float16 mask_msub_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 mask_msub_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
__forceinline float16 mask_mul_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 mask_mul_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
__forceinline float16 mask_sub_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
__forceinline float16 mask_sub_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float16& operator +=( float16& a, const float16& b ) { return a = a + b; }
__forceinline float16& operator +=( float16& a, const float& b ) { return a = a + b; }
__forceinline float16& operator -=( float16& a, const float16& b ) { return a = a - b; }
__forceinline float16& operator -=( float16& a, const float& b ) { return a = a - b; }
__forceinline float16& operator *=( float16& a, const float16& b ) { return a = a * b; }
__forceinline float16& operator *=( float16& a, const float& b ) { return a = a * b; }
__forceinline float16& operator /=( float16& a, const float16& b ) { return a = a / b; }
__forceinline float16& operator /=( float16& a, const float& b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool16 operator ==( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline const bool16 operator ==( const float16& a, const float& b ) { return a == float16(b); }
__forceinline const bool16 operator ==( const float& a, const float16& b ) { return float16(a) == b; }
__forceinline const bool16 operator !=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline const bool16 operator !=( const float16& a, const float& b ) { return a != float16(b); }
__forceinline const bool16 operator !=( const float& a, const float16& b ) { return float16(a) != b; }
__forceinline const bool16 operator < ( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline const bool16 operator < ( const float16& a, const float& b ) { return a < float16(b); }
__forceinline const bool16 operator < ( const float& a, const float16& b ) { return float16(a) < b; }
__forceinline const bool16 operator >=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline const bool16 operator >=( const float16& a, const float& b ) { return a >= float16(b); }
__forceinline const bool16 operator >=( const float& a, const float16& b ) { return float16(a) >= b; }
__forceinline const bool16 operator > ( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline const bool16 operator > ( const float16& a, const float& b ) { return a > float16(b); }
__forceinline const bool16 operator > ( const float& a, const float16& b ) { return float16(a) > b; }
__forceinline const bool16 operator <=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline const bool16 operator <=( const float16& a, const float& b ) { return a <= float16(b); }
__forceinline const bool16 operator <=( const float& a, const float16& b ) { return float16(a) <= b; }
__forceinline bool16 eq( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline bool16 eq(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_EQ); }
__forceinline bool16 ne( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline bool16 ne(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_NE); }
__forceinline bool16 lt( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline bool16 lt(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LT); }
__forceinline bool16 ge( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline bool16 ge(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GE); }
__forceinline bool16 gt( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline bool16 gt(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GT); }
__forceinline bool16 le( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline bool16 le(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LE); }
__forceinline const float16 select( const bool16& s, const float16& t, const float16& f ) {
return _mm512_mask_blend_ps(s, f, t);
}
__forceinline float16 lerp(const float16& a, const float16& b, const float16& t) {
return madd(t, b, madd(-t, a, a));
}
__forceinline void xchg(bool16 m, float16& a, float16& b)
{
float16 c = a;
a = select(m,b,a);
b = select(m,c,b);
}
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 vround(const float16& f,
const _MM_ROUND_MODE_ENUM mode,
const _MM_EXP_ADJ_ENUM exp = _MM_EXPADJ_NONE)
{
return _mm512_round_ps(f,mode,exp);
}
__forceinline float16 floor(const float16& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_DOWN, _MM_EXPADJ_NONE); }
__forceinline float16 ceil (const float16& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_UP , _MM_EXPADJ_NONE); }
__forceinline float16 trunc(const float16& a) { return _mm512_trunc_ps(a); }
__forceinline float16 frac( const float16& a ) { return a-trunc(a); }
__forceinline const float16 rcp_nr ( const float16& a ) {
const float16 ra = _mm512_rcp23_ps(a);
return (ra+ra) - (ra * a * ra);
};
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 swizzle(const float16& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_ps(x,perm32); }
__forceinline float16 permute(const float16& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_ps(x,perm128); }
template<int D, int C, int B, int A> __forceinline float16 swizzle (const float16& v) { return _mm512_shuffle_ps(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline float16 swizzle (const float16& x) { return swizzle<A,A,A,A>(v); }
template<> __forceinline float16 swizzle<0>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
template<> __forceinline float16 swizzle<1>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
template<> __forceinline float16 swizzle<2>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
template<> __forceinline float16 swizzle<3>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
template<int D, int C, int B, int A> __forceinline float16 permute(const float16& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline float16 permute(const float16& x) { return permute<A,A,A,A>(x); }
__forceinline float16 shuffle(const float16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
__forceinline float16 shuffle(const bool16& mask, float16& v, const float16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) {
return _mm512_mask_swizzle_ps(_mm512_mask_permute4f128_ps(v,mask,x,perm128),mask,x,perm32);
}
__forceinline float16 swAAAA(const float16 &x) {
return swizzle(x,_MM_SWIZ_REG_AAAA);
}
__forceinline float16 swBBBB(const float16 &x) {
return swizzle(x,_MM_SWIZ_REG_BBBB);
}
__forceinline float16 swCCCC(const float16 &x) {
return swizzle(x,_MM_SWIZ_REG_CCCC);
}
__forceinline float16 swDDDD(const float16 &x) {
return swizzle(x,_MM_SWIZ_REG_DDDD);
}
__forceinline float16 _mm512_permutev_ps(__m512i index, float16 v)
{
return _mm512_castsi512_ps(_mm512_permutev_epi32(index,_mm512_castps_si512(v)));
}
__forceinline float16 permute16f(__m512i index, float16 v)
{
return _mm512_castsi512_ps(_mm512_permutev_epi32(index,_mm512_castps_si512(v)));
}
template<int i>
__forceinline float16 align_shift_right(const float16 &a, const float16 &b)
{
return _mm512_castsi512_ps(_mm512_alignr_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b),i));
};
template<int i>
__forceinline float16 mask_align_shift_right(const bool16 &mask,float16 &c,const float16 &a, const float16 &b)
{
return _mm512_castsi512_ps(_mm512_mask_alignr_epi32(_mm512_castps_si512(c),mask,_mm512_castps_si512(a),_mm512_castps_si512(b),i));
};
__forceinline float16 shl1_zero_extend(const float16 &a)
{
float16 z = float16::zero();
return mask_align_shift_right<15>(0xfffe,z,a,a);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline float reduce_add(float16 a) { return _mm512_reduce_add_ps(a); }
__forceinline float reduce_mul(float16 a) { return _mm512_reduce_mul_ps(a); }
__forceinline float reduce_min(float16 a) {
#if defined(__AVX512F__)
return _mm512_reduce_min_ps(a);
#else
return _mm512_reduce_gmin_ps(a);
#endif
}
__forceinline float reduce_max(float16 a) {
#if defined(__AVX512F__)
return _mm512_reduce_max_ps(a);
#else
return _mm512_reduce_gmax_ps(a);
#endif
}
__forceinline float16 vreduce_min2(float16 x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline float16 vreduce_min4(float16 x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline float16 vreduce_min8(float16 x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline float16 vreduce_min (float16 x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline float16 vreduce_max2(float16 x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline float16 vreduce_max4(float16 x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline float16 vreduce_max8(float16 x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline float16 vreduce_max (float16 x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline float16 vreduce_add2(float16 x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline float16 vreduce_add4(float16 x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline float16 vreduce_add8(float16 x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline float16 vreduce_add (float16 x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline size_t select_min(const float16& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const float16& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool16& valid, const float16& v, const float16 &max_value) { const float16 a = select(valid,v,max_value); return __bsf(movemask(a == vreduce_min(a))); }
__forceinline size_t select_max(const bool16& valid, const float16& v, const float16 &min_value) { const float16 a = select(valid,v,min_value); return __bsf(movemask(a == vreduce_max(a))); }
__forceinline size_t select_max(const bool16& valid, const float16& v) { const float16 a = select(valid,v,float16(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
__forceinline size_t select_min(const bool16& valid, const float16& v) { const float16 a = select(valid,v,float16(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline float16 prefix_sum(const float16& a)
{
float16 v = a;
v = mask_add(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
v = mask_add(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
const float16 shuf_v0 = shuffle(v,_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
v = mask_add(0xf0f0,v,v,shuf_v0);
const float16 shuf_v1 = shuffle(v,_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
v = mask_add(0xff00,v,v,shuf_v1);
return v;
}
__forceinline float16 prefix_min(const float16& a)
{
float16 v = a;
v = mask_min(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
v = mask_min(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
const float16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
v = mask_min(0xf0f0,v,v,shuf_v0);
const float16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
v = mask_min(0xff00,v,v,shuf_v1);
return v;
}
__forceinline float16 prefix_max(const float16& a)
{
float16 v = a;
v = mask_max(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
v = mask_max(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
const float16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
v = mask_max(0xf0f0,v,v,shuf_v0);
const float16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
v = mask_max(0xff00,v,v,shuf_v1);
return v;
}
__forceinline float16 set_min4(float16 x) {
x = min(x,swizzle(x,_MM_SWIZ_REG_BADC));
x = min(x,swizzle(x,_MM_SWIZ_REG_CDAB));
return x;
}
__forceinline float16 set_min_lanes(float16 x) {
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
return x;
}
__forceinline float16 set_max_lanes(float16 x) {
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
return x;
}
__forceinline float16 set_min16(float16 x) {
return set_min_lanes(set_min4(x));
}
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 load1f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline float16 load16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline float16 load16f(const float16 d, const bool16 valid, const void *f) {
return _mm512_mask_extload_ps(d,valid,f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline float16 broadcast1to16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline float16 broadcast4to16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,0);
}
__forceinline float16 broadcast8to16f(const void *f) {
return _mm512_castpd_ps(_mm512_extload_pd(f,_MM_UPCONV_PD_NONE,_MM_BROADCAST_4X8,0));
}
__forceinline float16 load16f_uint8(const unsigned char *const ptr) {
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_UINT8,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/255.0f));
}
__forceinline float16 load16f_uint16(const unsigned short *const ptr) {
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_UINT16,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/65535.0f));
}
#if !defined(__AVX512F__)
__forceinline float16 uload16f_low_uint8(const bool16& mask, const void* addr, const float16& v1) {
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_UINT8, _MM_HINT_NONE);
}
#endif
__forceinline float16 load16f_int8(const char *const ptr) {
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_SINT8,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/127.0f));
}
__forceinline float16 gather16f_4f(const float *__restrict__ const ptr0,
const float *__restrict__ const ptr1,
const float *__restrict__ const ptr2,
const float *__restrict__ const ptr3)
{
float16 v = broadcast4to16f(ptr0);
v = select((bool16)0x00f0,broadcast4to16f(ptr1),v);
v = select((bool16)0x0f00,broadcast4to16f(ptr2),v);
v = select((bool16)0xf000,broadcast4to16f(ptr3),v);
return v;
}
__forceinline float16 gather16f_4f(const float16& v0,
const float16& v1,
const float16& v2,
const float16& v3)
{
float16 v = v0;
v = select((bool16)0xf0 ,v1,v);
v = select((bool16)0xf00 ,v2,v);
v = select((bool16)0xf000,v3,v);
return v;
}
__forceinline float16 gather_4f_zlc(const int16 &v_mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
const bool16 m_00f0 = 0x00f0;
const bool16 m_0f00 = 0x0f00;
const bool16 m_f000 = 0xf000;
int16 v = v_mask & broadcast4to16i((const int*)ptr0);
v = mask_and(m_00f0,v,v_mask, broadcast4to16i((const int*)ptr1));
v = mask_and(m_0f00,v,v_mask, broadcast4to16i((const int*)ptr2));
v = mask_and(m_f000,v,v_mask, broadcast4to16i((const int*)ptr3));
return cast(v);
}
__forceinline float16 gather_2f_zlc(const int16 &v_mask,
const bool16 &mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1)
{
int16 v = v_mask & broadcast4to16i((const int*)ptr0);
v = mask_and(mask,v,v_mask, broadcast4to16i((const int*)ptr1));
return cast(v);
}
__forceinline float16 gather16f_4f_align(const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
float16 v = broadcast4to16f(ptr3);
v = align_shift_right<12>(v,broadcast4to16f(ptr2));
v = align_shift_right<12>(v,broadcast4to16f(ptr1));
v = align_shift_right<12>(v,broadcast4to16f(ptr0));
return v;
}
__forceinline float16 gather16f_4f_align(const float16& v0,
const float16& v1,
const float16& v2,
const float16& v3)
{
float16 v = v3;
v = align_shift_right<12>(v,v2);
v = align_shift_right<12>(v,v1);
v = align_shift_right<12>(v,v0);
return v;
}
__forceinline float16 gather_4f_zlc_align(const int16 &v_mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
float16 v = gather16f_4f_align(ptr0,ptr1,ptr2,ptr3);
return cast(cast(v) & v_mask);
}
__forceinline float16 uload16f(const bool16& mask,const float *const addr) {
float16 r = float16::undefined();
r =_mm512_mask_extloadunpacklo_ps(r, mask,addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_mask_extloadunpackhi_ps(r, mask, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
return r;
}
__forceinline float16 uload16f(float16 &r, const bool16& mask, const float *const addr) {
r =_mm512_mask_extloadunpacklo_ps(r, mask,addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_mask_extloadunpackhi_ps(r, mask, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
return r;
}
__forceinline float16 uload16f(const float *const addr) {
float16 r = float16::undefined();
r =_mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
return _mm512_extloadunpackhi_ps(r, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline float16 uload16f_low(const float *const addr) {
float16 r = float16::undefined();
return _mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline float16 uload16f_low(const bool16& mask, const void* addr, const float16& v1) {
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline float16 uload16f_low(const bool16& mask, const void* addr) {
float16 v1 = float16::undefined();
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline void ustore16f(float *addr, const float16& reg) {
#if defined(__AVX512F__)
_mm512_storeu_ps(addr,reg);
#else
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps(addr+16 ,reg, _MM_DOWNCONV_PS_NONE , 0);
#endif
}
/* pass by value to avoid compiler generating inefficient code */
__forceinline void compactustore16f(const bool16& mask, float *addr, const float16 reg) {
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
_mm512_mask_extpackstorehi_ps(addr+16 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void compactustore16f_low(const bool16& mask, float * addr, const float16 &reg) {
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void compactustore16f_low_uint8(const bool16& mask, void * addr, const float16 &reg) {
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_UINT8 , 0);
}
__forceinline void ustore16f_low(float * addr, const float16& reg) {
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void compactustore16f_high(const bool16& mask, float *addr, const float16& reg) {
_mm512_extpackstorehi_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void store16f(const bool16& mask, void* addr, const float16& v2) {
_mm512_mask_extstore_ps(addr,mask,v2,_MM_DOWNCONV_PS_NONE,0);
}
__forceinline void store16f(void* addr, const float16& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_NONE,0);
}
__forceinline void store16f_int8(void* addr, const float16& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_SINT8,0);
}
__forceinline void store16f_uint16(void* addr, const float16& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_UINT16,0);
}
__forceinline void store4f_int8(void* addr, const float16& v1) {
assert((unsigned long)addr % 4 == 0);
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_SINT8 , 0);
}
__forceinline void store4f(void* addr, const float16& v1) {
assert((unsigned long)addr % 16 == 0);
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void store3f(void* addr, const float16& v1) {
assert((unsigned long)addr % 16 == 0);
_mm512_mask_extpackstorelo_ps(addr,0x7, v1, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void store4f_nt(void* addr, const float16& v1) {
assert((unsigned long)addr % 16 == 0);
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_NONE , _MM_HINT_NT);
}
__forceinline void store16f_nt(void *__restrict__ ptr, const float16& a) {
_mm512_storenr_ps(ptr,a);
}
__forceinline void store16f_ngo(void *__restrict__ ptr, const float16& a) {
_mm512_storenrngo_ps(ptr,a);
}
__forceinline void store1f(void *addr, const float16& reg) {
_mm512_mask_extpackstorelo_ps((float*)addr+0 ,(bool16)1, reg, _MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline float16 gather16f(const bool16& mask, const float *const ptr, __m512i index, const _MM_INDEX_SCALE_ENUM scale) {
float16 r = float16::undefined();
return _mm512_mask_i32extgather_ps(r,mask,index,ptr,_MM_UPCONV_PS_NONE,scale,0);
}
__forceinline void scatter16f(const bool16& mask,const float *const ptr, const __m512i index,const float16 v, const _MM_INDEX_SCALE_ENUM scale) {
_mm512_mask_i32extscatter_ps((void*)ptr,mask,index,v,_MM_DOWNCONV_PS_NONE,scale,0);
}
__forceinline float16 loadAOS4to16f(const float& x,const float& y, const float& z)
{
float16 f = float16::zero();
f = select(0x1111,broadcast1to16f(&x),f);
f = select(0x2222,broadcast1to16f(&y),f);
f = select(0x4444,broadcast1to16f(&z),f);
return f;
}
__forceinline float16 loadAOS4to16f(const unsigned int index,
const float16 &x,
const float16 &y,
const float16 &z)
{
float16 f = float16::zero();
f = select(0x1111,broadcast1to16f((float*)&x + index),f);
f = select(0x2222,broadcast1to16f((float*)&y + index),f);
f = select(0x4444,broadcast1to16f((float*)&z + index),f);
return f;
}
__forceinline float16 loadAOS4to16f(const unsigned int index,
const float16 &x,
const float16 &y,
const float16 &z,
const float16 &fill)
{
float16 f = fill;
f = select(0x1111,broadcast1to16f((float*)&x + index),f);
f = select(0x2222,broadcast1to16f((float*)&y + index),f);
f = select(0x4444,broadcast1to16f((float*)&z + index),f);
return f;
}
__forceinline float16 gather16f_4f_unalign(const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
float16 v = permute<0>(uload16f((float*)ptr3));
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr2)));
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr1)));
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr0)));
return v;
}
__forceinline float16 rcp_safe( const float16& a ) { return select(a != float16::zero(),_mm512_rcp23_ps(a),float16(1E-10f)); };
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float16 lcross_zxy(const float16 &ao, const float16 &bo) {
float16 ao_bo = bo * swizzle(ao,_MM_SWIZ_REG_DACB);
ao_bo = msub231(ao_bo,ao,swizzle(bo,_MM_SWIZ_REG_DACB));
return ao_bo;
}
__forceinline float16 ldot16_zxy(const float16 &a,const float16 &v0, const float16 &v1, const float16 &v2)
{
float16 v = v0 * swizzle(a,_MM_SWIZ_REG_BBBB);
v = madd231(v,v1,swizzle(a,_MM_SWIZ_REG_CCCC));
v = madd231(v,v2,swizzle(a,_MM_SWIZ_REG_AAAA));
return v;
}
__forceinline float16 ldot16_xyz(const float16 &a,const float16 &v0, const float16 &v1, const float16 &v2)
{
float16 v = v0 * swizzle(a,_MM_SWIZ_REG_AAAA);
v = madd231(v, v1,swizzle(a,_MM_SWIZ_REG_BBBB));
v = madd231(v, v2,swizzle(a,_MM_SWIZ_REG_CCCC));
return v;
}
__forceinline float16 lcross_xyz(const float16 &a, const float16 &b)
{
float16 c = b * swizzle(a,_MM_SWIZ_REG_DACB);
c = msub231(c,a,swizzle(b,_MM_SWIZ_REG_DACB));
c = swizzle(c,_MM_SWIZ_REG_DACB);
return c;
}
__forceinline float16 ldot3_xyz(const float16 &ao, const float16 &normal)
{
float16 vv = ao * normal;
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
return vv;
}
__forceinline float16 lsum3_xyz(const float16 &v)
{
float16 vv = v;
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
return vv;
}
__forceinline float16 ldot3_xyz(const bool16 &m_mask, const float16 &ao, const float16 &normal)
{
float16 vv = _mm512_mask_mul_ps(ao,m_mask,ao,normal);
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
return vv;
}
__forceinline float16 ldot3_zxy(const float16 &ao, const float16 &normal)
{
float16 vv = ao * swizzle(normal,_MM_SWIZ_REG_DACB);
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
return vv;
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline std::ostream &operator<<(std::ostream& cout, const float16& v)
{
cout << "<" << v[0];
for (int i=1; i<16; i++) cout << ", " << v[i];
cout << ">";
return cout;
}
}
+539
View File
@@ -0,0 +1,539 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#define EMBREE_FLOAT4
namespace embree
{
/*! 4-wide SSE float type. */
struct float4
{
typedef bool4 Mask; // mask type
typedef int4 Int; // int type
typedef float4 Float; // float type
enum { size = 4 }; // number of SIMD elements
union { __m128 m128; float f[4]; int i[4]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float4 ( ) {}
__forceinline float4 ( const float4& other ) { m128 = other.m128; }
__forceinline float4& operator=( const float4& other ) { m128 = other.m128; return *this; }
__forceinline float4( const __m128 a ) : m128(a) {}
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
__forceinline float4 ( float a ) : m128(_mm_set1_ps(a)) {}
__forceinline float4 ( float a, float b, float c, float d) : m128(_mm_set_ps(d, c, b, a)) {}
__forceinline explicit float4( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline float4( ZeroTy ) : m128(_mm_setzero_ps()) {}
__forceinline float4( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
__forceinline float4( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
__forceinline float4( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
__forceinline float4( StepTy ) : m128(_mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)) {}
__forceinline float4( NaNTy ) : m128(_mm_set1_ps(nan)) {}
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX__)
static __forceinline float4 broadcast( const void* const a ) { return _mm_broadcast_ss((float*)a); }
#else
static __forceinline float4 broadcast( const void* const a ) { return _mm_set1_ps(*(float*)a); }
#endif
static __forceinline float4 load( const float* const a ) {
return _mm_load_ps(a);
}
static __forceinline float4 loadu( const void* const a ) {
return _mm_loadu_ps((float*)a);
}
static __forceinline float4 load_nt ( const float* ptr ) {
#if defined (__SSE4_1__)
return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
#else
return _mm_load_ps(ptr);
#endif
}
#if defined(__SSE4_1__)
static __forceinline float4 load( const unsigned char* const ptr ) {
return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
}
#else
static __forceinline float4 load( const unsigned char* const ptr ) {
//return _mm_cvtpu8_ps(*(__m64*)ptr); // don't enable, will use MMX instructions
return float4(ptr[0],ptr[1],ptr[2],ptr[3]);
}
#endif
static __forceinline float4 load(const unsigned short* const ptr) {
return _mm_mul_ps(float4(int4::load(ptr)),float4(1.0f/65535.0f));
}
static __forceinline void store ( void* ptr, const float4& v ) {
_mm_store_ps((float*)ptr,v);
}
static __forceinline void storeu ( void* ptr, const float4& v ) {
_mm_storeu_ps((float*)ptr,v);
}
static __forceinline void storeu ( float* ptr, const float4& v, size_t n) // FIXME: is there a better way of implementing this
{
if (n >= 1) ptr[0] = v[0];
if (n >= 2) ptr[1] = v[1];
if (n >= 3) ptr[2] = v[2];
if (n >= 4) ptr[3] = v[3];
}
static __forceinline void store_nt ( float4* ptr, const float4& v)
{
#if defined (__SSE4_1__)
_mm_stream_ps((float*)ptr,v);
#else
_mm_store_ps((float*)ptr,v);
#endif
}
static __forceinline void store ( const bool4& mask, void* ptr, const float4& f )
{
#if defined (__AVX__)
_mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
#else
*(float4*)ptr = select(mask,f,*(float4*)ptr);
#endif
}
static __forceinline void storeu( const bool4& mask, void* ptr, const float4& f ) {
return _mm_storeu_ps((float*)ptr,select(mask,f,_mm_loadu_ps((float*)ptr)));
}
static __forceinline void store ( const bool4& mask, void* ptr, const int4& ofs, const float4& v, const int scale = 1 )
{
if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
}
static __forceinline void store ( const bool4& mask, char* ptr, const int4& ofs, const float4& v ) {
store(mask,ptr,ofs,v,1);
}
static __forceinline void store ( const bool4& mask, float* ptr, const int4& ofs, const float4& v ) {
store(mask,ptr,ofs,v,4);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const float& operator []( const size_t i ) const { assert(i < 4); return f[i]; }
__forceinline float& operator []( const size_t i ) { assert(i < 4); return f[i]; }
friend __forceinline const float4 select( const bool4& m, const float4& t, const float4& f ) {
#if defined(__SSE4_1__)
return _mm_blendv_ps(f, t, m);
#else
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
#endif
}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float4 cast (const __m128i& a) { return _mm_castsi128_ps(a); }
__forceinline const float4 operator +( const float4& a ) { return a; }
__forceinline const float4 operator -( const float4& a ) { return _mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
__forceinline const float4 abs ( const float4& a ) { return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
__forceinline const float4 sign ( const float4& a ) { return blendv_ps(float4(one), -float4(one), _mm_cmplt_ps (a,float4(zero))); }
__forceinline const float4 signmsk ( const float4& a ) { return _mm_and_ps(a.m128,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
__forceinline const float4 rcp ( const float4& a ) {
const float4 r = _mm_rcp_ps(a.m128);
#if defined(__AVX2__)
return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, float4(2.0f)));
#else
return _mm_mul_ps(r,_mm_sub_ps(float4(2.0f), _mm_mul_ps(r, a)));
#endif
}
__forceinline const float4 sqr ( const float4& a ) { return _mm_mul_ps(a,a); }
__forceinline const float4 sqrt ( const float4& a ) { return _mm_sqrt_ps(a.m128); }
__forceinline const float4 rsqrt( const float4& a ) {
const float4 r = _mm_rsqrt_ps(a.m128);
return _mm_add_ps(_mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r), _mm_mul_ps(r, r)));
}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float4 operator +( const float4& a, const float4& b ) { return _mm_add_ps(a.m128, b.m128); }
__forceinline const float4 operator +( const float4& a, const float& b ) { return a + float4(b); }
__forceinline const float4 operator +( const float& a, const float4& b ) { return float4(a) + b; }
__forceinline const float4 operator -( const float4& a, const float4& b ) { return _mm_sub_ps(a.m128, b.m128); }
__forceinline const float4 operator -( const float4& a, const float& b ) { return a - float4(b); }
__forceinline const float4 operator -( const float& a, const float4& b ) { return float4(a) - b; }
__forceinline const float4 operator *( const float4& a, const float4& b ) { return _mm_mul_ps(a.m128, b.m128); }
__forceinline const float4 operator *( const float4& a, const float& b ) { return a * float4(b); }
__forceinline const float4 operator *( const float& a, const float4& b ) { return float4(a) * b; }
__forceinline const float4 operator /( const float4& a, const float4& b ) { return _mm_div_ps(a.m128,b.m128); }
__forceinline const float4 operator /( const float4& a, const float& b ) { return a/float4(b); }
__forceinline const float4 operator /( const float& a, const float4& b ) { return float4(a)/b; }
__forceinline const float4 operator^( const float4& a, const float4& b ) { return _mm_xor_ps(a.m128,b.m128); }
__forceinline const float4 operator^( const float4& a, const int4& b ) { return _mm_xor_ps(a.m128,_mm_castsi128_ps(b.m128)); }
__forceinline const float4 min( const float4& a, const float4& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline const float4 min( const float4& a, const float& b ) { return _mm_min_ps(a.m128,float4(b)); }
__forceinline const float4 min( const float& a, const float4& b ) { return _mm_min_ps(float4(a),b.m128); }
__forceinline const float4 max( const float4& a, const float4& b ) { return _mm_max_ps(a.m128,b.m128); }
__forceinline const float4 max( const float4& a, const float& b ) { return _mm_max_ps(a.m128,float4(b)); }
__forceinline const float4 max( const float& a, const float4& b ) { return _mm_max_ps(float4(a),b.m128); }
#if defined(__SSE4_1__)
__forceinline float4 mini(const float4& a, const float4& b) {
const int4 ai = _mm_castps_si128(a);
const int4 bi = _mm_castps_si128(b);
const int4 ci = _mm_min_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
#if defined(__SSE4_1__)
__forceinline float4 maxi(const float4& a, const float4& b) {
const int4 ai = _mm_castps_si128(a);
const int4 bi = _mm_castps_si128(b);
const int4 ci = _mm_max_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX2__)
__forceinline const float4 madd ( const float4& a, const float4& b, const float4& c) { return _mm_fmadd_ps(a,b,c); }
__forceinline const float4 msub ( const float4& a, const float4& b, const float4& c) { return _mm_fmsub_ps(a,b,c); }
__forceinline const float4 nmadd ( const float4& a, const float4& b, const float4& c) { return _mm_fnmadd_ps(a,b,c); }
__forceinline const float4 nmsub ( const float4& a, const float4& b, const float4& c) { return _mm_fnmsub_ps(a,b,c); }
#else
__forceinline const float4 madd ( const float4& a, const float4& b, const float4& c) { return a*b+c; }
__forceinline const float4 msub ( const float4& a, const float4& b, const float4& c) { return a*b-c; }
__forceinline const float4 nmadd ( const float4& a, const float4& b, const float4& c) { return -a*b+c;}
__forceinline const float4 nmsub ( const float4& a, const float4& b, const float4& c) { return -a*b-c; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float4& operator +=( float4& a, const float4& b ) { return a = a + b; }
__forceinline float4& operator +=( float4& a, const float& b ) { return a = a + b; }
__forceinline float4& operator -=( float4& a, const float4& b ) { return a = a - b; }
__forceinline float4& operator -=( float4& a, const float& b ) { return a = a - b; }
__forceinline float4& operator *=( float4& a, const float4& b ) { return a = a * b; }
__forceinline float4& operator *=( float4& a, const float& b ) { return a = a * b; }
__forceinline float4& operator /=( float4& a, const float4& b ) { return a = a / b; }
__forceinline float4& operator /=( float4& a, const float& b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator ==( const float4& a, const float4& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
__forceinline const bool4 operator ==( const float4& a, const float& b ) { return a == float4(b); }
__forceinline const bool4 operator ==( const float& a, const float4& b ) { return float4(a) == b; }
__forceinline const bool4 operator !=( const float4& a, const float4& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
__forceinline const bool4 operator !=( const float4& a, const float& b ) { return a != float4(b); }
__forceinline const bool4 operator !=( const float& a, const float4& b ) { return float4(a) != b; }
__forceinline const bool4 operator < ( const float4& a, const float4& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
__forceinline const bool4 operator < ( const float4& a, const float& b ) { return a < float4(b); }
__forceinline const bool4 operator < ( const float& a, const float4& b ) { return float4(a) < b; }
__forceinline const bool4 operator >=( const float4& a, const float4& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
__forceinline const bool4 operator >=( const float4& a, const float& b ) { return a >= float4(b); }
__forceinline const bool4 operator >=( const float& a, const float4& b ) { return float4(a) >= b; }
__forceinline const bool4 operator > ( const float4& a, const float4& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
__forceinline const bool4 operator > ( const float4& a, const float& b ) { return a > float4(b); }
__forceinline const bool4 operator > ( const float& a, const float4& b ) { return float4(a) > b; }
__forceinline const bool4 operator <=( const float4& a, const float4& b ) { return _mm_cmple_ps (a.m128, b.m128); }
__forceinline const bool4 operator <=( const float4& a, const float& b ) { return a <= float4(b); }
__forceinline const bool4 operator <=( const float& a, const float4& b ) { return float4(a) <= b; }
#if defined(__SSE4_1__)
#if defined(__clang__) || defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || defined(_DEBUG))
__forceinline const float4 select(const int mask, const float4& t, const float4& f) {
return select(bool4(mask), t, f);
}
#else
__forceinline const float4 select(const int mask, const float4& t, const float4& f) {
return _mm_blend_ps(f, t, mask);
}
#endif
#endif
__forceinline float4 lerp(const float4& a, const float4& b, const float4& t) {
#if defined(__AVX2__)
return madd(t, b, madd(-t, a, a));
#else
return a + t*(b-a);
#endif
}
__forceinline bool isvalid ( const float4& v ) {
return all((v > float4(-FLT_LARGE)) & (v < float4(+FLT_LARGE)));
}
__forceinline bool is_finite ( const float4& a ) {
return all((a >= float4(-FLT_MAX) & (a <= float4(+FLT_MAX))));
}
__forceinline bool is_finite ( const bool4& valid, const float4& a ) {
return all(valid, a >= float4(-FLT_MAX) & (a <= float4(+FLT_MAX)));
}
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
#if defined (__SSE4_1__)
__forceinline const float4 floor ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const float4 ceil ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline const float4 trunc ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
#else
__forceinline const float4 floor ( const float4& a ) { return float4(floorf(a[0]),floorf(a[1]),floorf(a[2]),floorf(a[3])); }
__forceinline const float4 ceil ( const float4& a ) { return float4(ceilf (a[0]),ceilf (a[1]),ceilf (a[2]),ceilf (a[3])); }
//__forceinline const float4 trunc ( const float4& a ) { return float4(truncf(a[0]),truncf(a[1]),truncf(a[2]),truncf(a[3])); }
#endif
__forceinline const float4 frac ( const float4& a ) { return a-floor(a); }
__forceinline int4 floori (const float4& a) {
#if defined (__SSE4_1__)
return int4(floor(a));
#else
return int4(a-float4(0.5f));
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline float4 unpacklo( const float4& a, const float4& b ) { return _mm_unpacklo_ps(a.m128, b.m128); }
__forceinline float4 unpackhi( const float4& a, const float4& b ) { return _mm_unpackhi_ps(a.m128, b.m128); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float4 shuffle( const float4& b ) {
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float4 shuffle( const float4& a, const float4& b ) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
#if defined (__SSSE3__)
__forceinline const float4 shuffle8(const float4& a, const int4& shuf) {
return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
}
#endif
#if defined(__SSE3__)
template<> __forceinline const float4 shuffle<0, 0, 2, 2>( const float4& b ) { return _mm_moveldup_ps(b); }
template<> __forceinline const float4 shuffle<1, 1, 3, 3>( const float4& b ) { return _mm_movehdup_ps(b); }
template<> __forceinline const float4 shuffle<0, 1, 0, 1>( const float4& b ) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))); }
#endif
template<size_t i0> __forceinline const float4 shuffle( const float4& b ) {
return shuffle<i0,i0,i0,i0>(b);
}
#if defined (__SSE4_1__) && !defined(__GNUC__)
template<size_t i> __forceinline float extract ( const float4& a ) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); }
#else
template<size_t i> __forceinline float extract ( const float4& a ) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
#endif
template<> __forceinline float extract<0>( const float4& a ) { return _mm_cvtss_f32(a); }
#if defined (__SSE4_1__)
template<size_t dst, size_t src, size_t clr> __forceinline const float4 insert( const float4& a, const float4& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<size_t dst, size_t src> __forceinline const float4 insert( const float4& a, const float4& b ) { return insert<dst, src, 0>(a, b); }
template<size_t dst> __forceinline const float4 insert( const float4& a, const float b ) { return insert<dst, 0>(a, _mm_set_ss(b)); }
#else
template<size_t dst, size_t src> __forceinline const float4 insert( const float4& a, const float4& b ) { float4 c = a; c[dst] = b[src]; return c; }
template<size_t dst> __forceinline const float4 insert( const float4& a, const float b ) { float4 c = a; c[dst] = b; return c; }
#endif
__forceinline float4 broadcast4f( const float4& a, const size_t k ) {
return float4::broadcast(&a[k]);
}
#if defined (__AVX2__)
__forceinline float4 permute(const float4 &a, const __m128i &index) {
return _mm_permutevar_ps(a,index);
}
__forceinline float4 broadcast1f( const void* const a ) { return _mm_broadcast_ss((float*)a); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
__forceinline void transpose(const float4& r0, const float4& r1, const float4& r2, const float4& r3, float4& c0, float4& c1, float4& c2, float4& c3)
{
float4 l02 = unpacklo(r0,r2);
float4 h02 = unpackhi(r0,r2);
float4 l13 = unpacklo(r1,r3);
float4 h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
c3 = unpackhi(h02,h13);
}
__forceinline void transpose(const float4& r0, const float4& r1, const float4& r2, const float4& r3, float4& c0, float4& c1, float4& c2)
{
float4 l02 = unpacklo(r0,r2);
float4 h02 = unpackhi(r0,r2);
float4 l13 = unpacklo(r1,r3);
float4 h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const float4 vreduce_min(const float4& v) { float4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline const float4 vreduce_max(const float4& v) { float4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline const float4 vreduce_add(const float4& v) { float4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
__forceinline float reduce_min(const float4& v) { return _mm_cvtss_f32(vreduce_min(v)); }
__forceinline float reduce_max(const float4& v) { return _mm_cvtss_f32(vreduce_max(v)); }
__forceinline float reduce_add(const float4& v) { return _mm_cvtss_f32(vreduce_add(v)); }
__forceinline size_t select_min(const float4& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const float4& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool4& valid, const float4& v) { const float4 a = select(valid,v,float4(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const bool4& valid, const float4& v) { const float4 a = select(valid,v,float4(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline float4 load4f( const void* const a ) {
return _mm_load_ps((float*)a);
}
__forceinline void store4f ( void* ptr, const float4& v ) {
_mm_store_ps((float*)ptr,v);
}
__forceinline float4 loadu4f( const void* const a ) {
return _mm_loadu_ps((float*)a);
}
__forceinline void storeu4f ( void* ptr, const float4& v ) {
_mm_storeu_ps((float*)ptr,v);
}
__forceinline void store4f ( const bool4& mask, void* ptr, const float4& f ) {
#if defined (__AVX__)
_mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
#else
*(float4*)ptr = select(mask,f,*(float4*)ptr);
#endif
}
__forceinline float4 load4f_nt (void* ptr) {
#if defined (__SSE4_1__)
return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
#else
return _mm_load_ps((float*)ptr);
#endif
}
__forceinline void store4f_nt (void* ptr, const float4& v) {
#if defined (__SSE4_1__)
_mm_stream_ps((float*)ptr,v);
#else
_mm_store_ps((float*)ptr,v);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float dot ( const float4& a, const float4& b ) {
return reduce_add(a*b);
}
__forceinline float4 cross ( const float4& a, const float4& b )
{
const float4 a0 = a;
const float4 b0 = shuffle<1,2,0,3>(b);
const float4 a1 = shuffle<1,2,0,3>(a);
const float4 b1 = b;
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const float4& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+540
View File
@@ -0,0 +1,540 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#define EMBREE_FLOAT8
namespace embree
{
/*! 8-wide AVX float type. */
struct float8
{
typedef bool8 Mask; // mask type for us
typedef int8 Int ; // int type for us
enum { size = 8 }; // number of SIMD elements
union { __m256 m256; float v[8]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float8 ( ) {}
__forceinline float8 ( const float8& other ) { m256 = other.m256; }
__forceinline float8& operator=( const float8& other ) { m256 = other.m256; return *this; }
__forceinline float8( const __m256 a ) : m256(a) {}
__forceinline operator const __m256&( void ) const { return m256; }
__forceinline operator __m256&( void ) { return m256; }
__forceinline explicit float8( const float4& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
__forceinline float8( const float4& a, const float4& b ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
__forceinline explicit float8( const char* const a ) : m256(_mm256_loadu_ps((const float*)a)) {}
__forceinline float8( const float& a ) : m256(_mm256_broadcast_ss(&a)) {}
__forceinline float8( float a, float b) : m256(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
__forceinline float8( float a, float b, float c, float d ) : m256(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
__forceinline float8( float a, float b, float c, float d, float e, float f, float g, float h ) : m256(_mm256_set_ps(h, g, f, e, d, c, b, a)) {}
__forceinline explicit float8( const __m256i a ) : m256(_mm256_cvtepi32_ps(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline float8( ZeroTy ) : m256(_mm256_setzero_ps()) {}
__forceinline float8( OneTy ) : m256(_mm256_set1_ps(1.0f)) {}
__forceinline float8( PosInfTy ) : m256(_mm256_set1_ps(pos_inf)) {}
__forceinline float8( NegInfTy ) : m256(_mm256_set1_ps(neg_inf)) {}
__forceinline float8( StepTy ) : m256(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
__forceinline float8( NaNTy ) : m256(_mm256_set1_ps(nan)) {}
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
static __forceinline float8 broadcast( const void* const a ) {
return _mm256_broadcast_ss((float*)a);
}
static __forceinline const float8 broadcast4f(const void* ptr) { // FIXME: float4 input type?
return _mm256_broadcast_ps((__m128*)ptr);
}
static __forceinline float8 load( const unsigned char* const ptr ) {
#if defined(__AVX2__)
return _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
#else
return float8(float4::load(ptr),float4::load(ptr+4));
#endif
}
static __forceinline float8 load( const float* const a) {
return _mm256_load_ps(a);
}
static __forceinline void store(void* ptr, const float8& f ) {
return _mm256_store_ps((float*)ptr,f);
}
static __forceinline float8 loadu( const void* const a) {
return _mm256_loadu_ps((float*)a);
}
static __forceinline void storeu(void* ptr, const float8& f ) {
return _mm256_storeu_ps((float*)ptr,f);
}
static __forceinline void store( const bool8& mask, void* ptr, const float8& f ) {
return _mm256_maskstore_ps((float*)ptr,(__m256i)mask,f);
}
static __forceinline void storeu( const bool8& mask, void* ptr, const float8& f ) {
return _mm256_storeu_ps((float*)ptr,_mm256_blendv_ps(_mm256_loadu_ps((float*)ptr),f,mask));
}
#if defined (__AVX2__)
static __forceinline float8 load_nt(void* ptr) {
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
}
#endif
static __forceinline void store_nt(float* ptr, const float8& v) {
_mm256_stream_ps(ptr,v);
}
static __forceinline void store ( const bool8& mask, void* ptr, const int8& ofs, const float8& v, const int scale = 1 )
{
if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
if (likely(mask[4])) *(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
if (likely(mask[5])) *(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
if (likely(mask[6])) *(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
if (likely(mask[7])) *(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
}
static __forceinline void store ( const bool8& mask, char* ptr, const int8& ofs, const float8& v ) {
store(mask,ptr,ofs,v,1);
}
static __forceinline void store ( const bool8& mask, float* ptr, const int8& ofs, const float8& v ) {
store(mask,ptr,ofs,v,4);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const float& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
__forceinline float& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float8 cast (const int8& a ) { return _mm256_castsi256_ps(a); }
__forceinline const int8 cast (const float8& a ) { return _mm256_castps_si256(a); }
__forceinline const float8 operator +( const float8& a ) { return a; }
__forceinline const float8 operator -( const float8& a ) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
return _mm256_xor_ps(a.m256, mask);
}
__forceinline const float8 abs ( const float8& a ) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
return _mm256_and_ps(a.m256, mask);
}
__forceinline const float8 sign ( const float8& a ) { return _mm256_blendv_ps(float8(one), -float8(one), _mm256_cmp_ps(a, float8(zero), _CMP_NGE_UQ )); }
__forceinline const float8 signmsk ( const float8& a ) { return _mm256_and_ps(a.m256,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
__forceinline const float8 rcp ( const float8& a ) {
const float8 r = _mm256_rcp_ps(a.m256);
#if defined(__AVX2__)
return _mm256_mul_ps(r,_mm256_fnmadd_ps(r, a, float8(2.0f)));
#else
return _mm256_mul_ps(r,_mm256_sub_ps(float8(2.0f), _mm256_mul_ps(r, a)));
#endif
}
__forceinline const float8 sqr ( const float8& a ) { return _mm256_mul_ps(a,a); }
__forceinline const float8 sqrt ( const float8& a ) { return _mm256_sqrt_ps(a.m256); }
__forceinline const float8 rsqrt( const float8& a ) {
const float8 r = _mm256_rsqrt_ps(a.m256);
return _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(1.5f), r), _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const float8 operator +( const float8& a, const float8& b ) { return _mm256_add_ps(a.m256, b.m256); }
__forceinline const float8 operator +( const float8& a, const float b ) { return a + float8(b); }
__forceinline const float8 operator +( const float a, const float8& b ) { return float8(a) + b; }
__forceinline const float8 operator -( const float8& a, const float8& b ) { return _mm256_sub_ps(a.m256, b.m256); }
__forceinline const float8 operator -( const float8& a, const float b ) { return a - float8(b); }
__forceinline const float8 operator -( const float a, const float8& b ) { return float8(a) - b; }
__forceinline const float8 operator *( const float8& a, const float8& b ) { return _mm256_mul_ps(a.m256, b.m256); }
__forceinline const float8 operator *( const float8& a, const float b ) { return a * float8(b); }
__forceinline const float8 operator *( const float a, const float8& b ) { return float8(a) * b; }
__forceinline const float8 operator /( const float8& a, const float8& b ) { return _mm256_div_ps(a.m256, b.m256); }
__forceinline const float8 operator /( const float8& a, const float b ) { return a / float8(b); }
__forceinline const float8 operator /( const float a, const float8& b ) { return float8(a) / b; }
__forceinline const float8 operator^( const float8& a, const float8& b ) { return _mm256_xor_ps(a.m256,b.m256); }
__forceinline const float8 operator^( const float8& a, const int8& b ) { return _mm256_xor_ps(a.m256,_mm256_castsi256_ps(b.m256)); }
__forceinline const float8 operator&( const float8& a, const float8& b ) { return _mm256_and_ps(a.m256,b.m256); }
__forceinline const float8 min( const float8& a, const float8& b ) { return _mm256_min_ps(a.m256, b.m256); }
__forceinline const float8 min( const float8& a, const float b ) { return _mm256_min_ps(a.m256, float8(b)); }
__forceinline const float8 min( const float a, const float8& b ) { return _mm256_min_ps(float8(a), b.m256); }
__forceinline const float8 max( const float8& a, const float8& b ) { return _mm256_max_ps(a.m256, b.m256); }
__forceinline const float8 max( const float8& a, const float b ) { return _mm256_max_ps(a.m256, float8(b)); }
__forceinline const float8 max( const float a, const float8& b ) { return _mm256_max_ps(float8(a), b.m256); }
#if defined (__AVX2__)
__forceinline float8 mini(const float8& a, const float8& b) {
const int8 ai = _mm256_castps_si256(a);
const int8 bi = _mm256_castps_si256(b);
const int8 ci = _mm256_min_epi32(ai,bi);
return _mm256_castsi256_ps(ci);
}
__forceinline float8 maxi(const float8& a, const float8& b) {
const int8 ai = _mm256_castps_si256(a);
const int8 bi = _mm256_castps_si256(b);
const int8 ci = _mm256_max_epi32(ai,bi);
return _mm256_castsi256_ps(ci);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX2__)
__forceinline const float8 madd ( const float8& a, const float8& b, const float8& c) { return _mm256_fmadd_ps(a,b,c); }
__forceinline const float8 msub ( const float8& a, const float8& b, const float8& c) { return _mm256_fmsub_ps(a,b,c); }
__forceinline const float8 nmadd ( const float8& a, const float8& b, const float8& c) { return _mm256_fnmadd_ps(a,b,c); }
__forceinline const float8 nmsub ( const float8& a, const float8& b, const float8& c) { return _mm256_fnmsub_ps(a,b,c); }
#else
__forceinline const float8 madd ( const float8& a, const float8& b, const float8& c) { return a*b+c; }
__forceinline const float8 msub ( const float8& a, const float8& b, const float8& c) { return a*b-c; }
__forceinline const float8 nmadd ( const float8& a, const float8& b, const float8& c) { return -a*b+c;}
__forceinline const float8 nmsub ( const float8& a, const float8& b, const float8& c) { return -a*b-c; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline float8& operator +=( float8& a, const float8& b ) { return a = a + b; }
__forceinline float8& operator +=( float8& a, const float b ) { return a = a + b; }
__forceinline float8& operator -=( float8& a, const float8& b ) { return a = a - b; }
__forceinline float8& operator -=( float8& a, const float b ) { return a = a - b; }
__forceinline float8& operator *=( float8& a, const float8& b ) { return a = a * b; }
__forceinline float8& operator *=( float8& a, const float b ) { return a = a * b; }
__forceinline float8& operator /=( float8& a, const float8& b ) { return a = a / b; }
__forceinline float8& operator /=( float8& a, const float b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator ==( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_EQ_OQ ); }
__forceinline const bool8 operator ==( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_EQ_OQ ); }
__forceinline const bool8 operator ==( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_EQ_OQ ); }
__forceinline const bool8 operator !=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_NEQ_OQ); }
__forceinline const bool8 operator !=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_NEQ_OQ); }
__forceinline const bool8 operator !=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_NEQ_OQ); }
__forceinline const bool8 operator < ( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LT_OQ ); }
__forceinline const bool8 operator < ( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_LT_OQ ); }
__forceinline const bool8 operator < ( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_LT_OQ ); }
__forceinline const bool8 operator >=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GE_OQ); }
__forceinline const bool8 operator >=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_GE_OQ); }
__forceinline const bool8 operator >=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_GE_OQ); }
__forceinline const bool8 operator > ( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GT_OQ); }
__forceinline const bool8 operator > ( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_GT_OQ); }
__forceinline const bool8 operator > ( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_GT_OQ); }
__forceinline const bool8 operator <=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LE_OQ ); }
__forceinline const bool8 operator <=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_LE_OQ ); }
__forceinline const bool8 operator <=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_LE_OQ ); }
__forceinline const float8 select( const bool8& m, const float8& t, const float8& f ) {
return _mm256_blendv_ps(f, t, m);
}
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
__forceinline const float8 select(const int m, const float8& t, const float8& f) {
return select(bool8(m), t, f); // workaround for clang and Microsoft compiler bugs
}
#else
__forceinline const float8 select( const int m, const float8& t, const float8& f ) {
return _mm256_blend_ps(f, t, m);
}
#endif
__forceinline float8 lerp(const float8& a, const float8& b, const float8& t) {
#if defined(__AVX2__)
return madd(t, b, madd(-t, a, a));
#else
return a + t*(b-a);
#endif
}
__forceinline bool isvalid ( const float8& v ) {
return all((v > float8(-FLT_LARGE)) & (v < float8(+FLT_LARGE)));
}
__forceinline bool is_finite ( const float8& a ) {
return all((a >= float8(-FLT_MAX) & (a <= float8(+FLT_MAX))));
}
__forceinline bool is_finite ( const bool8& valid, const float8& a ) {
return all(valid, (a >= float8(-FLT_MAX) & (a <= float8(+FLT_MAX))));
}
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline const float8 floor ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const float8 ceil ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline const float8 trunc ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
__forceinline const float8 frac ( const float8& a ) { return a-floor(a); }
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline float8 unpacklo( const float8& a, const float8& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
__forceinline float8 unpackhi( const float8& a, const float8& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
template<size_t i> __forceinline const float8 shuffle( const float8& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
}
template<size_t i0, size_t i1> __forceinline const float8 shuffle( const float8& a ) {
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const float8 shuffle( const float8& a, const float8& b) {
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float8 shuffle( const float8& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float8 shuffle( const float8& a, const float8& b ) {
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<> __forceinline const float8 shuffle<0, 0, 2, 2>( const float8& b ) { return _mm256_moveldup_ps(b); }
template<> __forceinline const float8 shuffle<1, 1, 3, 3>( const float8& b ) { return _mm256_movehdup_ps(b); }
template<> __forceinline const float8 shuffle<0, 1, 0, 1>( const float8& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
__forceinline const float8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
template<size_t i> __forceinline const float8 insert (const float8& a, const float4& b) { return _mm256_insertf128_ps (a,b,i); }
template<size_t i> __forceinline const float4 extract (const float8& a ) { return _mm256_extractf128_ps(a ,i); }
template<> __forceinline const float4 extract<0>(const float8& a ) { return _mm256_castps256_ps128(a); }
template<size_t i> __forceinline float fextract (const float8& a ) { return _mm_cvtss_f32(_mm256_extractf128_ps(a ,i)); }
__forceinline float8 assign( const float4& a ) { return _mm256_castps128_ps256(a); }
#if defined (__AVX2__)
__forceinline float8 permute(const float8 &a, const __m256i &index) {
return _mm256_permutevar8x32_ps(a,index);
}
template<int i>
__forceinline float8 alignr(const float8 &a, const float8 &b) {
return _mm256_castsi256_ps(_mm256_alignr_epi8(_mm256_castps_si256(a), _mm256_castps_si256(b), i));
}
#endif
#if defined (__AVX_I__)
template<const int mode>
__forceinline int4 convert_to_hf16(const float8 &a) {
return _mm256_cvtps_ph(a,mode);
}
__forceinline float8 convert_from_hf16(const int4 &a) {
return _mm256_cvtph_ps(a);
}
#endif
__forceinline float4 broadcast4f( const float8& a, const size_t k ) {
return float4::broadcast(&a[k]);
}
__forceinline float8 broadcast8f( const float8& a, const size_t k ) {
return float8::broadcast(&a[k]);
}
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, float8& c0, float8& c1, float8& c2, float8& c3)
{
float8 l02 = unpacklo(r0,r2);
float8 h02 = unpackhi(r0,r2);
float8 l13 = unpacklo(r1,r3);
float8 h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
c3 = unpackhi(h02,h13);
}
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, float8& c0, float8& c1, float8& c2)
{
float8 l02 = unpacklo(r0,r2);
float8 h02 = unpackhi(r0,r2);
float8 l13 = unpacklo(r1,r3);
float8 h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
}
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, const float8& r4, const float8& r5, const float8& r6, const float8& r7,
float8& c0, float8& c1, float8& c2, float8& c3, float8& c4, float8& c5, float8& c6, float8& c7)
{
float8 h0,h1,h2,h3; transpose(r0,r1,r2,r3,h0,h1,h2,h3);
float8 h4,h5,h6,h7; transpose(r4,r5,r6,r7,h4,h5,h6,h7);
c0 = shuffle<0,2>(h0,h4);
c1 = shuffle<0,2>(h1,h5);
c2 = shuffle<0,2>(h2,h6);
c3 = shuffle<0,2>(h3,h7);
c4 = shuffle<1,3>(h0,h4);
c5 = shuffle<1,3>(h1,h5);
c6 = shuffle<1,3>(h2,h6);
c7 = shuffle<1,3>(h3,h7);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const float8 vreduce_min2(const float8& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const float8 vreduce_min4(const float8& v) { float8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const float8 vreduce_min (const float8& v) { float8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const float8 vreduce_max2(const float8& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const float8 vreduce_max4(const float8& v) { float8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const float8 vreduce_max (const float8& v) { float8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const float8 vreduce_add2(const float8& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const float8 vreduce_add4(const float8& v) { float8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const float8 vreduce_add (const float8& v) { float8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline float reduce_min(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_min(v))); }
__forceinline float reduce_max(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_max(v))); }
__forceinline float reduce_add(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const float8& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const float8& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool8& valid, const float8& v) { const float8 a = select(valid,v,float8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const bool8& valid, const float8& v) { const float8 a = select(valid,v,float8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline float8 load8f( const void* const a) {
return _mm256_load_ps((const float*)a);
}
__forceinline void store8f(void *ptr, const float8& f ) {
return _mm256_store_ps((float*)ptr,f);
}
__forceinline void storeu8f(void *ptr, const float8& f ) {
return _mm256_storeu_ps((float*)ptr,f);
}
__forceinline void store8f( const bool8& mask, void *ptr, const float8& f ) {
return _mm256_maskstore_ps((float*)ptr,(__m256i)mask,f);
}
#if defined (__AVX2__)
__forceinline float8 load8f_nt(void* ptr) {
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
}
#if 0 // FIXME: not compiling under VS2013
__forceinline float8 merge2x4(const float& a, const float& b)
{
const float8 va = broadcast(&a);
const float8 vb = broadcast(&b);
return select(0b00001111,va,vb);
}
#endif
#endif
__forceinline void store8f_nt(void* ptr, const float8& v) {
_mm256_stream_ps((float*)ptr,v);
}
__forceinline const float8 broadcast4f(const void* ptr) {
return _mm256_broadcast_ps((__m128*)ptr);
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
//__forceinline float8 dot ( const float8& a, const float8& b ) {
// return vreduce_add4(a*b);
//}
__forceinline float8 dot ( const float8& a, const float8& b ) {
return _mm256_dp_ps(a,b,0x7F);
}
__forceinline float8 cross ( const float8& a, const float8& b )
{
const float8 a0 = a;
const float8 b0 = shuffle<1,2,0,3>(b);
const float8 a1 = shuffle<1,2,0,3>(a);
const float8 b1 = b;
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const float8& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
File diff suppressed because it is too large Load Diff
+537
View File
@@ -0,0 +1,537 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 16-wide MIC integer type. */
class int16
{
public:
union {
__m512i v;
int i[16];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int16() {};
__forceinline int16(const int16& t) { v = t.v; };
__forceinline int16& operator=(const int16& f) { v = f.v; return *this; };
__forceinline int16(const __m512i& t) { v = t; };
__forceinline operator __m512i () const { return v; };
__forceinline int16(const int i) {
v = _mm512_set_1to16_epi32(i);
}
__forceinline int16(const int a, const int b, const int c, const int d) {
v = _mm512_set_4to16_epi32(a,b,c,d);
}
__forceinline explicit int16(const __m512 f) {
#if defined(__AVX512F__)
v = _mm512_cvt_roundps_epi32(f,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
#else
v = _mm512_cvtfxpnt_round_adjustps_epi32(f,_MM_FROUND_FLOOR,_MM_EXPADJ_NONE);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline int16( ZeroTy ) : v(_mm512_setzero_epi32()) {}
__forceinline int16( OneTy ) : v(_mm512_set_1to16_epi32(1)) {}
__forceinline int16( PosInfTy ) : v(_mm512_set_1to16_epi32(pos_inf)) {}
__forceinline int16( NegInfTy ) : v(_mm512_set_1to16_epi32(neg_inf)) {}
__forceinline int16( StepTy ) : v(_mm512_set_16to16_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
__forceinline static int16 zero() { return _mm512_setzero_epi32(); }
__forceinline static int16 one () { return _mm512_set_1to16_epi32(1); }
__forceinline static int16 neg_one () { return _mm512_set_1to16_epi32(-1); }
static __forceinline int16 loadu(const void* addr)
{
#if defined(__AVX512F__)
return _mm512_loadu_si512(addr);
#else
int16 r = _mm512_undefined_epi32();
r =_mm512_extloadunpacklo_epi32(r, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
return _mm512_extloadunpackhi_epi32(r, (int*)addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
#endif
}
static __forceinline int16 load(const void* addr) {
return _mm512_load_si512(addr);
}
static __forceinline void store(void* addr, const int16& v2) {
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
}
static __forceinline void storeu(void* ptr, const int16& f ) {
#if defined(__AVX512F__)
_mm512_storeu_si512(ptr,f);
#else
_mm512_extpackstorelo_ps((int*)ptr+0 ,_mm512_castsi512_ps(f), _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps((int*)ptr+16 ,_mm512_castsi512_ps(f), _MM_DOWNCONV_PS_NONE , 0);
#endif
}
static __forceinline void storeu(const bool16& mask, int* ptr, const int16& f ) {
#if defined(__AVX512F__)
_mm512_mask_storeu_epi32(ptr,mask,f);
#else
__m512 r = _mm512_undefined();
r = _mm512_extloadunpacklo_ps(r, ptr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_extloadunpackhi_ps(r, ptr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
r = _mm512_mask_blend_ps(mask,r,_mm512_castsi512_ps(f));
_mm512_extpackstorelo_ps(ptr, r, _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps(ptr+16 ,r, _MM_DOWNCONV_PS_NONE , 0);
#endif
}
static __forceinline void store(const bool16& mask, void* addr, const int16& v2) {
_mm512_mask_store_epi32(addr,mask,v2);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline int& operator[](const size_t index) { return i[index]; };
__forceinline const int& operator[](const size_t index) const { return i[index]; };
__forceinline unsigned int uint(const size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; };
__forceinline size_t& uint64_t(const size_t index) const { assert(index < 8); return ((size_t*)i)[index]; };
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int16 cast ( const __m512& a) { return _mm512_castps_si512(a); }
__forceinline const int16 operator +( const int16& a ) { return a; }
__forceinline const int16 operator -( const int16& a ) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int16 operator +( const int16& a, const int16& b ) { return _mm512_add_epi32(a, b); }
__forceinline const int16 operator +( const int16& a, const int b ) { return a + int16(b); }
__forceinline const int16 operator +( const int a, const int16& b ) { return int16(a) + b; }
__forceinline const int16 operator -( const int16& a, const int16& b ) { return _mm512_sub_epi32(a, b); }
__forceinline const int16 operator -( const int16& a, const int b ) { return a - int16(b); }
__forceinline const int16 operator -( const int a, const int16& b ) { return int16(a) - b; }
__forceinline const int16 operator *( const int16& a, const int16& b ) { return _mm512_mullo_epi32(a, b); }
__forceinline const int16 operator *( const int16& a, const int b ) { return a * int16(b); }
__forceinline const int16 operator *( const int a, const int16& b ) { return int16(a) * b; }
__forceinline const int16 operator &( const int16& a, const int16& b ) { return _mm512_and_epi32(a, b); }
__forceinline const int16 operator &( const int16& a, const int b ) { return a & int16(b); }
__forceinline const int16 operator &( const int a, const int16& b ) { return int16(a) & b; }
__forceinline const int16 operator |( const int16& a, const int16& b ) { return _mm512_or_epi32(a, b); }
__forceinline const int16 operator |( const int16& a, const int b ) { return a | int16(b); }
__forceinline const int16 operator |( const int a, const int16& b ) { return int16(a) | b; }
__forceinline const int16 operator ^( const int16& a, const int16& b ) { return _mm512_xor_epi32(a, b); }
__forceinline const int16 operator ^( const int16& a, const int b ) { return a ^ int16(b); }
__forceinline const int16 operator ^( const int a, const int16& b ) { return int16(a) ^ b; }
__forceinline const int16 operator <<( const int16& a, const int n ) { return _mm512_slli_epi32(a, n); }
__forceinline const int16 operator >>( const int16& a, const int n ) { return _mm512_srai_epi32(a, n); }
__forceinline const int16 operator <<( const int16& a, const int16& n ) { return _mm512_sllv_epi32(a, n); }
__forceinline const int16 operator >>( const int16& a, const int16& n ) { return _mm512_srav_epi32(a, n); }
__forceinline const int16 sra ( const int16& a, const int b ) { return _mm512_srai_epi32(a, b); }
__forceinline const int16 srl ( const int16& a, const int b ) { return _mm512_srli_epi32(a, b); }
__forceinline const int16 min( const int16& a, const int16& b ) { return _mm512_min_epi32(a, b); }
__forceinline const int16 min( const int16& a, const int b ) { return min(a,int16(b)); }
__forceinline const int16 min( const int a, const int16& b ) { return min(int16(a),b); }
__forceinline const int16 max( const int16& a, const int16& b ) { return _mm512_max_epi32(a, b); }
__forceinline const int16 max( const int16& a, const int b ) { return max(a,int16(b)); }
__forceinline const int16 max( const int a, const int16& b ) { return max(int16(a),b); }
__forceinline const int16 mask_add(const bool16& mask, int16& c, const int16& a, const int16& b) { return _mm512_mask_add_epi32(c,mask,a,b); };
__forceinline const int16 mask_sub(const bool16& mask, int16& c, const int16& a, const int16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); };
__forceinline const int16 mask_and(const bool16& m,int16& c, const int16& a, const int16& b) { return _mm512_mask_and_epi32(c,m,a,b); };
__forceinline const int16 mask_or (const bool16& m,int16& c, const int16& a, const int16& b) { return _mm512_mask_or_epi32(c,m,a,b); };
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int16& operator +=( int16& a, const int16& b ) { return a = a + b; }
__forceinline int16& operator +=( int16& a, const int b ) { return a = a + b; }
__forceinline int16& operator -=( int16& a, const int16& b ) { return a = a - b; }
__forceinline int16& operator -=( int16& a, const int b ) { return a = a - b; }
__forceinline int16& operator *=( int16& a, const int16& b ) { return a = a * b; }
__forceinline int16& operator *=( int16& a, const int b ) { return a = a * b; }
__forceinline int16& operator &=( int16& a, const int16& b ) { return a = a & b; }
__forceinline int16& operator &=( int16& a, const int b ) { return a = a & b; }
__forceinline int16& operator |=( int16& a, const int16& b ) { return a = a | b; }
__forceinline int16& operator |=( int16& a, const int b ) { return a = a | b; }
__forceinline int16& operator <<=( int16& a, const int b ) { return a = a << b; }
__forceinline int16& operator >>=( int16& a, const int b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool16 operator ==( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
__forceinline const bool16 operator ==( const int16& a, const int b ) { return a == int16(b); }
__forceinline const bool16 operator ==( const int a, const int16& b ) { return int16(a) == b; }
__forceinline const bool16 operator !=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
__forceinline const bool16 operator !=( const int16& a, const int b ) { return a != int16(b); }
__forceinline const bool16 operator !=( const int a, const int16& b ) { return int16(a) != b; }
__forceinline const bool16 operator < ( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
__forceinline const bool16 operator < ( const int16& a, const int b ) { return a < int16(b); }
__forceinline const bool16 operator < ( const int a, const int16& b ) { return int16(a) < b; }
__forceinline const bool16 operator >=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
__forceinline const bool16 operator >=( const int16& a, const int b ) { return a >= int16(b); }
__forceinline const bool16 operator >=( const int a, const int16& b ) { return int16(a) >= b; }
__forceinline const bool16 operator > ( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
__forceinline const bool16 operator > ( const int16& a, const int b ) { return a > int16(b); }
__forceinline const bool16 operator > ( const int a, const int16& b ) { return int16(a) > b; }
__forceinline const bool16 operator <=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
__forceinline const bool16 operator <=( const int16& a, const int b ) { return a <= int16(b); }
__forceinline const bool16 operator <=( const int a, const int16& b ) { return int16(a) <= b; }
__forceinline bool16 eq( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); };
__forceinline bool16 eq(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_EQ); };
__forceinline bool16 ne( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); };
__forceinline bool16 ne(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_NE); };
__forceinline bool16 lt( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); };
__forceinline bool16 lt(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LT); };
__forceinline bool16 ge( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); };
__forceinline bool16 ge(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GE); };
__forceinline bool16 gt( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); };
__forceinline bool16 gt(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GT); };
__forceinline bool16 le( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); };
__forceinline bool16 le(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LE); };
__forceinline const int16 select( const bool16& m, const int16& t, const int16& f ) {
return _mm512_mask_or_epi32(f,m,t,t);
}
__forceinline void xchg(const bool16& m, int16& a, int16& b) {
const int16 c = a; a = select(m,b,a); b = select(m,c,b);
}
__forceinline bool16 test(const bool16& m, const int16& a, const int16& b) {
return _mm512_mask_test_epi32_mask(m,a,b);
}
__forceinline bool16 test(const int16& a, const int16& b) {
return _mm512_test_epi32_mask(a,b);
}
////////////////////////////////////////////////////////////////////////////////
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline int16 swizzle(const int16& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_epi32(x,perm32); }
__forceinline int16 permute(const int16& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_epi32(x,perm128); }
template<int D, int C, int B, int A> __forceinline int16 swizzle (const int16& v) { return _mm512_shuffle_epi32(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline int16 swizzle (const int16& x) { return swizzle<A,A,A,A>(v); }
template<> __forceinline int16 swizzle<0>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
template<> __forceinline int16 swizzle<1>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
template<> __forceinline int16 swizzle<2>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
template<> __forceinline int16 swizzle<3>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
template<int D, int C, int B, int A> __forceinline int16 permute(const int16& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline int16 permute(const int16& x) { return permute<A,A,A,A>(x); }
__forceinline int16 shuffle(const int16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
__forceinline int16 shuffle(const bool16& mask, int16& v, const int16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) {
return _mm512_mask_swizzle_epi32(_mm512_mask_permute4f128_epi32(v,mask,x,perm128),mask,x,perm32);
}
__forceinline int16 swAAAA(const int16& x) {
return swizzle(x,_MM_SWIZ_REG_AAAA);
}
__forceinline int16 swBBBB(const int16& x) {
return swizzle(x,_MM_SWIZ_REG_BBBB);
}
__forceinline int16 swCCCC(const int16& x) {
return swizzle(x,_MM_SWIZ_REG_CCCC);
}
__forceinline int16 swDDDD(const int16& x) {
return swizzle(x,_MM_SWIZ_REG_DDDD);
}
template<int i>
__forceinline int16 align_shift_right(const int16& a, const int16& b)
{
return _mm512_alignr_epi32(a,b,i);
};
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline int reduce_add(int16 a) { return _mm512_reduce_add_epi32(a); }
__forceinline int reduce_mul(int16 a) { return _mm512_reduce_mul_epi32(a); }
__forceinline int reduce_min(int16 a) { return _mm512_reduce_min_epi32(a); }
__forceinline int reduce_max(int16 a) { return _mm512_reduce_max_epi32(a); }
__forceinline int reduce_and(int16 a) { return _mm512_reduce_and_epi32(a); }
__forceinline int16 vreduce_min2(int16 x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline int16 vreduce_min4(int16 x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline int16 vreduce_min8(int16 x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline int16 vreduce_min (int16 x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline int16 vreduce_max2(int16 x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline int16 vreduce_max4(int16 x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline int16 vreduce_max8(int16 x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline int16 vreduce_max (int16 x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline int16 vreduce_and2(int16 x) { return x & swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline int16 vreduce_and4(int16 x) { x = vreduce_and2(x); return x & swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline int16 vreduce_and8(int16 x) { x = vreduce_and4(x); return x & permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline int16 vreduce_and (int16 x) { x = vreduce_and8(x); return x & permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline int16 vreduce_or2(int16 x) { return x | swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline int16 vreduce_or4(int16 x) { x = vreduce_or2(x); return x | swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline int16 vreduce_or8(int16 x) { x = vreduce_or4(x); return x | permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline int16 vreduce_or (int16 x) { x = vreduce_or8(x); return x | permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline int16 vreduce_add2(int16 x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline int16 vreduce_add4(int16 x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline int16 vreduce_add8(int16 x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline int16 vreduce_add (int16 x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline int16 prefix_sum(const int16& a)
{
int16 v = a;
v = mask_add(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
v = mask_add(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
const int16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
v = mask_add(0xf0f0,v,v,shuf_v0);
const int16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
v = mask_add(0xff00,v,v,shuf_v1);
return v;
}
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int16 load1i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline int16 load16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline int16 load1i_uint8(const unsigned char *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline int16 load16i_uint8(const unsigned char *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST32_NONE,_MM_HINT_NONE);
}
__forceinline int16 broadcast4to16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
__forceinline int16 broadcast1to16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline int16 uload16i(const int *const addr) {
int16 r = _mm512_undefined_epi32();
r =_mm512_extloadunpacklo_epi32(r, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
return _mm512_extloadunpackhi_epi32(r, addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline int16 uload16i_low(const bool16& mask, const void* addr) {
int16 v = _mm512_undefined_epi32();
return _mm512_mask_extloadunpacklo_epi32(v, mask, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline int16 uload16i(const bool16& mask,const int *const addr) {
int16 r = _mm512_undefined_epi32();
r =_mm512_mask_extloadunpacklo_epi32(r, mask,addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
return _mm512_mask_extloadunpackhi_epi32(r, mask,addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline int16 gather16i_4i(const int *__restrict__ const ptr0,
const int *__restrict__ const ptr1,
const int *__restrict__ const ptr2,
const int *__restrict__ const ptr3)
{
int16 v = broadcast4to16i(ptr0);
v = select((bool16)0xf0 , broadcast4to16i(ptr1),v);
v = select((bool16)0xf00 , broadcast4to16i(ptr2),v);
v = select((bool16)0xf000, broadcast4to16i(ptr3),v);
return v;
}
__forceinline int16 gather16i_4i_align(const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
int16 v = broadcast4to16i((const int*)ptr3);
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr2));
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr1));
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr0));
return v;
}
__forceinline int16 gather16i_4i_align(const int16& v0,
const int16& v1,
const int16& v2,
const int16& v3)
{
int16 v = v3;
v = align_shift_right<12>(v,v2);
v = align_shift_right<12>(v,v1);
v = align_shift_right<12>(v,v0);
return v;
}
__forceinline int16 gather16i(const bool16& mask, const int *const ptr, const int16& index,const _MM_INDEX_SCALE_ENUM scale) {
return _mm512_mask_i32extgather_epi32(_mm512_undefined_epi32(),mask,index,ptr,_MM_UPCONV_EPI32_NONE,scale,0);
}
__forceinline int16 gather16i(const bool16& mask, int16& dest, const int *const ptr, const int16& index,const _MM_INDEX_SCALE_ENUM scale) {
return _mm512_mask_i32extgather_epi32(dest,mask,index,ptr,_MM_UPCONV_EPI32_NONE,scale,0);
}
__forceinline void scatter16i(const bool16& mask,int *const ptr, const int16& index,const int16& v, const _MM_INDEX_SCALE_ENUM scale) {
_mm512_mask_i32extscatter_epi32((int*)ptr,mask,index,v,_MM_DOWNCONV_EPI32_NONE,scale,0);
}
__forceinline void ustore16i(void *addr, const int16& reg) {
_mm512_extpackstorelo_epi32((int*)addr+0 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
_mm512_extpackstorehi_epi32((int*)addr+16 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
/* pass by value to avoid compiler generating inefficient code */
__forceinline void compactustore16i(const bool16 mask,void * addr, const int16 reg) {
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
_mm512_mask_extpackstorehi_epi32((int*)addr+16 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void compactustore16i_low(const bool16 mask, void *addr, const int16& reg) {
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void store1i(void *addr, const int16& reg) {
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,(bool16)1, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void ustore16i_low(void *addr, const int16& reg) {
_mm512_extpackstorelo_epi32((int*)addr+0 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void compactustore16i_high(const bool16 mask, int *addr, const int16& reg) {
_mm512_mask_extpackstorehi_epi32((int*)addr+16 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void store16i_nr(void *__restrict__ ptr, const int16& a) {
_mm512_storenr_ps(ptr,_mm512_castsi512_ps(a));
}
__forceinline void store16i_ngo(void *__restrict__ ptr, const int16& a) {
_mm512_storenrngo_ps(ptr,_mm512_castsi512_ps(a));
}
__forceinline void store16i(const bool16& mask, void* __restrict__ addr, const int16& v2) {
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
}
__forceinline void store16i_nt(void* __restrict__ addr, const int16& v2) {
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NT);
}
__forceinline void store16i(void* __restrict__ addr, const int16& v2) {
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
}
__forceinline void store16i_uint8(const bool16& mask, void* __restrict__ addr, const int16& v2) {
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_UINT8,_MM_HINT_NONE);
}
__forceinline int16 convert_uint32_t(const __m512 f) {
#if defined(__AVX512F__)
return _mm512_cvt_roundps_epu32(f,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
#else
return _mm512_cvtfxpnt_round_adjustps_epu32(f,_MM_FROUND_TO_ZERO,_MM_EXPADJ_NONE);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline std::ostream& operator<<(std::ostream& cout, const int16& v)
{
cout << "<" << v[0];
for (int i=1; i<16; i++) cout << ", " << v[i];
cout << ">";
return cout;
}
}
+414
View File
@@ -0,0 +1,414 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../math/math.h"
namespace embree
{
/*! 4-wide SSE integer type. */
struct int4
{
typedef bool4 Mask; // mask type
typedef int4 Int; // int type
typedef float4 Float; // float type
enum { size = 4 }; // number of SIMD elements
union { __m128i m128; int i[4]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int4 ( ) {}
__forceinline int4 ( const int4& a ) { m128 = a.m128; }
__forceinline int4& operator=( const int4& a ) { m128 = a.m128; return *this; }
__forceinline int4( const __m128i a ) : m128(a) {}
__forceinline operator const __m128i&( void ) const { return m128; }
__forceinline operator __m128i&( void ) { return m128; }
__forceinline int4 ( const int& a ) : m128(_mm_shuffle_epi32(_mm_castps_si128(_mm_load_ss((float*)&a)), _MM_SHUFFLE(0, 0, 0, 0))) {}
__forceinline int4 ( const uint32_t& a ) : m128(_mm_shuffle_epi32(_mm_castps_si128(_mm_load_ss((float*)&a)), _MM_SHUFFLE(0, 0, 0, 0))) {}
#if defined(__X86_64__)
__forceinline int4 ( const size_t a ) : m128(_mm_set1_epi32((int)a)) {}
#endif
__forceinline int4 ( int a, int b, int c, int d) : m128(_mm_set_epi32(d, c, b, a)) {}
__forceinline explicit int4( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline int4( ZeroTy ) : m128(_mm_setzero_si128()) {}
__forceinline int4( OneTy ) : m128(_mm_set_epi32(1, 1, 1, 1)) {}
__forceinline int4( PosInfTy ) : m128(_mm_set_epi32(pos_inf, pos_inf, pos_inf, pos_inf)) {}
__forceinline int4( NegInfTy ) : m128(_mm_set_epi32(neg_inf, neg_inf, neg_inf, neg_inf)) {}
__forceinline int4( StepTy ) : m128(_mm_set_epi32(3, 2, 1, 0)) {}
__forceinline int4( TrueTy ) { m128 = _mm_cmpeq_epi32(m128,m128); }
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
#if defined(__SSE4_1__)
static __forceinline int4 load( const unsigned char* const ptr ) {
return _mm_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr));
}
#endif
static __forceinline int4 load(const unsigned short* const ptr)
{
#if defined (__SSE4_1__)
return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
#else
return int4(ptr[0],ptr[1],ptr[2],ptr[3]);
#endif
}
static __forceinline int4 load( const void* const a ) {
return _mm_load_si128((__m128i*)a);
}
static __forceinline int4 loadu( const void* const a ) {
return _mm_loadu_si128((__m128i*)a);
}
static __forceinline void store(void* ptr, const int4& v) {
_mm_store_si128((__m128i*)ptr,v);
}
static __forceinline void storeu(void* ptr, const int4& v) {
_mm_storeu_si128((__m128i*)ptr,v);
}
static __forceinline void store( const bool4& mask, void* ptr, const int4& i ) {
#if defined (__AVX__)
_mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i));
#else
*(int4*)ptr = select(mask,i,*(int4*)ptr);
#endif
}
static __forceinline int4 load_nt (void* ptr) {
#if defined(__SSE4_1__)
return _mm_stream_load_si128((__m128i*)ptr);
#else
return _mm_load_si128((__m128i*)ptr);
#endif
}
static __forceinline void store_nt(void* ptr, const int4& v) {
#if defined(__SSE4_1__)
_mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
#else
_mm_store_si128((__m128i*)ptr,v);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int& operator []( const size_t index ) const { assert(index < 4); return i[index]; }
__forceinline int& operator []( const size_t index ) { assert(index < 4); return i[index]; }
friend __forceinline const int4 select( const bool4& m, const int4& t, const int4& f ) {
#if defined(__SSE4_1__)
return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
#else
return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
#endif
}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int4 cast ( const __m128& a ) { return _mm_castps_si128(a); }
__forceinline const int4 operator +( const int4& a ) { return a; }
__forceinline const int4 operator -( const int4& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
#if defined(__SSSE3__)
__forceinline const int4 abs ( const int4& a ) { return _mm_abs_epi32(a.m128); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int4 operator +( const int4& a, const int4& b ) { return _mm_add_epi32(a.m128, b.m128); }
__forceinline const int4 operator +( const int4& a, const int& b ) { return a + int4(b); }
__forceinline const int4 operator +( const int& a, const int4& b ) { return int4(a) + b; }
__forceinline const int4 operator -( const int4& a, const int4& b ) { return _mm_sub_epi32(a.m128, b.m128); }
__forceinline const int4 operator -( const int4& a, const int& b ) { return a - int4(b); }
__forceinline const int4 operator -( const int& a, const int4& b ) { return int4(a) - b; }
#if defined(__SSE4_1__)
__forceinline const int4 operator *( const int4& a, const int4& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
#else
__forceinline const int4 operator *( const int4& a, const int4& b ) { return int4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
#endif
__forceinline const int4 operator *( const int4& a, const int& b ) { return a * int4(b); }
__forceinline const int4 operator *( const int& a, const int4& b ) { return int4(a) * b; }
__forceinline const int4 operator &( const int4& a, const int4& b ) { return _mm_and_si128(a.m128, b.m128); }
__forceinline const int4 operator &( const int4& a, const int& b ) { return a & int4(b); }
__forceinline const int4 operator &( const int& a, const int4& b ) { return int4(a) & b; }
__forceinline const int4 operator |( const int4& a, const int4& b ) { return _mm_or_si128(a.m128, b.m128); }
__forceinline const int4 operator |( const int4& a, const int& b ) { return a | int4(b); }
__forceinline const int4 operator |( const int& a, const int4& b ) { return int4(a) | b; }
__forceinline const int4 operator ^( const int4& a, const int4& b ) { return _mm_xor_si128(a.m128, b.m128); }
__forceinline const int4 operator ^( const int4& a, const int& b ) { return a ^ int4(b); }
__forceinline const int4 operator ^( const int& a, const int4& b ) { return int4(a) ^ b; }
__forceinline const int4 operator <<( const int4& a, const int& n ) { return _mm_slli_epi32(a.m128, n); }
__forceinline const int4 operator >>( const int4& a, const int& n ) { return _mm_srai_epi32(a.m128, n); }
__forceinline const int4 sra ( const int4& a, const int& b ) { return _mm_srai_epi32(a.m128, b); }
__forceinline const int4 srl ( const int4& a, const int& b ) { return _mm_srli_epi32(a.m128, b); }
#if defined(__SSE4_1__)
__forceinline const int4 min( const int4& a, const int4& b ) { return _mm_min_epi32(a.m128, b.m128); }
__forceinline const int4 max( const int4& a, const int4& b ) { return _mm_max_epi32(a.m128, b.m128); }
__forceinline const int4 umin( const int4& a, const int4& b ) { return _mm_min_epu32(a.m128, b.m128); }
__forceinline const int4 umax( const int4& a, const int4& b ) { return _mm_max_epu32(a.m128, b.m128); }
#else
__forceinline const int4 min( const int4& a, const int4& b ) { return int4(min(a[0],b[0]),min(a[1],b[1]),min(a[2],b[2]),min(a[3],b[3])); }
__forceinline const int4 max( const int4& a, const int4& b ) { return int4(max(a[0],b[0]),max(a[1],b[1]),max(a[2],b[2]),max(a[3],b[3])); }
#endif
__forceinline const int4 min( const int4& a, const int& b ) { return min(a,int4(b)); }
__forceinline const int4 min( const int& a, const int4& b ) { return min(int4(a),b); }
__forceinline const int4 max( const int4& a, const int& b ) { return max(a,int4(b)); }
__forceinline const int4 max( const int& a, const int4& b ) { return max(int4(a),b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int4& operator +=( int4& a, const int4& b ) { return a = a + b; }
__forceinline int4& operator +=( int4& a, const int& b ) { return a = a + b; }
__forceinline int4& operator -=( int4& a, const int4& b ) { return a = a - b; }
__forceinline int4& operator -=( int4& a, const int& b ) { return a = a - b; }
#if defined(__SSE4_1__)
__forceinline int4& operator *=( int4& a, const int4& b ) { return a = a * b; }
__forceinline int4& operator *=( int4& a, const int& b ) { return a = a * b; }
#endif
__forceinline int4& operator &=( int4& a, const int4& b ) { return a = a & b; }
__forceinline int4& operator &=( int4& a, const int& b ) { return a = a & b; }
__forceinline int4& operator |=( int4& a, const int4& b ) { return a = a | b; }
__forceinline int4& operator |=( int4& a, const int& b ) { return a = a | b; }
__forceinline int4& operator <<=( int4& a, const int& b ) { return a = a << b; }
__forceinline int4& operator >>=( int4& a, const int& b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool4 operator ==( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m128, b.m128)); }
__forceinline const bool4 operator ==( const int4& a, const int& b ) { return a == int4(b); }
__forceinline const bool4 operator ==( const int& a, const int4& b ) { return int4(a) == b; }
__forceinline const bool4 operator !=( const int4& a, const int4& b ) { return !(a == b); }
__forceinline const bool4 operator !=( const int4& a, const int& b ) { return a != int4(b); }
__forceinline const bool4 operator !=( const int& a, const int4& b ) { return int4(a) != b; }
__forceinline const bool4 operator < ( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
__forceinline const bool4 operator < ( const int4& a, const int& b ) { return a < int4(b); }
__forceinline const bool4 operator < ( const int& a, const int4& b ) { return int4(a) < b; }
__forceinline const bool4 operator >=( const int4& a, const int4& b ) { return !(a < b); }
__forceinline const bool4 operator >=( const int4& a, const int& b ) { return a >= int4(b); }
__forceinline const bool4 operator >=( const int& a, const int4& b ) { return int4(a) >= b; }
__forceinline const bool4 operator > ( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
__forceinline const bool4 operator > ( const int4& a, const int& b ) { return a > int4(b); }
__forceinline const bool4 operator > ( const int& a, const int4& b ) { return int4(a) > b; }
__forceinline const bool4 operator <=( const int4& a, const int4& b ) { return !(a > b); }
__forceinline const bool4 operator <=( const int4& a, const int& b ) { return a <= int4(b); }
__forceinline const bool4 operator <=( const int& a, const int4& b ) { return int4(a) <= b; }
#if defined(__SSE4_1__)
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER) // FIXME: can this get removed?
__forceinline const int4 select(const int mask, const int4& t, const int4& f) {
return select(bool4(mask), t, f);
}
#else
__forceinline const int4 select(const int m, const int4& t, const int4& f) {
return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
}
#endif
#endif
////////////////////////////////////////////////////////////////////////////////
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline int4 unpacklo( const int4& a, const int4& b ) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
__forceinline int4 unpackhi( const int4& a, const int4& b ) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int4 shuffle( const int4& a ) {
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int4 shuffle( const int4& a, const int4& b ) {
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
#if defined(__SSE3__)
template<> __forceinline const int4 shuffle<0, 0, 2, 2>( const int4& a ) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(a))); }
template<> __forceinline const int4 shuffle<1, 1, 3, 3>( const int4& a ) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(a))); }
template<> __forceinline const int4 shuffle<0, 1, 0, 1>( const int4& a ) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(a))); }
#endif
template<size_t i0> __forceinline const int4 shuffle( const int4& b ) {
return shuffle<i0,i0,i0,i0>(b);
}
#if defined(__SSE4_1__)
template<size_t src> __forceinline int extract( const int4& b ) { return _mm_extract_epi32(b, src); }
template<size_t dst> __forceinline const int4 insert( const int4& a, const int b ) { return _mm_insert_epi32(a, b, dst); }
#else
template<size_t src> __forceinline int extract( const int4& b ) { return b[src]; }
template<size_t dst> __forceinline const int4 insert( const int4& a, const int b ) { int4 c = a; c[dst] = b; return c; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
#if defined(__SSE4_1__)
__forceinline const int4 vreduce_min(const int4& v) { int4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline const int4 vreduce_max(const int4& v) { int4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline const int4 vreduce_add(const int4& v) { int4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
__forceinline int reduce_min(const int4& v) { return extract<0>(vreduce_min(v)); }
__forceinline int reduce_max(const int4& v) { return extract<0>(vreduce_max(v)); }
__forceinline int reduce_add(const int4& v) { return extract<0>(vreduce_add(v)); }
__forceinline size_t select_min(const int4& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const int4& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool4& valid, const int4& v) { const int4 a = select(valid,v,int4(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const bool4& valid, const int4& v) { const int4 a = select(valid,v,int4(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
#else
__forceinline int reduce_min(const int4& v) { return min(v[0],v[1],v[2],v[3]); }
__forceinline int reduce_max(const int4& v) { return max(v[0],v[1],v[2],v[3]); }
__forceinline int reduce_add(const int4& v) { return v[0]+v[1]+v[2]+v[3]; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int4 load4i( const void* const a ) {
return _mm_load_si128((__m128i*)a);
}
__forceinline int4 loadu4i( const void* const a ) {
return _mm_loadu_si128((__m128i*)a);
}
__forceinline void store4i(void* ptr, const int4& v) {
_mm_store_si128((__m128i*)ptr,v);
}
__forceinline void storeu4i(void* ptr, const int4& v) {
_mm_storeu_si128((__m128i*)ptr,v);
}
__forceinline void store4i( const bool4& mask, void* ptr, const int4& i ) {
#if defined (__AVX__)
_mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i));
#else
*(int4*)ptr = select(mask,i,*(int4*)ptr);
#endif
}
__forceinline int4 load4i_nt (void* ptr) {
#if defined(__SSE4_1__)
return _mm_stream_load_si128((__m128i*)ptr);
#else
return _mm_load_si128((__m128i*)ptr);
#endif
}
__forceinline void store4i_nt(void* ptr, const int4& v) {
#if defined(__SSE4_1__)
_mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
#else
_mm_store_si128((__m128i*)ptr,v);
#endif
}
#if 0 // FIXME: not compiling under VS2013
#if defined (__AVX2__)
__forceinline int4 networkSort(const int4 &v)
{
const int4 a0 = v;
const int4 b0 = shuffle<1,0,3,2>(a0);
const int4 c0 = umin(a0,b0);
const int4 d0 = umax(a0,b0);
const int4 a1 = select(0b0101,c0,d0);
const int4 b1 = shuffle<2,3,0,1>(a1);
const int4 c1 = umin(a1,b1);
//const unsigned int min_dist_index = extract<0>(c1) & 3;
// 2 case border?
//assert(min_dist_index < 4);
const int4 d1 = umax(a1,b1);
const int4 a2 = select(0b0011,c1,d1);
const int4 b2 = shuffle<0,2,1,3>(a2);
const int4 c2 = umin(a2,b2);
const int4 d2 = umax(a2,b2);
const int4 a3 = select(0b0010,c2,d2);
return a3;
}
#endif
#endif
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const int4& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+290
View File
@@ -0,0 +1,290 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 8-wide AVX integer type. */
struct int8
{
typedef bool8 Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256i m256;
struct { __m128i l,h; };
int v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int8 ( ) {}
__forceinline int8 ( const int8& a ) { m256 = a.m256; }
__forceinline int8& operator=( const int8& a ) { m256 = a.m256; return *this; }
__forceinline int8( const __m256i a ) : m256(a) {}
__forceinline operator const __m256i&( void ) const { return m256; }
__forceinline operator __m256i&( void ) { return m256; }
__forceinline explicit int8( const int4& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
__forceinline int8( const int4& a, const int4& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline int8( const __m128i& a, const __m128i& b ) : l(a), h(b) {}
__forceinline explicit int8 ( const int* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
__forceinline int8 ( int a ) : m256(_mm256_set1_epi32(a)) {}
__forceinline int8 ( int a, int b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
__forceinline int8 ( int a, int b, int c, int d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
__forceinline int8 ( int a, int b, int c, int d, int e, int f, int g, int h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
__forceinline explicit int8( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline int8( ZeroTy ) : m256(_mm256_setzero_si256()) {}
__forceinline int8( OneTy ) : m256(_mm256_set_epi32(1,1,1,1,1,1,1,1)) {}
__forceinline int8( PosInfTy ) : m256(_mm256_set_epi32(pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf)) {}
__forceinline int8( NegInfTy ) : m256(_mm256_set_epi32(neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf)) {}
__forceinline int8( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
static __forceinline int8 load( const void* const a) {
return _mm256_castps_si256(_mm256_load_ps((float*)a));
}
static __forceinline int8 loadu( const void* const a) {
return _mm256_castps_si256(_mm256_loadu_ps((float*)a));
}
static __forceinline void store(void* ptr, const int8& f ) {
_mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f));
}
static __forceinline void storeu(void* ptr, const int8& f ) {
_mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f));
}
static __forceinline void store( const bool8& mask, void* ptr, const int8& f ) {
_mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f));
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 operator +( const int8& a ) { return a; }
__forceinline const int8 operator -( const int8& a ) { return int8(_mm_sub_epi32(_mm_setzero_si128(), a.l), _mm_sub_epi32(_mm_setzero_si128(), a.h)); }
__forceinline const int8 abs ( const int8& a ) { return int8(_mm_abs_epi32(a.l), _mm_abs_epi32(a.h)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 operator +( const int8& a, const int8& b ) { return int8(_mm_add_epi32(a.l, b.l), _mm_add_epi32(a.h, b.h)); }
__forceinline const int8 operator +( const int8& a, const int b ) { return a + int8(b); }
__forceinline const int8 operator +( const int a, const int8& b ) { return int8(a) + b; }
__forceinline const int8 operator -( const int8& a, const int8& b ) { return int8(_mm_sub_epi32(a.l, b.l), _mm_sub_epi32(a.h, b.h)); }
__forceinline const int8 operator -( const int8& a, const int b ) { return a - int8(b); }
__forceinline const int8 operator -( const int a, const int8& b ) { return int8(a) - b; }
__forceinline const int8 operator *( const int8& a, const int8& b ) { return int8(_mm_mullo_epi32(a.l, b.l), _mm_mullo_epi32(a.h, b.h)); }
__forceinline const int8 operator *( const int8& a, const int b ) { return a * int8(b); }
__forceinline const int8 operator *( const int a, const int8& b ) { return int8(a) * b; }
__forceinline const int8 operator &( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const int8 operator &( const int8& a, const int b ) { return a & int8(b); }
__forceinline const int8 operator &( const int a, const int8& b ) { return int8(a) & b; }
__forceinline const int8 operator |( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const int8 operator |( const int8& a, const int b ) { return a | int8(b); }
__forceinline const int8 operator |( const int a, const int8& b ) { return int8(a) | b; }
__forceinline const int8 operator ^( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const int8 operator ^( const int8& a, const int b ) { return a ^ int8(b); }
__forceinline const int8 operator ^( const int a, const int8& b ) { return int8(a) ^ b; }
__forceinline const int8 operator <<( const int8& a, const int n ) { return int8(_mm_slli_epi32(a.l, n), _mm_slli_epi32(a.h, n)); }
__forceinline const int8 operator >>( const int8& a, const int n ) { return int8(_mm_srai_epi32(a.l, n), _mm_srai_epi32(a.h, n)); }
__forceinline const int8 sra ( const int8& a, const int b ) { return int8(_mm_srai_epi32(a.l, b), _mm_srai_epi32(a.h, b)); }
__forceinline const int8 srl ( const int8& a, const int b ) { return int8(_mm_srli_epi32(a.l, b), _mm_srli_epi32(a.h, b)); }
__forceinline const int8 min( const int8& a, const int8& b ) { return int8(_mm_min_epi32(a.l, b.l), _mm_min_epi32(a.h, b.h)); }
__forceinline const int8 min( const int8& a, const int b ) { return min(a,int8(b)); }
__forceinline const int8 min( const int a, const int8& b ) { return min(int8(a),b); }
__forceinline const int8 max( const int8& a, const int8& b ) { return int8(_mm_max_epi32(a.l, b.l), _mm_max_epi32(a.h, b.h)); }
__forceinline const int8 max( const int8& a, const int b ) { return max(a,int8(b)); }
__forceinline const int8 max( const int a, const int8& b ) { return max(int8(a),b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int8& operator +=( int8& a, const int8& b ) { return a = a + b; }
__forceinline int8& operator +=( int8& a, const int b ) { return a = a + b; }
__forceinline int8& operator -=( int8& a, const int8& b ) { return a = a - b; }
__forceinline int8& operator -=( int8& a, const int b ) { return a = a - b; }
__forceinline int8& operator *=( int8& a, const int8& b ) { return a = a * b; }
__forceinline int8& operator *=( int8& a, const int b ) { return a = a * b; }
__forceinline int8& operator &=( int8& a, const int8& b ) { return a = a & b; }
__forceinline int8& operator &=( int8& a, const int b ) { return a = a & b; }
__forceinline int8& operator |=( int8& a, const int8& b ) { return a = a | b; }
__forceinline int8& operator |=( int8& a, const int b ) { return a = a | b; }
__forceinline int8& operator <<=( int8& a, const int b ) { return a = a << b; }
__forceinline int8& operator >>=( int8& a, const int b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator ==( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmpeq_epi32 (a.h, b.h))); }
__forceinline const bool8 operator ==( const int8& a, const int b ) { return a == int8(b); }
__forceinline const bool8 operator ==( const int a, const int8& b ) { return int8(a) == b; }
__forceinline const bool8 operator !=( const int8& a, const int8& b ) { return !(a == b); }
__forceinline const bool8 operator !=( const int8& a, const int b ) { return a != int8(b); }
__forceinline const bool8 operator !=( const int a, const int8& b ) { return int8(a) != b; }
__forceinline const bool8 operator < ( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmplt_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmplt_epi32 (a.h, b.h))); }
__forceinline const bool8 operator < ( const int8& a, const int b ) { return a < int8(b); }
__forceinline const bool8 operator < ( const int a, const int8& b ) { return int8(a) < b; }
__forceinline const bool8 operator >=( const int8& a, const int8& b ) { return !(a < b); }
__forceinline const bool8 operator >=( const int8& a, const int b ) { return a >= int8(b); }
__forceinline const bool8 operator >=( const int a, const int8& b ) { return int8(a) >= b; }
__forceinline const bool8 operator > ( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmpgt_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmpgt_epi32 (a.h, b.h))); }
__forceinline const bool8 operator > ( const int8& a, const int b ) { return a > int8(b); }
__forceinline const bool8 operator > ( const int a, const int8& b ) { return int8(a) > b; }
__forceinline const bool8 operator <=( const int8& a, const int8& b ) { return !(a > b); }
__forceinline const bool8 operator <=( const int8& a, const int b ) { return a <= int8(b); }
__forceinline const bool8 operator <=( const int a, const int8& b ) { return int8(a) <= b; }
__forceinline const int8 select( const bool8& m, const int8& t, const int8& f ) {
return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline int8 unpacklo( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline int8 unpackhi( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
template<size_t i> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i, i, i, i)));
}
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a, const int8& b) {
return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i3, i2, i1, i0)));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a, const int8& b ) {
return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
template<> __forceinline const int8 shuffle<0, 0, 2, 2>( const int8& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const int8 shuffle<1, 1, 3, 3>( const int8& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const int8 shuffle<0, 1, 0, 1>( const int8& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
__forceinline const int8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
template<size_t i> __forceinline const int8 insert (const int8& a, const int4& b) { return _mm256_insertf128_si256 (a,b,i); }
template<size_t i> __forceinline const int4 extract(const int8& a ) { return _mm256_extractf128_si256(a ,i); }
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 vreduce_min2(const int8& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const int8 vreduce_min4(const int8& v) { int8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const int8 vreduce_min (const int8& v) { int8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const int8 vreduce_max2(const int8& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const int8 vreduce_max4(const int8& v) { int8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const int8 vreduce_max (const int8& v) { int8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const int8 vreduce_add2(const int8& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const int8 vreduce_add4(const int8& v) { int8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const int8 vreduce_add (const int8& v) { int8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline int reduce_min(const int8& v) { return extract<0>(extract<0>(vreduce_min(v))); }
__forceinline int reduce_max(const int8& v) { return extract<0>(extract<0>(vreduce_max(v))); }
__forceinline int reduce_add(const int8& v) { return extract<0>(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const int8& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const int8& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// New stuff
////////////////////////////////////////////////////////////////////////////////
__forceinline void store8i(void* ptr, const int8& i) {
_mm256_store_ps((float*)ptr,_mm256_castsi256_ps(i));
}
__forceinline void store8i( const bool8 &mask, void *ptr, const int8& i ) {
_mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(i));
}
__forceinline void store8i_nt(void* ptr, const int8& v) {
store4i_nt((int*)ptr+0,v.l);
store4i_nt((int*)ptr+4,v.h);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const int8& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+391
View File
@@ -0,0 +1,391 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/*! 8-wide AVX integer type. */
struct int8
{
typedef bool8 Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256i m256;
int v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int8 ( ) {}
__forceinline int8 ( const int8& a ) { m256 = a.m256; }
__forceinline int8& operator=( const int8& a ) { m256 = a.m256; return *this; }
__forceinline int8( const __m256i a ) : m256(a) {}
__forceinline operator const __m256i&( void ) const { return m256; }
__forceinline operator __m256i&( void ) { return m256; }
__forceinline explicit int8( const int4& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
__forceinline int8( const int4& a, const int4& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline int8( const __m128i& a, const __m128i& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline explicit int8 ( const int* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
__forceinline int8 ( int a ) : m256(_mm256_set1_epi32(a)) {}
__forceinline int8 ( int a, int b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
__forceinline int8 ( int a, int b, int c, int d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
__forceinline int8 ( int a, int b, int c, int d, int e, int f, int g, int h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
__forceinline explicit int8( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline int8( ZeroTy ) : m256(_mm256_setzero_si256()) {}
__forceinline int8( OneTy ) : m256(_mm256_set1_epi32(1)) {}
__forceinline int8( PosInfTy ) : m256(_mm256_set1_epi32(pos_inf)) {}
__forceinline int8( NegInfTy ) : m256(_mm256_set1_epi32(neg_inf)) {}
__forceinline int8( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
__forceinline int8( TrueTy ) { /* m256 = _mm256_undefined_si256(); */ m256 = _mm256_cmpeq_epi32(m256,m256); }
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
static __forceinline int8 load( const unsigned char* const ptr ) {
return _mm256_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr));
}
static __forceinline const int8 load(const int* const i) {
return _mm256_load_si256((__m256i*)i);
}
static __forceinline const int8 uload(const int* const i) {
return _mm256_loadu_si256((__m256i*)i);
}
static __forceinline void store(void* ptr, const int8& i ) {
_mm256_store_si256((__m256i*)ptr,i);
}
static __forceinline void store( const bool8& mask, void *ptr, const int8& i ) {
_mm256_maskstore_epi32((int*)ptr,mask,i);
}
static __forceinline void storeu(void* ptr, const int8& f ) {
_mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f));
}
#if defined (__AVX2__)
static __forceinline int8 load_nt(void* ptr) {
return _mm256_stream_load_si256((__m256i*)ptr);
}
#endif
static __forceinline void store_nt(void* ptr, const int8& v) {
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 operator +( const int8& a ) { return a; }
__forceinline const int8 operator -( const int8& a ) { return _mm256_sub_epi32(_mm256_setzero_si256(), a.m256); }
__forceinline const int8 abs ( const int8& a ) { return _mm256_abs_epi32(a.m256); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 operator +( const int8& a, const int8& b ) { return _mm256_add_epi32(a.m256, b.m256); }
__forceinline const int8 operator +( const int8& a, const int b ) { return a + int8(b); }
__forceinline const int8 operator +( const int a, const int8& b ) { return int8(a) + b; }
__forceinline const int8 operator -( const int8& a, const int8& b ) { return _mm256_sub_epi32(a.m256, b.m256); }
__forceinline const int8 operator -( const int8& a, const int b ) { return a - int8(b); }
__forceinline const int8 operator -( const int a, const int8& b ) { return int8(a) - b; }
__forceinline const int8 operator *( const int8& a, const int8& b ) { return _mm256_mullo_epi32(a.m256, b.m256); }
__forceinline const int8 operator *( const int8& a, const int b ) { return a * int8(b); }
__forceinline const int8 operator *( const int a, const int8& b ) { return int8(a) * b; }
__forceinline const int8 operator &( const int8& a, const int8& b ) { return _mm256_and_si256(a.m256, b.m256); }
__forceinline const int8 operator &( const int8& a, const int b ) { return a & int8(b); }
__forceinline const int8 operator &( const int a, const int8& b ) { return int8(a) & b; }
__forceinline const int8 operator |( const int8& a, const int8& b ) { return _mm256_or_si256(a.m256, b.m256); }
__forceinline const int8 operator |( const int8& a, const int b ) { return a | int8(b); }
__forceinline const int8 operator |( const int a, const int8& b ) { return int8(a) | b; }
__forceinline const int8 operator ^( const int8& a, const int8& b ) { return _mm256_xor_si256(a.m256, b.m256); }
__forceinline const int8 operator ^( const int8& a, const int b ) { return a ^ int8(b); }
__forceinline const int8 operator ^( const int a, const int8& b ) { return int8(a) ^ b; }
__forceinline const int8 operator <<( const int8& a, const int n ) { return _mm256_slli_epi32(a.m256, n); }
__forceinline const int8 operator >>( const int8& a, const int n ) { return _mm256_srai_epi32(a.m256, n); }
__forceinline const int8 sra ( const int8& a, const int b ) { return _mm256_srai_epi32(a.m256, b); }
__forceinline const int8 srl ( const int8& a, const int b ) { return _mm256_srli_epi32(a.m256, b); }
__forceinline const int8 sra ( const int8& a, const int8 &b ) { return _mm256_srav_epi32(a.m256, b.m256); }
__forceinline const int8 srl ( const int8& a, const int8 &b ) { return _mm256_srlv_epi32(a.m256, b.m256); }
__forceinline const int8 min( const int8& a, const int8& b ) { return _mm256_min_epi32(a.m256, b.m256); }
__forceinline const int8 min( const int8& a, const int b ) { return min(a,int8(b)); }
__forceinline const int8 min( const int a, const int8& b ) { return min(int8(a),b); }
__forceinline const int8 max( const int8& a, const int8& b ) { return _mm256_max_epi32(a.m256, b.m256); }
__forceinline const int8 max( const int8& a, const int b ) { return max(a,int8(b)); }
__forceinline const int8 max( const int a, const int8& b ) { return max(int8(a),b); }
__forceinline const int8 umin( const int8& a, const int8& b ) { return _mm256_min_epu32(a.m256, b.m256); }
__forceinline const int8 umax( const int8& a, const int8& b ) { return _mm256_max_epu32(a.m256, b.m256); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline int8& operator +=( int8& a, const int8& b ) { return a = a + b; }
__forceinline int8& operator +=( int8& a, const int b ) { return a = a + b; }
__forceinline int8& operator -=( int8& a, const int8& b ) { return a = a - b; }
__forceinline int8& operator -=( int8& a, const int b ) { return a = a - b; }
__forceinline int8& operator *=( int8& a, const int8& b ) { return a = a * b; }
__forceinline int8& operator *=( int8& a, const int b ) { return a = a * b; }
__forceinline int8& operator &=( int8& a, const int8& b ) { return a = a & b; }
__forceinline int8& operator &=( int8& a, const int b ) { return a = a & b; }
__forceinline int8& operator |=( int8& a, const int8& b ) { return a = a | b; }
__forceinline int8& operator |=( int8& a, const int b ) { return a = a | b; }
__forceinline int8& operator <<=( int8& a, const int b ) { return a = a << b; }
__forceinline int8& operator >>=( int8& a, const int b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const bool8 operator ==( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32 (a.m256, b.m256)); }
__forceinline const bool8 operator ==( const int8& a, const int b ) { return a == int8(b); }
__forceinline const bool8 operator ==( const int a, const int8& b ) { return int8(a) == b; }
__forceinline const bool8 operator !=( const int8& a, const int8& b ) { return !(a == b); }
__forceinline const bool8 operator !=( const int8& a, const int b ) { return a != int8(b); }
__forceinline const bool8 operator !=( const int a, const int8& b ) { return int8(a) != b; }
__forceinline const bool8 operator < ( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (b.m256, a.m256)); }
__forceinline const bool8 operator < ( const int8& a, const int b ) { return a < int8(b); }
__forceinline const bool8 operator < ( const int a, const int8& b ) { return int8(a) < b; }
__forceinline const bool8 operator >=( const int8& a, const int8& b ) { return !(a < b); }
__forceinline const bool8 operator >=( const int8& a, const int b ) { return a >= int8(b); }
__forceinline const bool8 operator >=( const int a, const int8& b ) { return int8(a) >= b; }
__forceinline const bool8 operator > ( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (a.m256, b.m256)); }
__forceinline const bool8 operator > ( const int8& a, const int b ) { return a > int8(b); }
__forceinline const bool8 operator > ( const int a, const int8& b ) { return int8(a) > b; }
__forceinline const bool8 operator <=( const int8& a, const int8& b ) { return !(a > b); }
__forceinline const bool8 operator <=( const int8& a, const int b ) { return a <= int8(b); }
__forceinline const bool8 operator <=( const int a, const int8& b ) { return int8(a) <= b; }
__forceinline const int8 select( const bool8& m, const int8& t, const int8& f ) {
return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
}
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
__forceinline const int8 select(const int m, const int8& t, const int8& f) {
return select(bool8(m), t, f); // workaround for clang and Microsoft compiler bugs
}
#else
__forceinline const int8 select(const int m, const int8& t, const int8& f) {
return _mm256_blend_epi32(f, t, m);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline int8 unpacklo( const int8& a, const int8& b ) { return _mm256_unpacklo_epi32(a.m256, b.m256); }
__forceinline int8 unpackhi( const int8& a, const int8& b ) { return _mm256_unpackhi_epi32(a.m256, b.m256); }
template<size_t i> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i, i, i, i)));
}
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a, const int8& b) {
return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a ) {
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i3, i2, i1, i0)));
}
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a, const int8& b ) {
return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
template<> __forceinline const int8 shuffle<0, 0, 2, 2>( const int8& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const int8 shuffle<1, 1, 3, 3>( const int8& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const int8 shuffle<0, 1, 0, 1>( const int8& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
__forceinline const int8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
template<size_t i> __forceinline const int8 insert (const int8& a, const int4& b) { return _mm256_insertf128_si256 (a,b,i); }
template<size_t i> __forceinline const int4 extract(const int8& a ) { return _mm256_extractf128_si256(a ,i); }
__forceinline int8 permute(const int8& a, const __m256i& index) {
return _mm256_permutevar8x32_epi32(a,index);
}
__forceinline int8 permute4x32(const int8& a, const __m256i& index) {
return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(a),index));
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 vreduce_min2(const int8& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const int8 vreduce_min4(const int8& v) { int8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const int8 vreduce_min (const int8& v) { int8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const int8 vreduce_max2(const int8& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const int8 vreduce_max4(const int8& v) { int8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const int8 vreduce_max (const int8& v) { int8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const int8 vreduce_add2(const int8& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const int8 vreduce_add4(const int8& v) { int8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const int8 vreduce_add (const int8& v) { int8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline int reduce_min(const int8& v) { return extract<0>(extract<0>(vreduce_min(v))); }
__forceinline int reduce_max(const int8& v) { return extract<0>(extract<0>(vreduce_max(v))); }
__forceinline int reduce_add(const int8& v) { return extract<0>(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const int8& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const int8& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
__forceinline int8 assign( const int4& a ) { return _mm256_castsi128_si256(a); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline const int8 load8i(const int* const i) {
return _mm256_load_si256((__m256i*)i);
}
__forceinline const int8 uload8i(const int* const i) {
return _mm256_loadu_si256((__m256i*)i);
}
__forceinline void store8i(void *ptr, const int8& i ) {
_mm256_store_si256((__m256i*)ptr,i);
}
__forceinline void store8i( const bool8& mask, void *ptr, const int8& i ) {
_mm256_maskstore_epi32((int*)ptr,mask,i);
}
#if defined (__AVX2__)
__forceinline int8 load8i_nt(void* ptr) {
return _mm256_stream_load_si256((__m256i*)ptr);
}
#endif
__forceinline void store8i_nt(void* ptr, const int8& v) {
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
}
#if 0 // FIXME: not compiling under VS2013
__forceinline int8 sortNetwork2x4(const int8& v)
{
const int8 a0 = v;
const int8 b0 = shuffle<1,0,3,2>(a0);
const int8 c0 = umin(a0,b0);
const int8 d0 = umax(a0,b0);
const int8 a1 = (0b01010101,c0,d0);
const int8 b1 = shuffle<2,3,0,1>(a1);
const int8 c1 = umin(a1,b1);
const int8 d1 = umax(a1,b1);
const int8 a2 = (0b00110011,c1,d1);
const int8 b2 = shuffle<0,2,1,3>(a2);
const int8 c2 = umin(a2,b2);
const int8 d2 = umax(a2,b2);
const int8 a3 = select(0b00100010,c2,d2);
return a3;
}
__forceinline int8 sortNetwork(const int8& v)
{
const int8 a0 = v;
const int8 b0 = shuffle<1,0,3,2>(a0);
const int8 c0 = umin(a0,b0);
const int8 d0 = umax(a0,b0);
const int8 a1 = select(0b10011001,c0,d0);
const int8 b1 = shuffle<2,3,0,1>(a1);
const int8 c1 = umin(a1,b1);
const int8 d1 = umax(a1,b1);
const int8 a2 = select(0b11000011,c1,d1);
const int8 b2 = shuffle<1,0,3,2>(a2);
const int8 c2 = umin(a2,b2);
const int8 d2 = umax(a2,b2);
const int8 a3 = select(0b10100101,c2,d2);
const int8 b3 = shuffle<1,0>(a3);
const int8 c3 = umin(a3,b3);
const int8 d3 = umax(a3,b3);
const int8 a4 = select(0b00001111,c3,d3);
const int8 b4 = shuffle<2,3,0,1>(a4);
const int8 c4 = umin(a4,b4);
const int8 d4 = umax(a4,b4);
const int8 a5 = select(0b00110011,c4,d4);
const int8 b5 = shuffle<1,0,3,2>(a5);
const int8 c5 = umin(a5,b5);
const int8 d5 = umax(a5,b5);
const int8 a6 = select(0b01010101,c5,d5);
return a6;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const int8& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+40 -24
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -25,31 +25,47 @@
/* include AVX wrapper classes */
#if defined(__AVX__)
# include "avx.h"
#include "avx.h"
#endif
/* include AVX512 wrapper classes */
#if defined (__AVX512F__)
#if defined (__MIC__)
# include "avx512.h"
#endif
#if defined (__AVX__)
#if defined(__AVX512F__)
# define AVX_ZERO_UPPER()
#elif defined (__AVX__)
# define AVX_ZERO_UPPER() _mm256_zeroupper()
#define AVX_ZERO_UPPER()
#else
# define AVX_ZERO_UPPER()
#define AVX_ZERO_UPPER() _mm256_zeroupper()
#endif
#else
#define AVX_ZERO_UPPER()
#endif
namespace embree
{
#if defined (__AVX512F__) || defined (__MIC__)
typedef bool16 vbool;
typedef int16 vint;
typedef float16 vfloat;
#elif defined(__AVX__)
typedef bool8 vbool;
typedef int8 vint;
typedef float8 vfloat;
#else
typedef bool4 vbool;
typedef int4 vint;
typedef float4 vfloat;
#endif
/* foreach unique */
template<typename vbool, typename vint, typename Closure>
__forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
__forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
{
vbool valid1 = valid0;
while (any(valid1)) {
const int j = int(__bsf(movemask(valid1)));
const int j = __bsf(movemask(valid1));
const int i = vi[j];
const vbool valid2 = valid1 & (i == vi);
valid1 = valid1 & !valid2;
@@ -59,11 +75,11 @@ namespace embree
/* foreach unique */
template<typename vbool, typename vint, typename Closure>
__forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
__forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
{
vbool valid1 = valid0;
while (any(valid1)) {
const int j = (int) __bsf(movemask(valid1));
const int j = __bsf(movemask(valid1));
const int i = vi[j];
const vbool valid2 = valid1 & (i == vi);
valid1 = valid1 & !valid2;
@@ -74,24 +90,24 @@ namespace embree
template<typename Closure>
__forceinline void foreach2(int x0, int x1, int y0, int y1, const Closure& closure)
{
__aligned(64) int U[2*VSIZEX];
__aligned(64) int V[2*VSIZEX];
__aligned(64) int U[128];
__aligned(64) int V[128];
int index = 0;
for (int y=y0; y<y1; y++) {
const bool lasty = y+1>=y1;
const vintx vy = y;
for (int x=x0; x<x1; ) { //x+=VSIZEX) {
const bool lastx = x+VSIZEX >= x1;
vintx vx = x+vintx(step);
vintx::storeu(&U[index],vx);
vintx::storeu(&V[index],vy);
const int dx = min(x1-x,VSIZEX);
const vint vy = y;
for (int x=x0; x<x1; ) { //x+=vfloat::size) {
const bool lastx = x+vfloat::size >= x1;
vint vx = x+vint(step);
vint::storeu(&U[index],vx);
vint::storeu(&V[index],vy);
const int dx = min(x1-x,vfloat::size);
index += dx;
x += dx;
if (index >= VSIZEX || (lastx && lasty)) {
const vboolx valid = vintx(step) < vintx(index);
closure(valid,vintx::load(U),vintx::load(V));
x-= max(0,index-VSIZEX);
if (index >= vfloat::size || (lastx && lasty)) {
const vbool valid = vint(step) < vint(index);
closure(valid,vint::load(U),vint::load(V));
x-= max(0,index-vfloat::size);
index = 0;
}
}
+114
View File
@@ -0,0 +1,114 @@
// ======================================================================== //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once // FIXME: remove this file?
#ifndef __GNUC__
#pragma message (" --- Intel remark: SSE4 intrinsics are emulated with SSE3 ---")
#endif
#define _MM_FROUND_TO_NEAREST_INT 0x00
#define _MM_FROUND_TO_NEG_INF 0x01
#define _MM_FROUND_TO_POS_INF 0x02
#define _MM_FROUND_TO_ZERO 0x03
#define _MM_FROUND_CUR_DIRECTION 0x04
#define _mm_blendv_ps __emu_mm_blendv_ps
__forceinline __m128 _mm_blendv_ps( __m128 value, __m128 input, __m128 mask ) {
return _mm_or_ps(_mm_and_ps(mask, input), _mm_andnot_ps(mask, value));
}
#define _mm_blend_ps __emu_mm_blend_ps
__forceinline __m128 _mm_blend_ps( __m128 value, __m128 input, const int mask ) {
assert(mask < 0x10); return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]);
}
#define _mm_blendv_epi8 __emu_mm_blendv_epi8
__forceinline __m128i _mm_blendv_epi8( __m128i value, __m128i input, __m128i mask ) {
return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value));
}
#define _mm_mullo_epi32 __emu_mm_mullo_epi32
__forceinline __m128i _mm_mullo_epi32( __m128i value, __m128i input ) {
__m128i rvalue;
char* _r = (char*)(&rvalue + 1);
char* _v = (char*)(& value + 1);
char* _i = (char*)(& input + 1);
for ( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32_t*)(_r + i)) = *((int32_t*)(_v + i))* *((int32_t*)(_i + i));
return rvalue;
}
#define _mm_min_epi32 __emu_mm_min_epi32
__forceinline __m128i _mm_min_epi32( __m128i value, __m128i input ) {
return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input));
}
#define _mm_max_epi32 __emu_mm_max_epi32
__forceinline __m128i _mm_max_epi32( __m128i value, __m128i input ) {
return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input));
}
#define _mm_extract_epi32 __emu_mm_extract_epi32
__forceinline int _mm_extract_epi32( __m128i input, const int index ) {
switch ( index ) {
case 0: return _mm_cvtsi128_si32(input);
case 1: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
case 2: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
case 3: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(3, 3, 3, 3)));
default: assert(false); return 0;
}
}
#define _mm_insert_epi32 __emu_mm_insert_epi32
__forceinline __m128i _mm_insert_epi32( __m128i value, int input, const int index ) {
assert(index >= 0 && index < 4); ((int*)&value)[index] = input; return value;
}
#define _mm_extract_ps __emu_mm_extract_ps
__forceinline int _mm_extract_ps( __m128 input, const int index ) {
int32_t* ptr = (int32_t*)&input; return ptr[index];
}
#define _mm_insert_ps __emu_mm_insert_ps
__forceinline __m128 _mm_insert_ps( __m128 value, __m128 input, const int index )
{ assert(index < 0x100); ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6]; return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value); }
#define _mm_round_ps __emu_mm_round_ps
__forceinline __m128 _mm_round_ps( __m128 value, const int flags )
{
switch ( flags )
{
case _MM_FROUND_TO_NEAREST_INT: return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
case _MM_FROUND_TO_NEG_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
case _MM_FROUND_TO_POS_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps( 0.5f))));
case _MM_FROUND_TO_ZERO : return _mm_cvtepi32_ps(_mm_cvttps_epi32(value));
}
return value;
}
#ifdef _M_X64
#define _mm_insert_epi64 __emu_mm_insert_epi64
__forceinline __m128i _mm_insert_epi64( __m128i value, int64_t input, const int index ) {
assert(size_t(index) < 4); ((int64_t*)&value)[index] = input; return value;
}
#define _mm_extract_epi64 __emu_mm_extract_epi64
__forceinline int64_t _mm_extract_epi64( __m128i input, const int index ) {
assert(size_t(index) < 2);
return index == 0 ? _mm_cvtsi128_si64x(input) : _mm_cvtsi128_si64x(_mm_unpackhi_epi64(input, input));
}
#endif
+2 -11
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -16,8 +16,7 @@
#include "sse.h"
namespace embree
{
namespace embree {
const __m128 _mm_lookupmask_ps[16] = {
_mm_castsi128_ps(_mm_set_epi32( 0, 0, 0, 0)),
_mm_castsi128_ps(_mm_set_epi32( 0, 0, 0,-1)),
@@ -36,12 +35,4 @@ namespace embree
_mm_castsi128_ps(_mm_set_epi32(-1,-1,-1, 0)),
_mm_castsi128_ps(_mm_set_epi32(-1,-1,-1,-1))
};
const __m128d _mm_lookupmask_pd[4] = {
_mm_castsi128_pd(_mm_set_epi32( 0, 0, 0, 0)),
_mm_castsi128_pd(_mm_set_epi32( 0, 0,-1,-1)),
_mm_castsi128_pd(_mm_set_epi32(-1,-1, 0, 0)),
_mm_castsi128_pd(_mm_set_epi32(-1,-1,-1,-1))
};
}
+12 -14
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2015 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -19,29 +19,27 @@
#include "../sys/platform.h"
#include "../sys/intrinsics.h"
#include "../math/constants.h"
#include "varying.h"
#include "sse_special.h"
namespace embree
{
#if defined(__SSE4_1__)
__forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
__forceinline __m128 blendv_ps( __m128 f, __m128 t, __m128 mask ) {
return _mm_blendv_ps(f,t,mask);
}
#else
__forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
__forceinline __m128 blendv_ps( __m128 f, __m128 t, __m128 mask ) {
return _mm_or_ps(_mm_and_ps(mask, t), _mm_andnot_ps(mask, f));
}
#endif
extern const __m128 _mm_lookupmask_ps[16];
extern const __m128d _mm_lookupmask_pd[4];
extern const __m128 _mm_lookupmask_ps[16];
struct bool4;
struct int4;
struct float4;
}
#if defined(__AVX512VL__)
#include "vboolf4_avx512.h"
#else
#include "vboolf4_sse2.h"
#endif
#include "vint4_sse2.h"
#include "vuint4_sse2.h"
#include "vfloat4_sse2.h"
#include "bool4_sse2.h"
#include "int4_sse2.h"
#include "float4_sse2.h"
+761
View File
@@ -0,0 +1,761 @@
/* SIMD (SSE1+MMX or SSE2) implementation of sin, cos, exp and log
Inspired by Intel Approximate Math library, and based on the
corresponding algorithms of the cephes math library
The default is to use the SSE1 version. If you define USE_SSE2 the
the SSE2 intrinsics will be used in place of the MMX intrinsics. Do
not expect any significant performance improvement with SSE2.
*/
/* Copyright (C) 2007 Julien Pommier
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
(this is the zlib license)
*/
#include <xmmintrin.h>
/* yes I know, the top of this file is quite ugly */
#ifdef _MSC_VER /* visual c++ */
# define ALIGN16_BEG __declspec(align(16))
# define ALIGN16_END
# define USE_SSE2
#else /* gcc or icc */
# define ALIGN16_BEG
# define ALIGN16_END __attribute__((aligned(16)))
#endif
/* __m128 is ugly to write */
typedef __m128 v4sf; // vector of 4 float (sse1)
#ifdef USE_SSE2
# include <emmintrin.h>
typedef __m128i v4si; // vector of 4 int (sse2)
#else
typedef __m64 v2si; // vector of 2 int (mmx)
#endif
/* declare some SSE constants -- why can't I figure a better way to do that? */
#define _PS_CONST(Name, Val) \
static const ALIGN16_BEG float _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
#define _PI32_CONST(Name, Val) \
static const ALIGN16_BEG int _pi32_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
#define _PS_CONST_TYPE(Name, Type, Val) \
static const ALIGN16_BEG Type _ps_##Name[4] ALIGN16_END = { Val, Val, Val, Val }
_PS_CONST(1 , 1.0f);
_PS_CONST(0p5, 0.5f);
/* the smallest non denormalized float number */
_PS_CONST_TYPE(min_norm_pos, int, 0x00800000);
_PS_CONST_TYPE(mant_mask, int, 0x7f800000);
_PS_CONST_TYPE(inv_mant_mask, int, ~0x7f800000);
_PS_CONST_TYPE(sign_mask, int, 0x80000000);
_PS_CONST_TYPE(inv_sign_mask, int, ~0x80000000);
_PI32_CONST(1, 1);
_PI32_CONST(inv1, ~1);
_PI32_CONST(2, 2);
_PI32_CONST(4, 4);
_PI32_CONST(0x7f, 0x7f);
_PS_CONST(cephes_SQRTHF, 0.707106781186547524f);
_PS_CONST(cephes_log_p0, 7.0376836292E-2f);
_PS_CONST(cephes_log_p1, - 1.1514610310E-1f);
_PS_CONST(cephes_log_p2, 1.1676998740E-1f);
_PS_CONST(cephes_log_p3, - 1.2420140846E-1f);
_PS_CONST(cephes_log_p4, + 1.4249322787E-1f);
_PS_CONST(cephes_log_p5, - 1.6668057665E-1f);
_PS_CONST(cephes_log_p6, + 2.0000714765E-1f);
_PS_CONST(cephes_log_p7, - 2.4999993993E-1f);
_PS_CONST(cephes_log_p8, + 3.3333331174E-1f);
_PS_CONST(cephes_log_q1, -2.12194440e-4f);
_PS_CONST(cephes_log_q2, 0.693359375f);
#if defined (__MINGW32__)
/* the ugly part below: many versions of gcc used to be completely buggy with respect to some intrinsics
The movehl_ps is fixed in mingw 3.4.5, but I found out that all the _mm_cmp* intrinsics were completely
broken on my mingw gcc 3.4.5 ...
Note that the bug on _mm_cmp* does occur only at -O0 optimization level
*/
inline __m128 my_movehl_ps(__m128 a, const __m128 b) {
asm (
"movhlps %2,%0\n\t"
: "=x" (a)
: "0" (a), "x"(b)
);
return a; }
#warning "redefined _mm_movehl_ps (see gcc bug 21179)"
#define _mm_movehl_ps my_movehl_ps
inline __m128 my_cmplt_ps(__m128 a, const __m128 b) {
asm (
"cmpltps %2,%0\n\t"
: "=x" (a)
: "0" (a), "x"(b)
);
return a;
}
inline __m128 my_cmpgt_ps(__m128 a, const __m128 b) {
asm (
"cmpnleps %2,%0\n\t"
: "=x" (a)
: "0" (a), "x"(b)
);
return a;
}
inline __m128 my_cmpeq_ps(__m128 a, const __m128 b) {
asm (
"cmpeqps %2,%0\n\t"
: "=x" (a)
: "0" (a), "x"(b)
);
return a;
}
#warning "redefined _mm_cmpxx_ps functions..."
#define _mm_cmplt_ps my_cmplt_ps
#define _mm_cmpgt_ps my_cmpgt_ps
#define _mm_cmpeq_ps my_cmpeq_ps
#endif
#ifndef USE_SSE2
typedef union xmm_mm_union {
__m128 xmm;
__m64 mm[2];
} xmm_mm_union;
#define COPY_XMM_TO_MM(xmm_, mm0_, mm1_) { \
xmm_mm_union u; u.xmm = xmm_; \
mm0_ = u.mm[0]; \
mm1_ = u.mm[1]; \
}
#define COPY_MM_TO_XMM(mm0_, mm1_, xmm_) { \
xmm_mm_union u; u.mm[0]=mm0_; u.mm[1]=mm1_; xmm_ = u.xmm; \
}
#endif // USE_SSE2
/* natural logarithm computed for 4 simultaneous float
return NaN for x <= 0
*/
inline v4sf log_ps(v4sf x) {
#ifdef USE_SSE2
v4si emm0;
#else
v2si mm0, mm1;
#endif
v4sf one = *(v4sf*)_ps_1;
v4sf invalid_mask = _mm_cmple_ps(x, _mm_setzero_ps());
x = _mm_max_ps(x, *(v4sf*)_ps_min_norm_pos); /* cut off denormalized stuff */
#ifndef USE_SSE2
/* part 1: x = frexpf(x, &e); */
COPY_XMM_TO_MM(x, mm0, mm1);
mm0 = _mm_srli_pi32(mm0, 23);
mm1 = _mm_srli_pi32(mm1, 23);
#else
emm0 = _mm_srli_epi32(_mm_castps_si128(x), 23);
#endif
/* keep only the fractional part */
x = _mm_and_ps(x, *(v4sf*)_ps_inv_mant_mask);
x = _mm_or_ps(x, *(v4sf*)_ps_0p5);
#ifndef USE_SSE2
/* now e=mm0:mm1 contain the really base-2 exponent */
mm0 = _mm_sub_pi32(mm0, *(v2si*)_pi32_0x7f);
mm1 = _mm_sub_pi32(mm1, *(v2si*)_pi32_0x7f);
v4sf e = _mm_cvtpi32x2_ps(mm0, mm1);
_mm_empty(); /* bye bye mmx */
#else
emm0 = _mm_sub_epi32(emm0, *(v4si*)_pi32_0x7f);
v4sf e = _mm_cvtepi32_ps(emm0);
#endif
e = _mm_add_ps(e, one);
/* part2:
if( x < SQRTHF ) {
e -= 1;
x = x + x - 1.0;
} else { x = x - 1.0; }
*/
v4sf mask = _mm_cmplt_ps(x, *(v4sf*)_ps_cephes_SQRTHF);
v4sf tmp = _mm_and_ps(x, mask);
x = _mm_sub_ps(x, one);
e = _mm_sub_ps(e, _mm_and_ps(one, mask));
x = _mm_add_ps(x, tmp);
v4sf z = _mm_mul_ps(x,x);
v4sf y = *(v4sf*)_ps_cephes_log_p0;
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p1);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p2);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p3);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p4);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p5);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p6);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p7);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_log_p8);
y = _mm_mul_ps(y, x);
y = _mm_mul_ps(y, z);
tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q1);
y = _mm_add_ps(y, tmp);
tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
y = _mm_sub_ps(y, tmp);
tmp = _mm_mul_ps(e, *(v4sf*)_ps_cephes_log_q2);
x = _mm_add_ps(x, y);
x = _mm_add_ps(x, tmp);
x = _mm_or_ps(x, invalid_mask); // negative arg will be NAN
return x;
}
_PS_CONST(exp_hi, 88.3762626647949f);
_PS_CONST(exp_lo, -88.3762626647949f);
_PS_CONST(cephes_LOG2EF, 1.44269504088896341f);
_PS_CONST(cephes_exp_C1, 0.693359375f);
_PS_CONST(cephes_exp_C2, -2.12194440e-4f);
_PS_CONST(cephes_exp_p0, 1.9875691500E-4f);
_PS_CONST(cephes_exp_p1, 1.3981999507E-3f);
_PS_CONST(cephes_exp_p2, 8.3334519073E-3f);
_PS_CONST(cephes_exp_p3, 4.1665795894E-2f);
_PS_CONST(cephes_exp_p4, 1.6666665459E-1f);
_PS_CONST(cephes_exp_p5, 5.0000001201E-1f);
inline v4sf exp_ps(v4sf x) {
v4sf tmp = _mm_setzero_ps(), fx;
#ifdef USE_SSE2
v4si emm0;
#else
v2si mm0, mm1;
#endif
v4sf one = *(v4sf*)_ps_1;
x = _mm_min_ps(x, *(v4sf*)_ps_exp_hi);
x = _mm_max_ps(x, *(v4sf*)_ps_exp_lo);
/* express exp(x) as exp(g + n*log(2)) */
fx = _mm_mul_ps(x, *(v4sf*)_ps_cephes_LOG2EF);
fx = _mm_add_ps(fx, *(v4sf*)_ps_0p5);
/* how to perform a floorf with SSE: just below */
#ifndef USE_SSE2
/* step 1 : cast to int */
tmp = _mm_movehl_ps(tmp, fx);
mm0 = _mm_cvttps_pi32(fx);
mm1 = _mm_cvttps_pi32(tmp);
/* step 2 : cast back to float */
tmp = _mm_cvtpi32x2_ps(mm0, mm1);
#else
emm0 = _mm_cvttps_epi32(fx);
tmp = _mm_cvtepi32_ps(emm0);
#endif
/* if greater, substract 1 */
v4sf mask = _mm_cmpgt_ps(tmp, fx);
mask = _mm_and_ps(mask, one);
fx = _mm_sub_ps(tmp, mask);
tmp = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C1);
v4sf z = _mm_mul_ps(fx, *(v4sf*)_ps_cephes_exp_C2);
x = _mm_sub_ps(x, tmp);
x = _mm_sub_ps(x, z);
z = _mm_mul_ps(x,x);
v4sf y = *(v4sf*)_ps_cephes_exp_p0;
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p1);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p2);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p3);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p4);
y = _mm_mul_ps(y, x);
y = _mm_add_ps(y, *(v4sf*)_ps_cephes_exp_p5);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, x);
y = _mm_add_ps(y, one);
/* build 2^n */
#ifndef USE_SSE2
z = _mm_movehl_ps(z, fx);
mm0 = _mm_cvttps_pi32(fx);
mm1 = _mm_cvttps_pi32(z);
mm0 = _mm_add_pi32(mm0, *(v2si*)_pi32_0x7f);
mm1 = _mm_add_pi32(mm1, *(v2si*)_pi32_0x7f);
mm0 = _mm_slli_pi32(mm0, 23);
mm1 = _mm_slli_pi32(mm1, 23);
v4sf pow2n;
COPY_MM_TO_XMM(mm0, mm1, pow2n);
_mm_empty();
#else
emm0 = _mm_cvttps_epi32(fx);
emm0 = _mm_add_epi32(emm0, *(v4si*)_pi32_0x7f);
emm0 = _mm_slli_epi32(emm0, 23);
v4sf pow2n = _mm_castsi128_ps(emm0);
#endif
y = _mm_mul_ps(y, pow2n);
return y;
}
_PS_CONST(minus_cephes_DP1, -0.78515625f);
_PS_CONST(minus_cephes_DP2, -2.4187564849853515625e-4f);
_PS_CONST(minus_cephes_DP3, -3.77489497744594108e-8f);
_PS_CONST(sincof_p0, -1.9515295891E-4f);
_PS_CONST(sincof_p1, 8.3321608736E-3f);
_PS_CONST(sincof_p2, -1.6666654611E-1f);
_PS_CONST(coscof_p0, 2.443315711809948E-005f);
_PS_CONST(coscof_p1, -1.388731625493765E-003f);
_PS_CONST(coscof_p2, 4.166664568298827E-002f);
_PS_CONST(cephes_FOPI, 1.27323954473516f); // 4 / M_PI
/* evaluation of 4 sines at onces, using only SSE1+MMX intrinsics so
it runs also on old athlons XPs and the pentium III of your grand
mother.
The code is the exact rewriting of the cephes sinf function.
Precision is excellent as long as x < 8192 (I did not bother to
take into account the special handling they have for greater values
-- it does not return garbage for arguments over 8192, though, but
the extra precision is missing).
Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the
surprising but correct result.
Performance is also surprisingly good, 1.33 times faster than the
macos vsinf SSE2 function, and 1.5 times faster than the
__vrs4_sinf of amd's ACML (which is only available in 64 bits). Not
too bad for an SSE1 function (with no special tuning) !
However the latter libraries probably have a much better handling of NaN,
Inf, denormalized and other special arguments..
On my core 1 duo, the execution of this function takes approximately 95 cycles.
From what I have observed on the experiments with Intel AMath lib, switching to an
SSE2 version would improve the perf by only 10%.
Since it is based on SSE intrinsics, it has to be compiled at -O2 to
deliver full speed.
*/
inline v4sf sin_ps(v4sf x) { // any x
v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, sign_bit, y;
#ifdef USE_SSE2
v4si emm0, emm2;
#else
v2si mm0, mm1, mm2, mm3;
#endif
sign_bit = x;
/* take the absolute value */
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
/* extract the sign bit (upper one) */
sign_bit = _mm_and_ps(sign_bit, *(v4sf*)_ps_sign_mask);
/* scale by 4/Pi */
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
//printf("plop:"); print4(y);
#ifdef USE_SSE2
/* store the integer part of y in mm0 */
emm2 = _mm_cvttps_epi32(y);
/* j=(j+1) & (~1) (see the cephes sources) */
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
y = _mm_cvtepi32_ps(emm2);
/* get the swap sign flag */
emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4);
emm0 = _mm_slli_epi32(emm0, 29);
/* get the polynom selection mask
there is one polynom for 0 <= x <= Pi/4
and another one for Pi/4<x<=Pi/2
Both branches will be computed.
*/
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
v4sf swap_sign_bit = _mm_castsi128_ps(emm0);
v4sf poly_mask = _mm_castsi128_ps(emm2);
sign_bit = _mm_xor_ps(sign_bit, swap_sign_bit);
#else
/* store the integer part of y in mm0:mm1 */
xmm2 = _mm_movehl_ps(xmm2, y);
mm2 = _mm_cvttps_pi32(y);
mm3 = _mm_cvttps_pi32(xmm2);
/* j=(j+1) & (~1) (see the cephes sources) */
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
y = _mm_cvtpi32x2_ps(mm2, mm3);
/* get the swap sign flag */
mm0 = _mm_and_si64(mm2, *(v2si*)_pi32_4);
mm1 = _mm_and_si64(mm3, *(v2si*)_pi32_4);
mm0 = _mm_slli_pi32(mm0, 29);
mm1 = _mm_slli_pi32(mm1, 29);
/* get the polynom selection mask */
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
v4sf swap_sign_bit, poly_mask;
COPY_MM_TO_XMM(mm0, mm1, swap_sign_bit);
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
sign_bit = _mm_xor_ps(sign_bit, swap_sign_bit);
_mm_empty(); /* good-bye mmx */
#endif
/* The magic pass: "Extended precision modular arithmetic"
x = ((x - y * DP1) - y * DP2) - y * DP3; */
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
xmm1 = _mm_mul_ps(y, xmm1);
xmm2 = _mm_mul_ps(y, xmm2);
xmm3 = _mm_mul_ps(y, xmm3);
x = _mm_add_ps(x, xmm1);
x = _mm_add_ps(x, xmm2);
x = _mm_add_ps(x, xmm3);
/* Evaluate the first polynom (0 <= x <= Pi/4) */
y = *(v4sf*)_ps_coscof_p0;
v4sf z = _mm_mul_ps(x,x);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
y = _mm_mul_ps(y, z);
y = _mm_mul_ps(y, z);
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
y = _mm_sub_ps(y, tmp);
y = _mm_add_ps(y, *(v4sf*)_ps_1);
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
v4sf y2 = *(v4sf*)_ps_sincof_p0;
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_mul_ps(y2, x);
y2 = _mm_add_ps(y2, x);
/* select the correct result from the two polynoms */
xmm3 = poly_mask;
y2 = _mm_and_ps(xmm3, y2); //, xmm3);
y = _mm_andnot_ps(xmm3, y);
y = _mm_add_ps(y,y2);
/* update the sign */
y = _mm_xor_ps(y, sign_bit);
return y;
}
/* almost the same as sin_ps */
inline v4sf cos_ps(v4sf x) { // any x
v4sf xmm1, xmm2 = _mm_setzero_ps(), xmm3, y;
#ifdef USE_SSE2
v4si emm0, emm2;
#else
v2si mm0, mm1, mm2, mm3;
#endif
/* take the absolute value */
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
/* scale by 4/Pi */
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
#ifdef USE_SSE2
/* store the integer part of y in mm0 */
emm2 = _mm_cvttps_epi32(y);
/* j=(j+1) & (~1) (see the cephes sources) */
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
y = _mm_cvtepi32_ps(emm2);
emm2 = _mm_sub_epi32(emm2, *(v4si*)_pi32_2);
/* get the swap sign flag */
emm0 = _mm_andnot_si128(emm2, *(v4si*)_pi32_4);
emm0 = _mm_slli_epi32(emm0, 29);
/* get the polynom selection mask */
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
v4sf sign_bit = _mm_castsi128_ps(emm0);
v4sf poly_mask = _mm_castsi128_ps(emm2);
#else
/* store the integer part of y in mm0:mm1 */
xmm2 = _mm_movehl_ps(xmm2, y);
mm2 = _mm_cvttps_pi32(y);
mm3 = _mm_cvttps_pi32(xmm2);
/* j=(j+1) & (~1) (see the cephes sources) */
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
y = _mm_cvtpi32x2_ps(mm2, mm3);
mm2 = _mm_sub_pi32(mm2, *(v2si*)_pi32_2);
mm3 = _mm_sub_pi32(mm3, *(v2si*)_pi32_2);
/* get the swap sign flag in mm0:mm1 and the
polynom selection mask in mm2:mm3 */
mm0 = _mm_andnot_si64(mm2, *(v2si*)_pi32_4);
mm1 = _mm_andnot_si64(mm3, *(v2si*)_pi32_4);
mm0 = _mm_slli_pi32(mm0, 29);
mm1 = _mm_slli_pi32(mm1, 29);
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
v4sf sign_bit, poly_mask;
COPY_MM_TO_XMM(mm0, mm1, sign_bit);
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
_mm_empty(); /* good-bye mmx */
#endif
/* The magic pass: "Extended precision modular arithmetic"
x = ((x - y * DP1) - y * DP2) - y * DP3; */
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
xmm1 = _mm_mul_ps(y, xmm1);
xmm2 = _mm_mul_ps(y, xmm2);
xmm3 = _mm_mul_ps(y, xmm3);
x = _mm_add_ps(x, xmm1);
x = _mm_add_ps(x, xmm2);
x = _mm_add_ps(x, xmm3);
/* Evaluate the first polynom (0 <= x <= Pi/4) */
y = *(v4sf*)_ps_coscof_p0;
v4sf z = _mm_mul_ps(x,x);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
y = _mm_mul_ps(y, z);
y = _mm_mul_ps(y, z);
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
y = _mm_sub_ps(y, tmp);
y = _mm_add_ps(y, *(v4sf*)_ps_1);
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
v4sf y2 = *(v4sf*)_ps_sincof_p0;
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_mul_ps(y2, x);
y2 = _mm_add_ps(y2, x);
/* select the correct result from the two polynoms */
xmm3 = poly_mask;
y2 = _mm_and_ps(xmm3, y2); //, xmm3);
y = _mm_andnot_ps(xmm3, y);
y = _mm_add_ps(y,y2);
/* update the sign */
y = _mm_xor_ps(y, sign_bit);
return y;
}
/* since sin_ps and cos_ps are almost identical, sincos_ps could replace both of them..
it is almost as fast, and gives you a free cosine with your sine */
inline void sincos_ps(v4sf x, v4sf *s, v4sf *c) {
v4sf xmm1, xmm2, xmm3 = _mm_setzero_ps(), sign_bit_sin, y;
#ifdef USE_SSE2
v4si emm0, emm2, emm4;
#else
v2si mm0, mm1, mm2, mm3, mm4, mm5;
#endif
sign_bit_sin = x;
/* take the absolute value */
x = _mm_and_ps(x, *(v4sf*)_ps_inv_sign_mask);
/* extract the sign bit (upper one) */
sign_bit_sin = _mm_and_ps(sign_bit_sin, *(v4sf*)_ps_sign_mask);
/* scale by 4/Pi */
y = _mm_mul_ps(x, *(v4sf*)_ps_cephes_FOPI);
#ifdef USE_SSE2
/* store the integer part of y in emm2 */
emm2 = _mm_cvttps_epi32(y);
/* j=(j+1) & (~1) (see the cephes sources) */
emm2 = _mm_add_epi32(emm2, *(v4si*)_pi32_1);
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_inv1);
y = _mm_cvtepi32_ps(emm2);
emm4 = emm2;
/* get the swap sign flag for the sine */
emm0 = _mm_and_si128(emm2, *(v4si*)_pi32_4);
emm0 = _mm_slli_epi32(emm0, 29);
v4sf swap_sign_bit_sin = _mm_castsi128_ps(emm0);
/* get the polynom selection mask for the sine*/
emm2 = _mm_and_si128(emm2, *(v4si*)_pi32_2);
emm2 = _mm_cmpeq_epi32(emm2, _mm_setzero_si128());
v4sf poly_mask = _mm_castsi128_ps(emm2);
#else
/* store the integer part of y in mm2:mm3 */
xmm3 = _mm_movehl_ps(xmm3, y);
mm2 = _mm_cvttps_pi32(y);
mm3 = _mm_cvttps_pi32(xmm3);
/* j=(j+1) & (~1) (see the cephes sources) */
mm2 = _mm_add_pi32(mm2, *(v2si*)_pi32_1);
mm3 = _mm_add_pi32(mm3, *(v2si*)_pi32_1);
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_inv1);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_inv1);
y = _mm_cvtpi32x2_ps(mm2, mm3);
mm4 = mm2;
mm5 = mm3;
/* get the swap sign flag for the sine */
mm0 = _mm_and_si64(mm2, *(v2si*)_pi32_4);
mm1 = _mm_and_si64(mm3, *(v2si*)_pi32_4);
mm0 = _mm_slli_pi32(mm0, 29);
mm1 = _mm_slli_pi32(mm1, 29);
v4sf swap_sign_bit_sin;
COPY_MM_TO_XMM(mm0, mm1, swap_sign_bit_sin);
/* get the polynom selection mask for the sine */
mm2 = _mm_and_si64(mm2, *(v2si*)_pi32_2);
mm3 = _mm_and_si64(mm3, *(v2si*)_pi32_2);
mm2 = _mm_cmpeq_pi32(mm2, _mm_setzero_si64());
mm3 = _mm_cmpeq_pi32(mm3, _mm_setzero_si64());
v4sf poly_mask;
COPY_MM_TO_XMM(mm2, mm3, poly_mask);
#endif
/* The magic pass: "Extended precision modular arithmetic"
x = ((x - y * DP1) - y * DP2) - y * DP3; */
xmm1 = *(v4sf*)_ps_minus_cephes_DP1;
xmm2 = *(v4sf*)_ps_minus_cephes_DP2;
xmm3 = *(v4sf*)_ps_minus_cephes_DP3;
xmm1 = _mm_mul_ps(y, xmm1);
xmm2 = _mm_mul_ps(y, xmm2);
xmm3 = _mm_mul_ps(y, xmm3);
x = _mm_add_ps(x, xmm1);
x = _mm_add_ps(x, xmm2);
x = _mm_add_ps(x, xmm3);
#ifdef USE_SSE2
emm4 = _mm_sub_epi32(emm4, *(v4si*)_pi32_2);
emm4 = _mm_andnot_si128(emm4, *(v4si*)_pi32_4);
emm4 = _mm_slli_epi32(emm4, 29);
v4sf sign_bit_cos = _mm_castsi128_ps(emm4);
#else
/* get the sign flag for the cosine */
mm4 = _mm_sub_pi32(mm4, *(v2si*)_pi32_2);
mm5 = _mm_sub_pi32(mm5, *(v2si*)_pi32_2);
mm4 = _mm_andnot_si64(mm4, *(v2si*)_pi32_4);
mm5 = _mm_andnot_si64(mm5, *(v2si*)_pi32_4);
mm4 = _mm_slli_pi32(mm4, 29);
mm5 = _mm_slli_pi32(mm5, 29);
v4sf sign_bit_cos;
COPY_MM_TO_XMM(mm4, mm5, sign_bit_cos);
_mm_empty(); /* good-bye mmx */
#endif
sign_bit_sin = _mm_xor_ps(sign_bit_sin, swap_sign_bit_sin);
/* Evaluate the first polynom (0 <= x <= Pi/4) */
v4sf z = _mm_mul_ps(x,x);
y = *(v4sf*)_ps_coscof_p0;
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p1);
y = _mm_mul_ps(y, z);
y = _mm_add_ps(y, *(v4sf*)_ps_coscof_p2);
y = _mm_mul_ps(y, z);
y = _mm_mul_ps(y, z);
v4sf tmp = _mm_mul_ps(z, *(v4sf*)_ps_0p5);
y = _mm_sub_ps(y, tmp);
y = _mm_add_ps(y, *(v4sf*)_ps_1);
/* Evaluate the second polynom (Pi/4 <= x <= 0) */
v4sf y2 = *(v4sf*)_ps_sincof_p0;
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p1);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_add_ps(y2, *(v4sf*)_ps_sincof_p2);
y2 = _mm_mul_ps(y2, z);
y2 = _mm_mul_ps(y2, x);
y2 = _mm_add_ps(y2, x);
/* select the correct result from the two polynoms */
xmm3 = poly_mask;
v4sf ysin2 = _mm_and_ps(xmm3, y2);
v4sf ysin1 = _mm_andnot_ps(xmm3, y);
y2 = _mm_sub_ps(y2,ysin2);
y = _mm_sub_ps(y, ysin1);
xmm1 = _mm_add_ps(ysin1,ysin2);
xmm2 = _mm_add_ps(y,y2);
/* update the sign */
*s = _mm_xor_ps(xmm1, sign_bit_sin);
*c = _mm_xor_ps(xmm2, sign_bit_cos);
}
-137
View File
@@ -1,137 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../sys/platform.h"
namespace embree
{
/* Varying numeric types */
template<int N>
struct vfloat
{
union { float f[N]; int i[N]; };
__forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; }
__forceinline float& operator [](size_t index) { assert(index < N); return f[index]; }
};
template<int N>
struct vdouble
{
union { double f[N]; long long i[N]; };
__forceinline const double& operator [](size_t index) const { assert(index < N); return f[index]; }
__forceinline double& operator [](size_t index) { assert(index < N); return f[index]; }
};
template<int N>
struct vint
{
int i[N];
__forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; }
__forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
};
template<int N>
struct vuint
{
unsigned int i[N];
__forceinline const unsigned int& operator [](size_t index) const { assert(index < N); return i[index]; }
__forceinline unsigned int& operator [](size_t index) { assert(index < N); return i[index]; }
};
template<int N>
struct vllong
{
long long i[N];
__forceinline const long long& operator [](size_t index) const { assert(index < N); return i[index]; }
__forceinline long long& operator [](size_t index) { assert(index < N); return i[index]; }
};
/* Varying bool types */
template<int N> struct vboolf { int i[N]; }; // for float/int
template<int N> struct vboold { long long i[N]; }; // for double/long long
/* Aliases to default types */
template<int N> using vreal = vfloat<N>;
template<int N> using vbool = vboolf<N>;
/* Maximum supported varying size */
#if defined(__AVX512F__)
const int VSIZEX = 16;
#elif defined(__AVX__)
const int VSIZEX = 8;
#else
const int VSIZEX = 4;
#endif
/* Extends varying size N to optimal or up to max(N, N2) */
template<int N, int N2 = VSIZEX>
struct vextend
{
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
/* use 16-wide SIMD calculations on KNL even for 4 and 8 wide SIMD */
static const int size = (N2 == VSIZEX) ? VSIZEX : N;
#define SIMD_MODE(N) N, 16
#else
/* calculate with same SIMD width otherwise */
static const int size = N;
#define SIMD_MODE(N) N, N
#endif
};
/* 4-wide shortcuts */
typedef vfloat<4> vfloat4;
typedef vdouble<4> vdouble4;
typedef vreal<4> vreal4;
typedef vint<4> vint4;
typedef vuint<4> vuint4;
typedef vllong<4> vllong4;
typedef vbool<4> vbool4;
typedef vboolf<4> vboolf4;
typedef vboold<4> vboold4;
/* 8-wide shortcuts */
typedef vfloat<8> vfloat8;
typedef vdouble<8> vdouble8;
typedef vreal<8> vreal8;
typedef vint<8> vint8;
typedef vllong<8> vllong8;
typedef vbool<8> vbool8;
typedef vboolf<8> vboolf8;
typedef vboold<8> vboold8;
/* 16-wide shortcuts */
typedef vfloat<16> vfloat16;
typedef vdouble<16> vdouble16;
typedef vreal<16> vreal16;
typedef vint<16> vint16;
typedef vuint<16> vuint16;
typedef vllong<16> vllong16;
typedef vbool<16> vbool16;
typedef vboolf<16> vboolf16;
typedef vboold<16> vboold16;
/* Maximum shortcuts */
typedef vfloat<VSIZEX> vfloatx;
typedef vdouble<VSIZEX> vdoublex;
typedef vreal<VSIZEX> vrealx;
typedef vint<VSIZEX> vintx;
typedef vllong<VSIZEX> vllongx;
typedef vbool<VSIZEX> vboolx;
typedef vboolf<VSIZEX> vboolfx;
typedef vboold<VSIZEX> vbooldx;
}
-164
View File
@@ -1,164 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 4-wide AVX bool type for 64bit data types*/
template<>
struct vboold<4>
{
typedef vboold4 Bool;
enum { size = 4 }; // number of SIMD elements
union { // data
__m256d v;
struct { __m128d vl,vh; };
long long i[4];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold() {}
__forceinline vboold(const vboold4& a) { v = a.v; }
__forceinline vboold4& operator =(const vboold4& a) { v = a.v; return *this; }
__forceinline vboold(__m256d a) : v(a) {}
__forceinline vboold(__m256i a) : v(_mm256_castsi256_pd(a)) {}
__forceinline operator const __m256() const { return _mm256_castpd_ps(v); }
__forceinline operator const __m256i() const { return _mm256_castpd_si256(v); }
__forceinline operator const __m256d() const { return v; }
__forceinline vboold(int a)
{
assert(a >= 0 && a <= 255);
#if defined (__AVX2__)
const __m256i mask = _mm256_set_epi64x(0x8, 0x4, 0x2, 0x1);
const __m256i b = _mm256_set1_epi64x(a);
const __m256i c = _mm256_and_si256(b,mask);
v = _mm256_castsi256_pd(_mm256_cmpeq_epi64(c,mask));
#else
vl = _mm_lookupmask_pd[a & 0x3];
vh = _mm_lookupmask_pd[a >> 2];
#endif
}
__forceinline vboold(__m128d a, __m128d b) : vl(a), vh(b) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {}
__forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm256_movemask_pd(v) >> index) & 1; }
__forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator !(const vboold4& a) { return _mm256_xor_pd(a, vboold4(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm256_and_pd(a, b); }
__forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm256_or_pd (a, b); }
__forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
__forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
__forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
__forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
__forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(_mm256_xor_pd(a,b),vboold4(embree::True)); }
__forceinline vboold4 select(const vboold4& mask, const vboold4& t, const vboold4& f) {
return _mm256_blendv_pd(f, t, mask);
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); }
__forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); }
#if defined(__AVX2__)
template<int i0, int i1, int i2, int i3>
__forceinline vboold4 shuffle(const vboold4& v) {
return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<int i>
__forceinline vboold4 shuffle(const vboold4& v) {
return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i, i, i, i));
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and(const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
__forceinline bool reduce_or (const vboold4& a) { return !_mm256_testz_pd(a,a); }
__forceinline bool all (const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
__forceinline bool any (const vboold4& a) { return !_mm256_testz_pd(a,a); }
__forceinline bool none(const vboold4& a) { return _mm256_testz_pd(a,a) != 0; }
__forceinline bool all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
__forceinline bool any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
__forceinline bool none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
__forceinline unsigned int movemask(const vboold4& a) { return _mm256_movemask_pd(a); }
__forceinline size_t popcnt (const vboold4& a) { return __popcnt((size_t)_mm256_movemask_pd(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboold4& a, size_t index) { return a[index]; }
__forceinline void set (vboold4& a, size_t index) { a[index] = -1; }
__forceinline void clear(vboold4& a, size_t index) { a[index] = 0; }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboold4& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
-145
View File
@@ -1,145 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 4-wide AVX-512 bool type */
template<>
struct vboold<4>
{
typedef vboold4 Bool;
typedef vint4 Int;
enum { size = 4 }; // number of SIMD elements
__mmask8 v; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold() {}
__forceinline vboold(const vboold4& t) { v = t.v; }
__forceinline vboold4& operator =(const vboold4& f) { v = f.v; return *this; }
__forceinline vboold(const __mmask8 &t) { v = t; }
__forceinline operator __mmask8() const { return v; }
__forceinline vboold(bool b) { v = b ? 0xf : 0x0; }
__forceinline vboold(int t) { v = (__mmask8)t; }
__forceinline vboold(unsigned int t) { v = (__mmask8)t; }
/* return int8 mask */
__forceinline __m128i mask8() const {
return _mm_movm_epi8(v);
}
/* return int32 mask */
__forceinline __m128i mask32() const {
return _mm_movm_epi32(v);
}
/* return int64 mask */
__forceinline __m256i mask64() const {
return _mm256_movm_epi64(v);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold(FalseTy) : v(0x0) {}
__forceinline vboold(TrueTy) : v(0xf) {}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator !(const vboold4& a) { return _mm512_kandn(a, 0xf); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm512_kand(a, b); }
__forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm512_kor(a, b); }
__forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
__forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm512_kandn(b, a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
__forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
__forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
__forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
__forceinline vboold4 select(const vboold4& s, const vboold4& a, const vboold4& b) {
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all (const vboold4& a) { return a.v == 0xf; }
__forceinline int any (const vboold4& a) { return _mm512_kortestz(a, a) == 0; }
__forceinline int none(const vboold4& a) { return _mm512_kortestz(a, a) != 0; }
__forceinline int all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
__forceinline int any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
__forceinline int none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
__forceinline size_t movemask(const vboold4& a) { return _mm512_kmov(a); }
__forceinline size_t popcnt (const vboold4& a) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Conversion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt(const vboold4& a) { return mm512_mask2int(a); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboold4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
__forceinline void set(vboold4& a, size_t index) { assert(index < 4); a |= 1 << index; }
__forceinline void clear(vboold4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboold4& a)
{
cout << "<";
for (size_t i=0; i<4; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
-153
View File
@@ -1,153 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 8-wide AVX-512 bool type */
template<>
struct vboold<8>
{
typedef vboold8 Bool;
typedef vint8 Int;
enum { size = 8 }; // number of SIMD elements
__mmask8 v; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold() {}
__forceinline vboold(const vboold8& t) { v = t.v; }
__forceinline vboold8& operator =(const vboold8& f) { v = f.v; return *this; }
__forceinline vboold(const __mmask8& t) { v = t; }
__forceinline operator __mmask8() const { return v; }
__forceinline vboold(bool b) { v = b ? 0xff : 0x00; }
__forceinline vboold(int t) { v = (__mmask8)t; }
__forceinline vboold(unsigned int t) { v = (__mmask8)t; }
/* return int8 mask */
__forceinline __m128i mask8() const {
#if defined(__AVX512BW__)
return _mm_movm_epi8(v);
#else
const __m512i f = _mm512_set1_epi64(0);
const __m512i t = _mm512_set1_epi64(-1);
const __m512i m = _mm512_mask_or_epi64(f,v,t,t);
return _mm512_cvtepi64_epi8(m);
#endif
}
/* return int64 mask */
__forceinline __m512i mask64() const {
#if defined(__AVX512DQ__)
return _mm512_movm_epi64(v);
#else
const __m512i f = _mm512_set1_epi64(0);
const __m512i t = _mm512_set1_epi64(-1);
return _mm512_mask_or_epi64(f,v,t,t);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold(FalseTy) : v(0x00) {}
__forceinline vboold(TrueTy) : v(0xff) {}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold8 operator !(const vboold8& a) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold8 operator &(const vboold8& a, const vboold8& b) { return _mm512_kand(a, b); }
__forceinline vboold8 operator |(const vboold8& a, const vboold8& b) { return _mm512_kor(a, b); }
__forceinline vboold8 operator ^(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
__forceinline vboold8 andn(const vboold8& a, const vboold8& b) { return _mm512_kandn(b, a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold8& operator &=(vboold8& a, const vboold8& b) { return a = a & b; }
__forceinline vboold8& operator |=(vboold8& a, const vboold8& b) { return a = a | b; }
__forceinline vboold8& operator ^=(vboold8& a, const vboold8& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboold8 operator !=(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
__forceinline vboold8 operator ==(const vboold8& a, const vboold8& b) { return _mm512_kxnor(a, b); }
__forceinline vboold8 select(const vboold8& s, const vboold8& a, const vboold8& b) {
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all (const vboold8& a) { return a.v == 0xff; }
__forceinline int any (const vboold8& a) { return _mm512_kortestz(a, a) == 0; }
__forceinline int none(const vboold8& a) { return _mm512_kortestz(a, a) != 0; }
__forceinline int all (const vboold8& valid, const vboold8& b) { return all((!valid) | b); }
__forceinline int any (const vboold8& valid, const vboold8& b) { return any(valid & b); }
__forceinline int none(const vboold8& valid, const vboold8& b) { return none(valid & b); }
__forceinline size_t movemask(const vboold8& a) { return _mm512_kmov(a); }
__forceinline size_t popcnt (const vboold8& a) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Conversion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt(const vboold8& a) { return mm512_mask2int(a); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboold8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
__forceinline void set(vboold8& a, size_t index) { assert(index < 8); a |= 1 << index; }
__forceinline void clear(vboold8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboold8& a)
{
cout << "<";
for (size_t i=0; i<8; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
-163
View File
@@ -1,163 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 16-wide AVX-512 bool type */
template<>
struct vboolf<16>
{
typedef vboolf16 Bool;
typedef vint16 Int;
typedef vfloat16 Float;
enum { size = 16 }; // number of SIMD elements
__mmask16 v; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf() {}
__forceinline vboolf(const vboolf16& t) { v = t.v; }
__forceinline vboolf16& operator =(const vboolf16& f) { v = f.v; return *this; }
__forceinline vboolf(const __mmask16& t) { v = t; }
__forceinline operator __mmask16() const { return v; }
__forceinline vboolf(bool b) { v = b ? 0xFFFF : 0x0000; }
__forceinline vboolf(int t) { v = (__mmask16)t; }
__forceinline vboolf(unsigned int t) { v = (__mmask16)t; }
/* return int8 mask */
__forceinline __m128i mask8() const {
#if defined(__AVX512BW__)
return _mm_movm_epi8(v);
#else
const __m512i f = _mm512_set1_epi32(0);
const __m512i t = _mm512_set1_epi32(-1);
const __m512i m = _mm512_mask_or_epi32(f,v,t,t);
return _mm512_cvtepi32_epi8(m);
#endif
}
/* return int32 mask */
__forceinline __m512i mask32() const {
#if defined(__AVX512DQ__)
return _mm512_movm_epi32(v);
#else
const __m512i f = _mm512_set1_epi32(0);
const __m512i t = _mm512_set1_epi32(-1);
return _mm512_mask_or_epi32(f,v,t,t);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(0x0000) {}
__forceinline vboolf(TrueTy) : v(0xffff) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator [](size_t index) const {
assert(index < 16); return (mm512_mask2int(v) >> index) & 1;
}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf16 operator !(const vboolf16& a) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf16 operator &(const vboolf16& a, const vboolf16& b) { return _mm512_kand(a,b); }
__forceinline vboolf16 operator |(const vboolf16& a, const vboolf16& b) { return _mm512_kor(a,b); }
__forceinline vboolf16 operator ^(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a,b); }
__forceinline vboolf16 andn(const vboolf16& a, const vboolf16& b) { return _mm512_kandn(b,a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf16& operator &=(vboolf16& a, const vboolf16& b) { return a = a & b; }
__forceinline vboolf16& operator |=(vboolf16& a, const vboolf16& b) { return a = a | b; }
__forceinline vboolf16& operator ^=(vboolf16& a, const vboolf16& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf16 operator !=(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a, b); }
__forceinline vboolf16 operator ==(const vboolf16& a, const vboolf16& b) { return _mm512_kxnor(a, b); }
__forceinline vboolf16 select(const vboolf16& s, const vboolf16& a, const vboolf16& b) {
return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all (const vboolf16& a) { return _mm512_kortestc(a,a) != 0; }
__forceinline int any (const vboolf16& a) { return _mm512_kortestz(a,a) == 0; }
__forceinline int none(const vboolf16& a) { return _mm512_kortestz(a,a) != 0; }
__forceinline int all (const vboolf16& valid, const vboolf16& b) { return all((!valid) | b); }
__forceinline int any (const vboolf16& valid, const vboolf16& b) { return any(valid & b); }
__forceinline int none(const vboolf16& valid, const vboolf16& b) { return none(valid & b); }
__forceinline size_t movemask(const vboolf16& a) { return _mm512_kmov(a); }
__forceinline size_t popcnt (const vboolf16& a) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Convertion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); }
__forceinline vboolf16 toMask(const int& a) { return mm512_int2mask(a); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboolf16& a, size_t index) { assert(index < 16); return (toInt(a) >> index) & 1; }
__forceinline void set(vboolf16& a, size_t index) { assert(index < 16); a |= 1 << index; }
__forceinline void clear(vboolf16& a, size_t index) { assert(index < 16); a = andn(a, 1 << index); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboolf16& a)
{
cout << "<";
for (size_t i=0; i<16; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
-145
View File
@@ -1,145 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 4-wide AVX-512 bool type */
template<>
struct vboolf<4>
{
typedef vboolf4 Bool;
typedef vint4 Int;
enum { size = 4 }; // number of SIMD elements
__mmask8 v; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf() {}
__forceinline vboolf(const vboolf4& t) { v = t.v; }
__forceinline vboolf4& operator =(const vboolf4& f) { v = f.v; return *this; }
__forceinline vboolf(const __mmask8 &t) { v = t; }
__forceinline operator __mmask8() const { return v; }
__forceinline vboolf(bool b) { v = b ? 0xf : 0x0; }
__forceinline vboolf(int t) { v = (__mmask8)t; }
__forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
/* return int8 mask */
__forceinline __m128i mask8() const {
return _mm_movm_epi8(v);
}
/* return int32 mask */
__forceinline __m128i mask32() const {
return _mm_movm_epi32(v);
}
/* return int64 mask */
__forceinline __m256i mask64() const {
return _mm256_movm_epi64(v);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(0x0) {}
__forceinline vboolf(TrueTy) : v(0xf) {}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator !(const vboolf4& a) { return _mm512_kandn(a, 0xf); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm512_kand(a, b); }
__forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm512_kor(a, b); }
__forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
__forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm512_kandn(b, a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
__forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
__forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
__forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
__forceinline vboolf4 select(const vboolf4& s, const vboolf4& a, const vboolf4& b) {
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all (const vboolf4& a) { return a.v == 0xf; }
__forceinline int any (const vboolf4& a) { return _mm512_kortestz(a, a) == 0; }
__forceinline int none(const vboolf4& a) { return _mm512_kortestz(a, a) != 0; }
__forceinline int all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
__forceinline int any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
__forceinline int none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
__forceinline size_t movemask(const vboolf4& a) { return _mm512_kmov(a); }
__forceinline size_t popcnt (const vboolf4& a) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Conversion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt(const vboolf4& a) { return mm512_mask2int(a); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboolf4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
__forceinline void set(vboolf4& a, size_t index) { assert(index < 4); a |= 1 << index; }
__forceinline void clear(vboolf4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboolf4& a)
{
cout << "<";
for (size_t i=0; i<4; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
-182
View File
@@ -1,182 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 4-wide SSE bool type */
template<>
struct vboolf<4>
{
typedef vboolf4 Bool;
typedef vint4 Int;
typedef vfloat4 Float;
enum { size = 4 }; // number of SIMD elements
union { __m128 v; int i[4]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf() {}
__forceinline vboolf(const vboolf4& other) { v = other.v; }
__forceinline vboolf4& operator =(const vboolf4& other) { v = other.v; return *this; }
__forceinline vboolf(__m128 input) : v(input) {}
__forceinline operator const __m128&() const { return v; }
__forceinline operator const __m128i() const { return _mm_castps_si128(v); }
__forceinline operator const __m128d() const { return _mm_castps_pd(v); }
__forceinline vboolf(bool a)
: v(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
__forceinline vboolf(bool a, bool b)
: v(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline vboolf(bool a, bool b, bool c, bool d)
: v(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline vboolf(int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
__forceinline vboolf(unsigned int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
/* return int32 mask */
__forceinline __m128i mask32() const {
return _mm_castps_si128(v);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(_mm_setzero_ps()) {}
__forceinline vboolf(TrueTy) : v(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm_movemask_ps(v) >> index) & 1; }
__forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator !(const vboolf4& a) { return _mm_xor_ps(a, vboolf4(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm_and_ps(a, b); }
__forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm_or_ps (a, b); }
__forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
__forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
__forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
__forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
__forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) {
#if defined(__SSE4_1__)
return _mm_blendv_ps(f, t, m);
#else
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); }
__forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); }
template<int i0, int i1, int i2, int i3>
__forceinline vboolf4 shuffle(const vboolf4& v) {
return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<int i0, int i1, int i2, int i3>
__forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<int i0>
__forceinline vboolf4 shuffle(const vboolf4& v) {
return shuffle<i0,i0,i0,i0>(v);
}
#if defined(__SSE3__)
template<> __forceinline vboolf4 shuffle<0, 0, 2, 2>(const vboolf4& v) { return _mm_moveldup_ps(v); }
template<> __forceinline vboolf4 shuffle<1, 1, 3, 3>(const vboolf4& v) { return _mm_movehdup_ps(v); }
template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); }
#endif
#if defined(__SSE4_1__)
template<int dst, int src, int clr> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<int dst, int src> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert<dst, src, 0>(a, b); }
template<int dst> __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert<dst, 0>(a, vboolf4(b)); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and(const vboolf4& a) { return _mm_movemask_ps(a) == 0xf; }
__forceinline bool reduce_or (const vboolf4& a) { return _mm_movemask_ps(a) != 0x0; }
__forceinline bool all (const vboolf4& b) { return _mm_movemask_ps(b) == 0xf; }
__forceinline bool any (const vboolf4& b) { return _mm_movemask_ps(b) != 0x0; }
__forceinline bool none(const vboolf4& b) { return _mm_movemask_ps(b) == 0x0; }
__forceinline bool all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
__forceinline bool any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
__forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
__forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); }
#if defined(__SSE4_2__)
__forceinline size_t popcnt(const vboolf4& a) { return __popcnt((size_t)_mm_movemask_ps(a)); }
#else
__forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboolf4& a, size_t index) { return a[index]; }
__forceinline void set(vboolf4& a, size_t index) { a[index] = -1; }
__forceinline void clear(vboolf4& a, size_t index) { a[index] = 0; }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboolf4& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
-195
View File
@@ -1,195 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 8-wide AVX bool type */
template<>
struct vboolf<8>
{
typedef vboolf8 Bool;
typedef vint8 Int;
typedef vfloat8 Float;
enum { size = 8 }; // number of SIMD elements
union { // data
__m256 v;
struct { __m128 vl,vh; };
int i[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf() {}
__forceinline vboolf(const vboolf8& a) { v = a.v; }
__forceinline vboolf8& operator =(const vboolf8& a) { v = a.v; return *this; }
__forceinline vboolf(__m256 a) : v(a) {}
__forceinline operator const __m256&() const { return v; }
__forceinline operator const __m256i() const { return _mm256_castps_si256(v); }
__forceinline operator const __m256d() const { return _mm256_castps_pd(v); }
__forceinline vboolf(int a)
{
assert(a >= 0 && a <= 255);
#if defined (__AVX2__)
const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
const __m256i b = _mm256_set1_epi32(a);
const __m256i c = _mm256_and_si256(b,mask);
v = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
#else
vl = _mm_lookupmask_ps[a & 0xF];
vh = _mm_lookupmask_ps[a >> 4];
#endif
}
__forceinline vboolf(const vboolf4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
__forceinline vboolf(const vboolf4& a, const vboolf4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
__forceinline vboolf(__m128 a, __m128 b) : vl(a), vh(b) {}
__forceinline vboolf(bool a) : v(vboolf8(vboolf4(a), vboolf4(a))) {}
__forceinline vboolf(bool a, bool b) : v(vboolf8(vboolf4(a), vboolf4(b))) {}
__forceinline vboolf(bool a, bool b, bool c, bool d) : v(vboolf8(vboolf4(a,b), vboolf4(c,d))) {}
__forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h) : v(vboolf8(vboolf4(a,b,c,d), vboolf4(e,f,g,h))) {}
/* return int32 mask */
__forceinline __m256i mask32() const {
return _mm256_castps_si256(v);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {}
__forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator [](size_t index) const { assert(index < 8); return (_mm256_movemask_ps(v) >> index) & 1; }
__forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator !(const vboolf8& a) { return _mm256_xor_ps(a, vboolf8(embree::True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm256_and_ps(a, b); }
__forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm256_or_ps (a, b); }
__forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
__forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
__forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
__forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
__forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(_mm256_xor_ps(a,b),vboolf8(embree::True)); }
__forceinline vboolf8 select(const vboolf8& mask, const vboolf8& t, const vboolf8& f) {
return _mm256_blendv_ps(f, t, mask);
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 unpacklo(const vboolf8& a, const vboolf8& b) { return _mm256_unpacklo_ps(a, b); }
__forceinline vboolf8 unpackhi(const vboolf8& a, const vboolf8& b) { return _mm256_unpackhi_ps(a, b); }
template<int i>
__forceinline vboolf8 shuffle(const vboolf8& v) {
return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
}
template<int i0, int i1>
__forceinline vboolf8 shuffle4(const vboolf8& v) {
return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
}
template<int i0, int i1>
__forceinline vboolf8 shuffle4(const vboolf8& a, const vboolf8& b) {
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
}
template<int i0, int i1, int i2, int i3>
__forceinline vboolf8 shuffle(const vboolf8& v) {
return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<int i0, int i1, int i2, int i3>
__forceinline vboolf8 shuffle(const vboolf8& a, const vboolf8& b) {
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<> __forceinline vboolf8 shuffle<0, 0, 2, 2>(const vboolf8& v) { return _mm256_moveldup_ps(v); }
template<> __forceinline vboolf8 shuffle<1, 1, 3, 3>(const vboolf8& v) { return _mm256_movehdup_ps(v); }
template<> __forceinline vboolf8 shuffle<0, 1, 0, 1>(const vboolf8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
template<int i> __forceinline vboolf8 insert4(const vboolf8& a, const vboolf4& b) { return _mm256_insertf128_ps(a, b, i); }
template<int i> __forceinline vboolf4 extract4 (const vboolf8& a) { return _mm256_extractf128_ps(a, i); }
template<> __forceinline vboolf4 extract4<0>(const vboolf8& a) { return _mm256_castps256_ps128(a); }
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and(const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool reduce_or (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
__forceinline bool all (const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool any (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
__forceinline bool none(const vboolf8& a) { return _mm256_testz_ps(a,a) != 0; }
__forceinline bool all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
__forceinline bool any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
__forceinline bool none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
__forceinline unsigned int movemask(const vboolf8& a) { return _mm256_movemask_ps(a); }
__forceinline size_t popcnt (const vboolf8& a) { return __popcnt((size_t)_mm256_movemask_ps(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboolf8& a, size_t index) { return a[index]; }
__forceinline void set(vboolf8& a, size_t index) { a[index] = -1; }
__forceinline void clear(vboolf8& a, size_t index) { a[index] = 0; }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboolf8& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
-145
View File
@@ -1,145 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 8-wide AVX-512 bool type */
template<>
struct vboolf<8>
{
typedef vboolf8 Bool;
typedef vint8 Int;
enum { size = 8 }; // number of SIMD elements
__mmask8 v; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf() {}
__forceinline vboolf(const vboolf8& t) { v = t.v; }
__forceinline vboolf8& operator =(const vboolf8& f) { v = f.v; return *this; }
__forceinline vboolf(const __mmask8 &t) { v = t; }
__forceinline operator __mmask8() const { return v; }
__forceinline vboolf(bool b) { v = b ? 0xff : 0x00; }
__forceinline vboolf(int t) { v = (__mmask8)t; }
__forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
/* return int8 mask */
__forceinline __m128i mask8() const {
return _mm_movm_epi8(v);
}
/* return int32 mask */
__forceinline __m256i mask32() const {
return _mm256_movm_epi32(v);
}
/* return int64 mask */
__forceinline __m512i mask64() const {
return _mm512_movm_epi64(v);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf(FalseTy) : v(0x00) {}
__forceinline vboolf(TrueTy) : v(0xff) {}
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator !(const vboolf8& a) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm512_kand(a, b); }
__forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm512_kor(a, b); }
__forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
__forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm512_kandn(b, a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
__forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
__forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
__forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm512_kxnor(a, b); }
__forceinline vboolf8 select(const vboolf8& s, const vboolf8& a, const vboolf8& b) {
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all (const vboolf8& a) { return a.v == 0xff; }
__forceinline int any (const vboolf8& a) { return _mm512_kortestz(a, a) == 0; }
__forceinline int none(const vboolf8& a) { return _mm512_kortestz(a, a) != 0; }
__forceinline int all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
__forceinline int any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
__forceinline int none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
__forceinline size_t movemask(const vboolf8& a) { return _mm512_kmov(a); }
__forceinline size_t popcnt (const vboolf8& a) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Conversion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt(const vboolf8& a) { return mm512_mask2int(a); }
////////////////////////////////////////////////////////////////////////////////
/// Get/Set Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline bool get(const vboolf8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
__forceinline void set(vboolf8& a, size_t index) { assert(index < 8); a |= 1 << index; }
__forceinline void clear(vboolf8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator <<(std::ostream& cout, const vboolf8& a)
{
cout << "<";
for (size_t i=0; i<8; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
-306
View File
@@ -1,306 +0,0 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
// You may obtain a copy of the License at //
// //
// http://www.apache.org/licenses/LICENSE-2.0 //
// //
// Unless required by applicable law or agreed to in writing, software //
// distributed under the License is distributed on an "AS IS" BASIS, //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and //
// limitations under the License. //
// ======================================================================== //
#pragma once
namespace embree
{
/* 4-wide AVX 64-bit double type */
template<>
struct vdouble<4>
{
typedef vboold4 Bool;
enum { size = 4 }; // number of SIMD elements
union { // data
__m256d v;
double i[4];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble() {}
__forceinline vdouble(const vdouble4& t) { v = t.v; }
__forceinline vdouble4& operator =(const vdouble4& f) { v = f.v; return *this; }
__forceinline vdouble(const __m256d& t) { v = t; }
__forceinline operator __m256d() const { return v; }
__forceinline vdouble(double i) {
v = _mm256_set1_pd(i);
}
__forceinline vdouble(double a, double b, double c, double d) {
v = _mm256_set_pd(d,c,b,a);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble(ZeroTy) : v(_mm256_setzero_pd()) {}
__forceinline vdouble(OneTy) : v(_mm256_set1_pd(1)) {}
__forceinline vdouble(StepTy) : v(_mm256_set_pd(3.0,2.0,1.0,0.0)) {}
__forceinline vdouble(ReverseStepTy) : v(_mm256_setr_pd(3.0,2.0,1.0,0.0)) {}
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
static __forceinline void store_nt(double *__restrict__ ptr, const vdouble4& a) {
_mm256_stream_pd(ptr, a);
}
static __forceinline vdouble4 loadu(const double* addr) {
return _mm256_loadu_pd(addr);
}
static __forceinline vdouble4 load(const vdouble4* addr) {
return _mm256_load_pd((double*)addr);
}
static __forceinline vdouble4 load(const double* addr) {
return _mm256_load_pd(addr);
}
static __forceinline void store(double* ptr, const vdouble4& v) {
_mm256_store_pd(ptr, v);
}
static __forceinline void storeu(double* ptr, const vdouble4& v) {
_mm256_storeu_pd(ptr, v);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline double& operator [](size_t index) { assert(index < 4); return i[index]; }
__forceinline const double& operator [](size_t index) const { assert(index < 4); return i[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble4 operator +(const vdouble4& a) { return a; }
__forceinline vdouble4 operator -(const vdouble4& a) { return _mm256_sub_pd(_mm256_setzero_pd(), a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble4 operator +(const vdouble4& a, const vdouble4& b) { return _mm256_add_pd(a, b); }
__forceinline vdouble4 operator +(const vdouble4& a, double b) { return a + vdouble4(b); }
__forceinline vdouble4 operator +(double a, const vdouble4& b) { return vdouble4(a) + b; }
__forceinline vdouble4 operator -(const vdouble4& a, const vdouble4& b) { return _mm256_sub_pd(a, b); }
__forceinline vdouble4 operator -(const vdouble4& a, double b) { return a - vdouble4(b); }
__forceinline vdouble4 operator -(double a, const vdouble4& b) { return vdouble4(a) - b; }
__forceinline vdouble4 operator *(const vdouble4& a, const vdouble4& b) { return _mm256_mul_pd(a, b); }
__forceinline vdouble4 operator *(const vdouble4& a, double b) { return a * vdouble4(b); }
__forceinline vdouble4 operator *(double a, const vdouble4& b) { return vdouble4(a) * b; }
__forceinline vdouble4 operator &(const vdouble4& a, const vdouble4& b) { return _mm256_and_pd(a, b); }
__forceinline vdouble4 operator &(const vdouble4& a, double b) { return a & vdouble4(b); }
__forceinline vdouble4 operator &(double a, const vdouble4& b) { return vdouble4(a) & b; }
__forceinline vdouble4 operator |(const vdouble4& a, const vdouble4& b) { return _mm256_or_pd(a, b); }
__forceinline vdouble4 operator |(const vdouble4& a, double b) { return a | vdouble4(b); }
__forceinline vdouble4 operator |(double a, const vdouble4& b) { return vdouble4(a) | b; }
__forceinline vdouble4 operator ^(const vdouble4& a, const vdouble4& b) { return _mm256_xor_pd(a, b); }
__forceinline vdouble4 operator ^(const vdouble4& a, double b) { return a ^ vdouble4(b); }
__forceinline vdouble4 operator ^(double a, const vdouble4& b) { return vdouble4(a) ^ b; }
__forceinline vdouble4 min(const vdouble4& a, const vdouble4& b) { return _mm256_min_pd(a, b); }
__forceinline vdouble4 min(const vdouble4& a, double b) { return min(a,vdouble4(b)); }
__forceinline vdouble4 min(double a, const vdouble4& b) { return min(vdouble4(a),b); }
__forceinline vdouble4 max(const vdouble4& a, const vdouble4& b) { return _mm256_max_pd(a, b); }
__forceinline vdouble4 max(const vdouble4& a, double b) { return max(a,vdouble4(b)); }
__forceinline vdouble4 max(double a, const vdouble4& b) { return max(vdouble4(a),b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble4& operator +=(vdouble4& a, const vdouble4& b) { return a = a + b; }
__forceinline vdouble4& operator +=(vdouble4& a, double b) { return a = a + b; }
__forceinline vdouble4& operator -=(vdouble4& a, const vdouble4& b) { return a = a - b; }
__forceinline vdouble4& operator -=(vdouble4& a, double b) { return a = a - b; }
__forceinline vdouble4& operator *=(vdouble4& a, const vdouble4& b) { return a = a * b; }
__forceinline vdouble4& operator *=(vdouble4& a, double b) { return a = a * b; }
__forceinline vdouble4& operator &=(vdouble4& a, const vdouble4& b) { return a = a & b; }
__forceinline vdouble4& operator &=(vdouble4& a, double b) { return a = a & b; }
__forceinline vdouble4& operator |=(vdouble4& a, const vdouble4& b) { return a = a | b; }
__forceinline vdouble4& operator |=(vdouble4& a, double b) { return a = a | b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX512VL__)
__forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
__forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
__forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
#else
__forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_EQ_UQ); }
__forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_NEQ_UQ); }
__forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_LT_OQ); }
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_GE_OQ); }
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_GT_OQ); }
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_LE_OQ); }
#endif
__forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); }
__forceinline vboold4 operator ==(double a, const vdouble4& b) { return vdouble4(a) == b; }
__forceinline vboold4 operator !=(const vdouble4& a, double b) { return a != vdouble4(b); }
__forceinline vboold4 operator !=(double a, const vdouble4& b) { return vdouble4(a) != b; }
__forceinline vboold4 operator < (const vdouble4& a, double b) { return a < vdouble4(b); }
__forceinline vboold4 operator < (double a, const vdouble4& b) { return vdouble4(a) < b; }
__forceinline vboold4 operator >=(const vdouble4& a, double b) { return a >= vdouble4(b); }
__forceinline vboold4 operator >=(double a, const vdouble4& b) { return vdouble4(a) >= b; }
__forceinline vboold4 operator > (const vdouble4& a, double b) { return a > vdouble4(b); }
__forceinline vboold4 operator > (double a, const vdouble4& b) { return vdouble4(a) > b; }
__forceinline vboold4 operator <=(const vdouble4& a, double b) { return a <= vdouble4(b); }
__forceinline vboold4 operator <=(double a, const vdouble4& b) { return vdouble4(a) <= b; }
__forceinline vboold4 eq(const vdouble4& a, const vdouble4& b) { return a == b; }
__forceinline vboold4 ne(const vdouble4& a, const vdouble4& b) { return a != b; }
__forceinline vboold4 lt(const vdouble4& a, const vdouble4& b) { return a < b; }
__forceinline vboold4 ge(const vdouble4& a, const vdouble4& b) { return a >= b; }
__forceinline vboold4 gt(const vdouble4& a, const vdouble4& b) { return a > b; }
__forceinline vboold4 le(const vdouble4& a, const vdouble4& b) { return a <= b; }
#if defined(__AVX512VL__)
__forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_EQ); }
__forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_NE); }
__forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LT); }
__forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GE); }
__forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GT); }
__forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LE); }
#else
__forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a == b); }
__forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a != b); }
__forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a < b); }
__forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a >= b); }
__forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a > b); }
__forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a <= b); }
#endif
__forceinline vdouble4 select(const vboold4& m, const vdouble4& t, const vdouble4& f) {
#if defined(__AVX512VL__)
return _mm256_mask_blend_pd(m, f, t);
#else
return _mm256_blendv_pd(f, t, m);
#endif
}
__forceinline void xchg(const vboold4& m, vdouble4& a, vdouble4& b) {
const vdouble4 c = a; a = select(m,b,a); b = select(m,c,b);
}
__forceinline vboold4 test(const vdouble4& a, const vdouble4& b) {
#if defined(__AVX512VL__)
return _mm256_test_epi64_mask(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
#else
return _mm256_testz_si256(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
template<int i0, int i1>
__forceinline vdouble4 shuffle(const vdouble4& v) {
return _mm256_permute_pd(v, (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
}
template<int i>
__forceinline vdouble4 shuffle(const vdouble4& v) {
return shuffle<i, i>(v);
}
template<int i0, int i1>
__forceinline vdouble4 shuffle2(const vdouble4& v) {
return _mm256_permute2f128_pd(v, v, (i1 << 4) | i0);
}
__forceinline double toScalar(const vdouble4& v) {
return _mm_cvtsd_f64(_mm256_castpd256_pd128(v));
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline vdouble4 vreduce_min2(const vdouble4& x) { return min(x, shuffle<1,0>(x)); }
__forceinline vdouble4 vreduce_min (const vdouble4& y) { const vdouble4 x = vreduce_min2(y); return min(x, shuffle2<1,0>(x)); }
__forceinline vdouble4 vreduce_max2(const vdouble4& x) { return max(x,shuffle<1,0>(x)); }
__forceinline vdouble4 vreduce_max (const vdouble4& y) { const vdouble4 x = vreduce_max2(y); return max(x, shuffle2<1,0>(x)); }
__forceinline vdouble4 vreduce_and2(const vdouble4& x) { return x & shuffle<1,0>(x); }
__forceinline vdouble4 vreduce_and (const vdouble4& y) { const vdouble4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
__forceinline vdouble4 vreduce_or2(const vdouble4& x) { return x | shuffle<1,0>(x); }
__forceinline vdouble4 vreduce_or (const vdouble4& y) { const vdouble4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
__forceinline vdouble4 vreduce_add2(const vdouble4& x) { return x + shuffle<1,0>(x); }
__forceinline vdouble4 vreduce_add (const vdouble4& y) { const vdouble4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
__forceinline double reduce_add(const vdouble4& a) { return toScalar(vreduce_add(a)); }
__forceinline double reduce_min(const vdouble4& a) { return toScalar(vreduce_min(a)); }
__forceinline double reduce_max(const vdouble4& a) { return toScalar(vreduce_max(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline std::ostream& operator <<(std::ostream& cout, const vdouble4& v)
{
cout << "<" << v[0];
for (size_t i=1; i<4; i++) cout << ", " << v[i];
cout << ">";
return cout;
}
}

Some files were not shown because too many files have changed in this diff Show More