Compare commits

..
4 Commits
1013 changed files with 132220 additions and 126231 deletions
-2
View File
@@ -3,5 +3,3 @@ Win32
x64
*.suo
*.ncb
.*sw?
.DS_Store
-460
View File
@@ -1,460 +0,0 @@
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
application to use Embree without interfering with each other.
- Fixed memory leak in twolevel builder used for dynamic scenes.
- Fixed bug in tesselation cache that caused crashes for subdivision
surfaces.
- Fixed bug in internal task scheduler that caused deadlocks when
using `rtcCommitThread`.
- Improved hit-distance accuracy for thin triangles in robust mode.
- Added support to disable ray packet support in cmake.
### New Features in Embree 2.6.2
- Fixed bug triggered by instantiating motion blur geometry.
- Fixed bug in hit UV coordinates of static subdivision geometries.
- Performance improvements when only changing tessellation levels for
subdivision geometry per frame.
- 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.
- Bugfix for subdiv patches with non-matching winding order.
- Bugfix in ISA detection of AVX-512.
### 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
ISA
- Implemented intersection filter callback support for subdivision
surfaces
- Added `RTC_IGNORE_INVALID_RAYS` CMake option which makes the ray
intersectors more robust against full tree traversal caused by
invalid ray inputs (e.g. INF, NaN, etc)
### New Features in Embree 2.6.0
- Added `rtcInterpolate` function to interpolate per vertex
attributes
- Added `rtcSetBoundaryMode` function that can be used to select the
boundary handling for subdivision surfaces
- Fixed a traversal bug that caused rays with very small ray
direction components to miss geometry
- Performance improvements for the robust traversal mode
- Fixed deadlock when calling `rtcCommit` from multiple
threads on same scene
### New Features in Embree 2.5.1
- On dual socket workstations, the initial BVH build performance
almost doubled through a better memory allocation scheme
- Reduced memory usage for subdivision surface objects with crease
features
- `rtcCommit` performance is robust against unset "flush to zero" and
"denormals are zero" flags. However, enabling these flags in your
application is still recommended
- Reduced memory usage for subdivision surfaces with borders and
infinitely sharp creases
- Lots of internal cleanups and bug fixes for both Intel® Xeon® and
Intel® Xeon Phi™
### New Features in Embree 2.5.0
- Improved hierarchy build performance on both Intel Xeon and Intel
Xeon Phi
- Vastly improved tessellation cache for ray tracing subdivision
surfaces
- Added `rtcGetUserData` API call to query per geometry user pointer
set through `rtcSetUserData`
- Added support for memory monitor callback functions to track and
limit memory consumption
- Added support for progress monitor callback functions to track build
progress and cancel long build operations
- BVH builders can be used to build user defined hierarchies inside
the application (see tutorial [BVH Builder])
- Switched to TBB as default tasking system on Xeon to get even faster
hierarchy build times and better integration for applications that
also use TBB
- `rtcCommit` can get called from multiple TBB threads to join the
hierarchy build operations
### New Features in Embree 2.4
- Support for Catmull Clark subdivision surfaces (triangle/quad base
primitives)
- Support for vector displacements on Catmull Clark subdivision
surfaces
- Various bug fixes (e.g. 4-byte alignment of vertex buffers works)
### New Features in Embree 2.3.3
- BVH builders more robustly handle invalid input data (Intel Xeon
processor family)
- Motion blur support for hair geometry (Xeon)
- Improved motion blur performance for triangle geometry (Xeon)
- Improved robust ray tracing mode (Xeon)
- Added `rtcCommitThread` API call for easier integration into
existing tasking systems (Xeon and Intel Xeon Phi coprocessor)
- Added support for recording and replaying all
`rtcIntersect`/`rtcOccluded` calls (Xeon and Xeon Phi)
### New Features in Embree 2.3.2
- 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)
- (Enhanced) Morton code-based BVH builders use now tree rotations to
improve BVH quality (Xeon Phi)
- Bug fixes (Xeon and Xeon Phi)
### New Features in Embree 2.3.1
- High quality BVH mode improves spatial splits which result in up to
30% performance improvement for some scenes (Xeon)
- Compile time enabled intersection filter functions do not reduce
performance if no intersection filter is used in the scene (Xeon and
Xeon Phi)
- Improved ray tracing performance for hair geometry by \>20% on Xeon
Phi. BVH for hair geometry requires 20% less memory
- BVH8 for AVX/AVX2 targets improves performance for single ray
tracing on Haswell by up to 12% and by up to 5% for hybrid (Xeon)
- Memory conservative BVH for Xeon Phi now uses BVH node quantization
to lower memory footprint (requires half the memory footprint of the
default BVH)
### New Features in Embree 2.3
- Support for ray tracing hair geometry (Xeon and Xeon Phi)
- Catching errors through error callback function
- Faster hybrid traversal (Xeon and Xeon Phi)
- New memory conservative BVH for Xeon Phi
- Faster Morton code-based builder on Xeon
- Faster binned-SAH builder on Xeon Phi
- Lots of code cleanups/simplifications/improvements (Xeon and Xeon
Phi)
### New Features in Embree 2.2
- Support for motion blur on Xeon Phi
- Support for intersection filter callback functions
- Support for buffer sharing with the application
- Lots of AVX2 optimizations, e.g. \~20% faster 8-wide hybrid
traversal
- Experimental support for 8-wide (AVX/AVX2) and 16-wide BVHs (Xeon
Phi)
### New Features in Embree 2.1
- New future proof API with a strong focus on supporting dynamic
scenes
- Lots of optimizations for 8-wide AVX2 (Haswell architecture)
- Automatic runtime code selection for SSE, AVX, and AVX2
- Support for user-defined geometry
- New and improved BVH builders:
- Fast adaptive Morton code-based builder (without SAH-based
top-level rebuild)
- Both the SAH and Morton code-based builders got faster (Xeon
Phi)
- New variant of the SAH-based builder using triangle pre-splits
(Xeon Phi)
### New Features in Embree 2.0
- Support for the Intel® Xeon Phi™ coprocessor platform
- Support for high-performance "packet" kernels on SSE, AVX, and Xeon
Phi
- Integration with the Intel® SPMD Program Compiler (ISPC)
- Instantiation and fast BVH reconstruction
- Example photo-realistic rendering engine for both C++ and ISPC
+177 -321
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,365 +14,218 @@
## limitations under the License. ##
## ======================================================================== ##
SET(EMBREE_VERSION_MAJOR 2)
SET(EMBREE_VERSION_MINOR 17)
SET(EMBREE_VERSION_PATCH 0)
SET(EMBREE_VERSION_NOTE "-alpha.0")
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)
PROJECT(embree)
PROJECT(embree${EMBREE_VERSION_MAJOR})
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
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"
)
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/kernels/hash.h.in"
"${PROJECT_BINARY_DIR}/hash.h"
)
FILE(WRITE "${PROJECT_BINARY_DIR}/hash" "${EMBREE_HASH}")
IF(COMMAND cmake_policy)
if (POLICY CMP0003)
cmake_policy(SET CMP0003 NEW)
endif()
if (POLICY CMP0042)
cmake_policy(SET CMP0042 OLD)
endif()
ENDIF(COMMAND cmake_policy)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
MARK_AS_ADVANCED(CMAKE_BACKWARDS_COMPATIBILITY)
MARK_AS_ADVANCED(CMAKE_INSTALL_PREFIX)
MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH)
MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH)
MARK_AS_ADVANCED(CLEAR CMAKE_VERBOSE_MAKEFILE)
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)
##############################################################
# 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)
SET(EMBREE_LIB_TYPE STATIC)
ADD_DEFINITIONS(-DEMBREE_STATIC_LIB)
ELSE()
SET(EMBREE_LIB_TYPE SHARED)
SET(RTCORE_RAY_MASK OFF CACHE BOOL "Enables ray mask support.")
IF (RTCORE_RAY_MASK)
ADD_DEFINITIONS(-D__USE_RAY_MASK__)
ENDIF()
OPTION(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON)
OPTION(EMBREE_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)
ELSE()
SET(EMBREE_NATIVE_CURVE_BSPLINE OFF)
SET(RTCORE_STAT_COUNTERS OFF CACHE BOOL "Enables statistic counters.")
IF (RTCORE_STAT_COUNTERS)
ADD_DEFINITIONS(-D__USE_STAT_COUNTERS__)
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)
SET(RTCORE_BACKFACE_CULLING OFF CACHE BOOL "Enables backface culling.")
IF (RTCORE_BACKFACE_CULLING)
ADD_DEFINITIONS(-D__BACKFACE_CULLING__)
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)
ELSE()
SET(TASKING_INTERNAL ON )
SET(TASKING_TBB OFF)
SET(TASKING_PPL OFF )
ADD_DEFINITIONS(-DTASKING_INTERNAL)
LIST(APPEND ISPC_DEFINITIONS -DTASKING_INTERNAL)
IF (XEON_PHI_ISA)
# UNSET(RTCORE_INTERSECTION_FILTER CACHE)
SET(RTCORE_INTERSECTION_FILTER OFF CACHE BOOL "Enables intersection filter callback.")
ELSE ()
SET(RTCORE_INTERSECTION_FILTER ON CACHE BOOL "Enables intersection filter callback.")
ENDIF()
CONFIGURE_FILE(
"${PROJECT_SOURCE_DIR}/kernels/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
IF (RTCORE_INTERSECTION_FILTER)
ADD_DEFINITIONS(-D__INTERSECTION_FILTER__)
ENDIF()
SET(RTCORE_BUFFER_STRIDE ON CACHE BOOL "Enables buffer strides.")
IF (RTCORE_BUFFER_STRIDE)
ADD_DEFINITIONS(-D__BUFFER_STRIDE__)
ENDIF()
SET(RTCORE_SPINLOCKS OFF CACHE BOOL "Use spinning locks.")
IF (RTCORE_SPINLOCKS)
ADD_DEFINITIONS(-D__SPINLOCKS__)
ENDIF()
SET(RTCORE_TASKLOGGER OFF CACHE BOOL "Allows creating scheduling diagram of tasks.")
IF (RTCORE_TASKLOGGER)
ADD_DEFINITIONS(-D__LOG_TASKS__)
ENDIF()
SET(RTCORE_EXPORT_ALL_SYMBOLS OFF CACHE BOOL "Lets Embree shared library export all symbols.")
IF (RTCORE_EXPORT_ALL_SYMBOLS)
ADD_DEFINITIONS(-D__EXPORT_ALL_SYMBOLS__)
ENDIF()
SET(RTCORE_ENABLE_RAYSTREAM_LOGGER OFF CACHE BOOL "Enable ray stream logger")
IF (RTCORE_ENABLE_RAYSTREAM_LOGGER)
ADD_DEFINITIONS(-D__ENABLE_RAYSTREAM_LOGGER__)
ENDIF()
##############################################################
# 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)
SET(XEON_ISA "AVX2" CACHE STRING "Select highest ISA to support (SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX-I, AVX2")
SET(XEON_PHI_ISA OFF CACHE BOOL "Generate code path for Xeon Phi")
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 (XEON_ISA STREQUAL "SSE2")
SET(ISA 1)
ENDIF ()
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()
IF (XEON_ISA STREQUAL "SSE3")
SET(ISA 2)
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 (XEON_ISA STREQUAL "SSSE3")
SET(ISA 3)
ENDIF ()
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()
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)
ENDIF ()
IF (ISA GREATER 4)
SET(TARGET_SSE42 ON)
SET(ISPC_TARGETS ${ISPC_TARGETS} "sse4")
ENDIF ()
IF (ISA GREATER 5)
SET(TARGET_AVX ON)
SET(ISPC_TARGETS ${ISPC_TARGETS} "avx")
ENDIF ()
IF (ISA GREATER 6)
SET(TARGET_AVXI ON)
ENDIF ()
IF (ISA GREATER 7)
SET(TARGET_AVX2 ON)
SET(ISPC_TARGETS ${ISPC_TARGETS} "avx2")
ENDIF ()
IF (ISA GREATER 8)
SET(TARGET_AVX512 ON)
ENDIF ()
SET(ISPC_TARGETS "${ISPC_TARGETS}")
STRING(REGEX REPLACE ";" "," ISPC_TARGETS "${ISPC_TARGETS}")
##############################################################
# Compiler
##############################################################
SET(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo")
SET(COMPILER "GCC" CACHE STRING "Set to GCC, CLANG, or ICC")
IF (WIN32)
IF (NOT DEFAULT_CMAKE_CONFIGURATION_TYPES_SET)
SET(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}" CACHE STRING "List of generated configurations." FORCE)
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()
ELSE (WIN32)
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
INCLUDE(crayprgenv)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
INCLUDE (gcc)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
INCLUDE (clang)
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
INCLUDE (icc)
ELSE ()
MESSAGE(FATAL_ERROR "Unsupported compiler: " ${CMAKE_CXX_COMPILER_ID})
ENDIF ()
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Specifies the build type." FORCE)
SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CONFIGURATION_TYPES})
ENDIF(NOT CMAKE_BUILD_TYPE)
OPTION(CMAKE_VERBOSE_MAKEFILE "Enables verbose mode.")
MARK_AS_ADVANCED(CLEAR CMAKE_VERBOSE_MAKEFILE)
ENDIF (WIN32)
##############################################################
# ISA configuration continued
##############################################################
SET(SSE2 0)
SET(SSE42 1)
SET(AVX 2)
SET(AVX2 3)
SET(AVX512KNL 4)
SET(AVX512SKX 5)
UNSET(FLAGS_LOWEST)
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 (EMBREE_ISA_SSE42)
ADD_DEFINITIONS(-DEMBREE_TARGET_SSE42)
LIST(APPEND ISPC_TARGETS "sse4")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${SSE42})
SET(FLAGS_LOWEST ${FLAGS_SSE42})
ENDIF()
IF (COMPILER STREQUAL "GCC")
INCLUDE (gcc)
ELSEIF (COMPILER STREQUAL "CLANG")
INCLUDE (clang)
ELSEIF (COMPILER STREQUAL "ICC")
INCLUDE (icc)
ELSE ()
MESSAGE(FATAL_ERROR "Unknown compiler specified: " ${COMPILER})
ENDIF ()
IF (EMBREE_ISA_AVX)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX)
LIST(APPEND ISPC_TARGETS "avx")
IF(NOT FLAGS_LOWEST)
SET(ISA_LOWEST ${AVX})
SET(FLAGS_LOWEST ${FLAGS_AVX})
ENDIF()
ENDIF ()
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type: Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE)
IF (EMBREE_ISA_AVX2)
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX2)
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)
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 ()
SET(CMAKE_VERBOSE_MAKEFILE false CACHE BOOL "Enables verbose mode.")
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()
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/common)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES_ISPC(${PROJECT_SOURCE_DIR})
LINK_DIRECTORIES(${EXECUTABLE_OUTPUT_PATH})
##############################################################
# 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
@@ -380,26 +233,29 @@ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(kernels)
ADD_SUBDIRECTORY(tutorials)
IF (EMBREE_TUTORIALS)
ADD_SUBDIRECTORY(tutorials)
ENDIF()
SET (__XEON__ 1)
ADD_SUBDIRECTORY(tests)
IF (XEON_PHI_ISA)
SET (__XEON__ 0)
ADD_SUBDIRECTORY(tests tests_xeonphi)
ENDIF ()
##############################################################
# Uninstall
# Install Headers
##############################################################
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/common/cmake/uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake"
IMMEDIATE @ONLY)
INSTALL(DIRECTORY include/embree2 DESTINATION include FILES_MATCHING PATTERN "*.h")
INSTALL(DIRECTORY include/embree2 DESTINATION include FILES_MATCHING PATTERN "*.isph")
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake)
# ##################################################################
# Create Documentation. Call via 'make doc'
# ##################################################################
SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets)
ADD_CUSTOM_TARGET(doc
make -C ${CMAKE_CURRENT_SOURCE_DIR}/doc
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc
COMMENT "Generating documentation" VERBATIM)
##############################################################
# Has to be last
##############################################################
INCLUDE(CPack)
-202
View File
@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
-3188
View File
File diff suppressed because it is too large Load Diff
+8 -5
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,12 @@
## 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 (XEON_PHI_ISA)
SET(__XEON__ 0)
ADD_SUBDIRECTORY(sys sys_xeonphi)
ADD_SUBDIRECTORY(simd simd_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;
}
}
-61
View File
@@ -1,61 +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_for.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_for_regression_test : public RegressionTest
{
parallel_for_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
const size_t M = 10;
for (size_t N=10; N<10000000; N=size_t(2.1*N))
{
/* sequentially calculate sum of squares */
size_t sum0 = 0;
for (size_t i=0; i<N; i++) {
sum0 += i*i;
}
/* parallel calculation of sum of squares */
for (size_t m=0; m<M; m++)
{
std::atomic<size_t> sum1(0);
parallel_for( size_t(0), size_t(N), size_t(1024), [&](const range<size_t>& r)
{
size_t s = 0;
for (size_t i=r.begin(); i<r.end(); i++)
s += i*i;
sum1 += s;
});
passed = sum0 == sum1;
}
}
return passed;
}
};
parallel_for_regression_test parallel_for_regression("parallel_for_regression_test");
}
-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
}
-76
View File
@@ -1,76 +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_for_for.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_for_for_regression_test : public RegressionTest
{
parallel_for_for_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
/* create vector with random numbers */
size_t sum0 = 0;
size_t K = 0;
const size_t M = 1000;
std::vector<std::vector<size_t>* > array2(M);
for (size_t i=0; i<M; i++) {
const size_t N = rand() % 1024;
K+=N;
array2[i] = new std::vector<size_t>(N);
for (size_t j=0; j<N; j++)
sum0 += (*array2[i])[j] = rand();
}
/* array to test global index */
std::vector<atomic<size_t>> verify_k(K);
for (size_t i=0; i<K; i++) verify_k[i].store(0);
/* add all numbers using parallel_for_for */
std::atomic<size_t> sum1(0);
parallel_for_for( array2, size_t(1), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k) -> size_t
{
size_t s = 0;
for (size_t i=r.begin(); i<r.end(); i++) {
s += (*v)[i];
verify_k[k++]++;
}
sum1 += s;
return sum1;
});
passed &= (sum0 == sum1);
/* check global index */
for (size_t i=0; i<K; i++)
passed &= (verify_k[i] == 1);
/* delete vectors again */
for (size_t i=0; i<array2.size(); i++)
delete array2[i];
return passed;
}
};
parallel_for_for_regression_test parallel_for_for_regression("parallel_for_for_regression_test");
}
-162
View File
@@ -1,162 +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 ArrayArray, typename Func>
__forceinline void sequential_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
{
size_t k=0;
for (size_t i=0; i!=array2.size(); ++i) {
const size_t N = array2[i]->size();
if (N) func(array2[i],range<size_t>(0,N),k);
k+=N;
}
}
class ParallelForForState
{
public:
enum { MAX_TASKS = 512 };
__forceinline ParallelForForState ()
: taskCount(0) {}
template<typename ArrayArray>
__forceinline ParallelForForState (ArrayArray& array2, const size_t minStepSize) {
init(array2,minStepSize);
}
template<typename ArrayArray>
__forceinline void init ( ArrayArray& array2, const size_t minStepSize )
{
/* first calculate total number of elements */
size_t N = 0;
for (size_t i=0; i<array2.size(); i++) {
N += array2[i] ? array2[i]->size() : 0;
}
this->N = N;
/* calculate number of tasks to use */
const size_t numThreads = TaskScheduler::threadCount();
const size_t numBlocks = (N+minStepSize-1)/minStepSize;
taskCount = max(size_t(1),min(numThreads,numBlocks,size_t(ParallelForForState::MAX_TASKS)));
/* calculate start (i,j) for each task */
size_t taskIndex = 0;
i0[taskIndex] = 0;
j0[taskIndex] = 0;
size_t k0 = (++taskIndex)*N/taskCount;
for (size_t i=0, k=0; taskIndex < taskCount; i++)
{
assert(i<array2.size());
size_t j=0, M = array2[i] ? array2[i]->size() : 0;
while (j<M && k+M-j >= k0 && taskIndex < taskCount) {
assert(taskIndex<taskCount);
i0[taskIndex] = i;
j0[taskIndex] = j += k0-k;
k=k0;
k0 = (++taskIndex)*N/taskCount;
}
k+=M-j;
}
}
__forceinline size_t size() const {
return N;
}
public:
size_t i0[MAX_TASKS];
size_t j0[MAX_TASKS];
size_t taskCount;
size_t N;
};
template<typename ArrayArray, typename Func>
__forceinline void parallel_for_for( ArrayArray& array2, const size_t minStepSize, const Func& func )
{
ParallelForForState state(array2,minStepSize);
parallel_for(state.taskCount, [&](const size_t taskIndex)
{
/* calculate range */
const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
size_t i0 = state.i0[taskIndex];
size_t j0 = state.j0[taskIndex];
/* iterate over arrays */
size_t k=k0;
for (size_t i=i0; k<k1; i++) {
const size_t N = array2[i] ? array2[i]->size() : 0;
const size_t r0 = j0, r1 = min(N,r0+k1-k);
if (r1 > r0) func(array2[i],range<size_t>(r0,r1),k);
k+=r1-r0; j0 = 0;
}
});
}
template<typename ArrayArray, typename Func>
__forceinline void parallel_for_for( ArrayArray& array2, const Func& func )
{
parallel_for_for(array2,1,func);
}
template<typename ArrayArray, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_reduce( ArrayArray& array2, const size_t minStepSize, const Value& identity, const Func& func, const Reduction& reduction )
{
ParallelForForState state(array2,minStepSize);
Value temp[ParallelForForState::MAX_TASKS];
for (size_t i=0; i<state.taskCount; i++)
temp[i] = identity;
parallel_for(state.taskCount, [&](const size_t taskIndex)
{
/* calculate range */
const size_t k0 = (taskIndex+0)*state.size()/state.taskCount;
const size_t k1 = (taskIndex+1)*state.size()/state.taskCount;
size_t i0 = state.i0[taskIndex];
size_t j0 = state.j0[taskIndex];
/* iterate over arrays */
size_t k=k0;
for (size_t i=i0; k<k1; i++) {
const size_t N = array2[i] ? array2[i]->size() : 0;
const size_t r0 = j0, r1 = min(N,r0+k1-k);
if (r1 > r0) temp[taskIndex] = reduction(temp[taskIndex],func(array2[i],range<size_t>(r0,r1),k));
k+=r1-r0; j0 = 0;
}
});
Value ret = identity;
for (size_t i=0; i<state.taskCount; i++)
ret = reduction(ret,temp[i]);
return ret;
}
template<typename ArrayArray, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_reduce( ArrayArray& array2, const Value& identity, const Func& func, const Reduction& reduction)
{
return parallel_for_for_reduce(array2,1,identity,func,reduction);
}
}
@@ -1,98 +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_for_for_prefix_sum.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_for_for_prefix_sum_regression_test : public RegressionTest
{
parallel_for_for_prefix_sum_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
/* create vector with random numbers */
const size_t M = 10;
std::vector<atomic<size_t>> flattened;
typedef std::vector<std::vector<size_t>* > ArrayArray;
ArrayArray array2(M);
size_t K = 0;
for (size_t i=0; i<M; i++) {
const size_t N = rand() % 10;
K += N;
array2[i] = new std::vector<size_t>(N);
for (size_t j=0; j<N; j++)
(*array2[i])[j] = rand() % 10;
}
/* array to test global index */
std::vector<atomic<size_t>> verify_k(K);
for (size_t i=0; i<K; i++) verify_k[i].store(0);
ParallelForForPrefixSumState<size_t> state(array2,size_t(1));
/* dry run only counts */
size_t S = parallel_for_for_prefix_sum0( state, array2, size_t(0), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k) -> size_t
{
size_t s = 0;
for (size_t i=r.begin(); i<r.end(); i++) {
s += (*v)[i];
verify_k[k++]++;
}
return s;
}, [](size_t v0, size_t v1) { return v0+v1; });
/* create properly sized output array */
flattened.resize(S);
for (auto& a : flattened) a.store(0);
/* now we actually fill the flattened array */
parallel_for_for_prefix_sum1( state, array2, size_t(0), [&](std::vector<size_t>* v, const range<size_t>& r, size_t k, const size_t base) -> size_t
{
size_t s = 0;
for (size_t i=r.begin(); i<r.end(); i++) {
for (size_t j=0; j<(*v)[i]; j++) {
flattened[base+s+j]++;
}
s += (*v)[i];
verify_k[k++]++;
}
return s;
}, [](size_t v0, size_t v1) { return v0+v1; });
/* check global index */
for (size_t i=0; i<K; i++)
passed &= (verify_k[i] == 2);
/* check if each element was assigned exactly once */
for (size_t i=0; i<flattened.size(); i++)
passed &= (flattened[i] == 1);
/* delete arrays again */
for (size_t i=0; i<array2.size(); i++)
delete array2[i];
return passed;
}
};
parallel_for_for_prefix_sum_regression_test parallel_for_for_prefix_sum_regression("parallel_for_for_prefix_sum_regression_test");
}
@@ -1,125 +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_for.h"
#include "parallel_prefix_sum.h"
namespace embree
{
template<typename Value>
struct ParallelForForPrefixSumState : public ParallelForForState
{
__forceinline ParallelForForPrefixSumState () {}
template<typename ArrayArray>
__forceinline ParallelForForPrefixSumState (ArrayArray& array2, const size_t minStepSize)
: ParallelForForState(array2,minStepSize) {}
ParallelPrefixSumState<Value> prefix_state;
};
template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
const Value& identity, const Func& func, const Reduction& reduction)
{
/* calculate number of tasks to use */
const size_t taskCount = state.taskCount;
/* perform parallel prefix sum */
parallel_for(taskCount, [&](const size_t taskIndex)
{
const size_t k0 = (taskIndex+0)*state.size()/taskCount;
const size_t k1 = (taskIndex+1)*state.size()/taskCount;
size_t i0 = state.i0[taskIndex];
size_t j0 = state.j0[taskIndex];
/* iterate over arrays */
size_t k=k0;
Value N=identity;
for (size_t i=i0; k<k1; i++) {
const size_t size = array2[i] ? array2[i]->size() : 0;
const size_t r0 = j0, r1 = min(size,r0+k1-k);
if (r1 > r0) N = reduction(N, func(array2[i],range<size_t>(r0,r1),k));
k+=r1-r0; j0 = 0;
}
state.prefix_state.counts[taskIndex] = N;
});
/* calculate prefix sum */
Value sum=identity;
for (size_t i=0; i<taskCount; i++)
{
const Value c = state.prefix_state.counts[i];
state.prefix_state.sums[i] = sum;
sum=reduction(sum,c);
}
return sum;
}
template<typename ArrayArray, typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2, Index minStepSize,
const Value& identity, const Func& func, const Reduction& reduction)
{
/* calculate number of tasks to use */
const size_t taskCount = state.taskCount;
/* perform parallel prefix sum */
parallel_for(taskCount, [&](const size_t taskIndex)
{
const size_t k0 = (taskIndex+0)*state.size()/taskCount;
const size_t k1 = (taskIndex+1)*state.size()/taskCount;
size_t i0 = state.i0[taskIndex];
size_t j0 = state.j0[taskIndex];
/* iterate over arrays */
size_t k=k0;
Value N=identity;
for (size_t i=i0; k<k1; i++) {
const size_t size = array2[i] ? array2[i]->size() : 0;
const size_t r0 = j0, r1 = min(size,r0+k1-k);
if (r1 > r0) N = reduction(N, func(array2[i],range<size_t>(r0,r1),k,reduction(state.prefix_state.sums[taskIndex],N)));
k+=r1-r0; j0 = 0;
}
state.prefix_state.counts[taskIndex] = N;
});
/* calculate prefix sum */
Value sum=identity;
for (size_t i=0; i<taskCount; i++)
{
const Value c = state.prefix_state.counts[i];
state.prefix_state.sums[i] = sum;
sum=reduction(sum,c);
}
return sum;
}
template<typename ArrayArray, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_prefix_sum0( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
const Value& identity, const Func& func, const Reduction& reduction)
{
return parallel_for_for_prefix_sum0(state,array2,size_t(1),identity,func,reduction);
}
template<typename ArrayArray, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_for_for_prefix_sum1( ParallelForForPrefixSumState<Value>& state, ArrayArray& array2,
const Value& identity, const Func& func, const Reduction& reduction)
{
return parallel_for_for_prefix_sum1(state,array2,size_t(1),identity,func,reduction);
}
}
-60
View File
@@ -1,60 +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_map.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_map_regression_test : public RegressionTest
{
parallel_map_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
/* create key/value vectors with random numbers */
const size_t N = 10000;
std::vector<uint32_t> keys(N);
std::vector<uint32_t> vals(N);
for (size_t i=0; i<N; i++) keys[i] = 2*unsigned(i)*647382649;
for (size_t i=0; i<N; i++) std::swap(keys[i],keys[rand()%N]);
for (size_t i=0; i<N; i++) vals[i] = 2*rand();
/* create map */
parallel_map<uint32_t,uint32_t> map;
map.init(keys,vals);
/* check that all keys are properly mapped */
for (size_t i=0; i<N; i++) {
const uint32_t* val = map.lookup(keys[i]);
passed &= val && (*val == vals[i]);
}
/* check that these keys are not in the map */
for (size_t i=0; i<N; i++) {
passed &= !map.lookup(keys[i]+1);
}
return passed;
}
};
parallel_map_regression_test parallel_map_regression("parallel_map_regression_test");
}
-98
View File
@@ -1,98 +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_sort.h"
namespace embree
{
/*! implementation of a key/value map with parallel construction */
template<typename Key, typename Val>
class parallel_map
{
/* key/value pair to build the map */
struct KeyValue
{
__forceinline KeyValue () {}
__forceinline KeyValue (const Key key, const Val val)
: key(key), val(val) {}
__forceinline operator Key() const {
return key;
}
public:
Key key;
Val val;
};
public:
/*! parallel map constructors */
parallel_map () {}
/*! construction from pair of vectors */
template<typename KeyVector, typename ValVector>
parallel_map (const KeyVector& keys, const ValVector& values) { init(keys,values); }
/*! initialized the parallel map from a vector with keys and values */
template<typename KeyVector, typename ValVector>
void init(const KeyVector& keys, const ValVector& values)
{
/* reserve sufficient space for all data */
assert(keys.size() == values.size());
vec.resize(keys.size());
/* generate key/value pairs */
parallel_for( size_t(0), keys.size(), size_t(4*4096), [&](const range<size_t>& r) {
for (size_t i=r.begin(); i<r.end(); i++)
vec[i] = KeyValue((Key)keys[i],values[i]);
});
/* perform parallel radix sort of the key/value pairs */
std::vector<KeyValue> temp(keys.size());
radix_sort<KeyValue,Key>(vec.data(),temp.data(),keys.size());
}
/*! Returns a pointer to the value associated with the specified key. The pointer will be nullptr of the key is not contained in the map. */
__forceinline const Val* lookup(const Key& key) const
{
typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
if (i == vec.end()) return nullptr;
if (i->key != key) return nullptr;
return &i->val;
}
/*! If the key is in the map, the function returns the value associated with the key, otherwise it returns the default value. */
__forceinline Val lookup(const Key& key, const Val& def) const
{
typename std::vector<KeyValue>::const_iterator i = std::lower_bound(vec.begin(), vec.end(), key);
if (i == vec.end()) return def;
if (i->key != key) return def;
return i->val;
}
/*! clears all state */
void clear() {
vec.clear();
}
private:
std::vector<KeyValue> vec; //!< vector containing sorted elements
};
}
-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);
}
}
}
-61
View File
@@ -1,61 +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_prefix_sum.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_prefix_sum_regression_test : public RegressionTest
{
parallel_prefix_sum_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
const size_t M = 10;
for (size_t N=10; N<10000000; N=size_t(2.1*N))
{
/* initialize array with random numbers */
uint32_t sum0 = 0;
std::vector<uint32_t> src(N);
for (size_t i=0; i<N; i++) {
sum0 += src[i] = rand();
}
/* calculate parallel prefix sum */
std::vector<uint32_t> dst(N);
for (auto& v : dst) v = 0;
for (size_t i=0; i<M; i++) {
uint32_t sum1 = parallel_prefix_sum(src,dst,N,0,std::plus<uint32_t>());
passed &= (sum0 == sum1);
}
/* check if prefix sum is correct */
for (size_t i=0, sum=0; i<N; sum+=src[i++])
passed &= ((uint32_t)sum == dst[i]);
}
return passed;
}
};
parallel_prefix_sum_regression_test parallel_prefix_sum_regression("parallel_prefix_sum_regression");
}
-98
View File
@@ -1,98 +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 Value>
struct ParallelPrefixSumState
{
enum { MAX_TASKS = 512 };
Value counts[MAX_TASKS];
Value sums [MAX_TASKS];
};
template<typename Index, typename Value, typename Func, typename Reduction>
__forceinline Value parallel_prefix_sum( ParallelPrefixSumState<Value>& state, Index first, Index last, Index minStepSize, const Value& identity, const Func& func, const Reduction& reduction)
{
/* calculate number of tasks to use */
const size_t numThreads = TaskScheduler::threadCount();
const size_t numBlocks = (last-first+minStepSize-1)/minStepSize;
const size_t taskCount = min(numThreads,numBlocks,size_t(ParallelPrefixSumState<Value>::MAX_TASKS));
/* perform parallel prefix sum */
parallel_for(taskCount, [&](const size_t taskIndex)
{
const size_t i0 = first+(taskIndex+0)*(last-first)/taskCount;
const size_t i1 = first+(taskIndex+1)*(last-first)/taskCount;
state.counts[taskIndex] = func(range<size_t>(i0,i1),state.sums[taskIndex]);
});
/* calculate prefix sum */
Value sum=identity;
for (size_t i=0; i<taskCount; i++)
{
const Value c = state.counts[i];
state.sums[i] = sum;
sum=reduction(sum,c);
}
return sum;
}
/*! parallel calculation of prefix sums */
template<typename SrcArray, typename DstArray, typename Value, typename Add>
__forceinline Value parallel_prefix_sum(const SrcArray& src, DstArray& dst, size_t N, const Value& identity, const Add& add, const size_t SINGLE_THREAD_THRESHOLD = 4096)
{
/* perform single threaded prefix operation for small N */
if (N < SINGLE_THREAD_THRESHOLD)
{
Value sum=identity;
for (size_t i=0; i<N; sum=add(sum,src[i++])) dst[i] = sum;
return sum;
}
/* perform parallel prefix operation for large N */
else
{
ParallelPrefixSumState<Value> state;
/* initial run just sets up start values for subtasks */
parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
Value s = identity;
for (size_t i=r.begin(); i<r.end(); i++) s = add(s,src[i]);
return s;
}, add);
/* final run calculates prefix sum */
return parallel_prefix_sum( state, size_t(0), size_t(N), size_t(1024), identity, [&](const range<size_t>& r, const Value& sum) -> Value {
Value s = identity;
for (size_t i=r.begin(); i<r.end(); i++) {
dst[i] = add(sum,s);
s = add(s,src[i]);
}
return s;
}, add);
}
}
}
-62
View File
@@ -1,62 +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_reduce.h"
#include "../sys/regression.h"
namespace embree
{
struct parallel_reduce_regression_test : public RegressionTest
{
parallel_reduce_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
const size_t M = 10;
for (size_t N=10; N<10000000; N=size_t(2.1*N))
{
/* sequentially calculate sum of squares */
size_t sum0 = 0;
for (size_t i=0; i<N; i++) {
sum0 += i*i;
}
/* parallel calculation of sum of squares */
for (size_t m=0; m<M; m++)
{
size_t sum1 = parallel_reduce( size_t(0), size_t(N), size_t(1024), size_t(0), [&](const range<size_t>& r) -> size_t
{
size_t s = 0;
for (size_t i=r.begin(); i<r.end(); i++)
s += i*i;
return s;
},
[](const size_t v0, const size_t v1) {
return v0+v1;
});
passed = sum0 == sum1;
}
}
return passed;
}
};
parallel_reduce_regression_test parallel_reduce_regression("parallel_reduce_regression_test");
}
-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);
}
}
-65
View File
@@ -1,65 +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_sort.h"
namespace embree
{
/* implementation of a set of values with parallel construction */
template<typename T>
class parallel_set
{
public:
/*! default constructor for the parallel set */
parallel_set () {}
/*! construction from vector */
template<typename Vector>
parallel_set (const Vector& in) { init(in); }
/*! initialized the parallel set from a vector */
template<typename Vector>
void init(const Vector& in)
{
/* copy data to internal vector */
vec.resize(in.size());
parallel_for( size_t(0), in.size(), size_t(4*4096), [&](const range<size_t>& r) {
for (size_t i=r.begin(); i<r.end(); i++)
vec[i] = in[i];
});
/* sort the data */
std::vector<T> temp(in.size());
radix_sort<T>(vec.data(),temp.data(),vec.size());
}
/*! tests if some element is in the set */
__forceinline bool lookup(const T& elt) const {
return std::binary_search(vec.begin(), vec.end(), elt);
}
/*! clears all state */
void clear() {
vec.clear();
}
private:
std::vector<T> vec; //!< vector containing sorted elements
};
}
-63
View File
@@ -1,63 +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_sort.h"
#include "../sys/regression.h"
namespace embree
{
template<typename Key>
struct RadixSortRegressionTest : public RegressionTest
{
RadixSortRegressionTest(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
const size_t M = 10;
for (size_t N=10; N<1000000; N=size_t(2.1*N))
{
std::vector<Key> src(N); memset(src.data(),0,N*sizeof(Key));
std::vector<Key> tmp(N); memset(tmp.data(),0,N*sizeof(Key));
for (size_t i=0; i<N; i++) src[i] = uint64_t(rand())*uint64_t(rand());
/* calculate checksum */
Key sum0 = 0; for (size_t i=0; i<N; i++) sum0 += src[i];
/* sort numbers */
for (size_t i=0; i<M; i++) {
radix_sort<Key>(src.data(),tmp.data(),N);
}
/* calculate checksum */
Key sum1 = 0; for (size_t i=0; i<N; i++) sum1 += src[i];
if (sum0 != sum1) passed = false;
/* check if numbers are sorted */
for (size_t i=1; i<N; i++)
passed &= src[i-1] <= src[i];
}
return passed;
}
};
RadixSortRegressionTest<uint32_t> test_u32("RadixSortRegressionTestU32");
RadixSortRegressionTest<uint64_t> test_u64("RadixSortRegressionTestU64");
}
-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-2014 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)
-24
View File
@@ -1,24 +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. ##
## ======================================================================== ##
FIND_PATH( PNG_INCLUDE_DIR NAMES png.h )
FIND_LIBRARY( PNG_LIBRARIES NAMES png )
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PNG DEFAULT_MSG PNG_INCLUDE_DIR PNG_LIBRARIES)
MARK_AS_ADVANCED(PNG_INCLUDE_DIR)
MARK_AS_ADVANCED(PNG_LIBRARIES)
-128
View File
@@ -1,128 +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)
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.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)
ELSE()
SET(TBB_ARCH ia32)
ENDIF()
IF (MSVC10)
SET(TBB_VCVER vc10)
ELSEIF (MSVC11)
SET(TBB_VCVER vc11)
ELSE()
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})
IF (EMBREE_TBB_ROOT STREQUAL "")
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h)
FIND_LIBRARY(TBB_LIBRARY tbb)
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
ELSE()
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_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
DOC "Root of TBB installation"
PATHS ${PROJECT_SOURCE_DIR}/tbb /opt/intel/tbb
NO_DEFAULT_PATH
)
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h)
IF (EMBREE_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)
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)
ENDIF()
ENDIF()
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(TBB DEFAULT_MSG TBB_INCLUDE_DIR TBB_LIBRARY TBB_LIBRARY_MALLOC)
IF (TBB_FOUND)
SET(TBB_INCLUDE_DIRS ${TBB_INCLUDE_DIR})
SET(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_LIBRARY_MALLOC})
ENDIF()
MARK_AS_ADVANCED(TBB_INCLUDE_DIR)
MARK_AS_ADVANCED(TBB_LIBRARY)
MARK_AS_ADVANCED(TBB_LIBRARY_MALLOC)
##############################################################
# Install TBB
##############################################################
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)
IF (APPLE)
INSTALL(PROGRAMS ${EMBREE_TBB_ROOT}/lib/libtbb.dylib ${EMBREE_TBB_ROOT}/lib/libtbbmalloc.dylib DESTINATION ${CMAKE_INSTALL_LIBDIR} 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)
ENDIF()
ENDIF()
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,21 @@
## 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
)
FIND_PATH(EMBREE_INCLUDE_PATH embree2/rtcore.h
/usr/include
/usr/local/include
/opt/local/include)
SET_PROPERTY(TARGET algorithms PROPERTY FOLDER common)
FIND_LIBRARY(EMBREE_LIBRARY NAMES embree PATHS
/usr/lib
/usr/local/lib
/opt/local/lib)
FIND_LIBRARY(EMBREE_LIBRARY_MIC NAMES embree_xeonphi PATHS
/usr/lib
/usr/local/lib
/opt/local/lib)
IF (EMBREE_INCLUDE_PATH AND EMBREE_LIBRARY)
SET(EMBREE_FOUND TRUE)
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()
+15 -96
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 Intel Corporation ##
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); ##
## you may not use this file except in compliance with the License. ##
@@ -20,101 +20,20 @@ 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 "-march=knl")
SET(FLAGS_AVX512SKX "-march=skx")
SET(FLAGS_AVX2 "-mavx2 -mfma -mlzcnt -mbmi -mbmi2")
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")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O2")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wstrict-aliasing=0 ")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -g -O3 -Wstrict-aliasing=0 ")
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")
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")
+3 -2
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,4 +14,5 @@
// limitations under the License. //
// ======================================================================== //
#define RTCORE_HASH "@EMBREE_HASH@"
int main() { return 0; }
-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})
-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@)
+17 -50
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,25 @@
## ======================================================================== ##
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_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mabm -mbmi -mbmi2")
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")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O2")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wstrict-aliasing=0 ")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -g -O3 -Wstrict-aliasing=0 ")
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_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7")
ENDIF (APPLE)
+23 -134
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,28 @@
## 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 -static-intel -fasm-blocks")
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O2 ")
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -no-ansi-alias -restrict ")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -g -O3 -no-ansi-alias -restrict ")
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_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} -dynamiclib)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7")
ENDIF (APPLE)
+33
View File
@@ -0,0 +1,33 @@
## ======================================================================== ##
## Copyright 2009-2014 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 -fasm-blocks -fPIC")
SET (CMAKE_CXX_FLAGS_NOOPT "-g -O0 -DDEBUG")
SET (CMAKE_CXX_FLAGS_DEBUG "-g -w1 -O2 -DDEBUG ")
#--no-exceptions --no-rtti
# -ansi-alias # ISPC not working with ansi-alias flag
SET (CMAKE_CXX_FLAGS_RELEASE "-O3 -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 -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_LINKER icpc)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
#SET(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> -mmic -static-intel -rdynamic -fPIC -L${CMAKE_BINARY_DIR} <LINK_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES>")
#SET(CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> -mmic -static-intel <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_MODULE_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} <OBJECTS> <LINK_LIBRARIES> -zmuldefs")
+73 -127
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,109 +14,73 @@
## limitations under the License. ##
## ======================================================================== ##
# ##################################################################
# add macro INCLUDE_DIRECTORIES_ISPC() that allows to specify search
# paths for ISPC sources
# ##################################################################
SET(ISPC_INCLUDE_DIR "")
SET (ISPC_INCLUDE_DIR "")
MACRO (INCLUDE_DIRECTORIES_ISPC)
SET(ISPC_INCLUDE_DIR ${ISPC_INCLUDE_DIR} ${ARGN})
SET (ISPC_INCLUDE_DIR ${ISPC_INCLUDE_DIR} ${ARGN})
ENDMACRO ()
IF (EMBREE_ISPC_SUPPORT)
execute_process(COMMAND which ispc OUTPUT_VARIABLE ISPC_EXECUTABLE)
#IF (EXISTS "/home/benthin/Projects/ispc/ispc")
#"${ISPC_EXECUTABLE}")
#message(${ISPC_EXECUTABLE})
execute_process(COMMAND dirname ${ISPC_EXECUTABLE} OUTPUT_VARIABLE ISPC_DIR_TEMP)
#ENDIF()
STRING(REGEX REPLACE "\n" "" ISPC_DIR "${ISPC_DIR_TEMP}")
# 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)
IF (NOT EMBREE_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()
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.")
ELSE()
MESSAGE(STATUS "Found Intel SPMD Compiler (ISPC): ${EMBREE_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 (ISPC_VERSION VERSION_LESS ISPC_VERSION_REQUIRED)
MESSAGE(FATAL_ERROR "Need at least version ${ISPC_VERSION_REQUIRED} of Intel SPMD Compiler (ISPC).")
ENDIF()
GET_FILENAME_COMPONENT(ISPC_DIR ${EMBREE_ISPC_EXECUTABLE} PATH)
SET(EMBREE_ISPC_ADDRESSING 32 CACHE INT "32vs64 bit addressing in ispc")
SET(EMBREE_ISPC_ADDRESSING 32 CACHE INT
"32vs64 bit addressing in ispc")
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 (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(ISPC_ARCHITECTURE "x86-64")
MACRO (ispc_compile targets)
IF (__XEON__)
SET (ISPC_TARGET_EXT o)
ELSE()
SET(ISPC_ARCHITECTURE "x86")
SET (ISPC_TARGET_EXT cpp)
SET (ISPC_TARGET_ALIGNED_MEMORY --opt=force-aligned-memory)
ENDIF()
IF (CMAKE_OSX_ARCHITECTURES STREQUAL "i386")
SET(ISPC_ARCHITECTURE "x86")
ELSE()
SET(ISPC_ARCHITECTURE "x86-64")
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}")
SET(ISPC_INCLUDE_DIR_PARMS "-I" ${ISPC_INCLUDE_DIR_PARMS})
STRING(REGEX REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}")
SET(ISPC_INCLUDE_DIR_PARMS "-I" ${ISPC_INCLUDE_DIR_PARMS})
ENDIF()
IF (WIN32 OR "${CMAKE_BUILD_TYPE}" STREQUAL "Release")
SET(ISPC_OPT_FLAGS -O3)
IF (__XEON__)
STRING(REGEX REPLACE "," ";" target_list "${targets}")
SET(ISPC_TARGETS ${targets})
ELSE()
SET(ISPC_OPT_FLAGS -O2 -g)
ENDIF()
IF (WIN32)
SET(ISPC_ADDITIONAL_ARGS ${ISPC_ADDITIONAL_ARGS} --dllexport)
ELSE()
SET(ISPC_ADDITIONAL_ARGS ${ISPC_ADDITIONAL_ARGS} --pic)
SET(ISPC_TARGETS generic-16 --emit-c++ -D__XEON_PHI__ --c++-include-file=${ISPC_DIR}/examples/intrinsics/knc.h)
ENDIF()
SET(ISPC_OBJECTS "")
FOREACH(src ${ARGN})
GET_FILENAME_COMPONENT(fname ${src} NAME_WE)
GET_FILENAME_COMPONENT(dir ${src} PATH)
SET(outdir "${ISPC_TARGET_DIR}/${dir}")
SET(input ${CMAKE_CURRENT_SOURCE_DIR}/${src})
IF("${dir}" STREQUAL "")
SET(outdir ${ISPC_TARGET_DIR})
ELSE("${dir}" STREQUAL "")
SET(outdir ${ISPC_TARGET_DIR}/${dir})
ENDIF("${dir}" STREQUAL "")
SET(outdirh ${ISPC_TARGET_DIR})
SET(deps "")
IF (EXISTS ${outdir}/${fname}.dev.idep)
FILE(READ ${outdir}/${fname}.dev.idep contents)
STRING(REPLACE " " ";" contents "${contents}")
STRING(REPLACE ";" "\\\\;" contents "${contents}")
STRING(REPLACE "\n" ";" contents "${contents}")
STRING(REGEX REPLACE " " ";" contents "${contents}")
STRING(REGEX REPLACE ";" "\\\\;" contents "${contents}")
STRING(REGEX REPLACE "\n" ";" contents "${contents}")
FOREACH(dep ${contents})
IF (EXISTS ${dep})
SET(deps ${deps} ${dep})
@@ -124,49 +88,47 @@ MACRO (ISPC_COMPILE)
ENDFOREACH(dep ${contents})
ENDIF ()
SET(results "${outdir}/${fname}.dev${ISPC_TARGET_EXT}")
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__)
IF (${targets} MATCHES ".*,.*")
FOREACH(target ${target_list})
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}
-I ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT ${results} ${outdirh}/${fname}_ispc.h
COMMAND mkdir -p ${outdir} \; ispc
-I ${CMAKE_CURRENT_SOURCE_DIR}
${ISPC_INCLUDE_DIR_PARMS}
${ISPC_DEFINITIONS}
--arch=${ISPC_ARCHITECTURE}
--addressing=${EMBREE_ISPC_ADDRESSING}
${ISPC_OPT_FLAGS}
--target=${ISPC_TARGET_ARGS}
--addressing=${EMBREE_ISPC_ADDRESSING}
--pic
-O3
--target=${ISPC_TARGETS}
--woff
# --wno-perf
--opt=fast-math
${ISPC_ADDITIONAL_ARGS}
-h ${ISPC_TARGET_DIR}/${fname}_ispc.h
-MMM ${outdir}/${fname}.dev.idep
-o ${outdir}/${fname}.dev${ISPC_TARGET_EXT}
${input}
DEPENDS ${input} ${deps}
COMMENT "Building ISPC object ${outdir}/${fname}.dev${ISPC_TARGET_EXT}"
)
${ISPC_TARGET_ALIGNED_MEMORY}
# --opt=force-aligned-memory
-h ${outdirh}/${fname}_ispc.h
-MMM ${outdir}/${fname}.dev.idep
-o ${outdir}/${fname}.dev.${ISPC_TARGET_EXT}
${CMAKE_CURRENT_SOURCE_DIR}/${src}
\;
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src}
${deps})
SET(ISPC_OBJECTS ${ISPC_OBJECTS} ${results})
ENDFOREACH()
ENDMACRO()
MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
MACRO (add_ispc_executable name)
SET(ISPC_SOURCES "")
SET(OTHER_SOURCES "")
FOREACH(src ${ARGN})
@@ -177,11 +139,12 @@ MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
SET(OTHER_SOURCES ${OTHER_SOURCES} ${src})
ENDIF ()
ENDFOREACH()
ISPC_COMPILE(${ISPC_SOURCES})
ISPC_COMPILE (${ISPC_TARGETS} ${ISPC_SOURCES})
ADD_EXECUTABLE(${name} ${ISPC_OBJECTS} ${OTHER_SOURCES})
# SET_TARGET_PROPERTIES(${name} PROPERTIES LINKER_LANGUAGE C)
ENDMACRO()
MACRO (ADD_ISPC_LIBRARY name type)
MACRO (add_ispc_library name type)
SET(ISPC_SOURCES "")
SET(OTHER_SOURCES "")
FOREACH(src ${ARGN})
@@ -192,24 +155,7 @@ MACRO (ADD_ISPC_LIBRARY name type)
SET(OTHER_SOURCES ${OTHER_SOURCES} ${src})
ENDIF ()
ENDFOREACH()
ISPC_COMPILE(${ISPC_SOURCES})
ISPC_COMPILE (${ISPC_TARGETS} ${ISPC_SOURCES})
ADD_LIBRARY(${name} ${type} ${ISPC_OBJECTS} ${OTHER_SOURCES})
# SET_TARGET_PROPERTIES(${name} PROPERTIES LINKER_LANGUAGE C)
ENDMACRO()
ELSE (EMBREE_ISPC_SUPPORT)
MACRO (ADD_ISPC_LIBRARY name type)
SET(ISPC_SOURCES "")
SET(OTHER_SOURCES "")
FOREACH(src ${ARGN})
GET_FILENAME_COMPONENT(ext ${src} EXT)
IF (ext STREQUAL ".ispc")
SET(ISPC_SOURCES ${ISPC_SOURCES} ${src})
ELSE ()
SET(OTHER_SOURCES ${OTHER_SOURCES} ${src})
ENDIF ()
ENDFOREACH()
ADD_LIBRARY(${name} ${type} ${OTHER_SOURCES})
ENDMACRO()
ENDIF (EMBREE_ISPC_SUPPORT)
+37
View File
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup
Condition="'$(ISPCBeforeTargets)' == '' and '$(ISPCAfterTargets)' == '' and '$(ConfigurationType)' != 'Makefile'">
<ISPCBeforeTargets>Midl</ISPCBeforeTargets>
<ISPCAfterTargets>CustomBuild</ISPCAfterTargets>
</PropertyGroup>
<PropertyGroup>
<ISPCDependsOn
Condition="'$(ConfigurationType)' != 'Makefile'">_SelectedFiles;$(ISPCDependsOn)</ISPCDependsOn>
</PropertyGroup>
<ItemDefinitionGroup>
<ISPC>
<GenerateDebugInformation>False</GenerateDebugInformation>
<Assertions>true</Assertions>
<Aligned>False</Aligned>
<PIC>False</PIC>
<WarningsAsErrors>False</WarningsAsErrors>
<NoWarnings>False</NoWarnings>
<ObjectFileName>$(IntDir)%(Filename).ispc.obj</ObjectFileName>
<HeaderFile>$(IntDir)%(Filename)_ispc.h</HeaderFile>
<Architecture>1</Architecture>
<Processor>1</Processor>
<TargetISA>0</TargetISA>
<WarningLevel>1</WarningLevel>
<MathLibrary>0</MathLibrary>
<Opt>1</Opt>
<CommandLineTemplate>ispc.exe [AllOptions] [AdditionalOptions] [Inputs]</CommandLineTemplate>
<Outputs Condition="'$(Configuration)'=='Debug'">$(IntDir)%(Filename).ispc.obj;$(IntDir)%(Filename).ispc_sse2.obj;$(IntDir)%(Filename).ispc_sse4.obj</Outputs>
<Outputs Condition="'$(Configuration)'=='Release'">$(IntDir)%(Filename).ispc.obj;$(IntDir)%(Filename).ispc_sse2.obj;$(IntDir)%(Filename).ispc_sse4.obj</Outputs>
<Outputs Condition="'$(Configuration)'=='ReleaseAVX'">$(IntDir)%(Filename).ispc.obj;$(IntDir)%(Filename).ispc_sse2.obj;$(IntDir)%(Filename).ispc_sse4.obj;$(IntDir)%(Filename).ispc_avx.obj</Outputs>
<Outputs Condition="'$(Configuration)'=='ReleaseAVX2'">$(IntDir)%(Filename).ispc.obj;$(IntDir)%(Filename).ispc_sse2.obj;$(IntDir)%(Filename).ispc_sse4.obj;$(IntDir)%(Filename).ispc_avx.obj;;$(IntDir)%(Filename).ispc_avx2.obj</Outputs>
<Outputs Condition="'$(MSBuildProjectName)'=='embree'">$(IntDir)%(Filename).ispc.obj;$(IntDir)%(Filename).ispc_sse2.obj;$(IntDir)%(Filename).ispc_sse4.obj;$(IntDir)%(Filename).ispc_avx.obj;$(IntDir)%(Filename).ispc_avx2.obj</Outputs>
<ExecutionDescription>Compiling %(Filename)%(Extension) ...</ExecutionDescription>
</ISPC>
</ItemDefinitionGroup>
</Project>
+225
View File
@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile
Name="ISPC"
Version="8,00"
>
<Rules>
<CustomBuildRule
Name="ISPC"
DisplayName="Intel SPMD Programm Compiler (ISPC)"
CommandLine="ispc.exe [AllOptions] [AdditionalOptions] [Inputs]"
Outputs="$(IntDir)\$(InputName).ispc*.obj"
FileExtensions="*.ispc"
ExecutionDescription="Compiling $(InputFileName) ..."
>
<Properties>
<EnumProperty
Name="Architecture"
DisplayName="Target Architecture"
Description="Select Target Architecture."
DefaultValue="1"
>
<Values>
<EnumValue
Value="0"
Switch="--arch=x86"
DisplayName="x86"
/>
<EnumValue
Value="1"
Switch="--arch=x86-64"
DisplayName="x86-64"
/>
</Values>
</EnumProperty>
<EnumProperty
Name="TargetISA"
DisplayName="Target ISA"
Description="Select Target ISA."
>
<Values>
<EnumValue
Value="0"
Switch="--target=sse2"
DisplayName="SSE2"
/>
<EnumValue
Value="1"
Switch="--target=sse4"
DisplayName="SSE4"
/>
<EnumValue
Value="2"
Switch="--target=avx"
DisplayName="AVX"
/>
<EnumValue
Value="3"
Switch="--target=avx1.1"
DisplayName="AVX-I"
/>
<EnumValue
Value="4"
Switch="--target=AVX2"
DisplayName="AVX2"
/>
<EnumValue
Value="5"
Switch="--target=sse2,sse4"
DisplayName="SSE2,SSE4"
/>
<EnumValue
Value="6"
Switch="--target=sse2,sse4,avx"
DisplayName="SSE2,SSE4,AVX"
/>
<EnumValue
Value="7"
Switch="--target=sse2,sse4,avx,avx2"
DisplayName="SSE2,SSE4,AVX,AVX2"
/>
</Values>
</EnumProperty>
<StringProperty
Name="ObjectFileName"
DisplayName="Object File Name"
PropertyPageName="Output"
Description="Specifies the name of the output object file."
Switch="-o &quot;[value]&quot;"
DefaultValue="$(IntDir)\$(InputName).ispc.obj"
/>
<StringProperty
Name="PreprocessorDefinitions"
DisplayName="Preprocessor Definitions"
Description="Defines a text macro with the given name."
Switch="-D&quot;[value]&quot;"
Delimited="true"
Inheritable="true"
/>
<StringProperty
Name="IncludePaths"
DisplayName="Include Paths"
Description="Sets path for include file. "
Switch="-I &quot;[value]&quot;"
Delimited="true"
Inheritable="true"
/>
<EnumProperty
Name="WarningLevel"
DisplayName="Warning Level"
Description="Sets the warning level."
DefaultValue="1"
>
<Values>
<EnumValue
Value="0"
Switch="--woff"
DisplayName="Warning Level 0"
/>
<EnumValue
Value="1"
Switch="--wno-perf"
DisplayName="Warning Level 1"
/>
<EnumValue
Value="2"
DisplayName="Warning Level 2"
/>
</Values>
</EnumProperty>
<BooleanProperty
Name="GenerateDebugInformation"
DisplayName="Generate Debug Information"
Description="Generates Debug Information. (-g)"
Switch="-g"
/>
<EnumProperty
Name="MathLibrary"
DisplayName="Math Library"
Description="Select Math Library"
>
<Values>
<EnumValue
Value="0"
Switch="--math-lib=default"
DisplayName="ISPC Internal"
/>
<EnumValue
Value="1"
Switch="--math-lib=fast"
DisplayName="Fast"
/>
<EnumValue
Value="2"
Switch="--math-lib=svml"
DisplayName="SVML"
/>
<EnumValue
Value="3"
Switch="--math-lib=system"
DisplayName="System"
/>
</Values>
</EnumProperty>
<EnumProperty
Name="Opt"
DisplayName="Optimization Level"
Description="Optimization Level"
DefaultValue="1"
>
<Values>
<EnumValue
Value="0"
Switch="-O0"
DisplayName="O0"
/>
<EnumValue
Value="1"
Switch="-O1"
DisplayName="O1"
/>
</Values>
</EnumProperty>
<BooleanProperty
Name="Assertions"
DisplayName="Assertions"
Description="Disables Assertions"
Switch="--opt=disable-assertions"
DefaultValue="true"
/>
<BooleanProperty
Name="Aligned"
DisplayName="Force Aligned Loads"
Description="Forces Aligned Loads."
Switch="--opt=force-aligned-memory"
/>
<BooleanProperty
Name="PIC"
DisplayName="Position Independent Code"
Description="Generate Position Independent Code"
Switch="--pic"
/>
<BooleanProperty
Name="WarningsAsErrors"
DisplayName="Treat Warnings as Errors"
Description="Treat Warnings as Errors."
Switch="--werror"
/>
<StringProperty
Name="HeaderFile"
DisplayName="Header File Name"
PropertyPageName="Output"
Description="Interface Header File."
Switch="-h &quot;[value]&quot;"
DefaultValue="$(IntDir)\$(InputName)_ispc.h"
/>
<BooleanProperty
Name="NoWarnings"
DisplayName="Disable Warnings"
Description="Disable Warnings"
Switch="--woff"
/>
</Properties>
</CustomBuildRule>
</Rules>
</VisualStudioToolFile>
+96
View File
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema
Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
<AvailableItemName
Include="ISPC">
<Targets>_ISPC</Targets>
</AvailableItemName>
</ItemGroup>
<UsingTask
TaskName="ISPC"
TaskFactory="XamlTaskFactory"
AssemblyName="Microsoft.Build.Tasks.v4.0">
<Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
</UsingTask>
<Target
Name="_ISPC"
BeforeTargets="$(ISPCBeforeTargets)"
AfterTargets="$(ISPCAfterTargets)"
Condition="'@(ISPC)' != ''"
DependsOnTargets="$(ISPCDependsOn);ComputeISPCOutput"
Outputs="%(ISPC.Outputs)"
Inputs="%(ISPC.Identity);%(ISPC.AdditionalDependencies);$(MSBuildProjectFile)">
<ItemGroup
Condition="'@(SelectedFiles)' != ''">
<ISPC
Remove="@(ISPC)"
Condition="'%(Identity)' != '@(SelectedFiles)'" />
</ItemGroup>
<ItemGroup>
<ISPC_tlog
Include="%(ISPC.Outputs)"
Condition="'%(ISPC.Outputs)' != '' and '%(ISPC.ExcludedFromBuild)' != 'true'">
<Source>@(ISPC, '|')</Source>
</ISPC_tlog>
</ItemGroup>
<Message
Importance="High"
Text="%(ISPC.ExecutionDescription)" />
<WriteLinesToFile
Condition="'@(ISPC_tlog)' != '' and '%(ISPC_tlog.ExcludedFromBuild)' != 'true'"
File="$(IntDir)$(ProjectName).write.1.tlog"
Lines="^%(ISPC_tlog.Source);@(ISPC_tlog-&gt;'%(Fullpath)')" />
<ISPC
Condition="'@(ISPC)' != '' and '%(ISPC.ExcludedFromBuild)' != 'true'"
CommandLineTemplate="%(ISPC.CommandLineTemplate)"
GenerateDebugInformation="%(ISPC.GenerateDebugInformation)"
Assertions="%(ISPC.Assertions)"
Aligned="%(ISPC.Aligned)"
PIC="%(ISPC.PIC)"
WarningsAsErrors="%(ISPC.WarningsAsErrors)"
NoWarnings="%(ISPC.NoWarnings)"
ObjectFileName="%(ISPC.ObjectFileName)"
PreprocessorDefinitions="%(ISPC.PreprocessorDefinitions)"
IncludePaths="%(ISPC.IncludePaths)"
HeaderFile="%(ISPC.HeaderFile)"
Architecture="%(ISPC.Architecture)"
TargetISA="%(ISPC.TargetISA)"
WarningLevel="%(ISPC.WarningLevel)"
MathLibrary="%(ISPC.MathLibrary)"
Opt="%(ISPC.Opt)"
AdditionalOptions="%(ISPC.AdditionalOptions)"
Inputs="%(ISPC.Identity)" />
</Target>
<PropertyGroup>
<ComputeLinkInputsTargets>
$(ComputeLinkInputsTargets);
ComputeISPCOutput;
</ComputeLinkInputsTargets>
<ComputeLibInputsTargets>
$(ComputeLibInputsTargets);
ComputeISPCOutput;
</ComputeLibInputsTargets>
</PropertyGroup>
<Target
Name="ComputeISPCOutput"
Condition="'@(ISPC)' != ''">
<ItemGroup>
<ISPCDirsToMake
Condition="'@(ISPC)' != '' and '%(ISPC.ExcludedFromBuild)' != 'true'"
Include="%(ISPC.Outputs)" />
<Link
Include="%(ISPCDirsToMake.Identity)"
Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
<Lib
Include="%(ISPCDirsToMake.Identity)"
Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
<ImpLib
Include="%(ISPCDirsToMake.Identity)"
Condition="'%(Extension)'=='.obj' or '%(Extension)'=='.res' or '%(Extension)'=='.rsc' or '%(Extension)'=='.lib'" />
</ItemGroup>
<MakeDir
Directories="@(ISPCDirsToMake-&gt;'%(RootDir)%(Directory)')" />
</Target>
</Project>
+296
View File
@@ -0,0 +1,296 @@
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:transformCallback="Microsoft.Cpp.Dev10.ConvertPropertyCallback">
<Rule
Name="ISPC"
PageTemplate="tool"
DisplayName="Intel SPMD Programm Compiler (ISPC)"
Order="200">
<Rule.DataSource>
<DataSource
Persistence="ProjectFile"
ItemType="ISPC" />
</Rule.DataSource>
<Rule.Categories>
<Category
Name="General">
<Category.DisplayName>
<sys:String>General</sys:String>
</Category.DisplayName>
</Category>
<Category
Name="Command Line"
Subtype="CommandLine">
<Category.DisplayName>
<sys:String>Command Line</sys:String>
</Category.DisplayName>
</Category>
</Rule.Categories>
<StringListProperty
Name="Inputs"
Category="Command Line"
IsRequired="true"
Switch=" ">
<StringListProperty.DataSource>
<DataSource
Persistence="ProjectFile"
ItemType="ISPC"
SourceType="Item" />
</StringListProperty.DataSource>
</StringListProperty>
<BoolProperty
Name="GenerateDebugInformation"
HelpContext="0"
DisplayName="Generate Debug Information"
Description="Generates Debug Information. (-g)"
Switch="-g" />
<BoolProperty
Name="Assertions"
HelpContext="0"
DisplayName="Assertions"
Description="Disables Assertions"
Switch="--opt=disable-assertions" />
<BoolProperty
Name="Aligned"
HelpContext="0"
DisplayName="Force Aligned Loads"
Description="Forces Aligned Loads."
Switch="--opt=force-aligned-memory" />
<BoolProperty
Name="PIC"
HelpContext="0"
DisplayName="Position Independent Code"
Description="Generate Position Independent Code"
Switch="--pic" />
<BoolProperty
Name="WarningsAsErrors"
HelpContext="0"
DisplayName="Treat Warnings as Errors"
Description="Treat Warnings as Errors."
Switch="--werror" />
<BoolProperty
Name="NoWarnings"
HelpContext="0"
DisplayName="Disable Warnings"
Description="Disable Warnings"
Switch="--woff" />
<StringProperty
Name="ObjectFileName"
Category="Output"
HelpContext="0"
DisplayName="Object File Name"
Description="Specifies the name of the output object file."
Switch="-o &quot;[value]&quot;" />
<StringListProperty
Name="PreprocessorDefinitions"
HelpContext="0"
DisplayName="Preprocessor Definitions"
Description="Defines a text macro with the given name."
Separator=";"
Switch="-D&quot;[value]&quot;" />
<StringListProperty
Name="IncludePaths"
HelpContext="0"
DisplayName="Include Paths"
Description="Sets path for include file. "
Separator=";"
Switch="-I &quot;[value]&quot;" />
<StringProperty
Name="HeaderFile"
Category="Output"
HelpContext="0"
DisplayName="Header File Name"
Description="Interface Header File."
Switch="-h &quot;[value]&quot;" />
<EnumProperty
Name="Architecture"
HelpContext="0"
DisplayName="Target Architecture"
Description="Select Target Architecture.">
<EnumValue
Name="0"
DisplayName="x86"
Switch="--arch=x86" />
<EnumValue
Name="1"
DisplayName="x86-64"
Switch="--arch=x86-64" />
</EnumProperty>
<EnumProperty
Name="TargetISA"
HelpContext="0"
DisplayName="Target ISA"
Description="Select Target ISA.">
<EnumValue
Name="0"
DisplayName="SSE2"
Switch="--target=sse2" />
<EnumValue
Name="1"
DisplayName="SSE4"
Switch="--target=sse4" />
<EnumValue
Name="2"
DisplayName="AVX"
Switch="--target=avx" />
<EnumValue
Name="3"
DisplayName="AVX-I"
Switch="--target=avx1.1" />
<EnumValue
Name="4"
DisplayName="AVX2"
Switch="--target=AVX2" />
<EnumValue
Name="5"
DisplayName="SSE2,SSE4"
Switch="--target=sse2,sse4" />
<EnumValue
Name="6"
DisplayName="SSE2,SSE4,AVX"
Switch="--target=sse2,sse4,avx" />
<EnumValue
Name="7"
DisplayName="SSE2,SSE4,AVX,AVX2"
Switch="--target=sse2,sse4,avx,avx2" />
</EnumProperty>
<EnumProperty
Name="WarningLevel"
HelpContext="0"
DisplayName="Warning Level"
Description="Sets the warning level.">
<EnumValue
Name="0"
DisplayName="Warning Level 0"
Switch="--woff" />
<EnumValue
Name="1"
DisplayName="Warning Level 1"
Switch="--wno-perf" />
<EnumValue
Name="2"
DisplayName="Warning Level 2" />
</EnumProperty>
<EnumProperty
Name="MathLibrary"
HelpContext="0"
DisplayName="Math Library"
Description="Select Math Library">
<EnumValue
Name="0"
DisplayName="ISPC Internal"
Switch="--math-lib=default" />
<EnumValue
Name="1"
DisplayName="Fast"
Switch="--math-lib=fast" />
<EnumValue
Name="2"
DisplayName="SVML"
Switch="--math-lib=svml" />
<EnumValue
Name="3"
DisplayName="System"
Switch="--math-lib=system" />
</EnumProperty>
<EnumProperty
Name="Opt"
HelpContext="0"
DisplayName="Optimization Level"
Description="Optimization Level">
<EnumValue
Name="0"
DisplayName="O0"
Switch="-O0" />
<EnumValue
Name="1"
DisplayName="O1"
Switch="-O1" />
</EnumProperty>
<StringProperty
Name="CommandLineTemplate"
DisplayName="Command Line"
Visible="False"
IncludeInCommandLine="False" />
<DynamicEnumProperty
Name="ISPCBeforeTargets"
Category="General"
EnumProvider="Targets"
IncludeInCommandLine="False">
<DynamicEnumProperty.DisplayName>
<sys:String>Execute Before</sys:String>
</DynamicEnumProperty.DisplayName>
<DynamicEnumProperty.Description>
<sys:String>Specifies the targets for the build customization to run before.</sys:String>
</DynamicEnumProperty.Description>
<DynamicEnumProperty.ProviderSettings>
<NameValuePair
Name="Exclude"
Value="^ISPCBeforeTargets|^Compute" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource
Persistence="ProjectFile"
HasConfigurationCondition="true" />
</DynamicEnumProperty.DataSource>
</DynamicEnumProperty>
<DynamicEnumProperty
Name="ISPCAfterTargets"
Category="General"
EnumProvider="Targets"
IncludeInCommandLine="False">
<DynamicEnumProperty.DisplayName>
<sys:String>Execute After</sys:String>
</DynamicEnumProperty.DisplayName>
<DynamicEnumProperty.Description>
<sys:String>Specifies the targets for the build customization to run after.</sys:String>
</DynamicEnumProperty.Description>
<DynamicEnumProperty.ProviderSettings>
<NameValuePair
Name="Exclude"
Value="^ISPCAfterTargets|^Compute" />
</DynamicEnumProperty.ProviderSettings>
<DynamicEnumProperty.DataSource>
<DataSource
Persistence="ProjectFile"
ItemType=""
HasConfigurationCondition="true" />
</DynamicEnumProperty.DataSource>
</DynamicEnumProperty>
<StringListProperty
Name="Outputs"
DisplayName="Outputs"
Visible="False"
IncludeInCommandLine="False" />
<StringProperty
Name="ExecutionDescription"
DisplayName="Execution Description"
Visible="False"
IncludeInCommandLine="False" />
<StringListProperty
Name="AdditionalDependencies"
DisplayName="Additional Dependencies"
IncludeInCommandLine="False"
Visible="false" />
<StringProperty
Subtype="AdditionalOptions"
Name="AdditionalOptions"
Category="Command Line">
<StringProperty.DisplayName>
<sys:String>Additional Options</sys:String>
</StringProperty.DisplayName>
<StringProperty.Description>
<sys:String>Additional Options</sys:String>
</StringProperty.Description>
</StringProperty>
</Rule>
<ItemType
Name="ISPC"
DisplayName="Intel SPMD Programm Compiler (ISPC)" />
<FileExtension
Name="*.ispc"
ContentType="ISPC" />
<ContentType
Name="ISPC"
DisplayName="Intel SPMD Programm Compiler (ISPC)"
ItemType="ISPC" />
</ProjectSchemaDefinitions>
-62
View File
@@ -1,62 +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(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
ELSE()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
ENDIF()
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} ${FLAGS_SSE2}")
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_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)
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)
-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})
-266
View File
@@ -1,266 +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(GNUInstallDirs)
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})
ENDIF()
# use full absolute path as install name
IF (NOT EMBREE_ZIP_MODE)
SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
ELSE()
IF(APPLE)
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib")
ELSE()
SET(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
ENDIF()
ENDIF()
##############################################################
# Install Headers
##############################################################
INSTALL(DIRECTORY include/embree2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel)
##############################################################
# Install Models
##############################################################
INSTALL(DIRECTORY tutorials/models DESTINATION "${CMAKE_INSTALL_BINDIR}" 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)
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")
##############################################################
# Install scripts to set embree paths
##############################################################
IF (EMBREE_ZIP_MODE)
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)
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)
ENDIF()
ENDIF()
##############################################################
# Install Embree CMake Configuration
##############################################################
IF (NOT EMBREE_ZIP_MODE)
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})
ELSEIF (APPLE)
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree.${EMBREE_CONFIG_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX})
ELSE()
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree${CMAKE_SHARED_LIBRARY_SUFFIX}.${EMBREE_CONFIG_VERSION})
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)
##############################################################
# CPack specific stuff
##############################################################
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})
SET(CPACK_PACKAGE_VERSION_PATCH ${EMBREE_VERSION_PATCH})
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Embree: High Performance Ray Tracing Kernels")
SET(CPACK_PACKAGE_VENDOR "Intel Corporation")
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(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.")
# dependencies between components
SET(CPACK_COMPONENT_DEVEL_DEPENDS lib)
SET(CPACK_COMPONENT_EXAMPLES_DEPENDS lib)
SET(CPACK_COMPONENT_LIB_REQUIRED ON) # always install the libs
# point to readme and license files
SET(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
SET(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE.txt)
# Windows specific settings
IF(WIN32)
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(ARCH x64)
SET(PROGRAMFILES "\$PROGRAMFILES64")
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} x64")
ELSE()
SET(ARCH win32)
SET(PROGRAMFILES "\$PROGRAMFILES")
SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME} Win32")
ENDIF()
# NSIS specific settings
IF (NOT EMBREE_ZIP_MODE)
SET(CPACK_GENERATOR NSIS)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}")
SET(CPACK_COMPONENTS_ALL lib devel examples)
SET(CPACK_NSIS_INSTALL_ROOT "${PROGRAMFILES}\\\\Intel")
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_DISPLAY_NAME "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_PACKAGE_NAME "Embree v${EMBREE_VERSION} ${ARCH}")
SET(CPACK_NSIS_URL_INFO_ABOUT http://embree.github.io/)
#SET(CPACK_NSIS_HELP_LINK http://embree.github.io/downloads.html#windows)
SET(CPACK_NSIS_MUI_ICON ${PROJECT_SOURCE_DIR}/scripts/install_windows/icon32.ico)
SET(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT})
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\"")
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\documentation\\\"")
#SET(CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS} "\n CreateDirectory \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\tutorials\\\" \n")
#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
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})
SET(CPACK_GENERATOR PackageMaker)
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64")
#SET(CPACK_COMPONENTS_ALL lib devel examples)
SET(CPACK_MONOLITHIC_INSTALL 1)
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)
SET(CPACK_GENERATOR RPM)
SET(CPACK_COMPONENTS_ALL devel lib examples)
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_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()
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()
-1
View File
@@ -1 +0,0 @@
/sbin/ldconfig
-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()
-38
View File
@@ -1,38 +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. ##
## ======================================================================== ##
# additional parameters (beyond the name) are treated as additional dependencies
# if ADDITIONAL_LIBRARIES is set these will be included during linking
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 (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")
ENDIF()
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} PARENT_SCOPE)
ENDMACRO ()
-37
View File
@@ -1,37 +0,0 @@
## ======================================================================== ##
## 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. ##
## ======================================================================== ##
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
MESSAGE(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
STRING(REGEX REPLACE "\n" ";" files "${files}")
FOREACH(file ${files})
MESSAGE(STATUS "Uninstalling $ENV{DESTDIR}${file}")
IF(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
EXEC_PROGRAM(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
IF(NOT "${rm_retval}" STREQUAL 0)
MESSAGE(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
ENDIF(NOT "${rm_retval}" STREQUAL 0)
ELSE(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
MESSAGE(STATUS "File $ENV{DESTDIR}${file} does not exist.")
ENDIF(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
ENDFOREACH(file)
-18
View File
@@ -1,18 +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. ##
## ======================================================================== ##
ADD_LIBRARY(math STATIC constants.cpp)
SET_PROPERTY(TARGET math PROPERTY FOLDER common)
+13 -36
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,10 +16,9 @@
#pragma once
#include "linearspace2.h"
#include "linearspace3.h"
#include "quaternion.h"
#include "bbox.h"
#include "math/linearspace3.h"
#include "math/quaternion.h"
#include "math/bbox.h"
namespace embree
{
@@ -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
}
+33 -180
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 Intel Corporation //
// //
// Licensed under the Apache License, Version 2.0 (the "License"); //
// you may not use this file except in compliance with the License. //
@@ -41,26 +41,24 @@ namespace embree
/// Extending Bounds
////////////////////////////////////////////////////////////////////////////////
__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(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); }
__forceinline void extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); }
/*! tests if box is empty */
__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);
}
/*! computes the size of the box */
__forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
/*! computes the size of the box */
__forceinline T size() const { return upper - lower; }
/*! computes the center of the box */
__forceinline T center() const { return 0.5f*(lower+upper); }
/*! 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,32 +71,15 @@ 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));
}
#endif
/*! tests if box is finite */
__forceinline bool isvalid( const BBox<Vec3fa>& v ) {
return all(gt_mask(v.lower,Vec3fa_t(-FLT_LARGE)) & lt_mask(v.upper,Vec3fa_t(+FLT_LARGE)));
}
/*! tests if box has finite entries */
__forceinline bool is_finite( const BBox<Vec3fa>& b) {
return is_finite(b.lower) && is_finite(b.upper);
}
/*! test if point contained in box */
__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()); }
@@ -108,19 +89,10 @@ namespace embree
__forceinline float volume( const BBox<Vec3f>& b ) { return reduce_mul(b.size()); }
/*! computes the surface area of a bounding box */
template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = b.size(); return d.x*d.y; }
template<typename T> __forceinline const T halfArea( const BBox<Vec3<T> >& b ) { return halfArea(b.size()); }
template<typename T> __forceinline const T area( const BBox<Vec3<T> >& b ) { return 2.0f*halfArea(b); }
__forceinline float halfArea( const BBox<Vec3fa>& b ) { return halfArea(b.size()); }
__forceinline float area( const BBox<Vec3fa>& b ) { return 2.0f*halfArea(b); }
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);
}
template<typename T> __forceinline const T area( const BBox<Vec2<T> >& b ) { const Vec2<T> d = size(b); return d.x*d.y; }
__forceinline float area( const BBox<Vec3fa>& b ) { const Vec3fa d = b.size(); return 2.0f*(d.x*(d.y+d.z)+d.y*d.z); }
__forceinline float safeArea( const BBox<Vec3fa>& b ) { if (b.empty()) return 0.0f; else return area(b); }
__forceinline float halfArea( const BBox<Vec3fa>& b ) { const Vec3fa d = b.size(); return d.x*(d.y+d.z)+d.y*d.z; }
/*! 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 )); }
@@ -143,167 +115,48 @@ namespace embree
template<typename T> __forceinline BBox<T> operator *( const float& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
template<typename T> __forceinline BBox<T> operator *( const T& a, const BBox<T>& b ) { return BBox<T>(a*b.lower,a*b.upper); }
/*! translations */
template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower+b.lower,a.upper+b.upper); }
template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(a.lower-b.lower,a.upper-b.upper); }
template<typename T> __forceinline BBox<T> operator +( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower+b ,a.upper+b ); }
template<typename T> __forceinline BBox<T> operator -( const BBox<T>& a, const T & b ) { return BBox<T>(a.lower-b ,a.upper-b ); }
/*! extension */
template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower-b, a.upper+b); }
template<typename T> __forceinline BBox<T> enlarge(const BBox<T>& a, const T& b) { return BBox<T>(a.lower - b, a.upper +b); }
/*! 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(); }
template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b ) { return disjoint(a,BBox<T>(b)); }
template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b ) { return disjoint(BBox<T>(a),b); }
template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b )
{ const T d = min(a.upper, b.upper) - max(a.lower, b.lower); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return true; return false; }
template<typename T> __inline bool disjoint( const BBox<T>& a, const T& b )
{ const T d = min(a.upper, b) - max(a.lower, b); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return true; return false; }
template<typename T> __inline bool disjoint( const T& a, const BBox<T>& b )
{ const T d = min(a, b.upper) - max(a, b.lower); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return true; return false; }
/*! tests if bounding boxes (and points) are conjoint (non-empty intersection) */
template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b ) { return !intersect(a,b).empty(); }
template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b ) { return conjoint(a,BBox<T>(b)); }
template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b ) { return conjoint(BBox<T>(a),b); }
template<typename T> __inline bool conjoint( const BBox<T>& a, const BBox<T>& b )
{ const T d = min(a.upper, b.upper) - max(a.lower, b.lower); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return false; return true; }
template<typename T> __inline bool conjoint( const BBox<T>& a, const T& b )
{ const T d = min(a.upper, b) - max(a.lower, b); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return false; return true; }
template<typename T> __inline bool conjoint( const T& a, const BBox<T>& b )
{ const T d = min(a, b.upper) - max(a, b.lower); for ( size_t i = 0 ; i < T::N ; i++ ) if ( d[i] < typename T::Scalar(zero) ) return false; return true; }
/*! subset relation */
template<typename T> __inline bool subset( const BBox<T>& a, const BBox<T>& b )
{
for ( size_t i = 0; i < T::N; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
for ( size_t i = 0; i < T::N; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
for ( size_t i = 0 ; i < T::N ; i++ ) if ( a.lower[i] < b.lower[i] ) return false;
for ( size_t i = 0 ; i < T::N ; i++ ) if ( a.upper[i] > b.upper[i] ) return false;
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
}
+4 -3
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,8 @@
#pragma once
#include "math.h"
#include "sys/platform.h"
#include "math/math.h"
namespace embree
{
@@ -55,6 +56,6 @@ namespace embree
}
/*! default template instantiations */
typedef Col3<unsigned char> Col3uc;
typedef Col3<unsigned char> Col3c;
typedef Col3<float > Col3f;
}
+4 -3
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,8 @@
#pragma once
#include "math.h"
#include "sys/platform.h"
#include "math/math.h"
namespace embree
{
@@ -55,6 +56,6 @@ namespace embree
}
/*! default template instantiations */
typedef Col4<unsigned char> Col4uc;
typedef Col4<unsigned char> Col4c;
typedef Col4<float > Col4f;
}
+24 -56
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,12 +16,12 @@
#pragma once
#include "constants.h"
#include "../sys/constants.h"
#include "../simd/sse.h"
#include "col3.h"
#include "col4.h"
#include "../simd/sse.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
@@ -45,16 +45,16 @@ namespace embree
__forceinline explicit Color4 (const float v) : m128(_mm_set1_ps(v)) {}
__forceinline Color4 (const float r, const float g, const float b, const float a) : m128(_mm_set_ps(a,b,g,r)) {}
__forceinline explicit Color4 ( const Col3uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(255.0f,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
__forceinline explicit Color4 ( const Col3f& other ) { m128 = _mm_set_ps(1.0f,other.b,other.g,other.r); }
__forceinline explicit Color4 ( const Col4uc& other ) { m128 = _mm_mul_ps(_mm_set_ps(other.a,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
__forceinline explicit Color4 ( const Col4f& other ) { m128 = _mm_set_ps(other.a,other.b,other.g,other.r); }
__forceinline explicit Color4 ( const Col3c& other ) { m128 = _mm_mul_ps(_mm_set_ps(255.0f,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
__forceinline explicit Color4 ( const Col3f& other ) { m128 = _mm_set_ps(1.0f,other.b,other.g,other.r); }
__forceinline explicit Color4 ( const Col4c& other ) { m128 = _mm_mul_ps(_mm_set_ps(other.a,other.b,other.g,other.r),_mm_set1_ps(one_over_255)); }
__forceinline explicit Color4 ( const Col4f& other ) { m128 = _mm_set_ps(other.a,other.b,other.g,other.r); }
__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
@@ -62,21 +62,8 @@ namespace embree
__forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
__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;
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;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
d.a = (unsigned char)(s[3]);
}
__forceinline void set(Col3c& d) const { ssef s = clamp(ssef(m128))*255.0f; d.r = char(s[0]); d.g = char(s[1]); d.b = char(s[2]); }
__forceinline void set(Col4c& d) const { ssef s = clamp(ssef(m128))*255.0f; d.r = char(s[0]); d.g = char(s[1]); d.b = char(s[2]); d.a = char(s[3]); }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -115,8 +102,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
@@ -124,21 +111,8 @@ namespace embree
__forceinline void set(Col3f& d) const { d.r = r; d.g = g; d.b = b; }
__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;
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;
d.r = (unsigned char)(s[0]);
d.g = (unsigned char)(s[1]);
d.b = (unsigned char)(s[2]);
d.a = 255;
}
__forceinline void set(Col3c& d) const { ssef s = clamp(ssef(m128))*255.0f; d.r = char(s[0]); d.g = char(s[1]); d.b = char(s[2]); }
__forceinline void set(Col4c& d) const { ssef s = clamp(ssef(m128))*255.0f; d.r = char(s[0]); d.g = char(s[1]); d.b = char(s[2]); d.a = 1.0f; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -163,22 +137,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); }
@@ -237,7 +201,7 @@ namespace embree
__forceinline const Color select( bool s, const Color& t, const Color& 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);
return _mm_blendv_ps(f, t, mask);
}
////////////////////////////////////////////////////////////////////////////////
@@ -245,7 +209,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(ssef(a)<=ssef(zero),ssef(zero),ssef(exp_ps(log(a)*b)))); }
/*! output operator */
inline std::ostream& operator<<(std::ostream& cout, const Color& a) {
-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;
}
-160
View File
@@ -1,160 +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 "vec2.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// 2D Linear Transform (2x2 Matrix)
////////////////////////////////////////////////////////////////////////////////
template<typename T> struct LinearSpace2
{
typedef T Vector;
typedef typename T::Scalar Scalar;
/*! default matrix constructor */
__forceinline LinearSpace2 ( ) {}
__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) {}
/*! matrix construction from column vectors */
__forceinline LinearSpace2(const Vector& vx, const Vector& vy)
: vx(vx), vy(vy) {}
/*! matrix construction from row mayor data */
__forceinline LinearSpace2(const Scalar& m00, const Scalar& m01,
const Scalar& m10, const Scalar& m11)
: vx(m00,m10), vy(m01,m11) {}
/*! compute the determinant of the matrix */
__forceinline const Scalar det() const { return vx.x*vy.y - vx.y*vy.x; }
/*! compute adjoint matrix */
__forceinline const LinearSpace2 adjoint() const { return LinearSpace2(vy.y,-vy.x,-vx.y,vx.x); }
/*! compute inverse matrix */
__forceinline const LinearSpace2 inverse() const { return adjoint()/det(); }
/*! compute transposed matrix */
__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); }
/*! returns second row of matrix */
__forceinline Vector row1() const { return Vector(vx.y,vy.y); }
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline LinearSpace2( ZeroTy ) : vx(zero), vy(zero) {}
__forceinline LinearSpace2( OneTy ) : vx(one, zero), vy(zero, one) {}
/*! return matrix for scaling */
static __forceinline LinearSpace2 scale(const Vector& s) {
return LinearSpace2(s.x, 0,
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 */
Vector vx,vy;
};
////////////////////////////////////////////////////////////////////////////////
// Unary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a ) { return LinearSpace2<T>(-a.vx,-a.vy); }
template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a ) { return LinearSpace2<T>(+a.vx,+a.vy); }
template<typename T> __forceinline LinearSpace2<T> rcp ( const LinearSpace2<T>& a ) { return a.inverse(); }
////////////////////////////////////////////////////////////////////////////////
// Binary Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline LinearSpace2<T> operator +( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx+b.vx,a.vy+b.vy); }
template<typename T> __forceinline LinearSpace2<T> operator -( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return LinearSpace2<T>(a.vx-b.vx,a.vy-b.vy); }
template<typename T> __forceinline LinearSpace2<T> operator*(const typename T::Scalar & a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
template<typename T> __forceinline T operator*(const LinearSpace2<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy; }
template<typename T> __forceinline LinearSpace2<T> operator*(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return LinearSpace2<T>(a*b.vx, a*b.vy); }
template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const typename T::Scalar & b) { return LinearSpace2<T>(a.vx/b, a.vy/b); }
template<typename T> __forceinline LinearSpace2<T> operator/(const LinearSpace2<T>& a, const LinearSpace2<T>& b) { return a * rcp(b); }
template<typename T> __forceinline LinearSpace2<T>& operator *=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a * b; }
template<typename T> __forceinline LinearSpace2<T>& operator /=( LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline bool operator ==( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx == b.vx && a.vy == b.vy; }
template<typename T> __forceinline bool operator !=( const LinearSpace2<T>& a, const LinearSpace2<T>& b ) { return a.vx != b.vx || a.vy != b.vy; }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> static std::ostream& operator<<(std::ostream& cout, const LinearSpace2<T>& m) {
return cout << "{ vx = " << m.vx << ", vy = " << m.vy << "}";
}
/*! Shortcuts for common linear spaces. */
typedef LinearSpace2<Vec2f> LinearSpace2f;
}
+16 -45
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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
@@ -103,16 +103,13 @@ namespace embree
Vector vx,vy,vz;
};
#if !defined(__MIC__)
/*! compute transposed matrix */
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);
ssef rx,ry,rz; transpose((ssef&)vx,(ssef&)vy,(ssef&)vz,ssef(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
@@ -122,25 +119,15 @@ namespace embree
template<typename T> __forceinline LinearSpace3<T> operator +( const LinearSpace3<T>& a ) { return LinearSpace3<T>(+a.vx,+a.vy,+a.vz); }
template<typename T> __forceinline LinearSpace3<T> rcp ( const LinearSpace3<T>& a ) { return a.inverse(); }
/* 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 dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
const T dy = normalize(cross(N,dx));
/* constructs a coordinate frame form a normal */
template<typename T> __forceinline LinearSpace3<T> frame(const T& N) {
T dx0 = cross(T(one,zero,zero),N);
T dx1 = cross(T(zero,one,zero),N);
T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
T dy = normalize(cross(N,dx));
return LinearSpace3<T>(dx,dy,N);
}
/* constructs a coordinate frame from a normal and approximate x-direction */
template<typename T> __forceinline LinearSpace3<T> frame(const T& N, const T& dxi)
{
if (abs(dot(dxi,N)) > 0.99f) return frame(N); // fallback in case N and dxi are very parallel
const T dx = normalize(cross(dxi,N));
const T dy = normalize(cross(N,dx));
return LinearSpace3<T>(dx,dy,N);
}
/* clamps linear space to range -1 to +1 */
template<typename T> __forceinline LinearSpace3<T> clamp(const LinearSpace3<T>& space) {
return LinearSpace3<T>(clamp(space.vx,T(-1.0f),T(1.0f)),
@@ -156,7 +143,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 +163,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 +174,5 @@ namespace embree
/*! Shortcuts for common linear spaces. */
typedef LinearSpace3<Vec3f> LinearSpace3f;
typedef LinearSpace3<Vec3fa> LinearSpace3fa;
}
+91 -191
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,40 +16,17 @@
#pragma once
#include "../sys/platform.h"
#include "../sys/intrinsics.h"
#include "constants.h"
#include <cmath>
#include "sys/platform.h"
#include "sys/intrinsics.h"
#include <math.h>
#include <cmath>
#include <float.h>
#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; }
}
#endif
#endif
namespace embree
{
__forceinline bool isvalid ( const float& v ) {
return (v > -FLT_LARGE) & (v < +FLT_LARGE);
}
__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;
}
#if defined(__WIN32__)
__forceinline bool finite ( const float x ) { return _finite(x) != 0; }
#endif
@@ -57,54 +34,38 @@ 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 )
{
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
#if defined(__AVX2__)
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_fnmadd_ss(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))));
#endif
#ifndef __MIC__
__forceinline float rcp ( const float x )
{
const __m128 vx = _mm_set_ss(x);
const __m128 r = _mm_rcp_ps(vx);
return _mm_cvtss_f32(_mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), vx)));
}
__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,7 +85,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); }
__forceinline float frac ( const float x ) { return x-floor(x); }
#endif
__forceinline double abs ( const double x ) { return ::fabs(x); }
__forceinline double sign ( const double x ) { return x<0?-1.0:1.0; }
@@ -151,7 +112,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 +121,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 +129,30 @@ 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; }
__forceinline int min(int a, int b) { return a<b? a:b; }
__forceinline int64 min(int64 a, int64 b) { return a<b? a:b; }
__forceinline size_t min(size_t a, size_t b) { return a<b? a:b; }
#if !defined(__WIN32__)
__forceinline ssize_t min(ssize_t a, ssize_t b) { return a<b? a:b; }
#endif
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)); }
__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; }
__forceinline int max(int a, int b) { return a<b? b:a; }
__forceinline int64 max(int64 a, int64 b) { return a<b? b:a; }
__forceinline size_t max(size_t a, size_t b) { return a<b? b:a; }
#if !defined(__WIN32__)
__forceinline ssize_t max(ssize_t a, ssize_t b) { return a<b? b:a; }
#endif
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)); }
__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)); }
@@ -238,48 +169,22 @@ namespace embree
#else
__forceinline float madd ( const float a, const float b, const float c) { return a*b+c; }
__forceinline float msub ( const float a, const float b, const float c) { return a*b-c; }
__forceinline float nmadd ( const float a, const float b, const float c) { return -a*b+c;}
__forceinline float nmsub ( const float a, const float b, const float c) { return -a*b-c; }
__forceinline float nmadd ( const float a, const float b, const float c) { return -a*b-c;}
__forceinline float nmsub ( const float a, const float b, const float c) { return c-a*b; }
#endif
/*! random functions */
template<typename T> T random() { return T(0); }
#if defined(_WIN32)
template<> __forceinline int random() { return int(rand()) ^ (int(rand()) << 8) ^ (int(rand()) << 16); }
template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 8) ^ (uint32_t(rand()) << 16); }
#else
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); }
#if _WIN32
__forceinline double drand48() {
return double(rand())/double(RAND_MAX);
}
__forceinline void srand48(long seed) {
return srand(seed);
}
#endif
template<typename T> T random() { return T(0); }
template<> __forceinline int random() { return int(rand()); }
template<> __forceinline uint32 random() { return uint32(rand()); }
template<> __forceinline float random() { return random<uint32>()/float(RAND_MAX); }
template<> __forceinline double random() { return random<uint32>()/double(RAND_MAX); }
/*! selects */
__forceinline bool select(bool s, bool t , bool f) { return s ? t : f; }
__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)));
}
/*! exchange */
template<typename T> __forceinline void xchg ( T& a, T& b ) { const T tmp = a; a = b; b = tmp; }
@@ -301,62 +206,57 @@ 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);
}
#if _WIN32
__forceinline double drand48() {
return double(rand())/double(RAND_MAX);
}
#endif
}
+11 -11
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,32 +21,32 @@
namespace embree
{
/*! Oriented bounding box */
/*! Non-axis aligned bounds */
template<typename T>
struct OBBox
struct NAABBox
{
public:
__forceinline OBBox () {}
__forceinline NAABBox () {}
__forceinline OBBox (EmptyTy)
__forceinline NAABBox (EmptyTy)
: space(one), bounds(empty) {}
__forceinline OBBox (const BBox<T>& bounds)
__forceinline NAABBox (const BBox<T>& bounds)
: space(one), bounds(bounds) {}
__forceinline OBBox (const LinearSpace3<T>& space, const BBox<T>& bounds)
__forceinline NAABBox (const LinearSpace3<T>& space, const BBox<T>& bounds)
: space(space), bounds(bounds) {}
friend std::ostream& operator<<(std::ostream& cout, const OBBox& p) {
friend std::ostream& operator<<(std::ostream& cout, const NAABBox& p) {
return std::cout << "{ space = " << p.space << ", bounds = " << p.bounds << "}";
}
public:
LinearSpace3<T> space; //!< orthonormal transformation
BBox<T> bounds; //!< bounds in transformed space
BBox<T> bounds; //!< bounds in transformed space
};
typedef OBBox<Vec3f> OBBox3f;
typedef OBBox<Vec3fa> OBBox3fa;
typedef NAABBox<Vec3f> NAABBox3f;
typedef NAABBox<Vec3fa> NAABBox3fa;
}
+8 -7
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,12 +16,13 @@
#pragma once
#include "vec3.h"
#include "sys/platform.h"
#include "math/vec3.h"
namespace embree
{
////////////////////////////////////////////////////////////////
// Quaternion Struct
// Quaterion Struct
////////////////////////////////////////////////////////////////
template<typename T>
@@ -33,13 +34,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 +59,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;
};
}
+11 -45
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,8 @@
#pragma once
#include "math.h"
#include "sys/platform.h"
#include "math/math.h"
namespace embree
{
@@ -35,14 +36,15 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__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 Vec2( const Vec2& other ) { x = other.x; y = other.y; }
__forceinline Vec2 ( ) { }
__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; }
__forceinline explicit Vec2( const T& a ) : x(a), y(a) {}
__forceinline explicit Vec2( const T& x, const T& y ) : x(x), y(y) {}
__forceinline explicit Vec2( const T* const a, const ssize_t stride = 1 ) : x(a[0]), y(a[stride]) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
@@ -66,18 +68,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 ); }
@@ -88,20 +85,6 @@ 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) ); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
@@ -136,16 +119,10 @@ 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 dot ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.x + a.y*b.y; }
template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); }
template<typename T> __forceinline Vec2<T> normalize( const Vec2<T>& a ) { return a*rsqrt(dot(a,a)); }
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 ) {
const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) );
}
////////////////////////////////////////////////////////////////////////////////
/// Select
@@ -155,21 +132,10 @@ namespace embree
return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
}
template<typename T> __forceinline Vec2<T> select ( const Vec2<bool>& s, const Vec2<T>& t, const Vec2<T>& f ) {
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;
else return 1;
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
+79 -163
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,24 @@
#pragma once
#include "math.h"
#include "sys/platform.h"
#include "math/math.h"
#if defined __SSE__
#include "simd/sse.h"
#endif
#if defined __AVX__
#include "simd/avx.h"
#endif
#if defined __MIC__
#include "simd/sse_mic.h"
#endif
#if defined __MIC__
#include "simd/mic.h"
#endif
namespace embree
{
@@ -37,12 +54,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 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( 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; }
@@ -70,14 +87,10 @@ namespace embree
template<typename T> __forceinline Vec3<T> rcp ( const Vec3<T>& a ) { return Vec3<T>(rcp (a.x), rcp (a.y), rcp (a.z)); }
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 )
{
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> zero_fix( const Vec3<T>& a ) {
return Vec3<T>(select(a.x==0.0f,T(1E-10f),a.x),select(a.y==0.0f,T(1E-10f),a.y),select(a.z==0.0f,T(1E-10f),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 +115,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 a*b+c; }
template<typename T> __forceinline const Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return a*b-c; }
template<typename T> __forceinline const Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return -a*b-c;}
template<typename T> __forceinline const Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return c-a*b; }
////////////////////////////////////////////////////////////////////////////////
/// 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
@@ -144,6 +152,16 @@ namespace embree
return false;
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
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 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)); }
////////////////////////////////////////////////////////////////////////////////
/// Select
////////////////////////////////////////////////////////////////////////////////
@@ -156,29 +174,22 @@ 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;
}
}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline Vec3<bool> eq_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x==b.x,a.y==b.y,a.z==b.z); }
template<typename T> __forceinline Vec3<bool> neq_mask(const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x!=b.x,a.y!=b.y,a.z!=b.z); }
template<typename T> __forceinline Vec3<bool> lt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x< b.x,a.y< b.y,a.z< b.z); }
@@ -186,54 +197,6 @@ namespace embree
template<typename T> __forceinline Vec3<bool> gt_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x> b.x,a.y> b.y,a.z> b.z); }
template<typename T> __forceinline Vec3<bool> ge_mask( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<bool>(a.x>=b.x,a.y>=b.y,a.z>=b.z); }
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
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 )
{
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 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));
}
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 area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
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,93 +210,46 @@ namespace embree
typedef Vec3<float> Vec3f;
}
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
////////////////////////////////////////////////////////////////////////////////
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
#if defined __SSE__
#include "../simd/sse.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
#if defined __AVX__
#include "../simd/avx.h"
#endif
namespace embree
{
template<> __forceinline Vec3<float>::Vec3( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; }
#if defined(__AVX512F__)
#include "../simd/avx512.h"
#endif
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]));
#if defined (__SSE__)
template<> __forceinline Vec3<ssef>::Vec3( const Vec3fa& a ) {
const ssef v = ssef(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
}
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;
}
#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]));
}
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]));
}
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));
__forceinline Vec3<ssef> broadcast4f( const Vec3<ssef>& a, const size_t k ) {
return Vec3<ssef>(ssef::broadcast(&a.x[k]), ssef::broadcast(&a.y[k]), ssef::broadcast(&a.z[k]));
}
#endif
#if defined(__AVX__)
template<>
__forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
x = a.x; y = a.y; z = a.z;
template<> __forceinline Vec3<avxf>::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<ssef> broadcast4f( const Vec3<avxf>& a, const size_t k ) {
return Vec3<ssef>(ssef::broadcast(&a.x[k]), ssef::broadcast(&a.y[k]), ssef::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<avxf> broadcast8f( const Vec3<ssef>& a, const size_t k ) {
return Vec3<avxf>(avxf::broadcast(&a.x[k]), avxf::broadcast(&a.y[k]), avxf::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]));
}
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]));
}
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]));
}
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));
__forceinline Vec3<avxf> broadcast8f( const Vec3<avxf>& a, const size_t k ) {
return Vec3<avxf>(avxf::broadcast(&a.x[k]), avxf::broadcast(&a.y[k]), avxf::broadcast(&a.z[k]));
}
#endif
#if defined(__AVX512F__)
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
#if defined(__MIC__)
template<> __forceinline Vec3<ssef>::Vec3( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z) {}
template<> __forceinline Vec3<mic_f>::Vec3( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z) {}
#endif
}
+13 -16
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,9 +16,8 @@
#pragma once
#include "../sys/alloc.h"
#include "simd/sse.h"
#include "math.h"
#include "../simd/sse.h"
namespace embree
{
@@ -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(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
+117
View File
@@ -0,0 +1,117 @@
// ======================================================================== //
// Copyright 2009-2014 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"
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") << ")";
}
}
+72 -150
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,9 +16,8 @@
#pragma once
#include "../sys/alloc.h"
#include "simd/sse.h"
#include "math.h"
#include "../simd/sse.h"
namespace embree
{
@@ -28,8 +27,6 @@ namespace embree
struct __aligned(16) Vec3fa
{
ALIGNED_STRUCT;
typedef float Scalar;
enum { N = 3 };
union {
@@ -48,45 +45,22 @@ namespace embree
__forceinline Vec3fa& operator =( const Vec3<float>& other ) { x = other.x; y = other.y; z = other.z; return *this; }
__forceinline Vec3fa ( const Vec3fa& other ) { m128 = other.m128; }
__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 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 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; a = 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) {}
__forceinline explicit Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), a(a) {}
__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; }
#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)); }
#else
friend __forceinline 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 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);
}
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -104,66 +78,41 @@ 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 _mm_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)));
#else
const Vec3fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(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;
return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
}
__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 const Vec3fa zero_fix(const Vec3fa& a) { return _mm_blendv_ps(a, _mm_set1_ps(1E-10f), _mm_cmpeq_ps (a.m128, _mm_setzero_ps())); }
__forceinline const Vec3fa rcp_safe(const Vec3fa& a) { return rcp(zero_fix(a)); }
__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 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 +120,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 ssei ai = _mm_castps_si128(a);
const ssei bi = _mm_castps_si128(b);
const ssei 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 ssei ai = _mm_castps_si128(a);
const ssei bi = _mm_castps_si128(b);
const ssei 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));
}
@@ -217,15 +166,10 @@ namespace embree
#else
__forceinline Vec3fa madd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b+c; }
__forceinline Vec3fa msub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return a*b-c; }
__forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b+c;}
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
__forceinline Vec3fa nmadd ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c;}
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return c-a*b; }
#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
////////////////////////////////////////////////////////////////////////////////
@@ -260,14 +204,6 @@ namespace embree
__forceinline Vec3ba gt_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
__forceinline Vec3ba ge_mask( const Vec3fa& a, const Vec3fa& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
__forceinline bool isvalid ( const Vec3fa& v ) {
return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
}
__forceinline bool is_finite ( const Vec3fa& a ) {
return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
@@ -282,56 +218,40 @@ 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);
ssef a0 = ssef(a);
ssef b0 = shuffle<1,2,0,3>(ssef(b));
ssef a1 = shuffle<1,2,0,3>(ssef(a));
ssef b1 = ssef(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 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 area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
__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);
}
__forceinline float halfArea ( const Vec3fa& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
__forceinline Vec3fa reflect (const Vec3fa& V, const Vec3fa& N) { return 2.0f*dot(V,N)*N-V; }
////////////////////////////////////////////////////////////////////////////////
/// 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);
return _mm_blendv_ps(f, t, mask);
}
__forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
return blendv_ps(f, t, s);
__forceinline const Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
return _mm_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 +260,15 @@ 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)); }
#if !defined(__WIN32__)
__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
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -356,6 +278,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;
}
+258
View File
@@ -0,0 +1,258 @@
// ======================================================================== //
// Copyright 2009-2014 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"
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 ( 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( 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; }
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);
}
};
////////////////////////////////////////////////////////////////////////////////
/// 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; }
////////////////////////////////////////////////////////////////////////////////
/// 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); }
////////////////////////////////////////////////////////////////////////////////
/// 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); }
////////////////////////////////////////////////////////////////////////////////
/// 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 << ")";
}
}
+43 -47
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,9 +16,8 @@
#pragma once
#include "../sys/alloc.h"
#include "simd/sse.h"
#include "math.h"
#include "../simd/sse.h"
namespace embree
{
@@ -28,8 +27,6 @@ namespace embree
struct __aligned(16) Vec3ia
{
ALIGNED_STRUCT;
union {
__m128i m128;
struct { int x,y,z; int a; };
@@ -47,12 +44,12 @@ namespace embree
__forceinline Vec3ia( const Vec3ia& other ) : m128(other.m128) {}
__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 Vec3ia( const int a ) : m128(_mm_set1_epi32(a)) {}
__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,72 +73,71 @@ 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
////////////////////////////////////////////////////////////////////////////////
__forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia& b ) { return a = a + b; }
__forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
__forceinline Vec3ia& operator +=( Vec3ia& a, const int32& b ) { return a = a + b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia& b ) { return a = a - b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const int32& b ) { return a = a - b; }
#if defined(__SSE4_1__)
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia& b ) { return a = a * b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const int32& b ) { return a = a * b; }
#endif
__forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia& b ) { return a = a & b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const int32& b ) { return a = a & b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia& b ) { return a = a | b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const int32& 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 int32& b ) { return a = a << b; }
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int32& b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Reductions
@@ -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
////////////////////////////////////////////////////////////////////////////////
+229
View File
@@ -0,0 +1,229 @@
// ======================================================================== //
// Copyright 2009-2014 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"
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 int32& b ) { return a = a + b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia_t& b ) { return a = a - b; }
__forceinline Vec3ia& operator -=( Vec3ia& a, const int32& b ) { return a = a - b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia_t& b ) { return a = a * b; }
__forceinline Vec3ia& operator *=( Vec3ia& a, const int32& b ) { return a = a * b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia_t& b ) { return a = a & b; }
__forceinline Vec3ia& operator &=( Vec3ia& a, const int32& b ) { return a = a & b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia_t& b ) { return a = a | b; }
__forceinline Vec3ia& operator |=( Vec3ia& a, const int32& b ) { return a = a | b; }
__forceinline Vec3ia& operator <<=( Vec3ia& a, const int32& b ) { return a = a << b; }
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int32& 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 << ")";
}
}
+35 -96
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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 @@
#pragma once
#include "math.h"
#include "vec3.h"
#include "sys/platform.h"
namespace embree
{
@@ -36,18 +35,16 @@ namespace embree
/// Construction
////////////////////////////////////////////////////////////////////////////////
__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 Vec4( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
__forceinline Vec4( const Vec3fa& other );
__forceinline Vec4 ( ) { }
__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); }
__forceinline explicit Vec4( const T& a ) : x(a), y(a), z(a), w(a) {}
__forceinline explicit Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
__forceinline explicit Vec4( const T* const a, const size_t stride = 1 ) : x(a[0]), y(a[stride]), z(a[2*stride]), w(a[3*stride]) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
@@ -60,12 +57,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 +86,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,20 +118,11 @@ 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
////////////////////////////////////////////////////////////////////////////////
template<typename T> __forceinline T dot ( const Vec4<T>& a, const Vec4<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,madd(a.z,b.z,a.w*b.w))); }
template<typename T> __forceinline T dot ( const Vec4<T>& a, const Vec4<T>& b ) { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; }
template<typename T> __forceinline T length ( const Vec4<T>& a ) { return sqrt(dot(a,a)); }
template<typename T> __forceinline Vec4<T> normalize( const Vec4<T>& a ) { return a*rsqrt(dot(a,a)); }
template<typename T> __forceinline T distance ( const Vec4<T>& a, const Vec4<T>& b ) { return length(a-b); }
@@ -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,62 +153,46 @@ namespace embree
typedef Vec4<float > Vec4f;
}
#include "vec3ba.h"
#include "vec3ia.h"
#include "vec3fa.h"
////////////////////////////////////////////////////////////////////////////////
/// SSE / AVX / MIC specializations
////////////////////////////////////////////////////////////////////////////////
#if defined __SSE__
#include "../simd/sse.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
#if defined __AVX__
#include "../simd/avx.h"
#endif
#if defined __AVX512F__
#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<ssef>::Vec4( const Vec3fa& a ) {
const ssef v = ssef(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<ssef> broadcast4f( const Vec4<ssef>& a, const size_t k ) {
return Vec4<ssef>(ssef::broadcast(&a.x[k]), ssef::broadcast(&a.y[k]), ssef::broadcast(&a.z[k]), ssef::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<avxf>::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<ssef> broadcast4f( const Vec4<avxf>& a, const size_t k ) {
return Vec4<ssef>(ssef::broadcast(&a.x[k]), ssef::broadcast(&a.y[k]), ssef::broadcast(&a.z[k]), ssef::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<avxf> broadcast8f( const Vec4<ssef>& a, const size_t k ) {
return Vec4<avxf>(avxf::broadcast(&a.x[k]), avxf::broadcast(&a.y[k]), avxf::broadcast(&a.z[k]), avxf::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<avxf> broadcast8f( const Vec4<avxf>& a, const size_t k ) {
return Vec4<avxf>(avxf::broadcast(&a.x[k]), avxf::broadcast(&a.y[k]), avxf::broadcast(&a.z[k]), avxf::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<ssef>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
template<> __forceinline Vec4<mic_f>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
#endif
}
+7 -3
View File
@@ -1,5 +1,5 @@
## ======================================================================== ##
## Copyright 2009-2017 Intel Corporation ##
## Copyright 2009-2014 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,10 @@
## 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)
ELSE ()
INCLUDE(icc_xeonphi)
ADD_LIBRARY(simd_xeonphi STATIC mic_i.cpp mic_f.cpp mic_m.cpp)
ENDIF ()
+14 -25
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,30 +16,19 @@
#pragma once
#include "sse.h"
#include "simd/sse.h"
#if defined(__AVX512VL__)
#include "vboolf8_avx512.h"
#include "vboold4_avx512.h"
namespace embree
{
struct avxb;
struct avxi;
struct avxf;
}
#include "simd/avxb.h"
#if defined (__AVX2__)
#include "simd/avxi.h"
#else
#include "vboolf8_avx.h"
#include "vboold4_avx.h"
#include "simd/avxi_emu.h"
#endif
#if defined(__AVX2__)
#include "vint8_avx2.h"
#if defined(__X86_64__)
#include "vllong4_avx2.h"
#endif
#else
#include "vint8_avx.h"
#endif
#include "vfloat8_avx.h"
#if defined(__X86_64__)
#include "vdouble4_avx.h"
#endif
#if defined(__AVX512F__)
#include "avx512.h"
#endif
#include "simd/avxf.h"
-53
View File
@@ -1,53 +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 "../sys/intrinsics.h"
#include "../math/constants.h"
#include "varying.h"
#include "vboolf16_avx512.h"
#include "vint16_avx512.h"
#include "vfloat16_avx512.h"
#include "vuint16_avx512.h"
#include "vboold8_avx512.h"
#include "vllong8_avx512.h"
#include "vdouble8_avx512.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// Prefetching
////////////////////////////////////////////////////////////////////////////////
#define PFHINT_L1 0
#define PFHINT_L2 1
#define PFHINT_NT 2
template<const unsigned int mode>
__forceinline void prefetch(const void * __restrict__ const m)
{
if (mode == PFHINT_L1)
_mm_prefetch((const char*)m,_MM_HINT_T0);
else if (mode == PFHINT_L2)
_mm_prefetch((const char*)m,_MM_HINT_T1);
else if (mode == PFHINT_NT)
_mm_prefetch((const char*)m,_MM_HINT_NTA);
}
}
+172
View File
@@ -0,0 +1,172 @@
// ======================================================================== //
// Copyright 2009-2014 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 avxb
{
typedef avxb Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256 m256;
struct { __m128 l,h; };
int32 v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxb () {}
__forceinline avxb ( const avxb& a ) { m256 = a.m256; }
__forceinline avxb& operator=( const avxb& a ) { m256 = a.m256; return *this; }
__forceinline avxb( 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 avxb ( 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 avxb ( const sseb& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
__forceinline avxb ( const sseb& a, const sseb& b) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
__forceinline avxb ( const __m128 a, const __m128 b) : l(a), h(b) {}
__forceinline avxb ( bool a ) : m256(avxb(sseb(a), sseb(a))) {}
__forceinline avxb ( bool a, bool b) : m256(avxb(sseb(a), sseb(b))) {}
__forceinline avxb ( bool a, bool b, bool c, bool d) : m256(avxb(sseb(a,b), sseb(c,d))) {}
__forceinline avxb ( bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h ) : m256(avxb(sseb(a,b,c,d), sseb(e,f,g,h))) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline avxb( FalseTy ) : m256(_mm256_setzero_ps()) {}
__forceinline avxb( 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 int32& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator !( const avxb& a ) { return _mm256_xor_ps(a, avxb(True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator &( const avxb& a, const avxb& b ) { return _mm256_and_ps(a, b); }
__forceinline const avxb operator |( const avxb& a, const avxb& b ) { return _mm256_or_ps (a, b); }
__forceinline const avxb operator ^( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
__forceinline avxb operator &=( avxb& a, const avxb& b ) { return a = a & b; }
__forceinline avxb operator |=( avxb& a, const avxb& b ) { return a = a | b; }
__forceinline avxb operator ^=( avxb& a, const avxb& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator !=( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
__forceinline const avxb operator ==( const avxb& a, const avxb& b ) { return _mm256_xor_ps(_mm256_xor_ps(a,b),avxb(True)); }
__forceinline const avxb select( const avxb& mask, const avxb& t, const avxb& f ) {
return _mm256_blendv_ps(f, t, mask);
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline avxb unpacklo( const avxb& a, const avxb& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
__forceinline avxb unpackhi( const avxb& a, const avxb& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
template<size_t i> __forceinline const avxb shuffle( const avxb& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
}
template<size_t i0, size_t i1> __forceinline const avxb shuffle( const avxb& a ) {
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const avxb shuffle( const avxb& a, const avxb& 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 avxb shuffle( const avxb& 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 avxb shuffle( const avxb& a, const avxb& b ) {
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<> __forceinline const avxb shuffle<0, 0, 2, 2>( const avxb& b ) { return _mm256_moveldup_ps(b); }
template<> __forceinline const avxb shuffle<1, 1, 3, 3>( const avxb& b ) { return _mm256_movehdup_ps(b); }
template<> __forceinline const avxb shuffle<0, 1, 0, 1>( const avxb& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
template<size_t i> __forceinline const avxb insert (const avxb& a, const sseb& b) { return _mm256_insertf128_ps (a,b,i); }
template<size_t i> __forceinline const sseb extract(const avxb& a ) { return _mm256_extractf128_ps(a ,i); }
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const avxb& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool reduce_or ( const avxb& a ) { return !_mm256_testz_ps(a,a); }
__forceinline bool all ( const avxb& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
__forceinline bool any ( const avxb& a ) { return !_mm256_testz_ps(a,a); }
__forceinline bool none ( const avxb& a ) { return _mm256_testz_ps(a,a) != 0; }
__forceinline bool all ( const avxb& valid, const avxb& b ) { return all(!valid | b); }
__forceinline bool any ( const avxb& valid, const avxb& b ) { return any( valid & b); }
__forceinline bool none ( const avxb& valid, const avxb& b ) { return none(valid & b); }
__forceinline unsigned int movemask( const avxb& a ) { return _mm256_movemask_ps(a); }
__forceinline size_t popcnt ( const avxb& a ) { return __popcnt(_mm256_movemask_ps(a)); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const avxb& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+424
View File
@@ -0,0 +1,424 @@
// ======================================================================== //
// Copyright 2009-2014 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 float type. */
struct avxf
{
typedef avxb Mask; // mask type for us
typedef avxi Int ; // int type for us
enum { size = 8 }; // number of SIMD elements
union { __m256 m256; float v[8]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf ( ) {}
__forceinline avxf ( const avxf& other ) { m256 = other.m256; }
__forceinline avxf& operator=( const avxf& other ) { m256 = other.m256; return *this; }
__forceinline avxf( const __m256 a ) : m256(a) {}
__forceinline operator const __m256&( void ) const { return m256; }
__forceinline operator __m256&( void ) { return m256; }
__forceinline explicit avxf( const ssef& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
__forceinline avxf( const ssef& a, const ssef& b ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
static __forceinline avxf load( const void* const ptr ) { return *(__m256*)ptr; }
__forceinline explicit avxf( const char* const a ) : m256(_mm256_loadu_ps((const float*)a)) {}
__forceinline avxf( const float& a ) : m256(_mm256_broadcast_ss(&a)) {}
__forceinline avxf( float a, float b) : m256(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
__forceinline avxf( float a, float b, float c, float d ) : m256(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
__forceinline avxf( 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 avxf( const __m256i a ) : m256(_mm256_cvtepi32_ps(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf( ZeroTy ) : m256(_mm256_setzero_ps()) {}
__forceinline avxf( OneTy ) : m256(_mm256_set1_ps(1.0f)) {}
__forceinline avxf( PosInfTy ) : m256(_mm256_set1_ps(pos_inf)) {}
__forceinline avxf( NegInfTy ) : m256(_mm256_set1_ps(neg_inf)) {}
__forceinline avxf( StepTy ) : m256(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
__forceinline avxf( NaNTy ) : m256(_mm256_set1_ps(nan)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
static __forceinline avxf broadcast( const void* const a ) {
return _mm256_broadcast_ss((float*)a);
}
////////////////////////////////////////////////////////////////////////////////
/// 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 avxf cast (const avxi& a ) { return _mm256_castsi256_ps(a); }
__forceinline const avxi cast (const avxf& a ) { return _mm256_castps_si256(a); }
__forceinline const avxf operator +( const avxf& a ) { return a; }
__forceinline const avxf operator -( const avxf& a ) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
return _mm256_xor_ps(a.m256, mask);
}
__forceinline const avxf abs ( const avxf& a ) {
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
return _mm256_and_ps(a.m256, mask);
}
__forceinline const avxf sign ( const avxf& a ) { return _mm256_blendv_ps(avxf(one), -avxf(one), _mm256_cmp_ps(a, avxf(zero), _CMP_NGE_UQ )); }
__forceinline const avxf signmsk ( const avxf& a ) { return _mm256_and_ps(a.m256,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
__forceinline const avxf rcp ( const avxf& a ) {
const avxf r = _mm256_rcp_ps(a.m256);
return _mm256_sub_ps(_mm256_add_ps(r, r), _mm256_mul_ps(_mm256_mul_ps(r, r), a));
}
__forceinline const avxf sqr ( const avxf& a ) { return _mm256_mul_ps(a,a); }
__forceinline const avxf sqrt ( const avxf& a ) { return _mm256_sqrt_ps(a.m256); }
__forceinline const avxf rsqrt( const avxf& a ) {
const avxf 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 avxf operator +( const avxf& a, const avxf& b ) { return _mm256_add_ps(a.m256, b.m256); }
__forceinline const avxf operator +( const avxf& a, const float b ) { return a + avxf(b); }
__forceinline const avxf operator +( const float a, const avxf& b ) { return avxf(a) + b; }
__forceinline const avxf operator -( const avxf& a, const avxf& b ) { return _mm256_sub_ps(a.m256, b.m256); }
__forceinline const avxf operator -( const avxf& a, const float b ) { return a - avxf(b); }
__forceinline const avxf operator -( const float a, const avxf& b ) { return avxf(a) - b; }
__forceinline const avxf operator *( const avxf& a, const avxf& b ) { return _mm256_mul_ps(a.m256, b.m256); }
__forceinline const avxf operator *( const avxf& a, const float b ) { return a * avxf(b); }
__forceinline const avxf operator *( const float a, const avxf& b ) { return avxf(a) * b; }
__forceinline const avxf operator /( const avxf& a, const avxf& b ) { return _mm256_div_ps(a.m256, b.m256); }
__forceinline const avxf operator /( const avxf& a, const float b ) { return a / avxf(b); }
__forceinline const avxf operator /( const float a, const avxf& b ) { return avxf(a) / b; }
__forceinline const avxf operator^( const avxf& a, const avxf& b ) { return _mm256_xor_ps(a.m256,b.m256); }
__forceinline const avxf operator^( const avxf& a, const avxi& b ) { return _mm256_xor_ps(a.m256,_mm256_castsi256_ps(b.m256)); }
__forceinline const avxf operator&( const avxf& a, const avxf& b ) { return _mm256_and_ps(a.m256,b.m256); }
__forceinline const avxf min( const avxf& a, const avxf& b ) { return _mm256_min_ps(a.m256, b.m256); }
__forceinline const avxf min( const avxf& a, const float b ) { return _mm256_min_ps(a.m256, avxf(b)); }
__forceinline const avxf min( const float a, const avxf& b ) { return _mm256_min_ps(avxf(a), b.m256); }
__forceinline const avxf max( const avxf& a, const avxf& b ) { return _mm256_max_ps(a.m256, b.m256); }
__forceinline const avxf max( const avxf& a, const float b ) { return _mm256_max_ps(a.m256, avxf(b)); }
__forceinline const avxf max( const float a, const avxf& b ) { return _mm256_max_ps(avxf(a), b.m256); }
#if defined (__AVX2__)
__forceinline avxf mini(const avxf& a, const avxf& b) {
const avxi ai = _mm256_castps_si256(a);
const avxi bi = _mm256_castps_si256(b);
const avxi ci = _mm256_min_epi32(ai,bi);
return _mm256_castsi256_ps(ci);
}
__forceinline avxf maxi(const avxf& a, const avxf& b) {
const avxi ai = _mm256_castps_si256(a);
const avxi bi = _mm256_castps_si256(b);
const avxi ci = _mm256_max_epi32(ai,bi);
return _mm256_castsi256_ps(ci);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX2__)
__forceinline const avxf madd ( const avxf& a, const avxf& b, const avxf& c) { return _mm256_fmadd_ps(a,b,c); }
__forceinline const avxf msub ( const avxf& a, const avxf& b, const avxf& c) { return _mm256_fmsub_ps(a,b,c); }
__forceinline const avxf nmadd ( const avxf& a, const avxf& b, const avxf& c) { return _mm256_fnmadd_ps(a,b,c); }
__forceinline const avxf nmsub ( const avxf& a, const avxf& b, const avxf& c) { return _mm256_fnmsub_ps(a,b,c); }
#else
__forceinline const avxf madd ( const avxf& a, const avxf& b, const avxf& c) { return a*b+c; }
__forceinline const avxf msub ( const avxf& a, const avxf& b, const avxf& c) { return a*b-c; }
__forceinline const avxf nmadd ( const avxf& a, const avxf& b, const avxf& c) { return -a*b-c;}
__forceinline const avxf nmsub ( const avxf& a, const avxf& b, const avxf& c) { return c-a*b; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf& operator +=( avxf& a, const avxf& b ) { return a = a + b; }
__forceinline avxf& operator +=( avxf& a, const float b ) { return a = a + b; }
__forceinline avxf& operator -=( avxf& a, const avxf& b ) { return a = a - b; }
__forceinline avxf& operator -=( avxf& a, const float b ) { return a = a - b; }
__forceinline avxf& operator *=( avxf& a, const avxf& b ) { return a = a * b; }
__forceinline avxf& operator *=( avxf& a, const float b ) { return a = a * b; }
__forceinline avxf& operator /=( avxf& a, const avxf& b ) { return a = a / b; }
__forceinline avxf& operator /=( avxf& a, const float b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator ==( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_EQ_OQ ); }
__forceinline const avxb operator ==( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_EQ_OQ ); }
__forceinline const avxb operator ==( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_EQ_OQ ); }
__forceinline const avxb operator !=( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_NEQ_OQ); }
__forceinline const avxb operator !=( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_NEQ_OQ); }
__forceinline const avxb operator !=( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_NEQ_OQ); }
__forceinline const avxb operator < ( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LT_OQ ); }
__forceinline const avxb operator < ( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_LT_OQ ); }
__forceinline const avxb operator < ( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_LT_OQ ); }
__forceinline const avxb operator >=( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GE_OQ); }
__forceinline const avxb operator >=( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_GE_OQ); }
__forceinline const avxb operator >=( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_GE_OQ); }
__forceinline const avxb operator > ( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GT_OQ); }
__forceinline const avxb operator > ( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_GT_OQ); }
__forceinline const avxb operator > ( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_GT_OQ); }
__forceinline const avxb operator <=( const avxf& a, const avxf& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LE_OQ ); }
__forceinline const avxb operator <=( const avxf& a, const float b ) { return _mm256_cmp_ps(a.m256, avxf(b), _CMP_LE_OQ ); }
__forceinline const avxb operator <=( const float a, const avxf& b ) { return _mm256_cmp_ps(avxf(a), b.m256, _CMP_LE_OQ ); }
__forceinline const avxf select( const avxb& m, const avxf& t, const avxf& f ) {
return _mm256_blendv_ps(f, t, m);
}
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
__forceinline const avxf select(const int m, const avxf& t, const avxf& f) {
return select(avxb(m), t, f); // workaround for clang and Microsoft compiler bugs
}
#else
__forceinline const avxf select( const int m, const avxf& t, const avxf& f ) {
return _mm256_blend_ps(f, t, m);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxf round_even( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
__forceinline const avxf round_down( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const avxf round_up ( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline const avxf round_zero( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
__forceinline const avxf floor ( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const avxf ceil ( const avxf& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf unpacklo( const avxf& a, const avxf& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
__forceinline avxf unpackhi( const avxf& a, const avxf& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
template<size_t i> __forceinline const avxf shuffle( const avxf& a ) {
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
}
template<size_t i0, size_t i1> __forceinline const avxf shuffle( const avxf& a ) {
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const avxf shuffle( const avxf& a, const avxf& 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 avxf shuffle( const avxf& 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 avxf shuffle( const avxf& a, const avxf& b ) {
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
template<> __forceinline const avxf shuffle<0, 0, 2, 2>( const avxf& b ) { return _mm256_moveldup_ps(b); }
template<> __forceinline const avxf shuffle<1, 1, 3, 3>( const avxf& b ) { return _mm256_movehdup_ps(b); }
template<> __forceinline const avxf shuffle<0, 1, 0, 1>( const avxf& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
__forceinline const avxf broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
template<size_t i> __forceinline const avxf insert (const avxf& a, const ssef& b) { return _mm256_insertf128_ps (a,b,i); }
template<size_t i> __forceinline const ssef extract (const avxf& a ) { return _mm256_extractf128_ps(a ,i); }
template<> __forceinline const ssef extract<0>(const avxf& a ) { return _mm256_castps256_ps128(a); }
template<size_t i> __forceinline float fextract (const avxf& a ) { return _mm_cvtss_f32(_mm256_extractf128_ps(a ,i)); }
#if defined (__AVX2__)
__forceinline avxf permute(const avxf &a, const __m256i &index) {
return _mm256_permutevar8x32_ps(a,index);
}
template<int i>
__forceinline avxf alignr(const avxf &a, const avxf &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 ssei convert_to_hf16(const avxf &a) {
return _mm256_cvtps_ph(a,mode);
}
__forceinline avxf convert_from_hf16(const ssei &a) {
return _mm256_cvtph_ps(a);
}
#endif
__forceinline ssef broadcast4f( const avxf& a, const size_t k ) {
return ssef::broadcast(&a[k]);
}
__forceinline avxf broadcast8f( const avxf& a, const size_t k ) {
return avxf::broadcast(&a[k]);
}
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
__forceinline void transpose4(const avxf& r0, const avxf& r1, const avxf& r2, const avxf& r3, avxf& c0, avxf& c1, avxf& c2, avxf& c3)
{
avxf l02 = unpacklo(r0,r2);
avxf h02 = unpackhi(r0,r2);
avxf l13 = unpacklo(r1,r3);
avxf h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
c3 = unpackhi(h02,h13);
}
__forceinline void transpose(const avxf& r0, const avxf& r1, const avxf& r2, const avxf& r3, const avxf& r4, const avxf& r5, const avxf& r6, const avxf& r7,
avxf& c0, avxf& c1, avxf& c2, avxf& c3, avxf& c4, avxf& c5, avxf& c6, avxf& c7)
{
avxf h0,h1,h2,h3; transpose4(r0,r1,r2,r3,h0,h1,h2,h3);
avxf h4,h5,h6,h7; transpose4(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 avxf vreduce_min2(const avxf& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxf vreduce_min4(const avxf& v) { avxf v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxf vreduce_min (const avxf& v) { avxf v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const avxf vreduce_max2(const avxf& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxf vreduce_max4(const avxf& v) { avxf v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxf vreduce_max (const avxf& v) { avxf v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const avxf vreduce_add2(const avxf& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const avxf vreduce_add4(const avxf& v) { avxf v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const avxf vreduce_add (const avxf& v) { avxf v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline float reduce_min(const avxf& v) { return _mm_cvtss_f32(extract<0>(vreduce_min(v))); }
__forceinline float reduce_max(const avxf& v) { return _mm_cvtss_f32(extract<0>(vreduce_max(v))); }
__forceinline float reduce_add(const avxf& v) { return _mm_cvtss_f32(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const avxf& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const avxf& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const avxb& valid, const avxf& v) { const avxf a = select(valid,v,avxf(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const avxb& valid, const avxf& v) { const avxf a = select(valid,v,avxf(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf load8f( const void* const a) {
return _mm256_load_ps((const float*)a);
}
__forceinline void store8f(void *ptr, const avxf& f ) {
return _mm256_store_ps((float*)ptr,f);
}
__forceinline void store8f( const avxb& mask, void *ptr, const avxf& f ) {
return _mm256_maskstore_ps((float*)ptr,(__m256i)mask,f);
}
#if defined (__AVX2__)
__forceinline avxf load8f_nt(void* ptr) {
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
}
#endif
__forceinline void store8f_nt(void* ptr, const avxf& v) {
_mm256_stream_ps((float*)ptr,v);
}
__forceinline const avxf broadcast4f(const void* ptr) {
return _mm256_broadcast_ps((__m128*)ptr);
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxf dot ( const avxf& a, const avxf& b ) {
return vreduce_add4(a*b);
}
__forceinline avxf cross ( const avxf& a, const avxf& b )
{
const avxf a0 = a;
const avxf b0 = shuffle<1,2,0,3>(b);
const avxf a1 = shuffle<1,2,0,3>(a);
const avxf b1 = b;
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const avxf& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+289
View File
@@ -0,0 +1,289 @@
// ======================================================================== //
// Copyright 2009-2014 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 avxi
{
typedef avxb Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256i m256;
int32 v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi ( ) {}
__forceinline avxi ( const avxi& a ) { m256 = a.m256; }
__forceinline avxi& operator=( const avxi& a ) { m256 = a.m256; return *this; }
__forceinline avxi( const __m256i a ) : m256(a) {}
__forceinline operator const __m256i&( void ) const { return m256; }
__forceinline operator __m256i&( void ) { return m256; }
__forceinline explicit avxi( const ssei& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
__forceinline avxi( const ssei& a, const ssei& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline avxi( const __m128i& a, const __m128i& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline explicit avxi ( const int32* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
__forceinline avxi ( int32 a ) : m256(_mm256_set1_epi32(a)) {}
__forceinline avxi ( int32 a, int32 b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
__forceinline avxi ( int32 a, int32 b, int32 c, int32 d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
__forceinline avxi ( int32 a, int32 b, int32 c, int32 d, int32 e, int32 f, int32 g, int32 h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
__forceinline explicit avxi( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi( ZeroTy ) : m256(_mm256_setzero_si256()) {}
__forceinline avxi( OneTy ) : m256(_mm256_set1_epi32(1)) {}
__forceinline avxi( PosInfTy ) : m256(_mm256_set1_epi32(pos_inf)) {}
__forceinline avxi( NegInfTy ) : m256(_mm256_set1_epi32(neg_inf)) {}
__forceinline avxi( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int32& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
__forceinline int32& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi operator +( const avxi& a ) { return a; }
__forceinline const avxi operator -( const avxi& a ) { return _mm256_sub_epi32(_mm256_setzero_si256(), a.m256); }
__forceinline const avxi abs ( const avxi& a ) { return _mm256_abs_epi32(a.m256); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi operator +( const avxi& a, const avxi& b ) { return _mm256_add_epi32(a.m256, b.m256); }
__forceinline const avxi operator +( const avxi& a, const int32 b ) { return a + avxi(b); }
__forceinline const avxi operator +( const int32 a, const avxi& b ) { return avxi(a) + b; }
__forceinline const avxi operator -( const avxi& a, const avxi& b ) { return _mm256_sub_epi32(a.m256, b.m256); }
__forceinline const avxi operator -( const avxi& a, const int32 b ) { return a - avxi(b); }
__forceinline const avxi operator -( const int32 a, const avxi& b ) { return avxi(a) - b; }
__forceinline const avxi operator *( const avxi& a, const avxi& b ) { return _mm256_mullo_epi32(a.m256, b.m256); }
__forceinline const avxi operator *( const avxi& a, const int32 b ) { return a * avxi(b); }
__forceinline const avxi operator *( const int32 a, const avxi& b ) { return avxi(a) * b; }
__forceinline const avxi operator &( const avxi& a, const avxi& b ) { return _mm256_and_si256(a.m256, b.m256); }
__forceinline const avxi operator &( const avxi& a, const int32 b ) { return a & avxi(b); }
__forceinline const avxi operator &( const int32 a, const avxi& b ) { return avxi(a) & b; }
__forceinline const avxi operator |( const avxi& a, const avxi& b ) { return _mm256_or_si256(a.m256, b.m256); }
__forceinline const avxi operator |( const avxi& a, const int32 b ) { return a | avxi(b); }
__forceinline const avxi operator |( const int32 a, const avxi& b ) { return avxi(a) | b; }
__forceinline const avxi operator ^( const avxi& a, const avxi& b ) { return _mm256_xor_si256(a.m256, b.m256); }
__forceinline const avxi operator ^( const avxi& a, const int32 b ) { return a ^ avxi(b); }
__forceinline const avxi operator ^( const int32 a, const avxi& b ) { return avxi(a) ^ b; }
__forceinline const avxi operator <<( const avxi& a, const int32 n ) { return _mm256_slli_epi32(a.m256, n); }
__forceinline const avxi operator >>( const avxi& a, const int32 n ) { return _mm256_srai_epi32(a.m256, n); }
__forceinline const avxi sra ( const avxi& a, const int32 b ) { return _mm256_srai_epi32(a.m256, b); }
__forceinline const avxi srl ( const avxi& a, const int32 b ) { return _mm256_srli_epi32(a.m256, b); }
__forceinline const avxi min( const avxi& a, const avxi& b ) { return _mm256_min_epi32(a.m256, b.m256); }
__forceinline const avxi min( const avxi& a, const int32 b ) { return min(a,avxi(b)); }
__forceinline const avxi min( const int32 a, const avxi& b ) { return min(avxi(a),b); }
__forceinline const avxi max( const avxi& a, const avxi& b ) { return _mm256_max_epi32(a.m256, b.m256); }
__forceinline const avxi max( const avxi& a, const int32 b ) { return max(a,avxi(b)); }
__forceinline const avxi max( const int32 a, const avxi& b ) { return max(avxi(a),b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi& operator +=( avxi& a, const avxi& b ) { return a = a + b; }
__forceinline avxi& operator +=( avxi& a, const int32 b ) { return a = a + b; }
__forceinline avxi& operator -=( avxi& a, const avxi& b ) { return a = a - b; }
__forceinline avxi& operator -=( avxi& a, const int32 b ) { return a = a - b; }
__forceinline avxi& operator *=( avxi& a, const avxi& b ) { return a = a * b; }
__forceinline avxi& operator *=( avxi& a, const int32 b ) { return a = a * b; }
__forceinline avxi& operator &=( avxi& a, const avxi& b ) { return a = a & b; }
__forceinline avxi& operator &=( avxi& a, const int32 b ) { return a = a & b; }
__forceinline avxi& operator |=( avxi& a, const avxi& b ) { return a = a | b; }
__forceinline avxi& operator |=( avxi& a, const int32 b ) { return a = a | b; }
__forceinline avxi& operator <<=( avxi& a, const int32 b ) { return a = a << b; }
__forceinline avxi& operator >>=( avxi& a, const int32 b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator ==( const avxi& a, const avxi& b ) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32 (a.m256, b.m256)); }
__forceinline const avxb operator ==( const avxi& a, const int32 b ) { return a == avxi(b); }
__forceinline const avxb operator ==( const int32 a, const avxi& b ) { return avxi(a) == b; }
__forceinline const avxb operator !=( const avxi& a, const avxi& b ) { return !(a == b); }
__forceinline const avxb operator !=( const avxi& a, const int32 b ) { return a != avxi(b); }
__forceinline const avxb operator !=( const int32 a, const avxi& b ) { return avxi(a) != b; }
__forceinline const avxb operator < ( const avxi& a, const avxi& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (b.m256, a.m256)); }
__forceinline const avxb operator < ( const avxi& a, const int32 b ) { return a < avxi(b); }
__forceinline const avxb operator < ( const int32 a, const avxi& b ) { return avxi(a) < b; }
__forceinline const avxb operator >=( const avxi& a, const avxi& b ) { return !(a < b); }
__forceinline const avxb operator >=( const avxi& a, const int32 b ) { return a >= avxi(b); }
__forceinline const avxb operator >=( const int32 a, const avxi& b ) { return avxi(a) >= b; }
__forceinline const avxb operator > ( const avxi& a, const avxi& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (a.m256, b.m256)); }
__forceinline const avxb operator > ( const avxi& a, const int32 b ) { return a > avxi(b); }
__forceinline const avxb operator > ( const int32 a, const avxi& b ) { return avxi(a) > b; }
__forceinline const avxb operator <=( const avxi& a, const avxi& b ) { return !(a > b); }
__forceinline const avxb operator <=( const avxi& a, const int32 b ) { return a <= avxi(b); }
__forceinline const avxb operator <=( const int32 a, const avxi& b ) { return avxi(a) <= b; }
__forceinline const avxi select( const avxb& m, const avxi& t, const avxi& 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 avxi select(const int m, const avxi& t, const avxi& f) {
return select(avxb(m), t, f); // workaround for clang and Microsoft compiler bugs
}
#else
__forceinline const avxi select(const int m, const avxi& t, const avxi& f) {
return _mm256_blend_epi32(f, t, m);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi unpacklo( const avxi& a, const avxi& b ) { return _mm256_unpacklo_epi32(a.m256, b.m256); }
__forceinline avxi unpackhi( const avxi& a, const avxi& b ) { return _mm256_unpackhi_epi32(a.m256, b.m256); }
template<size_t i> __forceinline const avxi shuffle( const avxi& 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 avxi shuffle( const avxi& a ) {
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const avxi shuffle( const avxi& a, const avxi& 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 avxi shuffle( const avxi& 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 avxi shuffle( const avxi& a, const avxi& 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 avxi shuffle<0, 0, 2, 2>( const avxi& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const avxi shuffle<1, 1, 3, 3>( const avxi& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const avxi shuffle<0, 1, 0, 1>( const avxi& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
__forceinline const avxi broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
template<size_t i> __forceinline const avxi insert (const avxi& a, const ssei& b) { return _mm256_insertf128_si256 (a,b,i); }
template<size_t i> __forceinline const ssei extract(const avxi& a ) { return _mm256_extractf128_si256(a ,i); }
__forceinline avxi permute(const avxi& a, const __m256i& index) {
return _mm256_permutevar8x32_epi32(a,index);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi vreduce_min2(const avxi& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxi vreduce_min4(const avxi& v) { avxi v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxi vreduce_min (const avxi& v) { avxi v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const avxi vreduce_max2(const avxi& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxi vreduce_max4(const avxi& v) { avxi v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxi vreduce_max (const avxi& v) { avxi v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const avxi vreduce_add2(const avxi& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const avxi vreduce_add4(const avxi& v) { avxi v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const avxi vreduce_add (const avxi& v) { avxi v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline int reduce_min(const avxi& v) { return extract<0>(extract<0>(vreduce_min(v))); }
__forceinline int reduce_max(const avxi& v) { return extract<0>(extract<0>(vreduce_max(v))); }
__forceinline int reduce_add(const avxi& v) { return extract<0>(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const avxi& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const avxi& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const avxb& valid, const avxi& v) { const avxi a = select(valid,v,avxi(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const avxb& valid, const avxi& v) { const avxi a = select(valid,v,avxi(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi load8i(const int* const i) {
return _mm256_load_si256((__m256i*)i);
}
__forceinline const avxi uload8i(const int* const i) {
return _mm256_loadu_si256((__m256i*)i);
}
__forceinline void store8i(void *ptr, const avxi& i ) {
_mm256_store_si256((__m256i*)ptr,i);
}
__forceinline void store8i( const avxb &mask, void *ptr, const avxi& i ) {
_mm256_maskstore_epi32((int*)ptr,mask,i);
}
#if defined (__AVX2__)
__forceinline avxi load8i_nt(void* ptr) {
return _mm256_stream_load_si256((__m256i*)ptr);
}
#endif
__forceinline void store8i_nt(void* ptr, const avxi& v) {
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const avxi& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
}
}
+266
View File
@@ -0,0 +1,266 @@
// ======================================================================== //
// Copyright 2009-2014 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 avxi
{
typedef avxb Mask; // mask type for us
enum { size = 8 }; // number of SIMD elements
union { // data
__m256i m256;
struct { __m128i l,h; };
int32 v[8];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi ( ) {}
__forceinline avxi ( const avxi& a ) { m256 = a.m256; }
__forceinline avxi& operator=( const avxi& a ) { m256 = a.m256; return *this; }
__forceinline avxi( const __m256i a ) : m256(a) {}
__forceinline operator const __m256i&( void ) const { return m256; }
__forceinline operator __m256i&( void ) { return m256; }
__forceinline explicit avxi( const ssei& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
__forceinline avxi( const ssei& a, const ssei& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
__forceinline avxi( const __m128i& a, const __m128i& b ) : l(a), h(b) {}
__forceinline explicit avxi ( const int32* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
__forceinline avxi ( int32 a ) : m256(_mm256_set1_epi32(a)) {}
__forceinline avxi ( int32 a, int32 b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
__forceinline avxi ( int32 a, int32 b, int32 c, int32 d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
__forceinline avxi ( int32 a, int32 b, int32 c, int32 d, int32 e, int32 f, int32 g, int32 h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
__forceinline explicit avxi( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi( ZeroTy ) : m256(_mm256_setzero_si256()) {}
__forceinline avxi( OneTy ) : m256(_mm256_set_epi32(1,1,1,1,1,1,1,1)) {}
__forceinline avxi( PosInfTy ) : m256(_mm256_set_epi32(pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf)) {}
__forceinline avxi( NegInfTy ) : m256(_mm256_set_epi32(neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf)) {}
__forceinline avxi( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const int32& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
__forceinline int32& operator []( const size_t i ) { assert(i < 8); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi operator +( const avxi& a ) { return a; }
__forceinline const avxi operator -( const avxi& a ) { return avxi(_mm_sub_epi32(_mm_setzero_si128(), a.l), _mm_sub_epi32(_mm_setzero_si128(), a.h)); }
__forceinline const avxi abs ( const avxi& a ) { return avxi(_mm_abs_epi32(a.l), _mm_abs_epi32(a.h)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi operator +( const avxi& a, const avxi& b ) { return avxi(_mm_add_epi32(a.l, b.l), _mm_add_epi32(a.h, b.h)); }
__forceinline const avxi operator +( const avxi& a, const int32 b ) { return a + avxi(b); }
__forceinline const avxi operator +( const int32 a, const avxi& b ) { return avxi(a) + b; }
__forceinline const avxi operator -( const avxi& a, const avxi& b ) { return avxi(_mm_sub_epi32(a.l, b.l), _mm_sub_epi32(a.h, b.h)); }
__forceinline const avxi operator -( const avxi& a, const int32 b ) { return a - avxi(b); }
__forceinline const avxi operator -( const int32 a, const avxi& b ) { return avxi(a) - b; }
__forceinline const avxi operator *( const avxi& a, const avxi& b ) { return avxi(_mm_mullo_epi32(a.l, b.l), _mm_mullo_epi32(a.h, b.h)); }
__forceinline const avxi operator *( const avxi& a, const int32 b ) { return a * avxi(b); }
__forceinline const avxi operator *( const int32 a, const avxi& b ) { return avxi(a) * b; }
__forceinline const avxi operator &( const avxi& a, const avxi& b ) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const avxi operator &( const avxi& a, const int32 b ) { return a & avxi(b); }
__forceinline const avxi operator &( const int32 a, const avxi& b ) { return avxi(a) & b; }
__forceinline const avxi operator |( const avxi& a, const avxi& b ) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const avxi operator |( const avxi& a, const int32 b ) { return a | avxi(b); }
__forceinline const avxi operator |( const int32 a, const avxi& b ) { return avxi(a) | b; }
__forceinline const avxi operator ^( const avxi& a, const avxi& b ) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline const avxi operator ^( const avxi& a, const int32 b ) { return a ^ avxi(b); }
__forceinline const avxi operator ^( const int32 a, const avxi& b ) { return avxi(a) ^ b; }
__forceinline const avxi operator <<( const avxi& a, const int32 n ) { return avxi(_mm_slli_epi32(a.l, n), _mm_slli_epi32(a.h, n)); }
__forceinline const avxi operator >>( const avxi& a, const int32 n ) { return avxi(_mm_srai_epi32(a.l, n), _mm_srai_epi32(a.h, n)); }
__forceinline const avxi sra ( const avxi& a, const int32 b ) { return avxi(_mm_srai_epi32(a.l, b), _mm_srai_epi32(a.h, b)); }
__forceinline const avxi srl ( const avxi& a, const int32 b ) { return avxi(_mm_srli_epi32(a.l, b), _mm_srli_epi32(a.h, b)); }
__forceinline const avxi min( const avxi& a, const avxi& b ) { return avxi(_mm_min_epi32(a.l, b.l), _mm_min_epi32(a.h, b.h)); }
__forceinline const avxi min( const avxi& a, const int32 b ) { return min(a,avxi(b)); }
__forceinline const avxi min( const int32 a, const avxi& b ) { return min(avxi(a),b); }
__forceinline const avxi max( const avxi& a, const avxi& b ) { return avxi(_mm_max_epi32(a.l, b.l), _mm_max_epi32(a.h, b.h)); }
__forceinline const avxi max( const avxi& a, const int32 b ) { return max(a,avxi(b)); }
__forceinline const avxi max( const int32 a, const avxi& b ) { return max(avxi(a),b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi& operator +=( avxi& a, const avxi& b ) { return a = a + b; }
__forceinline avxi& operator +=( avxi& a, const int32 b ) { return a = a + b; }
__forceinline avxi& operator -=( avxi& a, const avxi& b ) { return a = a - b; }
__forceinline avxi& operator -=( avxi& a, const int32 b ) { return a = a - b; }
__forceinline avxi& operator *=( avxi& a, const avxi& b ) { return a = a * b; }
__forceinline avxi& operator *=( avxi& a, const int32 b ) { return a = a * b; }
__forceinline avxi& operator &=( avxi& a, const avxi& b ) { return a = a & b; }
__forceinline avxi& operator &=( avxi& a, const int32 b ) { return a = a & b; }
__forceinline avxi& operator |=( avxi& a, const avxi& b ) { return a = a | b; }
__forceinline avxi& operator |=( avxi& a, const int32 b ) { return a = a | b; }
__forceinline avxi& operator <<=( avxi& a, const int32 b ) { return a = a << b; }
__forceinline avxi& operator >>=( avxi& a, const int32 b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxb operator ==( const avxi& a, const avxi& b ) { return avxb(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmpeq_epi32 (a.h, b.h))); }
__forceinline const avxb operator ==( const avxi& a, const int32 b ) { return a == avxi(b); }
__forceinline const avxb operator ==( const int32 a, const avxi& b ) { return avxi(a) == b; }
__forceinline const avxb operator !=( const avxi& a, const avxi& b ) { return !(a == b); }
__forceinline const avxb operator !=( const avxi& a, const int32 b ) { return a != avxi(b); }
__forceinline const avxb operator !=( const int32 a, const avxi& b ) { return avxi(a) != b; }
__forceinline const avxb operator < ( const avxi& a, const avxi& b ) { return avxb(_mm_castsi128_ps(_mm_cmplt_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmplt_epi32 (a.h, b.h))); }
__forceinline const avxb operator < ( const avxi& a, const int32 b ) { return a < avxi(b); }
__forceinline const avxb operator < ( const int32 a, const avxi& b ) { return avxi(a) < b; }
__forceinline const avxb operator >=( const avxi& a, const avxi& b ) { return !(a < b); }
__forceinline const avxb operator >=( const avxi& a, const int32 b ) { return a >= avxi(b); }
__forceinline const avxb operator >=( const int32 a, const avxi& b ) { return avxi(a) >= b; }
__forceinline const avxb operator > ( const avxi& a, const avxi& b ) { return avxb(_mm_castsi128_ps(_mm_cmpgt_epi32 (a.l, b.l)),
_mm_castsi128_ps(_mm_cmpgt_epi32 (a.h, b.h))); }
__forceinline const avxb operator > ( const avxi& a, const int32 b ) { return a > avxi(b); }
__forceinline const avxb operator > ( const int32 a, const avxi& b ) { return avxi(a) > b; }
__forceinline const avxb operator <=( const avxi& a, const avxi& b ) { return !(a > b); }
__forceinline const avxb operator <=( const avxi& a, const int32 b ) { return a <= avxi(b); }
__forceinline const avxb operator <=( const int32 a, const avxi& b ) { return avxi(a) <= b; }
__forceinline const avxi select( const avxb& m, const avxi& t, const avxi& f ) {
return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline avxi unpacklo( const avxi& a, const avxi& b ) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
__forceinline avxi unpackhi( const avxi& a, const avxi& b ) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
template<size_t i> __forceinline const avxi shuffle( const avxi& 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 avxi shuffle( const avxi& a ) {
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
}
template<size_t i0, size_t i1> __forceinline const avxi shuffle( const avxi& a, const avxi& 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 avxi shuffle( const avxi& 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 avxi shuffle( const avxi& a, const avxi& 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 avxi shuffle<0, 0, 2, 2>( const avxi& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const avxi shuffle<1, 1, 3, 3>( const avxi& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
template<> __forceinline const avxi shuffle<0, 1, 0, 1>( const avxi& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
__forceinline const avxi broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
template<size_t i> __forceinline const avxi insert (const avxi& a, const ssei& b) { return _mm256_insertf128_si256 (a,b,i); }
template<size_t i> __forceinline const ssei extract(const avxi& a ) { return _mm256_extractf128_si256(a ,i); }
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const avxi vreduce_min2(const avxi& v) { return min(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxi vreduce_min4(const avxi& v) { avxi v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxi vreduce_min (const avxi& v) { avxi v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
__forceinline const avxi vreduce_max2(const avxi& v) { return max(v,shuffle<1,0,3,2>(v)); }
__forceinline const avxi vreduce_max4(const avxi& v) { avxi v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
__forceinline const avxi vreduce_max (const avxi& v) { avxi v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
__forceinline const avxi vreduce_add2(const avxi& v) { return v + shuffle<1,0,3,2>(v); }
__forceinline const avxi vreduce_add4(const avxi& v) { avxi v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
__forceinline const avxi vreduce_add (const avxi& v) { avxi v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
__forceinline int reduce_min(const avxi& v) { return extract<0>(extract<0>(vreduce_min(v))); }
__forceinline int reduce_max(const avxi& v) { return extract<0>(extract<0>(vreduce_max(v))); }
__forceinline int reduce_add(const avxi& v) { return extract<0>(extract<0>(vreduce_add(v))); }
__forceinline size_t select_min(const avxi& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const avxi& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const avxb& valid, const avxi& v) { const avxi a = select(valid,v,avxi(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const avxb& valid, const avxi& v) { const avxi a = select(valid,v,avxi(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// New stuff
////////////////////////////////////////////////////////////////////////////////
__forceinline void store8i(void* ptr, const avxi& i) {
_mm256_store_ps((float*)ptr,_mm256_castsi256_ps(i));
}
__forceinline void store8i( const avxb &mask, void *ptr, const avxi& i ) {
_mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(i));
}
__forceinline void store8i_nt(void* ptr, const avxi& 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 avxi& 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
+140
View File
@@ -0,0 +1,140 @@
// ======================================================================== //
// Copyright 2009-2014 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 "sys/intrinsics.h"
#include "sse_mic.h"
#include <zmmintrin.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 mic_m;
class mic_i;
class mic_f;
}
#include "mic_m.h"
#include "mic_i.h"
#include "mic_f.h"
namespace embree
{
////////////////////////////////////////////////////////////////////////////////
/// Prefetching
////////////////////////////////////////////////////////////////////////////////
#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)
{
if (mode == PFHINT_L1)
_mm_prefetch((const char*)m,_MM_HINT_T0);
else if (mode == PFHINT_L2)
_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 mic_m &m_active,
const void *const ptr,
const mic_i 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 mic_m &m_active,
void *const ptr,
const mic_i 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);
}
__forceinline void evictL1(const void * __restrict__ m) {
_mm_clevict(m,_MM_HINT_T0);
}
__forceinline void evictL2(const void * __restrict__ m) {
_mm_clevict(m,_MM_HINT_T1);
}
#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 mic_f lshuf(const mic_f &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 mic_f lshuf(const mic_m &mask, mic_f &dest, const mic_f &in)
{
return _mm512_mask_permute4f128_ps(dest,mask,in,(_MM_PERM_ENUM) _MM_SHUF_PERM(D,C,B,A));
}
template<const int lane>
__forceinline mic_f lane_shuffle_gather(const mic_f &v0,const mic_f &v1,const mic_f &v2,const mic_f &v3)
{
mic_f 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 mic_f convert(const ssef &v)
{
return broadcast4to16f(&v);
}
__forceinline mic_i mul_uint64( const mic_i& a, const mic_i& b) {
const mic_i low = _mm512_mullo_epi32(a, b);
const mic_i high = _mm512_mulhi_epu32(a, b);
return select(0x5555,low,high);
}
}
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,4 @@
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../../../common/math/math.h"
#include "mic.h"
+756
View File
@@ -0,0 +1,756 @@
// ======================================================================== //
// Copyright 2009-2014 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 mic_f
{
public:
union {
__m512 v;
float f[16];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f() {}
__forceinline mic_f(const mic_f& t) { v = t; };
__forceinline mic_f& operator=(const mic_f& f) { v = f.v; return *this; };
__forceinline mic_f(const __m512& t) { v = t; };
__forceinline operator __m512 () const { return v; };
__forceinline mic_f(const float& f) {
v = _mm512_set_1to16_ps(f);
}
__forceinline mic_f(const float& a, const float& b, const float& c, const float& d) {
v = _mm512_set_4to16_ps(a,b,c,d);
}
__forceinline explicit mic_f(const __m512i& a) {
v = _mm512_cvtfxpnt_round_adjustepi32_ps(a, _MM_FROUND_NO_EXC,_MM_EXPADJ_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f( ZeroTy ) : v(_mm512_setzero_ps()) {}
__forceinline mic_f( OneTy ) : v(_mm512_set_1to16_ps(1.0f)) {}
__forceinline mic_f( PosInfTy ) : v(_mm512_set_1to16_ps(pos_inf)) {}
__forceinline mic_f( NegInfTy ) : v(_mm512_set_1to16_ps(neg_inf)) {}
__forceinline mic_f( StepTy ) : v(_mm512_set_16to16_ps(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
__forceinline mic_f( NaNTy ) : v(_mm512_set_1to16_ps(nan)) {}
__forceinline static mic_f undefined() { return _mm512_undefined(); }
__forceinline static mic_f zero() { return _mm512_setzero_ps(); }
__forceinline static mic_f one () { return _mm512_set_1to16_ps(1.0f); }
__forceinline static mic_f ulp () { return _mm512_set_1to16_ps(embree::ulp); }
__forceinline static mic_f inf () { return _mm512_set_1to16_ps((float)pos_inf); }
__forceinline static mic_f minus_inf () { return _mm512_set_1to16_ps((float)neg_inf); }
////////////////////////////////////////////////////////////////////////////////
/// 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 mic_f cast (const __m512i& a) { return _mm512_castsi512_ps(a); }
__forceinline const mic_f operator +( const mic_f& a ) { return a; }
__forceinline const mic_f operator -( const mic_f& a ) { return _mm512_mul_ps(a,mic_f(-1)); }
__forceinline const mic_f abs ( const mic_f& a ) { return _mm512_gmaxabs_ps(a,a); }
__forceinline const mic_f signmsk ( const mic_f& a ) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
__forceinline const mic_f rcp ( const mic_f& a ) { return _mm512_rcp23_ps(a); };
__forceinline const mic_f sqr ( const mic_f& a ) { return _mm512_mul_ps(a,a); }
__forceinline const mic_f sqrt ( const mic_f& a ) { return _mm512_sqrt_ps(a); }
__forceinline const mic_f rsqrt( const mic_f& a ) { return _mm512_invsqrt_ps(a); }
//__forceinline mic_f floor(const mic_f& a) { return _mm512_floor_ps(a); }
//__forceinline mic_f ceil(const mic_f& a) { return _mm512_ceil_ps(a); }
__forceinline mic_f trunc(const mic_f& a) { return _mm512_trunc_ps(a); }
__forceinline mic_f exp(const mic_f& a) { return _mm512_exp_ps(a); }
__forceinline mic_f exp2(const mic_f& a) { return _mm512_exp2_ps(a); }
__forceinline mic_f pow(const mic_f& a, mic_f b) { return _mm512_pow_ps(a,b); }
__forceinline mic_f log(const mic_f& a) { return _mm512_log_ps(a); }
__forceinline mic_f log2(const mic_f& a) { return _mm512_log2_ps(a); }
__forceinline mic_f log10(const mic_f& a) { return _mm512_log10_ps(a); }
__forceinline mic_f sin(const mic_f& a) { return _mm512_sin_ps(a); }
__forceinline mic_f cos(const mic_f& a) { return _mm512_cos_ps(a); }
__forceinline mic_f tan(const mic_f& a) { return _mm512_tan_ps(a); }
__forceinline mic_f asin(const mic_f& a) { return _mm512_asin_ps(a); }
__forceinline mic_f acos(const mic_f& a) { return _mm512_acos_ps(a); }
__forceinline mic_f atan(const mic_f& a) { return _mm512_atan_ps(a); }
__forceinline mic_f atan2(const mic_f& a, mic_f b) { return _mm512_atan2_ps(a,b); }
__forceinline mic_f sinh(const mic_f& a) { return _mm512_sinh_ps(a); }
__forceinline mic_f cosh(const mic_f& a) { return _mm512_cosh_ps(a); }
__forceinline mic_f tanh(const mic_f& a) { return _mm512_tan_ps(a); }
__forceinline mic_f asinh(const mic_f& a) { return _mm512_asinh_ps(a); }
__forceinline mic_f acosh(const mic_f& a) { return _mm512_acosh_ps(a); }
__forceinline mic_f atanh(const mic_f& a) { return _mm512_atanh_ps(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_f operator +( const mic_f& a, const mic_f& b ) { return _mm512_add_ps(a, b); }
__forceinline const mic_f operator +( const mic_f& a, const float& b ) { return a + mic_f(b); }
__forceinline const mic_f operator +( const float& a, const mic_f& b ) { return mic_f(a) + b; }
__forceinline const mic_f operator -( const mic_f& a, const mic_f& b ) { return _mm512_sub_ps(a, b); }
__forceinline const mic_f operator -( const mic_f& a, const float& b ) { return a - mic_f(b); }
__forceinline const mic_f operator -( const float& a, const mic_f& b ) { return mic_f(a) - b; }
__forceinline const mic_f operator *( const mic_f& a, const mic_f& b ) { return _mm512_mul_ps(a, b); }
__forceinline const mic_f operator *( const mic_f& a, const float& b ) { return a * mic_f(b); }
__forceinline const mic_f operator *( const float& a, const mic_f& b ) { return mic_f(a) * b; }
__forceinline const mic_f operator /( const mic_f& a, const mic_f& b ) { return _mm512_div_ps(a,b); }
__forceinline const mic_f operator /( const mic_f& a, const float& b ) { return a/mic_f(b); }
__forceinline const mic_f operator /( const float& a, const mic_f& b ) { return mic_f(a)/b; }
__forceinline const mic_f operator^(const mic_f& a, const mic_f& b) {
return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b)));
}
__forceinline const mic_f min( const mic_f& a, const mic_f& b ) { return _mm512_gmin_ps(a,b); }
__forceinline const mic_f min( const mic_f& a, const float& b ) { return _mm512_gmin_ps(a,mic_f(b)); }
__forceinline const mic_f min( const float& a, const mic_f& b ) { return _mm512_gmin_ps(mic_f(a),b); }
__forceinline const mic_f max( const mic_f& a, const mic_f& b ) { return _mm512_gmax_ps(a,b); }
__forceinline const mic_f max( const mic_f& a, const float& b ) { return _mm512_gmax_ps(a,mic_f(b)); }
__forceinline const mic_f max( const float& a, const mic_f& b ) { return _mm512_gmax_ps(mic_f(a),b); }
__forceinline mic_f mask_add(const mic_m& mask, const mic_f& c, const mic_f& a, const mic_f& b) { return _mm512_mask_add_ps (c,mask,a,b); };
__forceinline mic_f mask_min(const mic_m& mask, const mic_f& c, const mic_f& a, const mic_f& b) { return _mm512_mask_gmin_ps(c,mask,a,b); };
__forceinline mic_f mask_max(const mic_m& mask, const mic_f& c, const mic_f& a, const mic_f& b) { return _mm512_mask_gmax_ps(c,mask,a,b); };
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f madd (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fmadd_ps(a,b,c); }
__forceinline mic_f msub (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline mic_f nmadd (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fnmadd_ps(a,b,c); }
__forceinline mic_f nmsub (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fnmsub_ps(a,b,c); }
__forceinline mic_f mask_msub (const mic_m& mask,const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_mask_fmsub_ps(a,mask,b,c); }
__forceinline mic_f madd231 (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fmadd_ps(c,b,a); }
__forceinline mic_f msub213 (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline mic_f msub231 (const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fmsub_ps(c,b,a); }
__forceinline mic_f msubr231(const mic_f& a, const mic_f& b, const mic_f& c) { return _mm512_fnmadd_ps(c,b,a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f& operator +=( mic_f& a, const mic_f& b ) { return a = a + b; }
__forceinline mic_f& operator +=( mic_f& a, const float& b ) { return a = a + b; }
__forceinline mic_f& operator -=( mic_f& a, const mic_f& b ) { return a = a - b; }
__forceinline mic_f& operator -=( mic_f& a, const float& b ) { return a = a - b; }
__forceinline mic_f& operator *=( mic_f& a, const mic_f& b ) { return a = a * b; }
__forceinline mic_f& operator *=( mic_f& a, const float& b ) { return a = a * b; }
__forceinline mic_f& operator /=( mic_f& a, const mic_f& b ) { return a = a / b; }
__forceinline mic_f& operator /=( mic_f& a, const float& b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_m operator ==( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline const mic_m operator ==( const mic_f& a, const float& b ) { return a == mic_f(b); }
__forceinline const mic_m operator ==( const float& a, const mic_f& b ) { return mic_f(a) == b; }
__forceinline const mic_m operator !=( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline const mic_m operator !=( const mic_f& a, const float& b ) { return a != mic_f(b); }
__forceinline const mic_m operator !=( const float& a, const mic_f& b ) { return mic_f(a) != b; }
__forceinline const mic_m operator < ( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline const mic_m operator < ( const mic_f& a, const float& b ) { return a < mic_f(b); }
__forceinline const mic_m operator < ( const float& a, const mic_f& b ) { return mic_f(a) < b; }
__forceinline const mic_m operator >=( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline const mic_m operator >=( const mic_f& a, const float& b ) { return a >= mic_f(b); }
__forceinline const mic_m operator >=( const float& a, const mic_f& b ) { return mic_f(a) >= b; }
__forceinline const mic_m operator > ( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline const mic_m operator > ( const mic_f& a, const float& b ) { return a > mic_f(b); }
__forceinline const mic_m operator > ( const float& a, const mic_f& b ) { return mic_f(a) > b; }
__forceinline const mic_m operator <=( const mic_f& a, const mic_f& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline const mic_m operator <=( const mic_f& a, const float& b ) { return a <= mic_f(b); }
__forceinline const mic_m operator <=( const float& a, const mic_f& b ) { return mic_f(a) <= b; }
__forceinline mic_m eq( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline mic_m eq(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_EQ); }
__forceinline mic_m ne( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline mic_m ne(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_NE); }
__forceinline mic_m lt( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline mic_m lt(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LT); }
__forceinline mic_m ge( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline mic_m ge(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GE); }
__forceinline mic_m gt( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline mic_m gt(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GT); }
__forceinline mic_m le( const mic_f& a, const mic_f& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline mic_m le(const mic_m& mask, const mic_f& a, const mic_f& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LE); }
__forceinline const mic_f select( const mic_m& s, const mic_f& t, const mic_f& f ) {
return _mm512_mask_blend_ps(s, f, t);
}
__forceinline void xchg(mic_m m, mic_f& a, mic_f& b)
{
mic_f c = a;
a = select(m,b,a);
b = select(m,c,b);
}
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f vround(const mic_f& f,
const _MM_ROUND_MODE_ENUM mode,
const _MM_EXP_ADJ_ENUM exp = _MM_EXPADJ_NONE)
{
return _mm512_round_ps(f,mode,exp);
}
__forceinline mic_f floor(const mic_f& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_DOWN, _MM_EXPADJ_NONE); }
__forceinline mic_f ceil (const mic_f& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_UP , _MM_EXPADJ_NONE); }
__forceinline const mic_f rcp_nr ( const mic_f& a ) {
const mic_f ra = _mm512_rcp23_ps(a);
return (ra+ra) - (ra * a * ra);
};
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f swizzle(const mic_f& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_ps(x,perm32); }
__forceinline mic_f permute(const mic_f& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_ps(x,perm128); }
template<int D, int C, int B, int A> __forceinline mic_f swizzle (const mic_f& v) { return _mm512_shuffle_ps(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline mic_f swizzle (const mic_f& x) { return swizzle<A,A,A,A>(v); }
template<> __forceinline mic_f swizzle<0>(const mic_f& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
template<> __forceinline mic_f swizzle<1>(const mic_f& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
template<> __forceinline mic_f swizzle<2>(const mic_f& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
template<> __forceinline mic_f swizzle<3>(const mic_f& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
template<int D, int C, int B, int A> __forceinline mic_f permute(const mic_f& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline mic_f permute(const mic_f& x) { return permute<A,A,A,A>(x); }
__forceinline mic_f shuffle(const mic_f& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
__forceinline mic_f shuffle(const mic_m& mask, mic_f& v, const mic_f& 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 mic_f swAAAA(const mic_f &x) {
return swizzle(x,_MM_SWIZ_REG_AAAA);
}
__forceinline mic_f swBBBB(const mic_f &x) {
return swizzle(x,_MM_SWIZ_REG_BBBB);
}
__forceinline mic_f swCCCC(const mic_f &x) {
return swizzle(x,_MM_SWIZ_REG_CCCC);
}
__forceinline mic_f swDDDD(const mic_f &x) {
return swizzle(x,_MM_SWIZ_REG_DDDD);
}
__forceinline mic_f _mm512_permutev_ps(__m512i index, mic_f v)
{
return _mm512_castsi512_ps(_mm512_permutev_epi32(index,_mm512_castps_si512(v)));
}
template<int i>
__forceinline mic_f align_shift_right(const mic_f &a, const mic_f &b)
{
return _mm512_castsi512_ps(_mm512_alignr_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b),i));
};
template<int i>
__forceinline mic_f mask_align_shift_right(const mic_m &mask,mic_f &c,const mic_f &a, const mic_f &b)
{
return _mm512_castsi512_ps(_mm512_mask_alignr_epi32(_mm512_castps_si512(c),mask,_mm512_castps_si512(a),_mm512_castps_si512(b),i));
};
__forceinline mic_f shl1_zero_extend(const mic_f &a)
{
mic_f z = mic_f::zero();
return mask_align_shift_right<15>(0xfffe,z,a,a);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline float reduce_add(mic_f a) { return _mm512_reduce_add_ps(a); }
__forceinline float reduce_mul(mic_f a) { return _mm512_reduce_mul_ps(a); }
__forceinline float reduce_min(mic_f a) { return _mm512_reduce_min_ps(a); }
__forceinline float reduce_max(mic_f a) { return _mm512_reduce_max_ps(a); }
__forceinline mic_f vreduce_min2(mic_f x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline mic_f vreduce_min4(mic_f x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline mic_f vreduce_min8(mic_f x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline mic_f vreduce_min (mic_f x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline mic_f vreduce_max2(mic_f x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline mic_f vreduce_max4(mic_f x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline mic_f vreduce_max8(mic_f x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline mic_f vreduce_max (mic_f x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline mic_f vreduce_add2(mic_f x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline mic_f vreduce_add4(mic_f x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline mic_f vreduce_add8(mic_f x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline mic_f vreduce_add (mic_f x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline size_t select_min(const mic_f& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const mic_f& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const mic_m& valid, const mic_f& v, const mic_f &max_value) { const mic_f a = select(valid,v,max_value); return __bsf(movemask(a == vreduce_min(a))); }
__forceinline size_t select_max(const mic_m& valid, const mic_f& v, const mic_f &min_value) { const mic_f a = select(valid,v,min_value); return __bsf(movemask(a == vreduce_max(a))); }
__forceinline size_t select_max(const mic_m& valid, const mic_f& v) { const mic_f a = select(valid,v,mic_f(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
__forceinline size_t select_min(const mic_m& valid, const mic_f& v) { const mic_f a = select(valid,v,mic_f(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline mic_f prefix_sum(const mic_f& a)
{
mic_f 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 mic_f shuf_v0 = shuffle(v,_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
v = mask_add(0xf0f0,v,v,shuf_v0);
const mic_f 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 mic_f prefix_min(const mic_f& a)
{
mic_f 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 mic_f 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 mic_f 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 mic_f prefix_max(const mic_f& a)
{
mic_f 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 mic_f 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 mic_f 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 mic_f set_min4(mic_f x) {
x = min(x,swizzle(x,_MM_SWIZ_REG_BADC));
x = min(x,swizzle(x,_MM_SWIZ_REG_CDAB));
return x;
}
__forceinline mic_f set_min_lanes(mic_f x) {
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
return x;
}
__forceinline mic_f set_max_lanes(mic_f x) {
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
return x;
}
__forceinline mic_f set_min16(mic_f x) {
return set_min_lanes(set_min4(x));
}
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f load1f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline mic_f load16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline mic_f load16f(const mic_f d, const mic_m valid, const void *f) {
return _mm512_mask_extload_ps(d,valid,f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline mic_f broadcast1to16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline mic_f broadcast4to16f(const void *f) {
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,0);
}
__forceinline mic_f broadcast8to16f(const void *f) {
return _mm512_castpd_ps(_mm512_extload_pd(f,_MM_UPCONV_PD_NONE,_MM_BROADCAST_4X8,0));
}
__forceinline mic_f 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),mic_f(1.0f/255.0f));
}
__forceinline mic_f uload16f_low_uint8(const mic_m& mask, const void* addr, const mic_f& v1) {
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_UINT8, _MM_HINT_NONE);
}
__forceinline mic_f load16f_int8(const char *const ptr) {
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_SINT8,_MM_BROADCAST_16X16,_MM_HINT_NONE),mic_f(1.0f/127.0f));
}
__forceinline mic_f gather16f_4f(const float *__restrict__ const ptr0,
const float *__restrict__ const ptr1,
const float *__restrict__ const ptr2,
const float *__restrict__ const ptr3)
{
mic_f v = broadcast4to16f(ptr0);
v = select((mic_m)0x00f0,broadcast4to16f(ptr1),v);
v = select((mic_m)0x0f00,broadcast4to16f(ptr2),v);
v = select((mic_m)0xf000,broadcast4to16f(ptr3),v);
return v;
}
__forceinline mic_f gather16f_4f(const mic_f& v0,
const mic_f& v1,
const mic_f& v2,
const mic_f& v3)
{
mic_f v = v0;
v = select((mic_m)0xf0 ,v1,v);
v = select((mic_m)0xf00 ,v2,v);
v = select((mic_m)0xf000,v3,v);
return v;
}
__forceinline mic_f gather_4f_zlc(const mic_i &v_mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
const mic_m m_00f0 = 0x00f0;
const mic_m m_0f00 = 0x0f00;
const mic_m m_f000 = 0xf000;
mic_i 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 mic_f gather_2f_zlc(const mic_i &v_mask,
const mic_m &mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1)
{
mic_i v = v_mask & broadcast4to16i((const int*)ptr0);
v = mask_and(mask,v,v_mask, broadcast4to16i((const int*)ptr1));
return cast(v);
}
__forceinline mic_f gather16f_4f_align(const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
mic_f 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 mic_f gather16f_4f_align(const mic_f& v0,
const mic_f& v1,
const mic_f& v2,
const mic_f& v3)
{
mic_f 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 mic_f gather_4f_zlc_align(const mic_i &v_mask,
const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
mic_f v = gather16f_4f_align(ptr0,ptr1,ptr2,ptr3);
return cast(cast(v) & v_mask);
}
__forceinline mic_f uload16f(const float *const addr) {
mic_f r = mic_f::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 mic_f uload16f_low(const float *const addr) {
mic_f r = mic_f::undefined();
return _mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline mic_f uload16f_low(const mic_m& mask, const void* addr, const mic_f& v1) {
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline void ustore16f(float *addr, const mic_f& reg) {
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
_mm512_extpackstorehi_ps(addr+16 ,reg, _MM_DOWNCONV_PS_NONE , 0);
}
/* pass by value to avoid compiler generating inefficient code */
__forceinline void compactustore16f(const mic_m& mask, float *addr, const mic_f 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 mic_m& mask, float * addr, const mic_f &reg) {
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void compactustore16f_low_uint8(const mic_m& mask, void * addr, const mic_f &reg) {
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_UINT8 , 0);
}
__forceinline void ustore16f_low(float * addr, const mic_f& reg) {
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void compactustore16f_high(const mic_m& mask, float *addr, const mic_f& reg) {
_mm512_extpackstorehi_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
}
__forceinline void store16f(const mic_m& mask, void* addr, const mic_f& v2) {
_mm512_mask_extstore_ps(addr,mask,v2,_MM_DOWNCONV_PS_NONE,0);
}
__forceinline void store16f(void* addr, const mic_f& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_NONE,0);
}
__forceinline void store16f_int8(void* addr, const mic_f& v2) {
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_SINT8,0);
}
__forceinline void store4f_int8(void* addr, const mic_f& 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 mic_f& 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 mic_f& 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 mic_f& 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 mic_f& a) {
_mm512_storenr_ps(ptr,a);
}
__forceinline void store16f_ngo(void *__restrict__ ptr, const mic_f& a) {
_mm512_storenrngo_ps(ptr,a);
}
__forceinline void store1f(void *addr, const mic_f& reg) {
_mm512_mask_extpackstorelo_ps((float*)addr+0 ,(mic_m)1, reg, _MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline mic_f gather16f(const mic_m& mask, const float *const ptr, __m512i index, const _MM_INDEX_SCALE_ENUM scale) {
mic_f r = mic_f::undefined();
return _mm512_mask_i32extgather_ps(r,mask,index,ptr,_MM_UPCONV_PS_NONE,scale,0);
}
__forceinline void scatter16f(const mic_m& mask,const float *const ptr, const __m512i index,const mic_f v, const _MM_INDEX_SCALE_ENUM scale) {
_mm512_mask_i32extscatter_ps((void*)ptr,mask,index,v,_MM_DOWNCONV_PS_NONE,scale,0);
}
__forceinline mic_f loadAOS4to16f(const float& x,const float& y, const float& z)
{
mic_f f = mic_f::zero();
f = select(0x1111,broadcast1to16f(&x),f);
f = select(0x2222,broadcast1to16f(&y),f);
f = select(0x4444,broadcast1to16f(&z),f);
return f;
}
__forceinline mic_f loadAOS4to16f(const unsigned int index,
const mic_f &x,
const mic_f &y,
const mic_f &z)
{
mic_f f = mic_f::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 mic_f loadAOS4to16f(const unsigned int index,
const mic_f &x,
const mic_f &y,
const mic_f &z,
const mic_f &fill)
{
mic_f 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 mic_f rcp_safe( const mic_f& a ) { return select(a != mic_f::zero(),_mm512_rcp23_ps(a),mic_f(1E-10f)); };
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_f lcross_zxy(const mic_f &ao, const mic_f &bo) {
mic_f 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 mic_f ldot16_zxy(const mic_f &a,const mic_f &v0, const mic_f &v1, const mic_f &v2)
{
mic_f 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 mic_f ldot16_xyz(const mic_f &a,const mic_f &v0, const mic_f &v1, const mic_f &v2)
{
mic_f 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 mic_f lcross_xyz(const mic_f &a, const mic_f &b)
{
mic_f 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 mic_f ldot3_xyz(const mic_f &ao, const mic_f &normal)
{
mic_f 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 mic_f ldot3_xyz(const mic_m &m_mask, const mic_f &ao, const mic_f &normal)
{
mic_f 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 mic_f ldot3_zxy(const mic_f &ao, const mic_f &normal)
{
mic_f 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 mic_f& v)
{
cout << "<" << v[0];
for (int i=1; i<16; i++) cout << ", " << v[i];
cout << ">";
return cout;
}
}
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,4 @@
// limitations under the License. //
// ======================================================================== //
#pragma once
#include "../../../common/math/linearspace3.h"
#include "mic.h"
+482
View File
@@ -0,0 +1,482 @@
// ======================================================================== //
// Copyright 2009-2014 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 mic_i
{
public:
union {
__m512i v;
int32 i[16];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_i() {};
__forceinline mic_i(const mic_i& t) { v = t.v; };
__forceinline mic_i& operator=(const mic_i& f) { v = f.v; return *this; };
__forceinline mic_i(const __m512i& t) { v = t; };
__forceinline operator __m512i () const { return v; };
__forceinline mic_i(const int& i) {
v = _mm512_set_1to16_epi32(i);
}
__forceinline mic_i(const int& a, const int& b, const int& c, const int& d) {
v = _mm512_set_4to16_epi32(a,b,c,d);
}
__forceinline explicit mic_i(const __m512 f) {
v = _mm512_cvtfxpnt_round_adjustps_epi32(f,_MM_FROUND_FLOOR,_MM_EXPADJ_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_i( ZeroTy ) : v(_mm512_setzero_epi32()) {}
__forceinline mic_i( OneTy ) : v(_mm512_set_1to16_epi32(1)) {}
__forceinline mic_i( PosInfTy ) : v(_mm512_set_1to16_epi32(pos_inf)) {}
__forceinline mic_i( NegInfTy ) : v(_mm512_set_1to16_epi32(neg_inf)) {}
__forceinline mic_i( StepTy ) : v(_mm512_set_16to16_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
__forceinline static mic_i zero() { return _mm512_setzero_epi32(); }
__forceinline static mic_i one () { return _mm512_set_1to16_epi32(1); }
__forceinline static mic_i neg_one () { return _mm512_set_1to16_epi32(-1); }
////////////////////////////////////////////////////////////////////////////////
/// 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(const size_t index) const { assert(index < 8); return ((size_t*)i)[index]; };
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_i cast ( const __m512& a) { return _mm512_castps_si512(a); }
__forceinline const mic_i operator +( const mic_i& a ) { return a; }
__forceinline const mic_i operator -( const mic_i& a ) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_i operator +( const mic_i& a, const mic_i& b ) { return _mm512_add_epi32(a, b); }
__forceinline const mic_i operator +( const mic_i& a, const int32& b ) { return a + mic_i(b); }
__forceinline const mic_i operator +( const int32& a, const mic_i& b ) { return mic_i(a) + b; }
__forceinline const mic_i operator -( const mic_i& a, const mic_i& b ) { return _mm512_sub_epi32(a, b); }
__forceinline const mic_i operator -( const mic_i& a, const int32& b ) { return a - mic_i(b); }
__forceinline const mic_i operator -( const int32& a, const mic_i& b ) { return mic_i(a) - b; }
__forceinline const mic_i operator *( const mic_i& a, const mic_i& b ) { return _mm512_mullo_epi32(a, b); }
__forceinline const mic_i operator *( const mic_i& a, const int32& b ) { return a * mic_i(b); }
__forceinline const mic_i operator *( const int32& a, const mic_i& b ) { return mic_i(a) * b; }
__forceinline const mic_i operator &( const mic_i& a, const mic_i& b ) { return _mm512_and_epi32(a, b); }
__forceinline const mic_i operator &( const mic_i& a, const int32& b ) { return a & mic_i(b); }
__forceinline const mic_i operator &( const int32& a, const mic_i& b ) { return mic_i(a) & b; }
__forceinline const mic_i operator |( const mic_i& a, const mic_i& b ) { return _mm512_or_epi32(a, b); }
__forceinline const mic_i operator |( const mic_i& a, const int32& b ) { return a | mic_i(b); }
__forceinline const mic_i operator |( const int32& a, const mic_i& b ) { return mic_i(a) | b; }
__forceinline const mic_i operator ^( const mic_i& a, const mic_i& b ) { return _mm512_xor_epi32(a, b); }
__forceinline const mic_i operator ^( const mic_i& a, const int32& b ) { return a ^ mic_i(b); }
__forceinline const mic_i operator ^( const int32& a, const mic_i& b ) { return mic_i(a) ^ b; }
__forceinline const mic_i operator <<( const mic_i& a, const int32& n ) { return _mm512_slli_epi32(a, n); }
__forceinline const mic_i operator >>( const mic_i& a, const int32& n ) { return _mm512_srai_epi32(a, n); }
__forceinline const mic_i operator <<( const mic_i& a, const mic_i& n ) { return _mm512_sllv_epi32(a, n); }
__forceinline const mic_i operator >>( const mic_i& a, const mic_i& n ) { return _mm512_srav_epi32(a, n); }
__forceinline const mic_i sra ( const mic_i& a, const int32& b ) { return _mm512_srai_epi32(a, b); }
__forceinline const mic_i srl ( const mic_i& a, const int32& b ) { return _mm512_srli_epi32(a, b); }
__forceinline const mic_i min( const mic_i& a, const mic_i& b ) { return _mm512_min_epi32(a, b); }
__forceinline const mic_i min( const mic_i& a, const int32& b ) { return min(a,mic_i(b)); }
__forceinline const mic_i min( const int32& a, const mic_i& b ) { return min(mic_i(a),b); }
__forceinline const mic_i max( const mic_i& a, const mic_i& b ) { return _mm512_max_epi32(a, b); }
__forceinline const mic_i max( const mic_i& a, const int32& b ) { return max(a,mic_i(b)); }
__forceinline const mic_i max( const int32& a, const mic_i& b ) { return max(mic_i(a),b); }
__forceinline const mic_i mask_add(const mic_m& mask, mic_i& c, const mic_i& a, const mic_i& b) { return _mm512_mask_add_epi32(c,mask,a,b); };
__forceinline const mic_i mask_sub(const mic_m& mask, mic_i& c, const mic_i& a, const mic_i& b) { return _mm512_mask_sub_epi32(c,mask,a,b); };
__forceinline const mic_i mask_and(const mic_m& m,mic_i& c, const mic_i& a, const mic_i& b) { return _mm512_mask_and_epi32(c,m,a,b); };
__forceinline const mic_i mask_or (const mic_m& m,mic_i& c, const mic_i& a, const mic_i& b) { return _mm512_mask_or_epi32(c,m,a,b); };
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_i& operator +=( mic_i& a, const mic_i& b ) { return a = a + b; }
__forceinline mic_i& operator +=( mic_i& a, const int32& b ) { return a = a + b; }
__forceinline mic_i& operator -=( mic_i& a, const mic_i& b ) { return a = a - b; }
__forceinline mic_i& operator -=( mic_i& a, const int32& b ) { return a = a - b; }
__forceinline mic_i& operator *=( mic_i& a, const mic_i& b ) { return a = a * b; }
__forceinline mic_i& operator *=( mic_i& a, const int32& b ) { return a = a * b; }
__forceinline mic_i& operator &=( mic_i& a, const mic_i& b ) { return a = a & b; }
__forceinline mic_i& operator &=( mic_i& a, const int32& b ) { return a = a & b; }
__forceinline mic_i& operator |=( mic_i& a, const mic_i& b ) { return a = a | b; }
__forceinline mic_i& operator |=( mic_i& a, const int32& b ) { return a = a | b; }
__forceinline mic_i& operator <<=( mic_i& a, const int32& b ) { return a = a << b; }
__forceinline mic_i& operator >>=( mic_i& a, const int32& b ) { return a = a >> b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_m operator ==( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
__forceinline const mic_m operator ==( const mic_i& a, const int32& b ) { return a == mic_i(b); }
__forceinline const mic_m operator ==( const int32& a, const mic_i& b ) { return mic_i(a) == b; }
__forceinline const mic_m operator !=( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
__forceinline const mic_m operator !=( const mic_i& a, const int32& b ) { return a != mic_i(b); }
__forceinline const mic_m operator !=( const int32& a, const mic_i& b ) { return mic_i(a) != b; }
__forceinline const mic_m operator < ( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
__forceinline const mic_m operator < ( const mic_i& a, const int32& b ) { return a < mic_i(b); }
__forceinline const mic_m operator < ( const int32& a, const mic_i& b ) { return mic_i(a) < b; }
__forceinline const mic_m operator >=( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
__forceinline const mic_m operator >=( const mic_i& a, const int32& b ) { return a >= mic_i(b); }
__forceinline const mic_m operator >=( const int32& a, const mic_i& b ) { return mic_i(a) >= b; }
__forceinline const mic_m operator > ( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
__forceinline const mic_m operator > ( const mic_i& a, const int32& b ) { return a > mic_i(b); }
__forceinline const mic_m operator > ( const int32& a, const mic_i& b ) { return mic_i(a) > b; }
__forceinline const mic_m operator <=( const mic_i& a, const mic_i& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
__forceinline const mic_m operator <=( const mic_i& a, const int32& b ) { return a <= mic_i(b); }
__forceinline const mic_m operator <=( const int32& a, const mic_i& b ) { return mic_i(a) <= b; }
__forceinline mic_m eq( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); };
__forceinline mic_m eq(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_EQ); };
__forceinline mic_m ne( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); };
__forceinline mic_m ne(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_NE); };
__forceinline mic_m lt( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); };
__forceinline mic_m lt(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LT); };
__forceinline mic_m ge( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); };
__forceinline mic_m ge(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GE); };
__forceinline mic_m gt( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); };
__forceinline mic_m gt(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GT); };
__forceinline mic_m le( const mic_i& a, const mic_i& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); };
__forceinline mic_m le(const mic_m mask, const mic_i& a, const mic_i& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LE); };
__forceinline const mic_i select( const mic_m& m, const mic_i& t, const mic_i& f ) {
return _mm512_mask_or_epi32(f,m,t,t);
}
__forceinline void xchg(const mic_m &m, mic_i& a, mic_i& b) {
const mic_i c = a; a = select(m,b,a); b = select(m,c,b);
}
__forceinline mic_m test(const mic_m &m, const mic_i& a, const mic_i& b) {
return _mm512_mask_test_epi32_mask(m,a,b);
}
__forceinline mic_m test(const mic_i& a, const mic_i& b) {
return _mm512_test_epi32_mask(a,b);
}
////////////////////////////////////////////////////////////////////////////////
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_i swizzle(const mic_i& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_epi32(x,perm32); }
__forceinline mic_i permute(const mic_i& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_epi32(x,perm128); }
template<int D, int C, int B, int A> __forceinline mic_i swizzle (const mic_i& v) { return _mm512_shuffle_epi32(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline mic_i swizzle (const mic_i& x) { return swizzle<A,A,A,A>(v); }
template<> __forceinline mic_i swizzle<0>(const mic_i& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
template<> __forceinline mic_i swizzle<1>(const mic_i& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
template<> __forceinline mic_i swizzle<2>(const mic_i& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
template<> __forceinline mic_i swizzle<3>(const mic_i& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
template<int D, int C, int B, int A> __forceinline mic_i permute(const mic_i& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
template<int A> __forceinline mic_i permute(const mic_i& x) { return permute<A,A,A,A>(x); }
__forceinline mic_i shuffle(const mic_i& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
__forceinline mic_i shuffle(const mic_m& mask, mic_i& v, const mic_i& 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 mic_i swAAAA(const mic_i &x) {
return swizzle(x,_MM_SWIZ_REG_AAAA);
}
__forceinline mic_i swBBBB(const mic_i &x) {
return swizzle(x,_MM_SWIZ_REG_BBBB);
}
__forceinline mic_i swCCCC(const mic_i &x) {
return swizzle(x,_MM_SWIZ_REG_CCCC);
}
__forceinline mic_i swDDDD(const mic_i &x) {
return swizzle(x,_MM_SWIZ_REG_DDDD);
}
template<int i>
__forceinline mic_i align_shift_right(const mic_i &a, const mic_i &b)
{
return _mm512_alignr_epi32(a,b,i);
};
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline int reduce_add(mic_i a) { return _mm512_reduce_add_epi32(a); }
__forceinline int reduce_mul(mic_i a) { return _mm512_reduce_mul_epi32(a); }
__forceinline int reduce_min(mic_i a) { return _mm512_reduce_min_epi32(a); }
__forceinline int reduce_max(mic_i a) { return _mm512_reduce_max_epi32(a); }
__forceinline int reduce_and(mic_i a) { return _mm512_reduce_and_epi32(a); }
__forceinline mic_i vreduce_min2(mic_i x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline mic_i vreduce_min4(mic_i x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline mic_i vreduce_min8(mic_i x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline mic_i vreduce_min (mic_i x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline mic_i vreduce_max2(mic_i x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
__forceinline mic_i vreduce_max4(mic_i x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
__forceinline mic_i vreduce_max8(mic_i x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
__forceinline mic_i vreduce_max (mic_i x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
__forceinline mic_i vreduce_and2(mic_i x) { return x & swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline mic_i vreduce_and4(mic_i x) { x = vreduce_and2(x); return x & swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline mic_i vreduce_and8(mic_i x) { x = vreduce_and4(x); return x & permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline mic_i vreduce_and (mic_i x) { x = vreduce_and8(x); return x & permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline mic_i vreduce_or2(mic_i x) { return x | swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline mic_i vreduce_or4(mic_i x) { x = vreduce_or2(x); return x | swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline mic_i vreduce_or8(mic_i x) { x = vreduce_or4(x); return x | permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline mic_i vreduce_or (mic_i x) { x = vreduce_or8(x); return x | permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline mic_i vreduce_add2(mic_i x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
__forceinline mic_i vreduce_add4(mic_i x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
__forceinline mic_i vreduce_add8(mic_i x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
__forceinline mic_i vreduce_add (mic_i x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
__forceinline mic_i prefix_sum(const mic_i& a)
{
mic_i 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 mic_i 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 mic_i 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 mic_i load1i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline mic_i load16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
}
__forceinline mic_i load1i_uint8(const unsigned char *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline mic_i load16i_uint8(const unsigned char *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST32_NONE,_MM_HINT_NONE);
}
__forceinline mic_i broadcast4to16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
__forceinline mic_i broadcast1to16i(const int *const ptr) {
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
}
__forceinline mic_i uload16i(const int *const addr) {
mic_i 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 mic_i uload16i_low(const mic_m& mask, const void* addr) {
mic_i v = _mm512_undefined_epi32();
return _mm512_mask_extloadunpacklo_epi32(v, mask, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline mic_i uload16i(const mic_m& mask,const int *const addr) {
mic_i 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 mic_i gather16i_4i(const int *__restrict__ const ptr0,
const int *__restrict__ const ptr1,
const int *__restrict__ const ptr2,
const int *__restrict__ const ptr3)
{
mic_i v = broadcast4to16i(ptr0);
v = select((mic_m)0xf0 , broadcast4to16i(ptr1),v);
v = select((mic_m)0xf00 , broadcast4to16i(ptr2),v);
v = select((mic_m)0xf000, broadcast4to16i(ptr3),v);
return v;
}
__forceinline mic_i gather16i_4i_align(const void *__restrict__ const ptr0,
const void *__restrict__ const ptr1,
const void *__restrict__ const ptr2,
const void *__restrict__ const ptr3)
{
mic_i 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 mic_i gather16i_4i_align(const mic_i &v0,
const mic_i &v1,
const mic_i &v2,
const mic_i &v3)
{
mic_i 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 mic_i gather16i(const mic_m& mask, const int *const ptr, const mic_i& 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 mic_i gather16i(const mic_m& mask, mic_i& dest, const int *const ptr, const mic_i& 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 mic_m& mask,int *const ptr, const mic_i& index,const mic_i& 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 mic_i& 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 mic_m mask,void * addr, const mic_i 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 mic_m mask, void *addr, const mic_i &reg) {
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void store1i(void *addr, const mic_i& reg) {
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,(mic_m)1, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void ustore16i_low(void *addr, const mic_i& reg) {
_mm512_extpackstorelo_epi32((int*)addr+0 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline void compactustore16i_high(const mic_m mask, int *addr, const mic_i& 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 mic_i& a) {
_mm512_storenr_ps(ptr,_mm512_castsi512_ps(a));
}
__forceinline void store16i_ngo(void *__restrict__ ptr, const mic_i& a) {
_mm512_storenrngo_ps(ptr,_mm512_castsi512_ps(a));
}
__forceinline void store16i(const mic_m& mask, void* __restrict__ addr, const mic_i& v2) {
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
}
__forceinline void store16i_nt(void* __restrict__ addr, const mic_i& v2) {
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NT);
}
__forceinline void store16i(void* __restrict__ addr, const mic_i& v2) {
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
}
__forceinline void store16i_uint8(const mic_m& mask, void* __restrict__ addr, const mic_i& v2) {
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_UINT8,_MM_HINT_NONE);
}
__forceinline mic_i convert_uint32(const __m512 f) {
return _mm512_cvtfxpnt_round_adjustps_epu32(f,_MM_FROUND_TO_ZERO,_MM_EXPADJ_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline std::ostream &operator<<(std::ostream& cout, const mic_i& v)
{
cout << "<" << v[0];
for (int i=1; i<16; i++) cout << ", " << v[i];
cout << ">";
return cout;
}
}
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,43 +14,44 @@
// limitations under the License. //
// ======================================================================== //
#include "parallel_set.h"
#include "../sys/regression.h"
#include "mic.h"
namespace embree
{
struct parallel_set_regression_test : public RegressionTest
{
parallel_set_regression_test(const char* name) : RegressionTest(name) {
registerRegressionTest(this);
}
bool run ()
{
bool passed = true;
/* create vector with random numbers */
const size_t N = 10000;
std::vector<uint32_t> unsorted(N);
for (size_t i=0; i<N; i++) unsorted[i] = 2*rand();
/* created set from numbers */
parallel_set<uint32_t> sorted;
sorted.init(unsorted);
/* check that all elements are in the set */
for (size_t i=0; i<N; i++) {
passed &= sorted.lookup(unsorted[i]);
}
/* check that these elements are not in the set */
for (size_t i=0; i<N; i++) {
passed &= !sorted.lookup(unsorted[i]+1);
}
return passed;
}
__aligned(64) unsigned int mic_m::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)
};
parallel_set_regression_test parallel_set_regression("parallel_set_regression_test");
}
};
+121
View File
@@ -0,0 +1,121 @@
// ======================================================================== //
// Copyright 2009-2014 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 mic_m
{
public:
__mmask v;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_m () {};
__forceinline mic_m (const mic_m &t) { v = t.v; };
__forceinline mic_m& operator=(const mic_m &f) { v = f.v; return *this; };
__forceinline mic_m (const __mmask &t) { v = t; };
__forceinline operator __mmask () const { return v; };
__forceinline mic_m(bool b) { v = b ? 0xFFFF : 0x0000; };
__forceinline mic_m(int t ) { v = (__mmask)t; };
__forceinline mic_m(unsigned int t ) { v = (__mmask)t; };
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_m( FalseTy ) : v(0x0000) {}
__forceinline mic_m( TrueTy ) : v(0xffff) {}
static unsigned int shift1[32];
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_m operator!(const mic_m &a) { return _mm512_knot(a); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline mic_m operator&(const mic_m &a, const mic_m &b) { return _mm512_kand(a,b); };
__forceinline mic_m operator|(const mic_m &a, const mic_m &b) { return _mm512_kor(a,b); };
__forceinline mic_m operator^(const mic_m &a, const mic_m &b) { return _mm512_kxor(a,b); };
__forceinline mic_m andn(const mic_m &a, const mic_m &b) { return _mm512_kandn(b,a); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_m operator &=( mic_m& a, const mic_m& b ) { return a = a & b; }
__forceinline const mic_m operator |=( mic_m& a, const mic_m& b ) { return a = a | b; }
__forceinline const mic_m operator ^=( mic_m& a, const mic_m& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const mic_m operator !=( const mic_m& a, const mic_m& b ) { return _mm512_kxor(a, b); }
__forceinline const mic_m operator ==( const mic_m& a, const mic_m& b ) { return _mm512_kxnor(a, b); }
__forceinline mic_m select (const mic_m &s, const mic_m &a, const mic_m &b) {
return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline int all(const mic_m &a) { return _mm512_kortestc(a,a) != 0; }
__forceinline int any(const mic_m &a) { return _mm512_kortestz(a,a) == 0; }
__forceinline int none(const mic_m &a) { return _mm512_kortestz(a,a) != 0; }
__forceinline int all ( const mic_m& valid, const mic_m& b ) { return all(!valid | b); }
__forceinline int any ( const mic_m& valid, const mic_m& b ) { return any( valid & b); }
__forceinline int none ( const mic_m& valid, const mic_m& b ) { return none(valid & b); }
__forceinline size_t movemask( const mic_m& a ) { return _mm512_kmov(a); }
__forceinline size_t popcnt ( const mic_m& a ) { return _mm_countbits_32(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Convertion Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline unsigned int toInt (const mic_m &a) { return _mm512_mask2int(a); };
__forceinline mic_m toMask(const int &a) { return _mm512_int2mask(a); };
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const mic_m& a)
{
cout << "<";
for (size_t i=0; i<16; i++) {
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
}
return cout << ">";
}
}
+13 -72
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,85 +16,26 @@
#pragma once
#include "../math/math.h"
#include "math/math.h"
/* include SSE emulation for Xeon Phi */
#if defined (__MIC__)
# include "simd/sse_mic.h"
# include "simd/mic.h"
#endif
/* include SSE wrapper classes */
#if defined(__SSE__)
# include "sse.h"
# include "simd/sse.h"
#endif
/* include AVX wrapper classes */
#if defined(__AVX__)
# include "avx.h"
#include "simd/avx.h"
#endif
/* include AVX512 wrapper classes */
#if defined (__AVX512F__)
# include "avx512.h"
#endif
#if defined(__AVX512F__)
# define AVX_ZERO_UPPER()
#elif defined (__AVX__)
# define AVX_ZERO_UPPER() _mm256_zeroupper()
#if defined (__AVX__)
#define AVX_ZERO_UPPER() _mm256_zeroupper()
#else
# define AVX_ZERO_UPPER()
#define AVX_ZERO_UPPER()
#endif
namespace embree
{
/* foreach unique */
template<typename vbool, typename vint, typename 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 i = vi[j];
const vbool valid2 = valid1 & (i == vi);
valid1 = valid1 & !valid2;
closure(valid2,i);
}
}
/* foreach unique */
template<typename vbool, typename vint, typename 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 i = vi[j];
const vbool valid2 = valid1 & (i == vi);
valid1 = valid1 & !valid2;
closure(valid2,i,j);
}
}
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];
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);
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);
index = 0;
}
}
}
}
}
+114
View File
@@ -0,0 +1,114 @@
// ======================================================================== //
// Copyright 2009-2014 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
#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*)(_r + i)) = *((int32*)(_v + i))* *((int32*)(_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* ptr = (int32*)&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 input, const int index ) {
assert(size_t(index) < 4); ((__int64*)&value)[index] = input; return value;
}
#define _mm_extract_epi64 __emu_mm_extract_epi64
__forceinline __int64 _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-2014 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))
};
}
+34 -23
View File
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,32 +16,43 @@
#pragma once
#include "../sys/platform.h"
#include "../sys/intrinsics.h"
#include "../math/constants.h"
#include "varying.h"
#include "sys/platform.h"
#include "sys/intrinsics.h"
#include "sse_special.h"
namespace embree
{
#if defined(__SSE4_1__)
__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) {
/* Workaround for Compiler bug in VS2008 */
#if !defined(__SSE4_1__) || defined(_MSC_VER) && (_MSC_VER < 1600) && !defined(__INTEL_COMPILER)
#define _mm_blendv_ps __emu_mm_blendv_ps
__forceinline __m128 _mm_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];
/* Workaround for Compiler bug in VS2008 */
#if defined(_MSC_VER) && (_MSC_VER < 1600) && !defined(__INTEL_COMPILER)
#define _mm_extract_epi32 __emu_mm_extract_epi32
__forceinline int _mm_extract_epi32( __m128i input, const int i ) {
return input.m128i_i32[i];
}
#endif
namespace embree
{
extern const __m128 _mm_lookupmask_ps[16];
struct sseb;
struct ssei;
struct ssef;
#if !defined(__MIC__)
typedef ssef ssef_t;
typedef ssei ssei_t;
typedef ssef ssef_m;
typedef ssei ssei_m;
#endif
}
#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 "simd/sseb.h"
#include "simd/ssei.h"
#include "simd/ssef.h"
@@ -1,5 +1,5 @@
// ======================================================================== //
// Copyright 2009-2017 Intel Corporation //
// Copyright 2009-2014 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,38 @@
// limitations under the License. //
// ======================================================================== //
#include "light.h"
#pragma once
#include "sys/platform.h"
#include "sys/intrinsics.h"
#include <immintrin.h>
namespace embree {
Light_EvalRes Light_eval(const Light* uniform,
const DifferentialGeometry&,
const Vec3fa&)
{
Light_EvalRes res;
res.value = Vec3fa(0.f);
res.dist = inf;
res.pdf = 0.f;
return res;
struct sseb_t;
struct ssei_t;
struct ssef_t;
struct sseb_m;
struct ssei_m;
struct ssef_m;
}
extern "C" void dummy() {} // just to avoid linker warning under MacOSX
} // namespace embree
#include "simd/sseb_mic.h"
#include "simd/ssei_mic.h"
#include "simd/ssef_mic.h"
namespace embree {
typedef sseb_m sseb;
typedef ssei_m ssei;
typedef ssef_m ssef;
__forceinline const ssei cast( const ssef& a ) { return *(ssei*)&a; }
__forceinline const ssef cast( const ssei& a ) { return *(ssef*)&a; }
__forceinline ssei_t floor_i( const ssef_t& other )
{
const __m512i m512 = _mm512_cvtfxpnt_round_adjustps_epi32(other.m512,_MM_FROUND_FLOOR,_MM_EXPADJ_NONE);
return ssei_t(m512);
}
}
+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);
}
+163
View File
@@ -0,0 +1,163 @@
// ======================================================================== //
// Copyright 2009-2014 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 sseb
{
typedef sseb Mask; // mask type
typedef ssei Int; // int type
typedef ssef Float; // float type
enum { size = 4 }; // number of SIMD elements
union { __m128 m128; int32 v[4]; }; // data
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline sseb ( ) {}
__forceinline sseb ( const sseb& other ) { m128 = other.m128; }
__forceinline sseb& operator=( const sseb& other ) { m128 = other.m128; return *this; }
__forceinline sseb( 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 sseb ( bool a )
: m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
__forceinline sseb ( bool a, bool b)
: m128(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
__forceinline sseb ( 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 sseb(int mask) {
assert(mask >= 0 && mask < 16);
m128 = _mm_lookupmask_ps[mask];
}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline sseb( FalseTy ) : m128(_mm_setzero_ps()) {}
__forceinline sseb( 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 int32& operator []( const size_t i ) { assert(i < 4); return v[i]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb operator !( const sseb& a ) { return _mm_xor_ps(a, sseb(True)); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb operator &( const sseb& a, const sseb& b ) { return _mm_and_ps(a, b); }
__forceinline const sseb operator |( const sseb& a, const sseb& b ) { return _mm_or_ps (a, b); }
__forceinline const sseb operator ^( const sseb& a, const sseb& b ) { return _mm_xor_ps(a, b); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb operator &=( sseb& a, const sseb& b ) { return a = a & b; }
__forceinline const sseb operator |=( sseb& a, const sseb& b ) { return a = a | b; }
__forceinline const sseb operator ^=( sseb& a, const sseb& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb operator !=( const sseb& a, const sseb& b ) { return _mm_xor_ps(a, b); }
__forceinline const sseb operator ==( const sseb& a, const sseb& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
__forceinline const sseb select( const sseb& m, const sseb& t, const sseb& 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 sseb unpacklo( const sseb& a, const sseb& b ) { return _mm_unpacklo_ps(a, b); }
__forceinline const sseb unpackhi( const sseb& a, const sseb& b ) { return _mm_unpackhi_ps(a, b); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& 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 sseb shuffle( const sseb& a, const sseb& b ) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
#if defined(__SSE3__)
template<> __forceinline const sseb shuffle<0, 0, 2, 2>( const sseb& a ) { return _mm_moveldup_ps(a); }
template<> __forceinline const sseb shuffle<1, 1, 3, 3>( const sseb& a ) { return _mm_movehdup_ps(a); }
template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& 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 sseb insert( const sseb& a, const sseb& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<size_t dst, size_t src> __forceinline const sseb insert( const sseb& a, const sseb& b ) { return insert<dst, src, 0>(a, b); }
template<size_t dst> __forceinline const sseb insert( const sseb& a, const bool b ) { return insert<dst,0>(a, sseb(b)); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const sseb& a ) { return _mm_movemask_ps(a) == 0xf; }
__forceinline bool reduce_or ( const sseb& a ) { return _mm_movemask_ps(a) != 0x0; }
__forceinline bool all ( const sseb& b ) { return _mm_movemask_ps(b) == 0xf; }
__forceinline bool any ( const sseb& b ) { return _mm_movemask_ps(b) != 0x0; }
__forceinline bool none ( const sseb& b ) { return _mm_movemask_ps(b) == 0x0; }
__forceinline bool all ( const sseb& valid, const sseb& b ) { return all(!valid | b); }
__forceinline bool any ( const sseb& valid, const sseb& b ) { return any( valid & b); }
__forceinline bool none ( const sseb& valid, const sseb& b ) { return none(valid & b); }
__forceinline size_t movemask( const sseb& a ) { return _mm_movemask_ps(a); }
#if defined(__SSE4_2__)
__forceinline size_t popcnt( const sseb& a ) { return __popcnt(_mm_movemask_ps(a)); }
#else
__forceinline size_t popcnt( const sseb& 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 sseb& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+148
View File
@@ -0,0 +1,148 @@
// ======================================================================== //
// Copyright 2009-2014 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
{
/* memory representation as bit vector */
struct __aligned(16) sseb_m
{
enum { size = 4 }; // number of SIMD elements
int32 v[4];
__forceinline sseb_m ( ) {}
__forceinline sseb_m ( bool a ) {
v[0] = a ? -1 : 0;
v[1] = a ? -1 : 0;
v[2] = a ? -1 : 0;
v[3] = a ? -1 : 0;
}
__forceinline sseb_m ( bool a, bool b ) {
v[0] = a ? -1 : 0;
v[1] = b ? -1 : 0;
v[2] = a ? -1 : 0;
v[3] = b ? -1 : 0;
}
__forceinline sseb_m ( bool a, bool b, bool c, bool d ) {
v[0] = a ? -1 : 0;
v[1] = b ? -1 : 0;
v[2] = c ? -1 : 0;
v[3] = d ? -1 : 0;
}
__forceinline sseb_m ( const sseb_t& other );
__forceinline sseb_m& operator=( const sseb_t& other );
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline sseb_m( FalseTy ) { v[0] = v[1] = v[2] = v[3] = 0; }
__forceinline sseb_m( TrueTy ) { v[0] = v[1] = v[2] = v[3] = -1; }
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline bool operator []( const size_t i ) const { assert(i < 4); return v[i] != 0; }
__forceinline int32& operator []( const size_t i ) { assert(i < 4); return v[i]; }
};
/*! 4-wide bool type emulated with 16-wide bit vectors. */
struct sseb_t
{
__mmask16 v;
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline sseb_t ( const __mmask16 a ) : v(a) {}
__forceinline sseb_t ( const sseb_t& other ) { v = other.v; }
__forceinline sseb_t& operator=( const sseb_t& other ) { v = other.v; return *this; }
__forceinline sseb_t ( const sseb_m& other ) {
__m512i i = _mm512_extload_epi32(&other,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
v = _mm512_cmp_epi32_mask(i,_mm512_set1_epi32(0),_MM_CMPINT_NE);
}
};
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline sseb_m::sseb_m ( const sseb_t& other ) {
__m512i i = _mm512_mask_blend_epi32(other.v, _mm512_set1_epi32(0), _mm512_set1_epi32(-1));
_mm512_mask_extpackstorelo_epi32(this,0xf,i,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
}
__forceinline sseb_m& sseb_m::operator=( const sseb_t& other ) {
__m512i i = _mm512_mask_blend_epi32(other.v, _mm512_set1_epi32(0), _mm512_set1_epi32(-1));
_mm512_mask_extpackstorelo_epi32(this,0xf,i,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb_t operator !( const sseb_t& a ) { return _mm512_knot(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb_t operator &( const sseb_t& a, const sseb_t& b ) { return _mm512_kand(a.v, b.v); }
__forceinline const sseb_t operator |( const sseb_t& a, const sseb_t& b ) { return _mm512_kor (a.v, b.v); }
__forceinline const sseb_t operator ^( const sseb_t& a, const sseb_t& b ) { return _mm512_kxor(a.v, b.v); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb_t operator &=( sseb_m& a, const sseb_t& b ) { return a = a & b; }
__forceinline const sseb_t operator |=( sseb_m& a, const sseb_t& b ) { return a = a | b; }
__forceinline const sseb_t operator ^=( sseb_m& a, const sseb_t& b ) { return a = a ^ b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb_t operator !=( const sseb_t& a, const sseb_t& b ) { return _mm512_kxor (a.v, b.v); }
__forceinline const sseb_t operator ==( const sseb_t& a, const sseb_t& b ) { return _mm512_kxnor(a.v, b.v); }
__forceinline const sseb_t select( const sseb_t& m, const sseb_t& a, const sseb_t& b ) { return _mm512_kor(_mm512_kand(m.v, a.v), _mm512_kandn(m.v, b.v)); }
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
__forceinline bool reduce_and( const sseb_t& a ) { return (a.v & 0xf) == 0xf; }
__forceinline bool reduce_or ( const sseb_t& a ) { return (a.v & 0xf) != 0x0; }
__forceinline bool all ( const sseb_t& a ) { return (a.v & 0xf) == 0xf; }
__forceinline bool any ( const sseb_t& a ) { return (a.v & 0xf) != 0x0; }
__forceinline bool none ( const sseb_t& a ) { return (a.v & 0xf) == 0x0; }
__forceinline size_t movemask( const sseb_t& a ) { return a.v & 0xf; }
__forceinline size_t popcnt( const sseb_t& a ) { return __popcnt(a.v); }
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const sseb_m& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+415
View File
@@ -0,0 +1,415 @@
// ======================================================================== //
// Copyright 2009-2014 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 float type. */
struct ssef
{
typedef sseb Mask; // mask type
typedef ssei Int; // int type
typedef ssef 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 ssef ( ) {}
__forceinline ssef ( const ssef& other ) { m128 = other.m128; }
__forceinline ssef& operator=( const ssef& other ) { m128 = other.m128; return *this; }
__forceinline ssef( const __m128 a ) : m128(a) {}
__forceinline operator const __m128&( void ) const { return m128; }
__forceinline operator __m128&( void ) { return m128; }
__forceinline ssef ( float a ) : m128(_mm_set1_ps(a)) {}
__forceinline ssef ( float a, float b, float c, float d) : m128(_mm_set_ps(d, c, b, a)) {}
__forceinline explicit ssef( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef( ZeroTy ) : m128(_mm_setzero_ps()) {}
__forceinline ssef( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
__forceinline ssef( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
__forceinline ssef( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
__forceinline ssef( StepTy ) : m128(_mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)) {}
__forceinline ssef( NaNTy ) : m128(_mm_set1_ps(nan)) {}
////////////////////////////////////////////////////////////////////////////////
/// Loads and Stores
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX__)
static __forceinline ssef broadcast( const void* const a ) { return _mm_broadcast_ss((float*)a); }
#else
static __forceinline ssef broadcast( const void* const a ) { return _mm_set1_ps(*(float*)a); }
#endif
////////////////////////////////////////////////////////////////////////////////
/// 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]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef cast (const __m128i& a) { return _mm_castsi128_ps(a); }
__forceinline const ssef operator +( const ssef& a ) { return a; }
__forceinline const ssef operator -( const ssef& a ) { return _mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
__forceinline const ssef abs ( const ssef& a ) { return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
__forceinline const ssef sign ( const ssef& a ) { return _mm_blendv_ps(ssef(one), -ssef(one), _mm_cmplt_ps (a,ssef(zero))); }
__forceinline const ssef signmsk ( const ssef& a ) { return _mm_and_ps(a.m128,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
__forceinline const ssef rcp ( const ssef& a ) {
const ssef r = _mm_rcp_ps(a.m128);
return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
}
__forceinline const ssef sqr ( const ssef& a ) { return _mm_mul_ps(a,a); }
__forceinline const ssef sqrt ( const ssef& a ) { return _mm_sqrt_ps(a.m128); }
__forceinline const ssef rsqrt( const ssef& a ) {
const ssef 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 ssef operator +( const ssef& a, const ssef& b ) { return _mm_add_ps(a.m128, b.m128); }
__forceinline const ssef operator +( const ssef& a, const float& b ) { return a + ssef(b); }
__forceinline const ssef operator +( const float& a, const ssef& b ) { return ssef(a) + b; }
__forceinline const ssef operator -( const ssef& a, const ssef& b ) { return _mm_sub_ps(a.m128, b.m128); }
__forceinline const ssef operator -( const ssef& a, const float& b ) { return a - ssef(b); }
__forceinline const ssef operator -( const float& a, const ssef& b ) { return ssef(a) - b; }
__forceinline const ssef operator *( const ssef& a, const ssef& b ) { return _mm_mul_ps(a.m128, b.m128); }
__forceinline const ssef operator *( const ssef& a, const float& b ) { return a * ssef(b); }
__forceinline const ssef operator *( const float& a, const ssef& b ) { return ssef(a) * b; }
__forceinline const ssef operator /( const ssef& a, const ssef& b ) { return _mm_div_ps(a.m128,b.m128); }
__forceinline const ssef operator /( const ssef& a, const float& b ) { return a/ssef(b); }
__forceinline const ssef operator /( const float& a, const ssef& b ) { return ssef(a)/b; }
__forceinline const ssef operator^( const ssef& a, const ssef& b ) { return _mm_xor_ps(a.m128,b.m128); }
__forceinline const ssef operator^( const ssef& a, const ssei& b ) { return _mm_xor_ps(a.m128,_mm_castsi128_ps(b.m128)); }
__forceinline const ssef min( const ssef& a, const ssef& b ) { return _mm_min_ps(a.m128,b.m128); }
__forceinline const ssef min( const ssef& a, const float& b ) { return _mm_min_ps(a.m128,ssef(b)); }
__forceinline const ssef min( const float& a, const ssef& b ) { return _mm_min_ps(ssef(a),b.m128); }
__forceinline const ssef max( const ssef& a, const ssef& b ) { return _mm_max_ps(a.m128,b.m128); }
__forceinline const ssef max( const ssef& a, const float& b ) { return _mm_max_ps(a.m128,ssef(b)); }
__forceinline const ssef max( const float& a, const ssef& b ) { return _mm_max_ps(ssef(a),b.m128); }
#if defined(__SSE4_1__)
__forceinline ssef mini(const ssef& a, const ssef& b) {
const ssei ai = _mm_castps_si128(a);
const ssei bi = _mm_castps_si128(b);
const ssei ci = _mm_min_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
#if defined(__SSE4_1__)
__forceinline ssef maxi(const ssef& a, const ssef& b) {
const ssei ai = _mm_castps_si128(a);
const ssei bi = _mm_castps_si128(b);
const ssei ci = _mm_max_epi32(ai,bi);
return _mm_castsi128_ps(ci);
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
#if defined(__AVX2__)
__forceinline const ssef madd ( const ssef& a, const ssef& b, const ssef& c) { return _mm_fmadd_ps(a,b,c); }
__forceinline const ssef msub ( const ssef& a, const ssef& b, const ssef& c) { return _mm_fmsub_ps(a,b,c); }
__forceinline const ssef nmadd ( const ssef& a, const ssef& b, const ssef& c) { return _mm_fnmadd_ps(a,b,c); }
__forceinline const ssef nmsub ( const ssef& a, const ssef& b, const ssef& c) { return _mm_fnmsub_ps(a,b,c); }
#else
__forceinline const ssef madd ( const ssef& a, const ssef& b, const ssef& c) { return a*b+c; }
__forceinline const ssef msub ( const ssef& a, const ssef& b, const ssef& c) { return a*b-c; }
__forceinline const ssef nmadd ( const ssef& a, const ssef& b, const ssef& c) { return -a*b-c;}
__forceinline const ssef nmsub ( const ssef& a, const ssef& b, const ssef& c) { return c-a*b; }
#endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef& operator +=( ssef& a, const ssef& b ) { return a = a + b; }
__forceinline ssef& operator +=( ssef& a, const float& b ) { return a = a + b; }
__forceinline ssef& operator -=( ssef& a, const ssef& b ) { return a = a - b; }
__forceinline ssef& operator -=( ssef& a, const float& b ) { return a = a - b; }
__forceinline ssef& operator *=( ssef& a, const ssef& b ) { return a = a * b; }
__forceinline ssef& operator *=( ssef& a, const float& b ) { return a = a * b; }
__forceinline ssef& operator /=( ssef& a, const ssef& b ) { return a = a / b; }
__forceinline ssef& operator /=( ssef& a, const float& b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb operator ==( const ssef& a, const ssef& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
__forceinline const sseb operator ==( const ssef& a, const float& b ) { return a == ssef(b); }
__forceinline const sseb operator ==( const float& a, const ssef& b ) { return ssef(a) == b; }
__forceinline const sseb operator !=( const ssef& a, const ssef& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
__forceinline const sseb operator !=( const ssef& a, const float& b ) { return a != ssef(b); }
__forceinline const sseb operator !=( const float& a, const ssef& b ) { return ssef(a) != b; }
__forceinline const sseb operator < ( const ssef& a, const ssef& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
__forceinline const sseb operator < ( const ssef& a, const float& b ) { return a < ssef(b); }
__forceinline const sseb operator < ( const float& a, const ssef& b ) { return ssef(a) < b; }
__forceinline const sseb operator >=( const ssef& a, const ssef& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
__forceinline const sseb operator >=( const ssef& a, const float& b ) { return a >= ssef(b); }
__forceinline const sseb operator >=( const float& a, const ssef& b ) { return ssef(a) >= b; }
__forceinline const sseb operator > ( const ssef& a, const ssef& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
__forceinline const sseb operator > ( const ssef& a, const float& b ) { return a > ssef(b); }
__forceinline const sseb operator > ( const float& a, const ssef& b ) { return ssef(a) > b; }
__forceinline const sseb operator <=( const ssef& a, const ssef& b ) { return _mm_cmple_ps (a.m128, b.m128); }
__forceinline const sseb operator <=( const ssef& a, const float& b ) { return a <= ssef(b); }
__forceinline const sseb operator <=( const float& a, const ssef& b ) { return ssef(a) <= b; }
__forceinline const ssef select( const sseb& m, const ssef& t, const ssef& 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
}
#if defined(__SSE4_1__)
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
__forceinline const ssef select(const int mask, const ssef& t, const ssef& f) {
return select(sseb(mask), t, f);
}
#else
__forceinline const ssef select(const int mask, const ssef& t, const ssef& f) {
return _mm_blend_ps(f, t, mask);
}
#endif
#endif
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
#if defined (__SSE4_1__)
__forceinline const ssef round_even( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
__forceinline const ssef round_down( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const ssef round_up ( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
__forceinline const ssef round_zero( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
__forceinline const ssef floor ( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
__forceinline const ssef ceil ( const ssef& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
#endif
__forceinline ssei floori (const ssef& a) {
#if defined (__SSE4_1__)
return ssei(floor(a));
#else
return ssei(a-ssef(0.5f));
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef unpacklo( const ssef& a, const ssef& b ) { return _mm_unpacklo_ps(a.m128, b.m128); }
__forceinline ssef unpackhi( const ssef& a, const ssef& b ) { return _mm_unpackhi_ps(a.m128, b.m128); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef shuffle( const ssef& 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 ssef shuffle( const ssef& a, const ssef& b ) {
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
#if defined (__SSSE3__)
__forceinline const ssef shuffle8(const ssef& a, const ssei& shuf) {
return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
}
#endif
#if defined(__SSE3__)
template<> __forceinline const ssef shuffle<0, 0, 2, 2>( const ssef& b ) { return _mm_moveldup_ps(b); }
template<> __forceinline const ssef shuffle<1, 1, 3, 3>( const ssef& b ) { return _mm_movehdup_ps(b); }
template<> __forceinline const ssef shuffle<0, 1, 0, 1>( const ssef& b ) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))); }
#endif
template<size_t i0> __forceinline const ssef shuffle( const ssef& b ) {
return shuffle<i0,i0,i0,i0>(b);
}
#if defined (__SSE4_1__) && !defined(__GNUC__)
template<size_t i> __forceinline float extract ( const ssef& a ) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); }
#else
template<size_t i> __forceinline float extract ( const ssef& a ) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
#endif
template<> __forceinline float extract<0>( const ssef& a ) { return _mm_cvtss_f32(a); }
#if defined (__SSE4_1__)
template<size_t dst, size_t src, size_t clr> __forceinline const ssef insert( const ssef& a, const ssef& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<size_t dst, size_t src> __forceinline const ssef insert( const ssef& a, const ssef& b ) { return insert<dst, src, 0>(a, b); }
template<size_t dst> __forceinline const ssef insert( const ssef& a, const float b ) { return insert<dst, 0>(a, _mm_set_ss(b)); }
#else
template<size_t dst> __forceinline const ssef insert( const ssef& a, const float b ) { ssef c = a; c[dst] = b; return c; }
#endif
__forceinline ssef broadcast4f( const ssef& a, const size_t k ) {
return ssef::broadcast(&a[k]);
}
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
__forceinline void transpose(const ssef& r0, const ssef& r1, const ssef& r2, const ssef& r3, ssef& c0, ssef& c1, ssef& c2, ssef& c3)
{
ssef l02 = unpacklo(r0,r2);
ssef h02 = unpackhi(r0,r2);
ssef l13 = unpacklo(r1,r3);
ssef h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
c3 = unpackhi(h02,h13);
}
__forceinline void transpose(const ssef& r0, const ssef& r1, const ssef& r2, const ssef& r3, ssef& c0, ssef& c1, ssef& c2)
{
ssef l02 = unpacklo(r0,r2);
ssef h02 = unpackhi(r0,r2);
ssef l13 = unpacklo(r1,r3);
ssef h13 = unpackhi(r1,r3);
c0 = unpacklo(l02,l13);
c1 = unpackhi(l02,l13);
c2 = unpacklo(h02,h13);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef vreduce_min(const ssef& v) { ssef h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline const ssef vreduce_max(const ssef& v) { ssef h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline const ssef vreduce_add(const ssef& v) { ssef h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
__forceinline float reduce_min(const ssef& v) { return _mm_cvtss_f32(vreduce_min(v)); }
__forceinline float reduce_max(const ssef& v) { return _mm_cvtss_f32(vreduce_max(v)); }
__forceinline float reduce_add(const ssef& v) { return _mm_cvtss_f32(vreduce_add(v)); }
__forceinline size_t select_min(const ssef& v) { return __bsf(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const ssef& v) { return __bsf(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
__forceinline size_t select_max(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef load4f( const void* const a ) {
return _mm_load_ps((float*)a);
}
__forceinline void store4f ( void* ptr, const ssef& v ) {
_mm_store_ps((float*)ptr,v);
}
__forceinline ssef loadu4f( const void* const a ) {
return _mm_loadu_ps((float*)a);
}
__forceinline void storeu4f ( void* ptr, const ssef& v ) {
_mm_storeu_ps((float*)ptr,v);
}
__forceinline void store4f ( const sseb& mask, void* ptr, const ssef& f ) {
#if defined (__AVX__)
_mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
#else
*(ssef*)ptr = select(mask,f,*(ssef*)ptr);
#endif
}
__forceinline ssef 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 ssef& 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 ssef& a, const ssef& b ) {
return reduce_add(a*b);
}
__forceinline ssef cross ( const ssef& a, const ssef& b )
{
const ssef a0 = a;
const ssef b0 = shuffle<1,2,0,3>(b);
const ssef a1 = shuffle<1,2,0,3>(a);
const ssef b1 = b;
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const ssef& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}
+352
View File
@@ -0,0 +1,352 @@
// ======================================================================== //
// Copyright 2009-2014 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
{
/* memory representation as 4 aligned floats */
struct __aligned(16) ssef_m
{
typedef sseb_m Mask;
typedef ssei_m Int;
typedef ssef_m Float;
enum { size = 4 }; // number of SIMD elements
union {
float f[4];
int i[4];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef_m ( ) {}
__forceinline ssef_m ( float a ) { f[0] = a; f[1] = a; f[2] = a; f[3] = a; }
__forceinline ssef_m ( float a, float b, float c, float d) { f[0] = a; f[1] = b; f[2] = c; f[3] = d; }
__forceinline ssef_m ( const ssef_t& other );
__forceinline ssef_m& operator=( const ssef_t& other );
////////////////////////////////////////////////////////////////////////////////
/// Constants
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef_m( ZeroTy ) { f[0] = f[1] = f[2] = f[3] = zero; }
__forceinline ssef_m( OneTy ) { f[0] = f[1] = f[2] = f[3] = one; }
__forceinline ssef_m( NegInfTy ) { f[0] = f[1] = f[2] = f[3] = neg_inf; }
__forceinline ssef_m( PosInfTy ) { f[0] = f[1] = f[2] = f[3] = pos_inf; }
__forceinline ssef_m( StepTy ) { f[0] = 0.0f; f[1] = 1.0f; f[2] = 2.0f; f[3] = 3.0f; }
__forceinline ssef_m( NaNTy ) { f[0] = f[1] = f[2] = f[3] = nan; }
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const float& operator []( const size_t index ) const { assert(index < 4); return f[index]; }
__forceinline float& operator []( const size_t index ) { assert(index < 4); return f[index]; }
};
/*! 4-wide SSE float type emulated with 16-wide vectors. */
struct __aligned(64) ssef_t
{
union {
__m512 m512;
float f[4];
int i[4];
};
////////////////////////////////////////////////////////////////////////////////
/// Constructors, Assignment & Cast Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef_t( const __m512 a ) : m512(a) {}
__forceinline ssef_t ( const ssef_t& other ) { m512 = other.m512; }
__forceinline ssef_t& operator=( const ssef_t& other ) { m512 = other.m512; return *this; }
__forceinline operator const __m512&( void ) const { return m512; }
__forceinline operator __m512&( void ) { return m512; }
__forceinline ssef_t( const ssei_t& v );
public:
__forceinline explicit ssef_t ( float a )
: m512(_mm512_set1_ps(a)) {}
__forceinline ssef_t ( const ssef_m& other ) {
m512 = _mm512_extload_ps(&other,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
////////////////////////////////////////////////////////////////////////////////
/// Array Access
////////////////////////////////////////////////////////////////////////////////
__forceinline const float& operator []( const size_t index ) const { assert(index < 4); return f[index]; }
__forceinline float& operator []( const size_t index ) { assert(index < 4); return f[index]; }
};
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
/* __forceinline ssei_m::ssei_m ( const ssef_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 ssef_t::ssef_t( const ssei_t& v ) {
m512 = _mm512_cvtfxpnt_round_adjustepi32_ps(v,_MM_ROUND_MODE_NEAREST,_MM_EXPADJ_NONE);
}
__forceinline ssei_t::ssei_t ( const ssef_t& other )
{
m512 = _mm512_cvtfxpnt_round_adjustps_epi32(other.m512,_MM_ROUND_NEAREST,_MM_EXPADJ_NONE);
}
__forceinline ssef_m::ssef_m ( const ssef_t& other ) {
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline ssef_m& ssef_m::operator=( const ssef_t& other ) {
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef_t operator +( const ssef_t& a ) { return a; }
__forceinline const ssef_t operator -( const ssef_t& a ) { return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a.m512), _mm512_set1_epi32(0x80000000))); }
__forceinline const ssef_t abs ( const ssef_t& a ) { return _mm512_gmaxabs_ps(a.m512,a.m512); }
__forceinline const ssef_t sign ( const ssef_t& a ) { return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a,ssef_t(ssef_m(zero)),_MM_CMPINT_LT), ssef_t(ssef_m(one)), -ssef_t(ssef_m(one))); }
__forceinline const ssef_t signmsk ( const ssef_t& a ) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a.m512),_mm512_set1_epi32(0x80000000))); }
__forceinline const ssef_t rcp ( const ssef_t& a ) { return _mm512_rcp23_ps(a.m512); }
__forceinline const ssef_t sqr ( const ssef_t& a ) { return _mm512_mul_ps(a.m512,a.m512); }
__forceinline const ssef_t sqrt ( const ssef_t& a ) { return _mm512_sqrt_ps(a.m512); }
__forceinline const ssef_t rsqrt( const ssef_t& a ) { return _mm512_invsqrt_ps(a.m512); }
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef_t operator +( const ssef_t& a, const ssef_t& b ) { return _mm512_add_ps(a.m512, b.m512); }
__forceinline const ssef_t operator +( const ssef_t& a, const float & b ) { return a + ssef_t(b); }
__forceinline const ssef_t operator +( const float & a, const ssef_t& b ) { return ssef_t(a) + b; }
__forceinline const ssef_t operator -( const ssef_t& a, const ssef_t& b ) { return _mm512_sub_ps(a.m512, b.m512); }
__forceinline const ssef_t operator -( const ssef_t& a, const float & b ) { return a - ssef_t(b); }
__forceinline const ssef_t operator -( const float & a, const ssef_t& b ) { return ssef_t(a) - b; }
__forceinline const ssef_t operator *( const ssef_t& a, const ssef_t& b ) { return _mm512_mul_ps(a.m512, b.m512); }
__forceinline const ssef_t operator *( const ssef_t& a, const float & b ) { return a * ssef_t(b); }
__forceinline const ssef_t operator *( const float & a, const ssef_t& b ) { return ssef_t(a) * b; }
__forceinline const ssef_t operator /( const ssef_t& a, const ssef_t& b ) { return _mm512_div_ps(a.m512,b.m512); }
__forceinline const ssef_t operator /( const ssef_t& a, const float & b ) { return a/ssef_t(b); }
__forceinline const ssef_t operator /( const float & a, const ssef_t& b ) { return ssef_t(a)/b; }
__forceinline const ssef_t operator^( const ssef_t& a, const ssef_t& b ) { return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a.m512),_mm512_castps_si512(b.m512))); }
__forceinline const ssef_t operator^( const ssef_t& a, const ssei_t& b ) { return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a.m512),b.m512)); }
__forceinline const ssef_t min( const ssef_t& a, const ssef_t& b ) { return _mm512_gmin_ps(a.m512,b.m512); }
__forceinline const ssef_t min( const ssef_t& a, const float & b ) { return _mm512_gmin_ps(a.m512,ssef_t(b)); }
__forceinline const ssef_t min( const float & a, const ssef_t& b ) { return _mm512_gmin_ps(ssef_t(a),b.m512); }
__forceinline const ssef_t max( const ssef_t& a, const ssef_t& b ) { return _mm512_gmax_ps(a.m512,b.m512); }
__forceinline const ssef_t max( const ssef_t& a, const float & b ) { return _mm512_gmax_ps(a.m512,ssef_t(b)); }
__forceinline const ssef_t max( const float & a, const ssef_t& b ) { return _mm512_gmax_ps(ssef_t(a),b.m512); }
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef_t madd ( const ssef_t& a, const ssef_t& b, const ssef_t& c) { return _mm512_fmadd_ps(a,b,c); }
__forceinline const ssef_t msub ( const ssef_t& a, const ssef_t& b, const ssef_t& c) { return _mm512_fmsub_ps(a,b,c); }
__forceinline const ssef_t nmadd ( const ssef_t& a, const ssef_t& b, const ssef_t& c) { return _mm512_fnmadd_ps(a,b,c); }
__forceinline const ssef_t nmsub ( const ssef_t& a, const ssef_t& b, const ssef_t& c) { return _mm512_fnmsub_ps(a,b,c); }
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef_t& operator +=( ssef_t& a, const ssef_t& b ) { return a = a + b; }
__forceinline ssef_t& operator +=( ssef_t& a, const float & b ) { return a = a + b; }
__forceinline ssef_t& operator -=( ssef_t& a, const ssef_t& b ) { return a = a - b; }
__forceinline ssef_t& operator -=( ssef_t& a, const float & b ) { return a = a - b; }
__forceinline ssef_t& operator *=( ssef_t& a, const ssef_t& b ) { return a = a * b; }
__forceinline ssef_t& operator *=( ssef_t& a, const float & b ) { return a = a * b; }
__forceinline ssef_t& operator /=( ssef_t& a, const ssef_t& b ) { return a = a / b; }
__forceinline ssef_t& operator /=( ssef_t& a, const float & b ) { return a = a / b; }
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
__forceinline const sseb_t operator ==( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
__forceinline const sseb_t operator ==( const ssef_t& a, const float & b ) { return a == ssef_t(b); }
__forceinline const sseb_t operator ==( const float & a, const ssef_t& b ) { return ssef_t(a) == b; }
__forceinline const sseb_t operator !=( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
__forceinline const sseb_t operator !=( const ssef_t& a, const float & b ) { return a != ssef_t(b); }
__forceinline const sseb_t operator !=( const float & a, const ssef_t& b ) { return ssef_t(a) != b; }
__forceinline const sseb_t operator < ( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
__forceinline const sseb_t operator < ( const ssef_t& a, const float & b ) { return a < ssef_t(b); }
__forceinline const sseb_t operator < ( const float & a, const ssef_t& b ) { return ssef_t(a) < b; }
__forceinline const sseb_t operator >=( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
__forceinline const sseb_t operator >=( const ssef_t& a, const float & b ) { return a >= ssef_t(b); }
__forceinline const sseb_t operator >=( const float & a, const ssef_t& b ) { return ssef_t(a) >= b; }
__forceinline const sseb_t operator > ( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
__forceinline const sseb_t operator > ( const ssef_t& a, const float & b ) { return a > ssef_t(b); }
__forceinline const sseb_t operator > ( const float & a, const ssef_t& b ) { return ssef_t(a) > b; }
__forceinline const sseb_t operator <=( const ssef_t& a, const ssef_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
__forceinline const sseb_t operator <=( const ssef_t& a, const float & b ) { return a <= ssef_t(b); }
__forceinline const sseb_t operator <=( const float & a, const ssef_t& b ) { return ssef_t(a) <= b; }
__forceinline const ssef_t select( const sseb_t& mask, const ssef_t& t, const ssef_t& f ) { return _mm512_mask_blend_ps(mask.v, f, t); }
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef_t round_even( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_NEAREST , _MM_EXPADJ_NONE); }
__forceinline const ssef_t round_down( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_DOWN , _MM_EXPADJ_NONE); }
__forceinline const ssef_t round_up ( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_UP , _MM_EXPADJ_NONE); }
__forceinline const ssef_t round_zero( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_TOWARD_ZERO, _MM_EXPADJ_NONE); }
__forceinline const ssef_t floor ( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_DOWN , _MM_EXPADJ_NONE); }
__forceinline const ssef_t ceil ( const ssef_t& a ) { return _mm512_round_ps(a, _MM_ROUND_MODE_UP , _MM_EXPADJ_NONE); }
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
//__forceinline ssef_t unpacklo( const ssef_t& a, const ssef_t& b ) { return _mm512_unpacklo_ps(a.m512, b.m512); }
//__forceinline ssef_t unpackhi( const ssef_t& a, const ssef_t& b ) { return _mm512_unpackhi_ps(a.m512, b.m512); }
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef_t shuffle( const ssef_t& b ) {
return _mm512_castsi512_ps(_mm512_shuffle_epi32(_mm512_castps_si512(b),(_MM_PERM_ENUM)_MM_SHUFFLE(i3, i2, i1, i0)));
}
//template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef_t shuffle( const ssef_t& a, const ssef_t& b ) {
// return _mm512_shuffle_ps(a, b, _MM512_SHUFFLE(i3, i2, i1, i0));
//}
//__forceinline const ssef_t shuffle8(const ssef_t& a, const ssei& shuf) {
// return _mm512_castsi512_ps(_mm512_shuffle_epi8(_mm512_castps_si512(a), shuf));
//}
template<size_t i0> __forceinline const ssef_t shuffle( const ssef_t& b ) {
return shuffle<i0,i0,i0,i0>(b);
}
template<size_t i> __forceinline float extract( const ssef_t& a ) { return a[i]; }
//template<size_t dst, size_t src, size_t clr> __forceinline const ssef_t insert( const ssef_t& a, const ssef_t& b ) { return _mm512_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
template<size_t dst, size_t src> __forceinline const ssef_t insert( const ssef_t& a, const ssef_t& b ) { ssef_t c = a; c[dst] = b[src]; return c; }
template<size_t dst> __forceinline const ssef_t insert( const ssef_t& a, const float b ) { ssef_t c = a; c[dst] = b; return c; }
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
__forceinline void transpose(const ssef_t& r0, const ssef_t& r1, const ssef_t& r2, const ssef_t& r3, ssef_m& c0, ssef_m& c1, ssef_m& c2, ssef_m& c3)
{
c0[0] = r0[0]; c0[1] = r1[0]; c0[2] = r2[0]; c0[3] = r3[0];
c1[0] = r0[1]; c1[1] = r1[1]; c1[2] = r2[1]; c1[3] = r3[1];
c2[0] = r0[2]; c2[1] = r1[2]; c2[2] = r2[2]; c2[3] = r3[2];
c3[0] = r0[3]; c3[1] = r1[3]; c3[2] = r2[3]; c3[3] = r3[3];
}
__forceinline void transpose(const ssef_t& r0, const ssef_t& r1, const ssef_t& r2, const ssef_t& r3, ssef_m& c0, ssef_m& c1, ssef_m& c2)
{
c0[0] = r0[0]; c0[1] = r1[0]; c0[2] = r2[0]; c0[3] = r3[0];
c1[0] = r0[1]; c1[1] = r1[1]; c1[2] = r2[1]; c1[3] = r3[1];
c2[0] = r0[2]; c2[1] = r1[2]; c2[2] = r2[2]; c2[3] = r3[2];
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
__forceinline const ssef_t vreduce_min(const ssef_t& v) { ssef_t h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
__forceinline const ssef_t vreduce_max(const ssef_t& v) { ssef_t h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
__forceinline const ssef_t vreduce_add(const ssef_t& v) { ssef_t h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
__forceinline float reduce_min(const ssef_t& v) { return _mm512_cvtss_f32(vreduce_min(v)); }
__forceinline float reduce_max(const ssef_t& v) { return _mm512_cvtss_f32(vreduce_max(v)); }
__forceinline float reduce_add(const ssef_t& v) { return _mm512_cvtss_f32(vreduce_add(v)); }
__forceinline size_t select_min(const ssef_t& v) { return bitscan(movemask(v == vreduce_min(v))); }
__forceinline size_t select_max(const ssef_t& v) { return bitscan(movemask(v == vreduce_max(v))); }
__forceinline size_t select_min(const sseb_t& valid, const ssef_t& v) {
const ssef_t a = select(valid,v,ssef_m(pos_inf));
return bitscan(movemask(valid & (a == vreduce_min(a))));
}
__forceinline size_t select_max(const sseb_t& valid, const ssef_t& v) {
const ssef_t a = select(valid,v,ssef_m(neg_inf));
return bitscan(movemask(valid & (a == vreduce_max(a))));
}
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
__forceinline ssef_t load4f( const void* const a ) {
return _mm512_extload_ps(a,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
}
__forceinline void store4f( void* ptr, const ssef_t& v ) {
assert((size_t)ptr % 16 == 0);
_mm512_mask_extpackstorelo_ps(ptr,0xf,v.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline void storeu4f( void* ptr, const ssef_t& v ) {
_mm512_mask_extpackstorelo_ps(ptr,0xf,v.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
_mm512_mask_extpackstorehi_ps(ptr,0xf,v.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
}
__forceinline void store4f( const sseb_t& mask, void* ptr, const ssef_t& f ) {
store4f(ptr,select(mask,f,*(ssef_m*)ptr));
}
__forceinline ssef_t load4f_nt(void* ptr) {
return _mm512_extload_ps(ptr,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,_MM_HINT_NT);
}
__forceinline void store4f_nt(void* ptr, const ssef_t& v) {
assert((size_t)ptr % 16 == 0);
_mm512_mask_extpackstorelo_ps(ptr,0xf,v.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NT);
}
////////////////////////////////////////////////////////////////////////////////
/// Output Operators
////////////////////////////////////////////////////////////////////////////////
inline std::ostream& operator<<(std::ostream& cout, const ssef_m& a) {
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
}
}

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