Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9b0573179 | ||
|
|
3ea4631d7b | ||
|
|
fca5d42066 | ||
|
|
e6519a3720 | ||
|
|
4d95f3e270 | ||
|
|
de0261841d |
+29
-290
@@ -1,290 +1,6 @@
|
||||
Version History
|
||||
---------------
|
||||
|
||||
### New Features in Embree 2.16.5
|
||||
- Bugfix in the robust triangle intersector that rarely caused NaNs.
|
||||
- Fixed bug in hybrid traversal kernel when BVH leaf was entered with no
|
||||
active rays. This rarely caused crashes when used with instancing.
|
||||
- Fixed bug introduced in Embree 2.16.2 which caused instancing not to
|
||||
work properly when a smaller than the native SIMD width was
|
||||
used in ray packet mode.
|
||||
- Fixed bug in the curve geometry intersector that caused rendering
|
||||
artefacts for Bézier curves with p0=p1 and/or p2=p3.
|
||||
- Fixed bug in the curve geometry intersector that caused hit results
|
||||
with NaNs to be reported.
|
||||
- Fixed masking bug that caused rare cracks in curve geometry.
|
||||
- Enabled support for SSE2 in precompiled binaries again.
|
||||
|
||||
### New Features in Embree 2.16.4
|
||||
- Bugfix in the ribbon intersector for hair primitives. Non-normalized
|
||||
rays caused wrong intersection distance to be reported.
|
||||
|
||||
### New Features in Embree 2.16.3
|
||||
- Increased accuracy for handling subdivision surfaces. This fixes
|
||||
cracks when using displacement mapping but reduces performance
|
||||
at irregular vertices.
|
||||
- Fixed a bug where subdivision geometry was not properly updated
|
||||
when modifying only the tesselation rate and vertex array.
|
||||
|
||||
### New Features in Embree 2.16.2
|
||||
- Fixed bug that caused NULL intersection context in intersection
|
||||
filter when instancing was used.
|
||||
- Fixed an issue where uv's where outside the triangle (or quad) for
|
||||
very small triangles (or quads). In robust mode we improved the uv
|
||||
calculation to avoid that issue, in fast mode we accept that
|
||||
inconsistency for better performance.
|
||||
- Changed UV encoding for non-quad subdivision patches to
|
||||
allow a subpatch UV range of `[-0.5,1.5[`. Using this new encoding
|
||||
one can use finite differences to calculate derivatives if required.
|
||||
Please adjust your code in case you rely on the old encoding.
|
||||
|
||||
### New Features in Embree 2.16.1
|
||||
- Workaround for compile issues with Visual Studio 2017
|
||||
- Fixed bug in subdiv code for static scenes when using tessellation
|
||||
levels larger than 50.
|
||||
- Fixed low performance when adding many geometries to a scene.
|
||||
- Fixed high memory consumption issue when using instances in
|
||||
dynamic scene (by disabling two level builder for user geometries
|
||||
and instances).
|
||||
|
||||
### New Features in Embree 2.16.0
|
||||
- Improved multi-segment motion blur support for scenes with
|
||||
different number of time steps per mesh.
|
||||
- New top level BVH builder that improves build times and BVH quality
|
||||
of two-level BVHs.
|
||||
- Added support to enable only a single ISA. Previously code was
|
||||
always compiled for SSE2.
|
||||
- Improved single ray tracing performance for incoherent rays on
|
||||
AVX-512 architectures by 5-10%.
|
||||
- Improved packet/hybrid ray tracing performance for incoherent rays
|
||||
on AVX-512 architectures by 10-30%.
|
||||
- Improved stream ray tracing performance for coherent rays in
|
||||
structure-of-pointers layout by 40-70%.
|
||||
- BVH builder for compact scenes of triangles and quads needs
|
||||
essentially no temporary memory anymore. This doubles the
|
||||
maximal scene size that can be rendered in compact mode.
|
||||
- Triangles no longer store the geometry normal in fast/default mode
|
||||
which reduces memory consumption by up to 20%.
|
||||
- Compact mode uses BVH4 now consistently which reduces memory
|
||||
consumption by up to 10%.
|
||||
- Reduced memory consumption for small scenes (of 10k-100k primitives)
|
||||
and dynamic scenes.
|
||||
- Improved performance of user geometries and instances through BVH8
|
||||
support.
|
||||
- The API supports now specifying the geometry ID of a geometry at
|
||||
construction time. This way matching the geometry ID used by
|
||||
Embree and the application is simplified.
|
||||
- Fixed a bug that would have caused a failure of the BVH builder
|
||||
for dynamic scenes when run on a machine with more then 1000 threads.
|
||||
- Fixed a bug that could have been triggered when reaching the maximal
|
||||
number of mappings under Linux (`vm.max_map_count`). This could have
|
||||
happened when creating a large number of small static scenes.
|
||||
- Added huge page support for Windows and MacOSX (experimental).
|
||||
- Added support for Visual Studio 2017.
|
||||
- Removed support for Visual Studio 2012.
|
||||
- Precompiled binaries now require a CPU supporting at least the
|
||||
SSE4.2 ISA.
|
||||
- We no longer provide precompiled binaries for 32 bit on Windows.
|
||||
- Under Windows one now has to use the platform toolset option in
|
||||
CMake to switch to Clang or the Intel® Compiler.
|
||||
- Fixed a bug for subdivision meshes when using the incoherent scene
|
||||
flag.
|
||||
- Fixed a bug in the line geometry intersection, that caused reporting
|
||||
an invalid line segment intersection with primID -1.
|
||||
- Buffer stride for vertex buffers of different time steps of triangle
|
||||
and quad meshes have to be identical now.
|
||||
- Fixed a bug in the curve geometry intersection code when passed a
|
||||
perfect cylinder.
|
||||
|
||||
### New Features in Embree 2.15.0
|
||||
|
||||
- Added `rtcCommitJoin` mode that allows thread to join a build
|
||||
operation. When using the internal tasking system this allows
|
||||
Embree to solely use the threads that called `rtcCommitJoin` to
|
||||
build the scene, while previously also normal worker threads
|
||||
participated in the build. You should no longer use `rtcCommit`
|
||||
to join a build.
|
||||
- Added `rtcDeviceSetErrorFunction2` API call, which sets an error
|
||||
callback function which additionally gets passed a user provided
|
||||
pointer (`rtcDeviceSetErrorFunction` is now deprecated).
|
||||
- Added `rtcDeviceSetMemoryMonitorFunction2` API call, which sets a
|
||||
memory monitor callback function which additionally get passed a
|
||||
user provided pointer. (`rtcDeviceSetMemoryMonitorFunction` is now
|
||||
deprecated).
|
||||
- Build performance for hair geometry improved by up to 2×.
|
||||
- Standard BVH build performance increased by 5%.
|
||||
- Added API extension to use internal Morton-code based builder, the
|
||||
standard binned-SAH builder, and the spatial split-based SAH builder.
|
||||
- Added support for BSpline hair and curves. Embree uses
|
||||
either the Bézier or BSpline basis internally, and converts other
|
||||
curves, which requires more memory during rendering. For reduced
|
||||
memory consumption set the `EMBREE_NATIVE_SPLINE_BASIS` to the basis
|
||||
your application uses (which is set to `BEZIER` by default).
|
||||
- Setting the number of threads through `tbb::taskscheduler_init`
|
||||
object on the application side is now working properly.
|
||||
- Windows and Linux releases are build using AVX-512 support.
|
||||
- Implemented hybrid traversal for hair and line segments for
|
||||
improved ray packet performance.
|
||||
- AVX-512 code compiles with Clang 4.0.0
|
||||
- Fixed crash when ray packets were disabled in CMake.
|
||||
|
||||
### New Features in Embree 2.14.0
|
||||
|
||||
- Added `ignore_config_files` option to init flags that allows the
|
||||
application to ignore Embree configuration files.
|
||||
- Face-varying interpolation is now supported for subdivision surfaces.
|
||||
- Up to 16 user vertex buffers are supported for vertex
|
||||
attribute interpolation.
|
||||
- Deprecated `rtcSetBoundaryMode` function, please use the new
|
||||
`rtcSetSubdivisionMode` function.
|
||||
- Added `RTC_SUBDIV_PIN_BOUNDARY` mode for handling boundaries of
|
||||
subdivision meshes.
|
||||
- Added `RTC_SUBDIV_PIN_ALL` mode to enforce linear interpolation
|
||||
for subdivision meshes.
|
||||
- Optimized object generation performance for dynamic scenes.
|
||||
- Reduced memory consumption when using lots of small dynamic objects.
|
||||
- Fixed bug for subdivision surfaces using low tessellation rates.
|
||||
- Hair geometry now uses a new ribbon intersector that intersects with
|
||||
ray-facing quads. The new intersector also returns the v-coordinate
|
||||
of the hair intersection, and fixes artefacts at junction points
|
||||
between segments, at the cost of a small performance hit.
|
||||
- Added `rtcSetBuffer2` function, that additionally gets the number of
|
||||
elements of a buffer. In dynamic scenes, this function allows to
|
||||
quickly change buffer sizes, making it possible to change the number
|
||||
of primitives of a mesh or the number of crease features for
|
||||
subdivision surfaces.
|
||||
- Added simple 'viewer_anim' tutorial for rendering key
|
||||
frame animations and 'buildbench' for measuring BVH (re-)build
|
||||
performance for static and dynamic scenes.
|
||||
- Added more AVX-512 optimizations for future architectures.
|
||||
|
||||
### New Features in Embree 2.13.0
|
||||
|
||||
- Improved performance for compact (but not robust) scenes.
|
||||
- Added robust mode for motion blurred triangles and quads.
|
||||
- Added fast dynamic mode for user geometries.
|
||||
- Up to 20% faster BVH build performance on the second generation
|
||||
Intel® Xeon Phi™ processor codenamed Knights Landing.
|
||||
- Improved quality of the spatial split builder.
|
||||
- Improved performance for coherent streams of ray packets (SOA
|
||||
layout), e.g. for fast primary visibility.
|
||||
- Various bug fixes in tessellation cache, quad-based spatial
|
||||
split builder, etc.
|
||||
|
||||
### New Features in Embree 2.12.0
|
||||
|
||||
- Added support for multi-segment motion blur for all primitive types.
|
||||
- API support for stream of pointers to single rays (`rtcIntersect1Mp`
|
||||
and `rtcOccluded1Mp`)
|
||||
- Improved BVH refitting performance for dynamic scenes.
|
||||
- Improved high-quality mode for quads (added spatial split builder
|
||||
for quads)
|
||||
- Faster dynamic scenes for triangle and quad-based meshes on AVX2
|
||||
enabled machines.
|
||||
- Performance and correctness bugfix in optimization for streams of
|
||||
coherent (single) rays.
|
||||
- Fixed large memory consumption (issue introduced in Embree v2.11.0).
|
||||
If you use Embree v2.11.0 please upgrade to Embree v2.12.0.
|
||||
- Reduced memory consumption for dynamic scenes containing small
|
||||
meshes.
|
||||
- Added support to start and affinitize TBB worker threads by passing
|
||||
"`start_threads=1,set_affinity=1`" to `rtcNewDevice`. These settings
|
||||
are recommended on systems with a high thread count.
|
||||
- `rtcInterpolate2` can now be called within a displacement shader.
|
||||
- Added initial support for Microsoft's Parallel Pattern Library (PPL)
|
||||
as tasking system alternative (for optimal performance TBB is
|
||||
highly recommended).
|
||||
- Updated to TBB 2017 which is released under the Apache v2.0 license.
|
||||
- Dropped support for Visual Studio 2012 Win32 compiler. Visual Studio
|
||||
2012 x64 is still supported.
|
||||
|
||||
### New Features in Embree 2.11.0
|
||||
|
||||
- Improved performance for streams of coherent (single) rays flagged
|
||||
with `RTC_INTERSECT_COHERENT`. For such coherent ray streams, e.g.
|
||||
primary rays, the performance typically improves by 1.3-2×.
|
||||
- New spatial split BVH builder for triangles, which is 2-6× faster
|
||||
than the previous version and more memory conservative.
|
||||
- Improved performance and scalability of all standard BVH builders on
|
||||
systems with large core counts.
|
||||
- Fixed `rtcGetBounds` for motion blur scenes.
|
||||
- Thread affinity is now on by default when running on the latest
|
||||
Intel® Xeon Phi™ processor.
|
||||
- Added AVX-512 support for future Intel® Xeon processors.
|
||||
|
||||
### New Features in Embree 2.10.0
|
||||
|
||||
- Added a new curve geometry which renders the sweep surface of a
|
||||
circle along a Bézier curve.
|
||||
- Intersection filters can update the `tfar` ray distance.
|
||||
- Geometry types can get disabled at compile time.
|
||||
- Modified and extended the ray stream API.
|
||||
- Added new callback mechanism for the ray stream API.
|
||||
- Improved ray stream performance (up to 5-10%).
|
||||
- Up to 20% faster morton builder on machines with large core counts.
|
||||
- Lots of optimizations for the second generation Intel® Xeon Phi™
|
||||
processor codenamed Knights Landing.
|
||||
- Added experimental support for compressed BVH nodes (reduces node
|
||||
size to 56-62% of uncompressed size). Compression introduces a
|
||||
typical performance overhead of ~10%.
|
||||
- Bugfix in backface culling mode. We do now properly cull the
|
||||
backfaces and not the frontfaces.
|
||||
- Feature freeze for the first generation Intel® Xeon Phi™ coprocessor
|
||||
codenamed Knights Corner. We will still maintain and add bug fixes
|
||||
to Embree v2.9.0, but Embree 2.10 and future versions will no longer
|
||||
support it.
|
||||
|
||||
### New Features in Embree 2.9.0
|
||||
|
||||
- Improved shadow ray performance (10-100% depending on the scene).
|
||||
- Added initial support for ray streams (10-30% higher performance
|
||||
depending on ray coherence in the stream).
|
||||
- Added support to calculate second order derivatives using the
|
||||
`rtcInterpolate2` function.
|
||||
- Changed the parametrization for triangular subdivision faces to
|
||||
the same scheme used for pentagons.
|
||||
- Added support to query the Embree configuration using the
|
||||
`rtcDeviceGetParameter` function.
|
||||
|
||||
### New Features in Embree 2.8.1
|
||||
|
||||
- Added support for setting per geometry tessellation rate (supported
|
||||
for subdivision and Bézier geometries).
|
||||
- Added support for motion blurred instances.
|
||||
|
||||
### New Features in Embree 2.8.0
|
||||
|
||||
- Added support for line segment geometry.
|
||||
- Added support for quad geometry (replaces triangle-pairs feature).
|
||||
- Added support for linear motion blur of user geometries.
|
||||
- Improved performance through AVX-512 optimizations.
|
||||
- Improved performance of lazy scene build (when using TBB 4.4 update
|
||||
2).
|
||||
- Improved performance through huge page support under linux.
|
||||
|
||||
### New Features in Embree 2.7.1
|
||||
|
||||
- Internal tasking system supports cancellation of build operations.
|
||||
- ISPC mode for robust and compact scenes got significantly faster
|
||||
(implemented hybrid traversal for bvh4.triangle4v and
|
||||
bvh4.triangle4i).
|
||||
- Hair rendering got faster as we fixed some issues with the SAH
|
||||
heuristic cost factors.
|
||||
- BVH8 got slight faster for single ray traversal (improved sorting
|
||||
when hitting more than 4 boxes).
|
||||
- BVH build performance got up to 30% faster on CPUs with high core
|
||||
counts (improved parallel partition code).
|
||||
- High quality build mode again working properly (spatial splits had
|
||||
been deactivated in v2.7.0 due to some bug).
|
||||
- Support for merging two adjacent triangles sharing a common edge
|
||||
into a triangle-pair primitive (can reduce memory consumption and
|
||||
BVH build times by up to 50% for mostly quad-based input meshes).
|
||||
- Internal cleanups (reduced number of traversal kernels by more
|
||||
templating).
|
||||
- Reduced stack size requirements of BVH builders.
|
||||
- Fixed crash for dynamic scenes, triggered by deleting all
|
||||
geometries from the scene.
|
||||
|
||||
### New Features in Embree 2.7.0
|
||||
|
||||
- Added device concept to Embree to allow different components of an
|
||||
@@ -293,7 +9,7 @@ Version History
|
||||
- Fixed bug in tesselation cache that caused crashes for subdivision
|
||||
surfaces.
|
||||
- Fixed bug in internal task scheduler that caused deadlocks when
|
||||
using `rtcCommitThread`.
|
||||
using rtcCommitThread.
|
||||
- Improved hit-distance accuracy for thin triangles in robust mode.
|
||||
- Added support to disable ray packet support in cmake.
|
||||
|
||||
@@ -306,17 +22,17 @@ Version History
|
||||
- Added ray packet intersectors for subdivision geometry, resulting in
|
||||
improved performance for coherent rays.
|
||||
- Reduced virtual address space usage for static geometries.
|
||||
- Fixed some AVX2 code paths when compiling with GCC or Clang.
|
||||
- Fixed some AVX2 code paths when compiling with GCC or CLANG.
|
||||
- Bugfix for subdiv patches with non-matching winding order.
|
||||
- Bugfix in ISA detection of AVX-512.
|
||||
|
||||
- Bugfix in ISA detection of AVX512.
|
||||
|
||||
### New Features in Embree 2.6.1
|
||||
|
||||
- Major performance improvements for ray tracing subdivision surfaces,
|
||||
e.g. up to 2× faster for scenes where only the tessellation levels
|
||||
are changing per frame, and up to 3× faster for scenes with lots of
|
||||
crease features
|
||||
- Initial support for architectures supporting the new 16-wide AVX-512
|
||||
- Initial support for architectures supporting the new 16-wide AVX512
|
||||
ISA
|
||||
- Implemented intersection filter callback support for subdivision
|
||||
surfaces
|
||||
@@ -394,7 +110,7 @@ Version History
|
||||
|
||||
- Improved mixed AABB/OBB-BVH for hair geometry (Xeon Phi)
|
||||
- Reduced amount of pre-allocated memory for BVH builders (Xeon Phi)
|
||||
- New 64 bit Morton code-based BVH builder (Xeon Phi)
|
||||
- New 64\ bit Morton code-based BVH builder (Xeon Phi)
|
||||
- (Enhanced) Morton code-based BVH builders use now tree rotations to
|
||||
improve BVH quality (Xeon Phi)
|
||||
- Bug fixes (Xeon and Xeon Phi)
|
||||
@@ -450,6 +166,29 @@ Version History
|
||||
- New variant of the SAH-based builder using triangle pre-splits
|
||||
(Xeon Phi)
|
||||
|
||||
### Example Performance Numbers for Embree 2.1
|
||||
|
||||
BVH rebuild performance (including triangle accel generation, excluding
|
||||
memory allocation) for scenes with 2--12 million triangles:
|
||||
|
||||
- Intel® Core™ i7 (Haswell-based CPU, 4 cores @ 3.0\ GHz)
|
||||
- 7--8 million triangles/s for the SAH-based BVH builder
|
||||
- 30--36 million triangles/s for the Morton code-based BVH builder
|
||||
- Intel® Xeon Phi™ 7120
|
||||
- 37--40 million triangles/s for the SAH-based BVH builder
|
||||
- 140--160 million triangles/s for the Morton code-based BVH
|
||||
builder
|
||||
|
||||
Rendering of the Crown model (`crown.ecs`) with 4\ samples per pixel
|
||||
(`-spp 4`):
|
||||
|
||||
- Intel® Core™ i7 (Haswell-based CPU, 4 cores CPU @ 3.0\ GHz)
|
||||
- 1024×1024 resolution: 7.8 million rays per sec
|
||||
- 1920×1080 resolution: 9.9 million rays per sec
|
||||
- Intel® Xeon Phi™ 7120
|
||||
- 1024×1024 resolution: 47.1 million rays per sec
|
||||
- 1920×1080 resolution: 61.1 million rays per sec
|
||||
|
||||
### New Features in Embree 2.0
|
||||
|
||||
- Support for the Intel® Xeon Phi™ coprocessor platform
|
||||
|
||||
+143
-249
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -15,9 +15,9 @@
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(EMBREE_VERSION_MAJOR 2)
|
||||
SET(EMBREE_VERSION_MINOR 17)
|
||||
SET(EMBREE_VERSION_MINOR 7)
|
||||
SET(EMBREE_VERSION_PATCH 0)
|
||||
SET(EMBREE_VERSION_NOTE "-alpha.0")
|
||||
SET(EMBREE_VERSION_NOTE "")
|
||||
SET(EMBREE_VERSION ${EMBREE_VERSION_MAJOR}.${EMBREE_VERSION_MINOR}.${EMBREE_VERSION_PATCH})
|
||||
MATH(EXPR EMBREE_VERSION_NUMBER "10000*${EMBREE_VERSION_MAJOR} + 100*${EMBREE_VERSION_MINOR} + ${EMBREE_VERSION_PATCH}")
|
||||
SET(CPACK_RPM_PACKAGE_RELEASE 1)
|
||||
@@ -26,30 +26,11 @@ PROJECT(embree${EMBREE_VERSION_MAJOR})
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
|
||||
|
||||
# find git version
|
||||
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
FIND_PACKAGE(Git)
|
||||
IF(GIT_FOUND)
|
||||
EXECUTE_PROCESS(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE "EMBREE_HASH"
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
ELSE()
|
||||
SET(EMBREE_HASH 0)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
CONFIGURE_FILE(
|
||||
"${PROJECT_SOURCE_DIR}/kernels/rtcore_version.h.in"
|
||||
"${PROJECT_SOURCE_DIR}/include/embree2/rtcore_version.h"
|
||||
"${PROJECT_SOURCE_DIR}/kernels/version.h.in"
|
||||
"${PROJECT_BINARY_DIR}/version.h"
|
||||
)
|
||||
CONFIGURE_FILE(
|
||||
"${PROJECT_SOURCE_DIR}/kernels/hash.h.in"
|
||||
"${PROJECT_BINARY_DIR}/hash.h"
|
||||
)
|
||||
FILE(WRITE "${PROJECT_BINARY_DIR}/hash" "${EMBREE_HASH}")
|
||||
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}")
|
||||
|
||||
IF(COMMAND cmake_policy)
|
||||
if (POLICY CMP0003)
|
||||
@@ -67,88 +48,60 @@ MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH)
|
||||
MARK_AS_ADVANCED(CMAKE_OSX_ARCHITECTURES)
|
||||
MARK_AS_ADVANCED(CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
MARK_AS_ADVANCED(CMAKE_OSX_SYSROOT)
|
||||
MARK_AS_ADVANCED(CLEAR CMAKE_CXX_COMPILER)
|
||||
MARK_AS_ADVANCED(GLUT_cocoa_LIBRARY)
|
||||
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/common/cmake ${CMAKE_MODULE_PATH})
|
||||
|
||||
INCLUDE(test)
|
||||
##############################################################
|
||||
# Create Binary Packages
|
||||
##############################################################
|
||||
include(package)
|
||||
|
||||
##############################################################
|
||||
# Embree configuration
|
||||
##############################################################
|
||||
|
||||
GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
|
||||
IF(SHARED_LIBS_SUPPORTED)
|
||||
OPTION(EMBREE_STATIC_LIB "Build Embree as a static library.")
|
||||
MARK_AS_ADVANCED(CLEAR EMBREE_STATIC_LIB)
|
||||
ELSE()
|
||||
SET(EMBREE_STATIC_LIB ON CACHE BOOL "Build Embree as a static library." FORCE)
|
||||
MARK_AS_ADVANCED(EMBREE_STATIC_LIB)
|
||||
ENDIF()
|
||||
IF (EMBREE_STATIC_LIB)
|
||||
OPTION(ENABLE_STATIC_LIB "Build Embree as a static library." OFF)
|
||||
IF (ENABLE_STATIC_LIB)
|
||||
SET(EMBREE_LIB_TYPE STATIC)
|
||||
ADD_DEFINITIONS(-DEMBREE_STATIC_LIB)
|
||||
ADD_DEFINITIONS(-DENABLE_STATIC_LIB)
|
||||
ELSE()
|
||||
SET(EMBREE_LIB_TYPE SHARED)
|
||||
ENDIF()
|
||||
|
||||
OPTION(EMBREE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON)
|
||||
OPTION(EMBREE_TUTORIALS "Enable to build Embree tutorials" ON)
|
||||
OPTION(ENABLE_ISPC_SUPPORT "Build Embree with support for ISPC applications." ON)
|
||||
OPTION(ENABLE_TUTORIALS "Enable to build Embree tutorials" ON)
|
||||
|
||||
##############################################################################
|
||||
# Configurations (add configurations also to common/cmake/embree-config-default.cmake)
|
||||
|
||||
OPTION(EMBREE_STAT_COUNTERS "Enables statistic counters.")
|
||||
OPTION(EMBREE_STACK_PROTECTOR "When enabled Embree compiles with stack protection against return address overrides." OFF)
|
||||
|
||||
OPTION(EMBREE_RAY_MASK "Enables ray mask support.")
|
||||
OPTION(EMBREE_BACKFACE_CULLING "Enables backface culling.")
|
||||
OPTION(EMBREE_INTERSECTION_FILTER "Enables intersection filter callback." ON)
|
||||
OPTION(EMBREE_INTERSECTION_FILTER_RESTORE "Restores previous hit when hit is filtered out." ON)
|
||||
OPTION(EMBREE_IGNORE_INVALID_RAYS "Ignores invalid rays." OFF) # FIXME: enable by default?
|
||||
|
||||
OPTION(EMBREE_GEOMETRY_TRIANGLES "Enables support for triangle geometries." ON)
|
||||
OPTION(EMBREE_GEOMETRY_QUADS "Enables support for quad geometries." ON)
|
||||
OPTION(EMBREE_GEOMETRY_LINES "Enables support for line geometries." ON)
|
||||
OPTION(EMBREE_GEOMETRY_HAIR "Enables support for hair geometries." ON)
|
||||
OPTION(EMBREE_GEOMETRY_SUBDIV "Enables support for subdiv geometries." ON)
|
||||
OPTION(EMBREE_GEOMETRY_USER "Enables support for user geometries." ON)
|
||||
OPTION(EMBREE_RAY_PACKETS "Enabled support for ray packets." ON)
|
||||
|
||||
SET(EMBREE_NATIVE_SPLINE_BASIS BEZIER CACHE STRING "Sets the basis for curves which Embree uses internally. Other types are converted and need more memory.")
|
||||
SET_PROPERTY(CACHE EMBREE_NATIVE_SPLINE_BASIS PROPERTY STRINGS BSPLINE BEZIER)
|
||||
IF (EMBREE_NATIVE_SPLINE_BASIS STREQUAL "BSPLINE")
|
||||
SET(EMBREE_NATIVE_CURVE_BSPLINE ON)
|
||||
# only support Xeon Phi on Linux
|
||||
IF (NOT WIN32 AND NOT APPLE)
|
||||
OPTION(ENABLE_XEON_PHI_SUPPORT "Generates code path for Xeon Phi.")
|
||||
ELSE()
|
||||
SET(EMBREE_NATIVE_CURVE_BSPLINE OFF)
|
||||
SET(ENABLE_XEON_PHI_SUPPORT OFF CACHE INTERNAL "Xeon Phi only supported on Linux.")
|
||||
ENDIF()
|
||||
|
||||
SET(EMBREE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system")
|
||||
IF (WIN32)
|
||||
SET_PROPERTY(CACHE EMBREE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL PPL)
|
||||
ELSE()
|
||||
SET_PROPERTY(CACHE EMBREE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL)
|
||||
ENDIF()
|
||||
IF (ENABLE_XEON_PHI_SUPPORT)
|
||||
SET(ENABLE_ISPC_SUPPORT ON CACHE BOOL "Build Embree with support for ISPC applications." FORCE)
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_TASKING_SYSTEM STREQUAL "TBB")
|
||||
SET(TASKING_TBB ON )
|
||||
SET(TASKING_INTERNAL OFF)
|
||||
SET(TASKING_PPL OFF )
|
||||
ADD_DEFINITIONS(-DTASKING_TBB)
|
||||
LIST(APPEND ISPC_DEFINITIONS -DTASKING_TBB)
|
||||
ELSEIF (EMBREE_TASKING_SYSTEM STREQUAL "PPL")
|
||||
SET(TASKING_PPL ON )
|
||||
SET(TASKING_TBB OFF )
|
||||
SET(TASKING_INTERNAL OFF)
|
||||
ADD_DEFINITIONS(-DTASKING_PPL)
|
||||
LIST(APPEND ISPC_DEFINITIONS -DTASKING_PPL)
|
||||
OPTION(RTCORE_RAY_MASK "Enables ray mask support.")
|
||||
OPTION(RTCORE_STAT_COUNTERS "Enables statistic counters.")
|
||||
OPTION(RTCORE_BACKFACE_CULLING "Enables backface culling.")
|
||||
OPTION(RTCORE_INTERSECTION_FILTER "Enables intersection filter callback." ON)
|
||||
OPTION(RTCORE_BUFFER_STRIDE "Enables buffer strides." ON)
|
||||
OPTION(RTCORE_EXPORT_ALL_SYMBOLS "Lets Embree library export all symbols.")
|
||||
OPTION(RTCORE_ENABLE_RAYSTREAM_LOGGER "Enables ray stream logger.")
|
||||
OPTION(RTCORE_IGNORE_INVALID_RAYS "Ignores invalid rays." OFF) # FIXME: enable by default?
|
||||
OPTION(RTCORE_RAY_PACKETS "Enabled support for ray packets." ON)
|
||||
|
||||
SET(RTCORE_TASKING_SYSTEM "TBB" CACHE STRING "Selects tasking system")
|
||||
SET_PROPERTY(CACHE RTCORE_TASKING_SYSTEM PROPERTY STRINGS TBB INTERNAL)
|
||||
|
||||
IF (RTCORE_TASKING_SYSTEM STREQUAL "TBB")
|
||||
SET(TASKING_TBB ON)
|
||||
FIND_PACKAGE(TBB REQUIRED)
|
||||
INCLUDE_DIRECTORIES(${TBB_INCLUDE_DIRS})
|
||||
ELSE()
|
||||
SET(TASKING_INTERNAL ON )
|
||||
SET(TASKING_TBB OFF)
|
||||
SET(TASKING_PPL OFF )
|
||||
ADD_DEFINITIONS(-DTASKING_INTERNAL)
|
||||
LIST(APPEND ISPC_DEFINITIONS -DTASKING_INTERNAL)
|
||||
SET(TASKING_INTERNAL ON)
|
||||
ENDIF()
|
||||
|
||||
CONFIGURE_FILE(
|
||||
@@ -156,83 +109,6 @@ CONFIGURE_FILE(
|
||||
"${PROJECT_BINARY_DIR}/config.h"
|
||||
)
|
||||
|
||||
##############################################################
|
||||
# ISA configuration
|
||||
##############################################################
|
||||
|
||||
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
|
||||
SET(EMBREE_MAX_ISA "NONE" CACHE STRING "Selects highest ISA to support.")
|
||||
ELSE()
|
||||
SET(EMBREE_MAX_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
|
||||
ENDIF()
|
||||
SET_PROPERTY(CACHE EMBREE_MAX_ISA PROPERTY STRINGS NONE SSE2 SSE4.2 AVX AVX2 AVX512KNL AVX512SKX)
|
||||
|
||||
IF (EMBREE_MAX_ISA STREQUAL "NONE")
|
||||
OPTION(EMBREE_ISA_SSE2 "Enables SSE2 ISA.")
|
||||
OPTION(EMBREE_ISA_SSE42 "Enables SSE4.2 ISA.")
|
||||
OPTION(EMBREE_ISA_AVX "Enables AVX ISA.")
|
||||
OPTION(EMBREE_ISA_AVX2 "Enables AVX2 ISA.")
|
||||
OPTION(EMBREE_ISA_AVX512KNL "Enables AVX512 ISA for Knights Landing.")
|
||||
OPTION(EMBREE_ISA_AVX512SKX "Enables AVX512 ISA for Skylake.")
|
||||
IF(NOT (EMBREE_ISA_SSE2 OR EMBREE_ISA_SSE42 OR EMBREE_ISA_AVX OR
|
||||
EMBREE_ISA_AVX2 OR EMBREE_ISA_AVX512KNL OR EMBREE_ISA_AVX512SKX))
|
||||
MESSAGE(STATUS "Detecting default ISA:")
|
||||
INCLUDE(check_isa_default)
|
||||
CHECK_ISA_DEFAULT(EMBREE_ISA_DEFAULT)
|
||||
MESSAGE(STATUS "Detecting default ISA: ${EMBREE_ISA_DEFAULT}")
|
||||
SET(EMBREE_ISA_${EMBREE_ISA_DEFAULT} ON)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
UNSET(EMBREE_ISA_SSE2 CACHE)
|
||||
UNSET(EMBREE_ISA_SSE42 CACHE)
|
||||
UNSET(EMBREE_ISA_AVX CACHE)
|
||||
UNSET(EMBREE_ISA_AVX2 CACHE)
|
||||
UNSET(EMBREE_ISA_AVX512KNL CACHE)
|
||||
UNSET(EMBREE_ISA_AVX512SKX CACHE)
|
||||
|
||||
IF(EMBREE_MAX_ISA STREQUAL "SSE2")
|
||||
SET(ISA 1)
|
||||
ELSEIF(EMBREE_MAX_ISA STREQUAL "SSE4.2")
|
||||
SET(ISA 2)
|
||||
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX")
|
||||
SET(ISA 3)
|
||||
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX2")
|
||||
SET(ISA 4)
|
||||
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512KNL")
|
||||
SET(ISA 5)
|
||||
ELSEIF(EMBREE_MAX_ISA STREQUAL "AVX512SKX")
|
||||
SET(ISA 6)
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "Unsupported ISA specified: " ${EMBREE_MAX_ISA})
|
||||
ENDIF()
|
||||
|
||||
SET(EMBREE_ISA_SSE2 OFF)
|
||||
SET(EMBREE_ISA_SSE42 OFF)
|
||||
SET(EMBREE_ISA_AVX OFF)
|
||||
SET(EMBREE_ISA_AVX2 OFF)
|
||||
SET(EMBREE_ISA_AVX512KNL OFF)
|
||||
SET(EMBREE_ISA_AVX512SKX OFF)
|
||||
|
||||
IF (ISA GREATER 0)
|
||||
SET(EMBREE_ISA_SSE2 ON)
|
||||
ENDIF ()
|
||||
IF (ISA GREATER 1)
|
||||
SET(EMBREE_ISA_SSE42 ON)
|
||||
ENDIF ()
|
||||
IF (ISA GREATER 2)
|
||||
SET(EMBREE_ISA_AVX ON)
|
||||
ENDIF ()
|
||||
IF (ISA GREATER 3)
|
||||
SET(EMBREE_ISA_AVX2 ON)
|
||||
ENDIF ()
|
||||
IF (ISA GREATER 4)
|
||||
SET(EMBREE_ISA_AVX512KNL ON)
|
||||
ENDIF ()
|
||||
IF (ISA GREATER 5)
|
||||
SET(EMBREE_ISA_AVX512SKX ON)
|
||||
ENDIF ()
|
||||
ENDIF()
|
||||
|
||||
##############################################################
|
||||
# Compiler
|
||||
##############################################################
|
||||
@@ -245,31 +121,20 @@ IF (WIN32)
|
||||
SET(DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON CACHE INTERNAL "Default CMake configuration types set.")
|
||||
ENDIF()
|
||||
SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
IF (${CMAKE_GENERATOR_TOOLSET} MATCHES "^LLVM" )
|
||||
MESSAGE("CLANG detected")
|
||||
INCLUDE(clang)
|
||||
ELSEIF(${CMAKE_GENERATOR_TOOLSET} MATCHES "^Intel")
|
||||
MESSAGE("Intel Compiler detected")
|
||||
INCLUDE (icc)
|
||||
ELSE()
|
||||
IF (EMBREE_ISA_AVX512KNL OR EMBREE_ISA_AVX512SKX)
|
||||
MESSAGE(FATAL_ERROR "Microsoft Visual C++ Compiler does not support AVX512. Please use Intel Compiler or Clang.")
|
||||
ENDIF()
|
||||
INCLUDE (msvc)
|
||||
ENDIF()
|
||||
INCLUDE (msvc)
|
||||
|
||||
ELSE (WIN32)
|
||||
IF(CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
|
||||
INCLUDE(crayprgenv)
|
||||
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
|
||||
SET(COMPILER "GCC" CACHE STRING "Selects compiler to use.")
|
||||
SET_PROPERTY(CACHE COMPILER PROPERTY STRINGS GCC CLANG ICC)
|
||||
|
||||
IF (COMPILER STREQUAL "GCC")
|
||||
INCLUDE (gcc)
|
||||
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
||||
ELSEIF (COMPILER STREQUAL "CLANG")
|
||||
INCLUDE (clang)
|
||||
ELSEIF (${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel")
|
||||
ELSEIF (COMPILER STREQUAL "ICC")
|
||||
INCLUDE (icc)
|
||||
ELSE ()
|
||||
MESSAGE(FATAL_ERROR "Unsupported compiler: " ${CMAKE_CXX_COMPILER_ID})
|
||||
MESSAGE(FATAL_ERROR "Unknown compiler specified: " ${COMPILER})
|
||||
ENDIF ()
|
||||
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
@@ -283,96 +148,119 @@ ELSE (WIN32)
|
||||
ENDIF (WIN32)
|
||||
|
||||
##############################################################
|
||||
# ISA configuration continued
|
||||
# ISA configuration
|
||||
##############################################################
|
||||
|
||||
SET(SSE2 0)
|
||||
SET(SSE42 1)
|
||||
SET(AVX 2)
|
||||
SET(AVX2 3)
|
||||
SET(AVX512KNL 4)
|
||||
SET(AVX512SKX 5)
|
||||
IF(APPLE)
|
||||
SET(XEON_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
|
||||
ELSEIF(NOT COMPILER STREQUAL "ICC")
|
||||
SET(XEON_ISA "AVX2" CACHE STRING "Selects highest ISA to support.")
|
||||
ELSE()
|
||||
SET(XEON_ISA "AVX512" CACHE STRING "Selects highest ISA to support.")
|
||||
ENDIF ()
|
||||
|
||||
UNSET(FLAGS_LOWEST)
|
||||
SET_PROPERTY(CACHE XEON_ISA PROPERTY STRINGS SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 AVX AVX-I AVX2 AVX512)
|
||||
|
||||
IF (EMBREE_ISA_SSE2)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_SSE2)
|
||||
LIST(APPEND ISPC_TARGETS "sse2")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${SSE2})
|
||||
SET(FLAGS_LOWEST ${FLAGS_SSE2})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF (XEON_ISA STREQUAL "SSE2")
|
||||
SET(ISA 1)
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_ISA_SSE42)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_SSE42)
|
||||
IF (XEON_ISA STREQUAL "SSE3")
|
||||
SET(ISA 2)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "SSSE3")
|
||||
SET(ISA 3)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "SSE4.1")
|
||||
SET(ISA 4)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "SSE4.2")
|
||||
SET(ISA 5)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "AVX")
|
||||
SET(ISA 6)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "AVX-I")
|
||||
SET(ISA 7)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "AVX2")
|
||||
SET(ISA 8)
|
||||
ENDIF ()
|
||||
|
||||
IF (XEON_ISA STREQUAL "AVX512")
|
||||
SET(ISA 9)
|
||||
ENDIF ()
|
||||
|
||||
SET(TARGET_SSE2 OFF)
|
||||
SET(TARGET_SSE3 OFF)
|
||||
SET(TARGET_SSSE3 OFF)
|
||||
SET(TARGET_SSE41 OFF)
|
||||
SET(TARGET_SSE42 OFF)
|
||||
SET(TARGET_AVX OFF)
|
||||
SET(TARGET_AVXI OFF)
|
||||
SET(TARGET_AVX2 OFF)
|
||||
SET(TARGET_AVX512 OFF)
|
||||
|
||||
IF (ISA GREATER 0)
|
||||
SET(TARGET_SSE2 ON)
|
||||
SET(ISPC_TARGETS "sse2")
|
||||
ENDIF ()
|
||||
|
||||
IF (ISA GREATER 1)
|
||||
SET(TARGET_SSE3 ON)
|
||||
ENDIF ()
|
||||
|
||||
IF (ISA GREATER 2)
|
||||
SET(TARGET_SSSE3 ON)
|
||||
ENDIF ()
|
||||
|
||||
IF (ISA GREATER 3)
|
||||
SET(TARGET_SSE41 ON)
|
||||
LIST(APPEND ISPC_TARGETS "sse4")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${SSE42})
|
||||
SET(FLAGS_LOWEST ${FLAGS_SSE42})
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_ISA_AVX)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX)
|
||||
IF (ISA GREATER 4)
|
||||
SET(TARGET_SSE42 ON)
|
||||
ENDIF ()
|
||||
|
||||
IF (ISA GREATER 5)
|
||||
SET(TARGET_AVX ON)
|
||||
LIST(APPEND ISPC_TARGETS "avx")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${AVX})
|
||||
SET(FLAGS_LOWEST ${FLAGS_AVX})
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_ISA_AVX2)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX2)
|
||||
IF (ISA GREATER 6)
|
||||
SET(TARGET_AVXI ON)
|
||||
ENDIF ()
|
||||
|
||||
IF (ISA GREATER 7)
|
||||
SET(TARGET_AVX2 ON)
|
||||
LIST(APPEND ISPC_TARGETS "avx2")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${AVX2})
|
||||
SET(FLAGS_LOWEST ${FLAGS_AVX2})
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_ISA_AVX512KNL)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512KNL)
|
||||
IF (ISA GREATER 8)
|
||||
SET(TARGET_AVX512 ON)
|
||||
LIST(APPEND ISPC_TARGETS "avx512knl-i32x16")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${AVX512KNL})
|
||||
SET(FLAGS_LOWEST ${FLAGS_AVX512KNL})
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
IF (EMBREE_ISA_AVX512SKX)
|
||||
ADD_DEFINITIONS(-DEMBREE_TARGET_AVX512SKX)
|
||||
LIST(APPEND ISPC_TARGETS "avx512skx-i32x16")
|
||||
IF(NOT FLAGS_LOWEST)
|
||||
SET(ISA_LOWEST ${AVX512SKX})
|
||||
SET(FLAGS_LOWEST ${FLAGS_AVX512SKX})
|
||||
ENDIF()
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE (ispc)
|
||||
|
||||
##############################################################
|
||||
# Create Binary Packages (uses above config options)
|
||||
##############################################################
|
||||
include(package)
|
||||
|
||||
##############################################################
|
||||
# Search paths
|
||||
##############################################################
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include)
|
||||
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}")
|
||||
INCLUDE_DIRECTORIES_ISPC("${PROJECT_BINARY_DIR}")
|
||||
IF (TASKING_TBB)
|
||||
FIND_PACKAGE(TBB REQUIRED)
|
||||
INCLUDE_DIRECTORIES(${TBB_INCLUDE_DIRS})
|
||||
ENDIF()
|
||||
|
||||
##############################################################
|
||||
# Output paths
|
||||
##############################################################
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
|
||||
##############################################################
|
||||
# Directories to compile
|
||||
@@ -381,8 +269,16 @@ SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(kernels)
|
||||
|
||||
IF (EMBREE_TUTORIALS)
|
||||
IF (ENABLE_TUTORIALS)
|
||||
ADD_SUBDIRECTORY(tutorials)
|
||||
|
||||
SET (__XEON__ 1)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
|
||||
IF (ENABLE_XEON_PHI_SUPPORT)
|
||||
SET (__XEON__ 0)
|
||||
ADD_SUBDIRECTORY(tests tests_xeonphi)
|
||||
ENDIF ()
|
||||
ENDIF()
|
||||
|
||||
##############################################################
|
||||
@@ -397,8 +293,6 @@ configure_file(
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake)
|
||||
|
||||
SET_PROPERTY(TARGET uninstall PROPERTY FOLDER CMakePredefinedTargets)
|
||||
|
||||
##############################################################
|
||||
# Has to be last
|
||||
##############################################################
|
||||
|
||||
+10
-3
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,9 +14,16 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(__XEON__ 1)
|
||||
ADD_SUBDIRECTORY(sys)
|
||||
ADD_SUBDIRECTORY(math)
|
||||
ADD_SUBDIRECTORY(simd)
|
||||
ADD_SUBDIRECTORY(lexers)
|
||||
ADD_SUBDIRECTORY(tasking)
|
||||
ADD_SUBDIRECTORY(algorithms)
|
||||
|
||||
IF (ENABLE_XEON_PHI_SUPPORT)
|
||||
SET(__XEON__ 0)
|
||||
ADD_SUBDIRECTORY(sys sys_xeonphi)
|
||||
ADD_SUBDIRECTORY(simd simd_xeonphi)
|
||||
ADD_SUBDIRECTORY(lexers lexers_xeonphi)
|
||||
ADD_SUBDIRECTORY(tasking tasking_xeonphi)
|
||||
ENDIF ()
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,456 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../simd/simd.h"
|
||||
#include "parallel_for.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace embree
|
||||
{
|
||||
template<class T>
|
||||
__forceinline void insertionsort_ascending(T *__restrict__ array, const size_t length)
|
||||
{
|
||||
for(size_t i = 1;i<length;++i)
|
||||
{
|
||||
T v = array[i];
|
||||
size_t j = i;
|
||||
while(j > 0 && v < array[j-1])
|
||||
{
|
||||
array[j] = array[j-1];
|
||||
--j;
|
||||
}
|
||||
array[j] = v;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
__forceinline void insertionsort_decending(T *__restrict__ array, const size_t length)
|
||||
{
|
||||
for(size_t i = 1;i<length;++i)
|
||||
{
|
||||
T v = array[i];
|
||||
size_t j = i;
|
||||
while(j > 0 && v > array[j-1])
|
||||
{
|
||||
array[j] = array[j-1];
|
||||
--j;
|
||||
}
|
||||
array[j] = v;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void quicksort_ascending(T *__restrict__ t,
|
||||
const ssize_t begin,
|
||||
const ssize_t end)
|
||||
{
|
||||
if (likely(begin < end))
|
||||
{
|
||||
const T pivotvalue = t[begin];
|
||||
ssize_t left = begin - 1;
|
||||
ssize_t right = end + 1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while (t[--right] > pivotvalue);
|
||||
while (t[++left] < pivotvalue);
|
||||
|
||||
if (left >= right) break;
|
||||
|
||||
const T temp = t[right];
|
||||
t[right] = t[left];
|
||||
t[left] = temp;
|
||||
}
|
||||
|
||||
const int pivot = right;
|
||||
quicksort_ascending(t, begin, pivot);
|
||||
quicksort_ascending(t, pivot + 1, end);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void quicksort_decending(T *__restrict__ t,
|
||||
const ssize_t begin,
|
||||
const ssize_t end)
|
||||
{
|
||||
if (likely(begin < end))
|
||||
{
|
||||
const T pivotvalue = t[begin];
|
||||
ssize_t left = begin - 1;
|
||||
ssize_t right = end + 1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while (t[--right] < pivotvalue);
|
||||
while (t[++left] > pivotvalue);
|
||||
|
||||
if (left >= right) break;
|
||||
|
||||
const T temp = t[right];
|
||||
t[right] = t[left];
|
||||
t[left] = temp;
|
||||
}
|
||||
|
||||
const int pivot = right;
|
||||
quicksort_decending(t, begin, pivot);
|
||||
quicksort_decending(t, pivot + 1, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, ssize_t THRESHOLD>
|
||||
void quicksort_insertionsort_ascending(T *__restrict__ t,
|
||||
const ssize_t begin,
|
||||
const ssize_t end)
|
||||
{
|
||||
if (likely(begin < end))
|
||||
{
|
||||
const ssize_t size = end-begin+1;
|
||||
if (likely(size <= THRESHOLD))
|
||||
{
|
||||
insertionsort_ascending<T>(&t[begin],size);
|
||||
}
|
||||
else
|
||||
{
|
||||
const T pivotvalue = t[begin];
|
||||
ssize_t left = begin - 1;
|
||||
ssize_t right = end + 1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while (t[--right] > pivotvalue);
|
||||
while (t[++left] < pivotvalue);
|
||||
|
||||
if (left >= right) break;
|
||||
|
||||
const T temp = t[right];
|
||||
t[right] = t[left];
|
||||
t[left] = temp;
|
||||
}
|
||||
|
||||
const ssize_t pivot = right;
|
||||
quicksort_insertionsort_ascending<T,THRESHOLD>(t, begin, pivot);
|
||||
quicksort_insertionsort_ascending<T,THRESHOLD>(t, pivot + 1, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, ssize_t THRESHOLD>
|
||||
void quicksort_insertionsort_decending(T *__restrict__ t,
|
||||
const ssize_t begin,
|
||||
const ssize_t end)
|
||||
{
|
||||
if (likely(begin < end))
|
||||
{
|
||||
const ssize_t size = end-begin+1;
|
||||
if (likely(size <= THRESHOLD))
|
||||
{
|
||||
insertionsort_decending<T>(&t[begin],size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
const T pivotvalue = t[begin];
|
||||
ssize_t left = begin - 1;
|
||||
ssize_t right = end + 1;
|
||||
|
||||
while(1)
|
||||
{
|
||||
while (t[--right] < pivotvalue);
|
||||
while (t[++left] > pivotvalue);
|
||||
|
||||
if (left >= right) break;
|
||||
|
||||
const T temp = t[right];
|
||||
t[right] = t[left];
|
||||
t[left] = temp;
|
||||
}
|
||||
|
||||
const ssize_t pivot = right;
|
||||
quicksort_insertionsort_decending<T,THRESHOLD>(t, begin, pivot);
|
||||
quicksort_insertionsort_decending<T,THRESHOLD>(t, pivot + 1, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void radixsort32(T* const morton, const size_t num, const unsigned int shift = 3*8)
|
||||
{
|
||||
static const unsigned int BITS = 8;
|
||||
static const unsigned int BUCKETS = (1 << BITS);
|
||||
static const unsigned int CMP_SORT_THRESHOLD = 16;
|
||||
|
||||
__aligned(64) unsigned int count[BUCKETS];
|
||||
|
||||
/* clear buckets */
|
||||
for (size_t i=0;i<BUCKETS;i++) count[i] = 0;
|
||||
|
||||
/* count buckets */
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma nounroll
|
||||
#endif
|
||||
for (size_t i=0;i<num;i++)
|
||||
count[(unsigned(morton[i]) >> shift) & (BUCKETS-1)]++;
|
||||
|
||||
/* prefix sums */
|
||||
__aligned(64) unsigned int head[BUCKETS];
|
||||
__aligned(64) unsigned int tail[BUCKETS];
|
||||
|
||||
head[0] = 0;
|
||||
for (size_t i=1; i<BUCKETS; i++)
|
||||
head[i] = head[i-1] + count[i-1];
|
||||
|
||||
for (size_t i=0; i<BUCKETS-1; i++)
|
||||
tail[i] = head[i+1];
|
||||
|
||||
tail[BUCKETS-1] = head[BUCKETS-1] + count[BUCKETS-1];
|
||||
|
||||
assert(tail[BUCKETS-1] == head[BUCKETS-1] + count[BUCKETS-1]);
|
||||
assert(tail[BUCKETS-1] == num);
|
||||
|
||||
/* in-place swap */
|
||||
for (size_t i=0;i<BUCKETS;i++)
|
||||
{
|
||||
/* process bucket */
|
||||
while(head[i] < tail[i])
|
||||
{
|
||||
T v = morton[head[i]];
|
||||
while(1)
|
||||
{
|
||||
const size_t b = (unsigned(v) >> shift) & (BUCKETS-1);
|
||||
if (b == i) break;
|
||||
std::swap(v,morton[head[b]++]);
|
||||
}
|
||||
assert((unsigned(v) >> shift & (BUCKETS-1)) == i);
|
||||
morton[head[i]++] = v;
|
||||
}
|
||||
}
|
||||
if (shift == 0) return;
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t i=0;i<BUCKETS;i++)
|
||||
if (count[i])
|
||||
{
|
||||
|
||||
for (size_t j=offset;j<offset+count[i]-1;j++)
|
||||
assert(((unsigned(morton[j]) >> shift) & (BUCKETS-1)) == i);
|
||||
|
||||
if (unlikely(count[i] < CMP_SORT_THRESHOLD))
|
||||
insertionsort_ascending(morton + offset, count[i]);
|
||||
else
|
||||
radixsort32(morton + offset, count[i], shift-BITS);
|
||||
|
||||
for (size_t j=offset;j<offset+count[i]-1;j++)
|
||||
assert(morton[j] <= morton[j+1]);
|
||||
|
||||
offset += count[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ty, typename Key>
|
||||
class ParallelRadixSort
|
||||
{
|
||||
static const size_t MAX_TASKS = 512;
|
||||
static const size_t BITS = 8;
|
||||
static const size_t BUCKETS = (1 << BITS);
|
||||
typedef unsigned int TyRadixCount[BUCKETS];
|
||||
|
||||
template<typename T>
|
||||
static bool compare(const T& v0, const T& v1) {
|
||||
return (Key)v0 < (Key)v1;
|
||||
}
|
||||
|
||||
public:
|
||||
ParallelRadixSort (Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize)
|
||||
: radixCount(nullptr), src(src), tmp(tmp), N(N)
|
||||
{
|
||||
assert(blockSize > 0);
|
||||
|
||||
/* perform single threaded sort for small N */
|
||||
if (N<=blockSize) // handles also special case of 0!
|
||||
{
|
||||
/* do inplace sort inside destination array */
|
||||
std::sort(src,src+N,compare<Ty>);
|
||||
}
|
||||
|
||||
/* perform parallel sort for large N */
|
||||
else
|
||||
{
|
||||
const size_t numThreads = min((N+blockSize-1)/blockSize,TaskScheduler::threadCount(),size_t(MAX_TASKS));
|
||||
tbbRadixSort(numThreads);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void tbbRadixIteration0(const Key shift,
|
||||
const Ty* __restrict const src,
|
||||
Ty* __restrict const dst,
|
||||
const size_t threadIndex, const size_t threadCount)
|
||||
{
|
||||
const size_t startID = (threadIndex+0)*N/threadCount;
|
||||
const size_t endID = (threadIndex+1)*N/threadCount;
|
||||
|
||||
/* mask to extract some number of bits */
|
||||
const Key mask = BUCKETS-1;
|
||||
|
||||
/* count how many items go into the buckets */
|
||||
for (size_t i=0; i<BUCKETS; i++)
|
||||
radixCount[threadIndex][i] = 0;
|
||||
|
||||
/* iterate over src array and count buckets */
|
||||
unsigned int * __restrict const count = radixCount[threadIndex];
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma nounroll
|
||||
#endif
|
||||
for (size_t i=startID; i<endID; i++) {
|
||||
#if defined(__X86_64__)
|
||||
const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
|
||||
#else
|
||||
const Key index = ((Key)src[i] >> shift) & mask;
|
||||
#endif
|
||||
count[index]++;
|
||||
}
|
||||
}
|
||||
|
||||
void tbbRadixIteration1(const Key shift,
|
||||
const Ty* __restrict const src,
|
||||
Ty* __restrict const dst,
|
||||
const size_t threadIndex, const size_t threadCount)
|
||||
{
|
||||
const size_t startID = (threadIndex+0)*N/threadCount;
|
||||
const size_t endID = (threadIndex+1)*N/threadCount;
|
||||
|
||||
/* mask to extract some number of bits */
|
||||
const Key mask = BUCKETS-1;
|
||||
|
||||
/* calculate total number of items for each bucket */
|
||||
__aligned(64) unsigned int total[BUCKETS];
|
||||
/*
|
||||
for (size_t i=0; i<BUCKETS; i++)
|
||||
total[i] = 0;
|
||||
*/
|
||||
for (size_t i=0; i<BUCKETS; i+=VSIZEX)
|
||||
vintx::store(&total[i], zero);
|
||||
|
||||
for (size_t i=0; i<threadCount; i++)
|
||||
{
|
||||
/*
|
||||
for (size_t j=0; j<BUCKETS; j++)
|
||||
total[j] += radixCount[i][j];
|
||||
*/
|
||||
for (size_t j=0; j<BUCKETS; j+=VSIZEX)
|
||||
vintx::store(&total[j], vintx::load(&total[j]) + vintx::load(&radixCount[i][j]));
|
||||
}
|
||||
|
||||
/* calculate start offset of each bucket */
|
||||
__aligned(64) unsigned int offset[BUCKETS];
|
||||
offset[0] = 0;
|
||||
for (size_t i=1; i<BUCKETS; i++)
|
||||
offset[i] = offset[i-1] + total[i-1];
|
||||
|
||||
/* calculate start offset of each bucket for this thread */
|
||||
for (size_t i=0; i<threadIndex; i++)
|
||||
{
|
||||
/*
|
||||
for (size_t j=0; j<BUCKETS; j++)
|
||||
offset[j] += radixCount[i][j];
|
||||
*/
|
||||
for (size_t j=0; j<BUCKETS; j+=VSIZEX)
|
||||
vintx::store(&offset[j], vintx::load(&offset[j]) + vintx::load(&radixCount[i][j]));
|
||||
}
|
||||
|
||||
/* copy items into their buckets */
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#pragma nounroll
|
||||
#endif
|
||||
for (size_t i=startID; i<endID; i++) {
|
||||
const Ty elt = src[i];
|
||||
#if defined(__X86_64__)
|
||||
const size_t index = ((size_t)(Key)src[i] >> (size_t)shift) & (size_t)mask;
|
||||
#else
|
||||
const size_t index = ((Key)src[i] >> shift) & mask;
|
||||
#endif
|
||||
dst[offset[index]++] = elt;
|
||||
}
|
||||
}
|
||||
|
||||
void tbbRadixIteration(const Key shift, const bool last,
|
||||
const Ty* __restrict src, Ty* __restrict dst,
|
||||
const size_t numTasks)
|
||||
{
|
||||
affinity_partitioner ap;
|
||||
parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration0(shift,src,dst,taskIndex,numTasks); },ap);
|
||||
parallel_for_affinity(numTasks,[&] (size_t taskIndex) { tbbRadixIteration1(shift,src,dst,taskIndex,numTasks); },ap);
|
||||
}
|
||||
|
||||
void tbbRadixSort(const size_t numTasks)
|
||||
{
|
||||
radixCount = (TyRadixCount*) alignedMalloc(MAX_TASKS*sizeof(TyRadixCount));
|
||||
|
||||
if (sizeof(Key) == sizeof(uint32_t)) {
|
||||
tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
|
||||
tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(3*BITS,1,tmp,src,numTasks);
|
||||
}
|
||||
else if (sizeof(Key) == sizeof(uint64_t))
|
||||
{
|
||||
tbbRadixIteration(0*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(1*BITS,0,tmp,src,numTasks);
|
||||
tbbRadixIteration(2*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(3*BITS,0,tmp,src,numTasks);
|
||||
tbbRadixIteration(4*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(5*BITS,0,tmp,src,numTasks);
|
||||
tbbRadixIteration(6*BITS,0,src,tmp,numTasks);
|
||||
tbbRadixIteration(7*BITS,1,tmp,src,numTasks);
|
||||
}
|
||||
alignedFree(radixCount);
|
||||
radixCount = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
TyRadixCount* radixCount;
|
||||
Ty* const src;
|
||||
Ty* const tmp;
|
||||
const size_t N;
|
||||
};
|
||||
|
||||
template<typename Ty>
|
||||
void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
|
||||
{
|
||||
ParallelRadixSort<Ty,Ty>(src,tmp,N,blockSize);
|
||||
}
|
||||
|
||||
template<typename Ty, typename Key>
|
||||
void radix_sort(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192)
|
||||
{
|
||||
ParallelRadixSort<Ty,Key>(src,tmp,N,blockSize);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
void radix_sort_u32(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
|
||||
radix_sort<Ty,uint32_t>(src,tmp,N,blockSize);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
void radix_sort_u64(Ty* const src, Ty* const tmp, const size_t N, const size_t blockSize = 8192) {
|
||||
radix_sort<Ty,uint64_t>(src,tmp,N,blockSize);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,20 +14,23 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
set(CTEST_PROJECT_NAME "Embree")
|
||||
set(CTEST_NIGHTLY_START_TIME "22:00:00 UTC")
|
||||
set(TEST_MODELS_HASH 01ada7ec1ace15ddba73aaab3f53ac6aac6a0309)
|
||||
FIND_PATH(COI_INCLUDE_PATH source/COIProcess_source.h /opt/intel/mic/coi/include /usr/include/intel-coi)
|
||||
FIND_PATH(COI_HOST_LIBRARY_DIR libcoi_host.so /opt/intel/mic/coi/host-linux-release/lib/)
|
||||
FIND_PATH(COI_DEV_LIBRARY_DIR libcoi_device.so /opt/mpss/*/sysroots/k1om-mpss-linux/usr/lib64/)
|
||||
|
||||
IF (NOT CTEST_DROP_SITE)
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "cdash")
|
||||
set(CTEST_DROP_LOCATION "/CDash/submit.php?project=Embree")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
endif()
|
||||
IF (COI_INCLUDE_PATH AND COI_HOST_LIBRARY_DIR AND COI_DEV_LIBRARY_DIR)
|
||||
SET(COI_FOUND TRUE)
|
||||
SET(COI_INCLUDE_PATHS ${COI_INCLUDE_PATH})
|
||||
SET(COI_HOST_LIBRARIES ${COI_HOST_LIBRARY_DIR}/libcoi_host.so)
|
||||
SET(COI_DEV_LIBRARIES ${COI_DEV_LIBRARY_DIR}/libcoi_device.so)
|
||||
ELSE ()
|
||||
MESSAGE(FATAL_ERROR "COI installation not found")
|
||||
ENDIF ()
|
||||
|
||||
list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning #1478") # deprecated function used
|
||||
#list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "warning #10237") # -lcilkrts linked in dynamically, static library not available")
|
||||
list (APPEND CTEST_CUSTOM_WARNING_EXCEPTION "-Wextern-initializer")
|
||||
MARK_AS_ADVANCED(COI_INCLUDE_PATH)
|
||||
MARK_AS_ADVANCED(COI_HOST_LIBRARY_DIR)
|
||||
MARK_AS_ADVANCED(COI_DEV_LIBRARY_DIR)
|
||||
|
||||
SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE 200000)
|
||||
SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE 800000)
|
||||
MARK_AS_ADVANCED(COI_INCLUDE_PATHS)
|
||||
MARK_AS_ADVANCED(COI_HOST_LIBRARIES)
|
||||
MARK_AS_ADVANCED(COI_DEV_LIBRARIES)
|
||||
@@ -0,0 +1,44 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(LIBRARY_PATHS
|
||||
/usr/lib /usr/local/lib /opt/local/lib)
|
||||
|
||||
FIND_PATH(OPENEXR_INCLUDE_DIR ImfHeader.h
|
||||
/usr/include /usr/include/OpenEXR
|
||||
/usr/local/include /usr/local/include/OpenEXR
|
||||
/opt/local/include /opt/local/include/OpenEXR)
|
||||
|
||||
FIND_LIBRARY(OPENEXR_HALF_LIBRARY NAMES Half PATHS ${LIBRARY_PATHS})
|
||||
FIND_LIBRARY(OPENEXR_IEX_LIBRARY NAMES Iex PATHS ${LIBRARY_PATHS})
|
||||
FIND_LIBRARY(OPENEXR_IMATH_LIBRARY NAMES Imath PATHS ${LIBRARY_PATHS})
|
||||
FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY NAMES IlmImf PATHS ${LIBRARY_PATHS})
|
||||
FIND_LIBRARY(OPENEXR_ILMTHREAD_LIBRARY NAMES IlmThread PATHS ${LIBRARY_PATHS})
|
||||
|
||||
SET(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR})
|
||||
SET(OPENEXR_LIBRARIES ${OPENEXR_HALF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY})
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENEXR DEFAULT_MSG OPENEXR_INCLUDE_DIR OPENEXR_HALF_LIBRARY OPENEXR_IEX_LIBRARY OPENEXR_IMATH_LIBRARY OPENEXR_ILMIMF_LIBRARY OPENEXR_ILMTHREAD_LIBRARY)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
OPENEXR_INCLUDE_DIR
|
||||
OPENEXR_HALF_LIBRARY
|
||||
OPENEXR_IEX_LIBRARY
|
||||
OPENEXR_IMATH_LIBRARY
|
||||
OPENEXR_ILMIMF_LIBRARY
|
||||
OPENEXR_ILMTHREAD_LIBRARY
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,16 +14,13 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
ADD_LIBRARY(scenegraph STATIC
|
||||
xml_parser.cpp
|
||||
xml_loader.cpp
|
||||
xml_writer.cpp
|
||||
obj_loader.cpp
|
||||
ply_loader.cpp
|
||||
corona_loader.cpp
|
||||
texture.cpp
|
||||
scenegraph.cpp
|
||||
geometry_creation.cpp)
|
||||
FIND_PATH( OPENSUBDIV_INCLUDE_DIR NAMES opensubdiv/version.h )
|
||||
FIND_LIBRARY( OPENSUBDIV_LIBRARY NAMES osdCPU)
|
||||
|
||||
TARGET_LINK_LIBRARIES(scenegraph sys math lexers image)
|
||||
SET_PROPERTY(TARGET scenegraph PROPERTY FOLDER tutorials/common)
|
||||
SET(OPENSUBDIV_LIBRARIES ${OPENSUBDIV_LIBRARY} )
|
||||
SET(OPENSUBDIV_INCLUDE_DIRS ${OPENSUBDIV_INCLUDE_DIR} )
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENSUBDIV DEFAULT_MSG OPENSUBDIV_INCLUDE_DIR OPENSUBDIV_LIBRARY)
|
||||
|
||||
MARK_AS_ADVANCED(OPENSUBDIV_INCLUDE_DIR OPENSUBDIV_LIBRARY)
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -22,3 +22,4 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(PNG DEFAULT_MSG PNG_INCLUDE_DIR PNG_LIBRARIES)
|
||||
|
||||
MARK_AS_ADVANCED(PNG_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(PNG_LIBRARIES)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,19 +14,14 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
ADD_LIBRARY(algorithms OBJECT
|
||||
parallel_for.cpp
|
||||
parallel_reduce.cpp
|
||||
parallel_prefix_sum.cpp
|
||||
parallel_for_for.cpp
|
||||
parallel_for_for_prefix_sum.cpp
|
||||
parallel_partition.cpp
|
||||
parallel_sort.cpp
|
||||
parallel_set.cpp
|
||||
parallel_map.cpp
|
||||
parallel_filter.cpp
|
||||
)
|
||||
|
||||
SET_PROPERTY(TARGET algorithms PROPERTY FOLDER common)
|
||||
SET(PTEX_ROOT ${PROJECT_SOURCE_DIR}/ptex CACHE STRING "Root of Ptex installation")
|
||||
|
||||
FIND_PATH (PTEX_INCLUDE_DIRS Ptexture.h PATHS ${PTEX_ROOT}/include ${PTEX_ROOT}/src/ptex )
|
||||
FIND_LIBRARY(PTEX_LIBRARIES Ptex PATHS ${PTEX_ROOT}/lib ${PTEX_ROOT}/build/ptex )
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PTEX DEFAULT_MSG PTEX_INCLUDE_DIRS PTEX_LIBRARIES)
|
||||
|
||||
MARK_AS_ADVANCED(PTEX_INCLUDE_DIRS)
|
||||
MARK_AS_ADVANCED(PTEX_LIBRARIES)
|
||||
|
||||
+21
-43
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -15,12 +15,10 @@
|
||||
## ======================================================================== ##
|
||||
|
||||
IF (WIN32)
|
||||
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h
|
||||
FIND_PATH(TBB_ROOT include/tbb/task_scheduler_init.h
|
||||
DOC "Root of TBB installation"
|
||||
PATHS ${PROJECT_SOURCE_DIR}/tbb "C:/Program Files (x86)/Intel/Composer XE/tbb"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h)
|
||||
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET(TBB_ARCH intel64)
|
||||
@@ -36,10 +34,10 @@ IF (WIN32)
|
||||
SET(TBB_VCVER vc12)
|
||||
ENDIF()
|
||||
|
||||
SET(TBB_LIBDIR ${EMBREE_TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER})
|
||||
SET(TBB_BINDIR ${EMBREE_TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER})
|
||||
SET(TBB_LIBDIR ${TBB_ROOT}/lib/${TBB_ARCH}/${TBB_VCVER})
|
||||
SET(TBB_BINDIR ${TBB_ROOT}/bin/${TBB_ARCH}/${TBB_VCVER})
|
||||
|
||||
IF (EMBREE_TBB_ROOT STREQUAL "")
|
||||
IF (TBB_ROOT STREQUAL "")
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
|
||||
@@ -47,53 +45,34 @@ IF (WIN32)
|
||||
SET(TBB_INCLUDE_DIR TBB_INCLUDE_DIR-NOTFOUND)
|
||||
SET(TBB_LIBRARY TBB_LIBRARY-NOTFOUND)
|
||||
SET(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND)
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_LIBDIR} NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_LIBDIR} NO_DEFAULT_PATH)
|
||||
ENDIF()
|
||||
|
||||
ELSE ()
|
||||
|
||||
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h
|
||||
FIND_PATH(TBB_ROOT include/tbb/task_scheduler_init.h
|
||||
DOC "Root of TBB installation"
|
||||
PATHS ${PROJECT_SOURCE_DIR}/tbb /opt/intel/tbb
|
||||
NO_DEFAULT_PATH
|
||||
PATHS ${PROJECT_SOURCE_DIR}/tbb /opt/intel/composerxe/tbb
|
||||
)
|
||||
FIND_PATH(EMBREE_TBB_ROOT include/tbb/tbb.h)
|
||||
|
||||
IF (EMBREE_TBB_ROOT STREQUAL "")
|
||||
|
||||
IF (TBB_ROOT STREQUAL "")
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc)
|
||||
|
||||
ELSEIF (EXISTS ${EMBREE_TBB_ROOT}/src)
|
||||
OPTION(EMBREE_TBB_STATIC_LIB "Build TBB as a static library (building TBB as a static library is NOT recommended)")
|
||||
if (EMBREE_TBB_STATIC_LIB)
|
||||
include(${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
|
||||
tbb_build(TBB_ROOT ${EMBREE_TBB_ROOT} CONFIG_DIR TBB_DIR MAKE_ARGS extra_inc=big_iron.inc)
|
||||
SET(TBB_INCLUDE_DIR ${EMBREE_TBB_ROOT}/include)
|
||||
SET(TBB_LIBRARY ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbb.a)
|
||||
SET(TBB_LIBRARY_MALLOC ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbbmalloc.a)
|
||||
else()
|
||||
include(${EMBREE_TBB_ROOT}/cmake/TBBBuild.cmake)
|
||||
tbb_build(TBB_ROOT ${EMBREE_TBB_ROOT} CONFIG_DIR TBB_DIR)
|
||||
SET(TBB_INCLUDE_DIR ${EMBREE_TBB_ROOT}/include)
|
||||
SET(TBB_LIBRARY ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbb.so.2)
|
||||
SET(TBB_LIBRARY_MALLOC ${PROJECT_BINARY_DIR}/tbb_cmake_build/tbb_cmake_build_subdir_release/libtbbmalloc.so.2)
|
||||
endif()
|
||||
|
||||
ELSE()
|
||||
SET(TBB_INCLUDE_DIR TBB_INCLUDE_DIR-NOTFOUND)
|
||||
SET(TBB_LIBRARY TBB_LIBRARY-NOTFOUND)
|
||||
SET(TBB_LIBRARY_MALLOC TBB_LIBRARY_MALLOC-NOTFOUND)
|
||||
IF (APPLE)
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${EMBREE_TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${EMBREE_TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib NO_DEFAULT_PATH)
|
||||
ELSE()
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${EMBREE_TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4 ${EMBREE_TBB_ROOT}/lib ${EMBREE_TBB_ROOT}/lib64 /usr/libx86_64-linux-gnu/ NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4 ${EMBREE_TBB_ROOT}/lib ${EMBREE_TBB_ROOT}/lib64 /usr/libx86_64-linux-gnu/ NO_DEFAULT_PATH)
|
||||
FIND_PATH(TBB_INCLUDE_DIR tbb/task_scheduler_init.h PATHS ${TBB_ROOT}/include NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY tbb PATHS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 NO_DEFAULT_PATH)
|
||||
FIND_LIBRARY(TBB_LIBRARY_MALLOC tbbmalloc PATHS ${TBB_ROOT}/lib/intel64/gcc4.4 ${TBB_ROOT}/lib ${TBB_ROOT}/lib64 NO_DEFAULT_PATH)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
@@ -116,13 +95,12 @@ MARK_AS_ADVANCED(TBB_LIBRARY_MALLOC)
|
||||
##############################################################
|
||||
|
||||
IF (WIN32)
|
||||
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
|
||||
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
|
||||
INSTALL(PROGRAMS ${TBB_LIBDIR}/tbb.lib ${TBB_LIBDIR}/tbbmalloc.lib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
|
||||
ELSEIF (EMBREE_ZIP_MODE)
|
||||
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION bin COMPONENT examples)
|
||||
INSTALL(PROGRAMS ${TBB_BINDIR}/tbb.dll ${TBB_BINDIR}/tbbmalloc.dll DESTINATION lib COMPONENT lib)
|
||||
ELSEIF (NOT ENABLE_INSTALLER)
|
||||
IF (APPLE)
|
||||
INSTALL(PROGRAMS ${EMBREE_TBB_ROOT}/lib/libtbb.dylib ${EMBREE_TBB_ROOT}/lib/libtbbmalloc.dylib DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
|
||||
INSTALL(PROGRAMS ${TBB_ROOT}/lib/libc++/libtbb.dylib ${TBB_ROOT}/lib/libc++/libtbbmalloc.dylib DESTINATION lib COMPONENT lib)
|
||||
ELSE()
|
||||
INSTALL(PROGRAMS ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4/libtbb.so.2 ${EMBREE_TBB_ROOT}/lib/intel64/gcc4.4/libtbbmalloc.so.2 DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib)
|
||||
INSTALL(PROGRAMS ${TBB_ROOT}/lib/intel64/gcc4.4/libtbb.so.2 ${TBB_ROOT}/lib/intel64/gcc4.4/libtbbmalloc.so.2 DESTINATION lib COMPONENT lib)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
@@ -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()
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -1,37 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
IF (WIN32 OR APPLE)
|
||||
return()
|
||||
ENDIF()
|
||||
|
||||
execute_process(COMMAND objdump -d ${file} OUTPUT_VARIABLE output)
|
||||
string(REPLACE "\n" ";" output ${output})
|
||||
|
||||
SET(lastfunc "")
|
||||
foreach (line ${output})
|
||||
if ("${line}" MATCHES "^.*<([^>]*)>:$")
|
||||
SET(lastfunc ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
if ("${line}" MATCHES ".*sub[ ]+[$]([^,]*),%rsp.*")
|
||||
set(bytes ${CMAKE_MATCH_1})
|
||||
if ("${bytes}" GREATER "4096")
|
||||
if ("${lastfunc}" MATCHES ".*recurse.*")
|
||||
message(WARNING "Large stack space requirement: ${lastfunc} size: ${bytes}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
+16
-95
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -21,100 +21,21 @@ SET(FLAGS_SSE41 "-msse4.1")
|
||||
SET(FLAGS_SSE42 "-msse4.2")
|
||||
SET(FLAGS_AVX "-mavx")
|
||||
SET(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
|
||||
SET(FLAGS_AVX512KNL "-march=knl")
|
||||
SET(FLAGS_AVX512SKX "-march=skx")
|
||||
SET(FLAGS_AVX512 "-mavx512")
|
||||
|
||||
IF (WIN32)
|
||||
|
||||
SET(COMMON_CXX_FLAGS "")
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
|
||||
# SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -Xclang -fcxx-exceptions") # enable C++ exceptions in Clang
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
|
||||
ELSE()
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-vectorize") # disable auto vectorization
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-vectorize") # disable auto vectorization
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
|
||||
SET(SECURE_LINKER_FLAGS "")
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
|
||||
ENDIF()
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
|
||||
INCLUDE(msvc_post)
|
||||
|
||||
ELSE()
|
||||
|
||||
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
|
||||
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
|
||||
SET(CMAKE_CXX_FLAGS "")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
|
||||
IF (NOT APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable optimizations
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enable assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configure TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
|
||||
ELSE(APPLE)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
|
||||
ENDIF(APPLE)
|
||||
SET(CMAKE_CXX_COMPILER "clang++")
|
||||
SET(CMAKE_C_COMPILER "clang")
|
||||
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 -fno-strict-aliasing -Wno-narrowing -Wno-deprecated-register")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
|
||||
ENDIF()
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 ") # we only use MacOSX 10.7 features
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) # link against C++11 stdlib
|
||||
ENDIF (APPLE)
|
||||
|
||||
@@ -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")
|
||||
@@ -1,17 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
file(WRITE ${dst} "#include \"${src}\"\n")
|
||||
@@ -1,23 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
# use default install config
|
||||
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/embree-config-install.cmake)
|
||||
|
||||
# and override path variables to match for build directory
|
||||
SET(EMBREE_INCLUDE_DIRS @PROJECT_SOURCE_DIR@/include)
|
||||
SET(EMBREE_LIBRARY @PROJECT_BINARY_DIR@/@EMBREE_LIBRARY_NAME@)
|
||||
SET(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,6 +14,8 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(EMBREE_ISPC_SUPPORT OFF)
|
||||
INCLUDE(tutorial)
|
||||
ADD_TUTORIAL(buildbench)
|
||||
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
|
||||
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../libembree.so.@EMBREE_CONFIG_VERSION@)
|
||||
SET(EMBREE_LIBRARY_XEONPHI ${CMAKE_CURRENT_LIST_DIR}/../../libembree_xeonphi.so.@EMBREE_CONFIG_VERSION@)
|
||||
|
||||
MARK_AS_ADVANCED(embree_DIR)
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,7 +14,7 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
INCLUDE(tutorial)
|
||||
ADD_TUTORIAL(viewer_stream)
|
||||
|
||||
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
|
||||
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../libembree.@EMBREE_CONFIG_VERSION@.dylib)
|
||||
|
||||
MARK_AS_ADVANCED(embree_DIR)
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,7 +14,7 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
INCLUDE(tutorial)
|
||||
ADD_TUTORIAL(viewer_anim)
|
||||
|
||||
SET(EMBREE_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/../../../include)
|
||||
SET(EMBREE_LIBRARY ${CMAKE_CURRENT_LIST_DIR}/../../embree.lib)
|
||||
|
||||
MARK_AS_ADVANCED(embree_DIR)
|
||||
@@ -1,59 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(EMBREE_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/@EMBREE_RELATIV_ROOT_DIR@)
|
||||
GET_FILENAME_COMPONENT(EMBREE_ROOT_DIR "${EMBREE_ROOT_DIR}" ABSOLUTE)
|
||||
|
||||
SET(EMBREE_INCLUDE_DIRS ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_INCLUDEDIR@)
|
||||
SET(EMBREE_LIBRARY ${EMBREE_ROOT_DIR}/@CMAKE_INSTALL_LIBDIR@/@EMBREE_LIBRARY_NAME@)
|
||||
SET(EMBREE_LIBRARIES ${EMBREE_LIBRARY})
|
||||
|
||||
MARK_AS_ADVANCED(embree_DIR)
|
||||
|
||||
SET(EMBREE_VERSION @EMBREE_VERSION@)
|
||||
SET(EMBREE_VERSION_MAJOR @EMBREE_VERSION_MAJOR@)
|
||||
SET(EMBREE_VERSION_MINOR @EMBREE_VERSION_MINOR@)
|
||||
SET(EMBREE_VERSION_PATCH @EMBREE_VERSION_PATCH@)
|
||||
SET(EMBREE_VERSION_NOTE "@EMBREE_VERSION_NOTE@")
|
||||
|
||||
SET(EMBREE_MAX_ISA @EMBREE_MAX_ISA@)
|
||||
SET(EMBREE_ISA_SSE2 @EMBREE_ISA_SSE2@)
|
||||
SET(EMBREE_ISA_SSE42 @EMBREE_ISA_SSE42@)
|
||||
SET(EMBREE_ISA_AVX @EMBREE_ISA_AVX@)
|
||||
SET(EMBREE_ISA_AVX2 @EMBREE_ISA_AVX2@)
|
||||
SET(EMBREE_ISA_AVX512KNL @EMBREE_ISA_AVX512KNL@)
|
||||
SET(EMBREE_ISA_AVX512SKX @EMBREE_ISA_AVX512SKX@)
|
||||
|
||||
SET(EMBREE_BUILD_TYPE @CMAKE_BUILD_TYPE@)
|
||||
SET(EMBREE_ISPC_SUPPORT @EMBREE_ISPC_SUPPORT@)
|
||||
SET(EMBREE_STATIC_LIB @EMBREE_STATIC_LIB@)
|
||||
SET(EMBREE_TUTORIALS @EMBREE_TUTORIALS@)
|
||||
|
||||
SET(EMBREE_RAY_MASK @EMBREE_RAY_MASK@)
|
||||
SET(EMBREE_STAT_COUNTERS @EMBREE_STAT_COUNTERS@)
|
||||
SET(EMBREE_BACKFACE_CULLING @EMBREE_BACKFACE_CULLING@)
|
||||
SET(EMBREE_INTERSECTION_FILTER @EMBREE_INTERSECTION_FILTER@)
|
||||
SET(EMBREE_INTERSECTION_FILTER_RESTORE @EMBREE_INTERSECTION_FILTER_RESTORE@)
|
||||
SET(EMBREE_IGNORE_INVALID_RAYS @EMBREE_IGNORE_INVALID_RAYS@)
|
||||
SET(EMBREE_TASKING_SYSTEM @EMBREE_TASKING_SYSTEM@)
|
||||
|
||||
SET(EMBREE_GEOMETRY_TRIANGLES @EMBREE_GEOMETRY_TRIANGLES@)
|
||||
SET(EMBREE_GEOMETRY_QUADS @EMBREE_GEOMETRY_QUADS@)
|
||||
SET(EMBREE_GEOMETRY_LINES @EMBREE_GEOMETRY_LINES@)
|
||||
SET(EMBREE_GEOMETRY_HAIR @EMBREE_GEOMETRY_HAIR@)
|
||||
SET(EMBREE_GEOMETRY_SUBDIV @EMBREE_GEOMETRY_SUBDIV@)
|
||||
SET(EMBREE_GEOMETRY_USER @EMBREE_GEOMETRY_USER@)
|
||||
SET(EMBREE_RAY_PACKETS @EMBREE_RAY_PACKETS@)
|
||||
+18
-48
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -15,58 +15,28 @@
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(FLAGS_SSE2 "-msse2")
|
||||
SET(FLAGS_SSE3 "-msse3")
|
||||
SET(FLAGS_SSSE3 "-mssse3")
|
||||
SET(FLAGS_SSE41 "-msse4.1")
|
||||
SET(FLAGS_SSE42 "-msse4.2")
|
||||
SET(FLAGS_AVX "-mavx")
|
||||
SET(FLAGS_AVX2 "-mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
|
||||
SET(FLAGS_AVX512KNL "-mavx512f -mavx512pf -mavx512er -mavx512cd -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
|
||||
SET(FLAGS_AVX512SKX "-mavx512f -mavx512dq -mavx512cd -mavx512bw -mavx512vl -mf16c -mavx2 -mfma -mlzcnt -mbmi -mbmi2")
|
||||
SET(FLAGS_AVX512 "-mavx512f -mavx512pf -mavx512er -mavx512cd")
|
||||
|
||||
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
|
||||
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
|
||||
SET(CMAKE_CXX_FLAGS "")
|
||||
SET(CMAKE_CXX_COMPILER "g++")
|
||||
SET(CMAKE_C_COMPILER "gcc")
|
||||
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 -fno-strict-aliasing -Wno-narrowing")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
|
||||
IF (NOT APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") # disables strict aliasing rules
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-vectorize") # disable auto vectorizer
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enable assertions
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configure TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable optimizations
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # enable full optimizations
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enable assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configure TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # enable full optimizations
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
|
||||
ELSE(APPLE)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
|
||||
ENDIF(APPLE)
|
||||
SET (CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} -dynamiclib)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 -stdlib=libc++")
|
||||
ENDIF (APPLE)
|
||||
|
||||
|
||||
+25
-134
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,139 +14,30 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
IF (WIN32)
|
||||
SET(FLAGS_SSE2 "-xsse2")
|
||||
SET(FLAGS_SSE3 "-xsse3")
|
||||
SET(FLAGS_SSSE3 "-xssse3")
|
||||
SET(FLAGS_SSE41 "-xsse4.1")
|
||||
SET(FLAGS_SSE42 "-xsse4.2")
|
||||
SET(FLAGS_AVX "-xAVX")
|
||||
SET(FLAGS_AVX2 "-xCORE-AVX2")
|
||||
SET(FLAGS_AVX512 "-xMIC-AVX512")
|
||||
|
||||
SET(FLAGS_SSE2 "/QxSSE2")
|
||||
SET(FLAGS_SSE42 "/QxSSE4.2")
|
||||
SET(FLAGS_AVX "/arch:AVX")
|
||||
SET(FLAGS_AVX2 "/QxCORE-AVX2")
|
||||
SET(FLAGS_AVX512KNL "/QxMIC-AVX512")
|
||||
SET(FLAGS_AVX512SKX "/QxCORE-AVX512")
|
||||
|
||||
SET(COMMON_CXX_FLAGS "")
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qvec-") # disable auto vectorizer
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
|
||||
ELSE()
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
|
||||
ENDIF()
|
||||
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11074 ") # remark #11074: Inlining inhibited by limit max-size
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /Qdiag-disable:11075 ") # remark #11075: To get full report use -Qopt-report:4 -Qopt-report-phase ipo
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Qinline-max-total-size-") # no size limit when performing inlining
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Qinline-factor=200") # increase default inline factors by 2x
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Qinline-max-total-size-") # no size limit when performing inlining
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Qinline-factor=200") # increase default inline factors by 2x
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
|
||||
SET(SECURE_LINKER_FLAGS "")
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
|
||||
ENDIF()
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4217") # locally defined symbol XXX imported in function YYY (happens as the ISPC API layer uses exported library functions)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4049") # warning LNK4049: locally defined symbol _rtcOccluded1M imported
|
||||
|
||||
INCLUDE(msvc_post)
|
||||
|
||||
ELSE()
|
||||
|
||||
IF (APPLE)
|
||||
SET(FLAGS_SSE2 "-xssse3") # on MacOSX ICC does not support SSE2
|
||||
ELSE()
|
||||
SET(FLAGS_SSE2 "-xsse2")
|
||||
ENDIF()
|
||||
SET(FLAGS_SSE42 "-xsse4.2")
|
||||
SET(FLAGS_AVX "-xAVX")
|
||||
SET(FLAGS_AVX2 "-xCORE-AVX2")
|
||||
SET(FLAGS_AVX512KNL "-xMIC-AVX512")
|
||||
SET(FLAGS_AVX512SKX "-xCORE-AVX512")
|
||||
|
||||
OPTION(EMBREE_IGNORE_CMAKE_CXX_FLAGS "When enabled Embree ignores default CMAKE_CXX_FLAGS." ON)
|
||||
IF (EMBREE_IGNORE_CMAKE_CXX_FLAGS)
|
||||
SET(CMAKE_CXX_FLAGS "")
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # enables most warnings
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security") # enables string format vulnerability warnings
|
||||
IF (NOT APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE") # enables support for more secure position independent execution
|
||||
ENDIF()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # generate position independent code suitable for shared libraries
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # enables C++11 features
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") # makes all symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") # makes all inline symbols hidden by default
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-ansi-alias") # disables strict aliasing rules
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_FORTIFY_SOURCE=2") # perform extra security checks for some standard library calls
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-vec") # disable auto vectorizer
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fasm-blocks") # enable assembly blocks
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector") # protects against return address overrides
|
||||
ENDIF()
|
||||
IF(NOT CMAKE_CXX_COMPILER_WRAPPER STREQUAL "CrayPrgEnv")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel") # links intel runtime statically
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-intel-extensions") # disables some intel extensions which cause symbols to be exported
|
||||
ENDIF()
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") # enables assertions
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DTBB_USE_DEBUG") # configures TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # disable all optimizations
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") # disable assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") # full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -restrict") # enable restrict keyword
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-total-size") # no size limit when performing inlining
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -no-inline-max-per-compile") # no maximal number of inlinings per compilation unit
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -inline-factor=200") # increase default inline factors limits by 2x
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG") # enables assertions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DTBB_USE_DEBUG") # configures TBB in debug mode
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -g") # generate debug information
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3") # full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -restrict") # enable restrict keyword
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -no-inline-max-total-size") # no size limit when performing inlining
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -no-inline-max-per-compile") # no maximal number of inlinings per compilation unit
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -inline-factor=200") # increase default inline factors by 2x
|
||||
|
||||
#SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -g -debug inline-debug-info")
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS "-g")
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7") # makes sure code runs on older MacOSX versions
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") # link against libc++ which supports C++11 features
|
||||
ELSE(APPLE)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") # issues link error for undefined symbols in shared library
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z noexecstack") # we do not need an executable stack
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -z relro -z now") # re-arranges data sections to increase security
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") # enables position independent execution for executable
|
||||
ENDIF(APPLE)
|
||||
SET(CMAKE_CXX_COMPILER "icpc")
|
||||
SET(CMAKE_C_COMPILER "icc")
|
||||
SET(CMAKE_CXX_FLAGS "-Wall -fPIC -std=c++11 -no-ansi-alias -static-intel -fasm-blocks")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG -g -O0")
|
||||
## SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -restrict -g -debug inline-debug-info")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -restrict")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DDEBUG -g -O3 -restrict")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "-g")
|
||||
|
||||
IF (NOT RTCORE_EXPORT_ALL_SYMBOLS)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden -fvisibility=hidden")
|
||||
ENDIF()
|
||||
|
||||
IF (APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.7 ") # we only use MacOSX 10.7 features
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++" ) # link against C++11 stdlib
|
||||
ENDIF (APPLE)
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET (CMAKE_CXX_COMPILER icpc)
|
||||
SET (CMAKE_CXX_FLAGS "-mmic -restrict -Wall -wd177 -fasm-blocks -fPIC -std=c++11")
|
||||
SET (CMAKE_CXX_FLAGS_NOOPT "-g -O0 -DDEBUG")
|
||||
SET (CMAKE_CXX_FLAGS_DEBUG "-g -w1 -O2 -DDEBUG ")
|
||||
|
||||
SET (CMAKE_CXX_FLAGS_RELEASE "-O3 -g -DNDEBUG -fp-model fast -fimf-precision=low -fasm-blocks -no-inline-max-total-size -inline-factor=200 -fPIC -fma -restrict -no-prec-div -no-prec-sqrt -mGLOB_default_function_attrs=\"use_vec_for_imul=on;use_fast_math=on;gather_scatter_loop_jknzd=on;gather_scatter_loop_unroll=2;use_gather_scatter_hint=on;c_sch_nop_insertion=on;c_avoid_movz_and_movs=off;c_avoid_integer_ciscization=on;avoid_long_vector_ints=on;avoid_loads_with_extend=on;smart_mem_conflicts=on\" -mP2OPT_hlo_prefetch=F ")
|
||||
|
||||
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O3 -DDEBUG -fp-model fast -fimf-precision=low -fasm-blocks -no-inline-max-total-size -inline-factor=200 -fPIC -fma -restrict -no-prec-div -no-prec-sqrt -mGLOB_default_function_attrs=\"use_vec_for_imul=on;use_fast_math=on;gather_scatter_loop_jknzd=on;gather_scatter_loop_unroll=2;use_gather_scatter_hint=on;c_sch_nop_insertion=on;c_avoid_movz_and_movs=off;c_avoid_integer_ciscization=on;avoid_long_vector_ints=on;avoid_loads_with_extend=on;smart_mem_conflicts=on\" -mP2OPT_hlo_prefetch=F ")
|
||||
|
||||
SET(CMAKE_LINKER icpc)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
|
||||
+53
-45
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -23,50 +23,44 @@ MACRO (INCLUDE_DIRECTORIES_ISPC)
|
||||
SET(ISPC_INCLUDE_DIR ${ISPC_INCLUDE_DIR} ${ARGN})
|
||||
ENDMACRO ()
|
||||
|
||||
IF (EMBREE_ISPC_SUPPORT)
|
||||
IF (ENABLE_ISPC_SUPPORT)
|
||||
|
||||
# ISPC versions to look for, in decending order (newest first)
|
||||
SET(ISPC_VERSION_WORKING "1.9.1" "1.9.0" "1.8.3" "1.8.2")
|
||||
LIST(GET ISPC_VERSION_WORKING -1 ISPC_VERSION_REQUIRED)
|
||||
SET(ISPC_VERSION_REQUIRED "1.8.2")
|
||||
|
||||
IF (NOT EMBREE_ISPC_EXECUTABLE)
|
||||
IF (NOT ISPC_EXECUTABLE)
|
||||
# try sibling folder as hint for path of ISPC
|
||||
IF (APPLE)
|
||||
SET(ISPC_DIR_SUFFIX "osx")
|
||||
ELSEIF(WIN32)
|
||||
SET(ISPC_DIR_SUFFIX "windows")
|
||||
IF (MSVC14)
|
||||
LIST(APPEND ISPC_DIR_SUFFIX "windows-vs2015")
|
||||
ELSE()
|
||||
LIST(APPEND ISPC_DIR_SUFFIX "windows-vs2013")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(ISPC_DIR_SUFFIX "linux")
|
||||
ENDIF()
|
||||
FOREACH(ver ${ISPC_VERSION_WORKING})
|
||||
FOREACH(suffix ${ISPC_DIR_SUFFIX})
|
||||
LIST(APPEND ISPC_DIR_HINT ${PROJECT_SOURCE_DIR}/../ispc-v${ver}-${suffix})
|
||||
ENDFOREACH()
|
||||
ENDFOREACH()
|
||||
SET(ISPC_DIR_HINT ${PROJECT_SOURCE_DIR}/../ispc-v${ISPC_VERSION_REQUIRED}-${ISPC_DIR_SUFFIX})
|
||||
|
||||
FIND_PROGRAM(EMBREE_ISPC_EXECUTABLE ispc PATHS ${ISPC_DIR_HINT} DOC "Path to the ISPC executable.")
|
||||
IF (NOT EMBREE_ISPC_EXECUTABLE)
|
||||
MESSAGE(FATAL_ERROR "Intel SPMD Compiler (ISPC) not found. Disable EMBREE_ISPC_SUPPORT or install ISPC.")
|
||||
FIND_PROGRAM(ISPC_EXECUTABLE ispc PATHS ${ISPC_DIR_HINT} DOC "Path to the ISPC executable.")
|
||||
IF (NOT ISPC_EXECUTABLE)
|
||||
MESSAGE(FATAL_ERROR "Intel SPMD Compiler (ISPC) not found. Disable ENABLE_ISPC_SUPPORT or install ISPC.")
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Found Intel SPMD Compiler (ISPC): ${EMBREE_ISPC_EXECUTABLE}")
|
||||
MESSAGE(STATUS "Found Intel SPMD Compiler (ISPC): ${ISPC_EXECUTABLE}")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# check ISPC version
|
||||
EXECUTE_PROCESS(COMMAND ${EMBREE_ISPC_EXECUTABLE} --version OUTPUT_VARIABLE ISPC_OUTPUT)
|
||||
STRING(REGEX MATCH " ([0-9]+[.][0-9]+[.][0-9]+)(dev|knl)? " DUMMY "${ISPC_OUTPUT}")
|
||||
SET(ISPC_VERSION ${CMAKE_MATCH_1})
|
||||
IF(NOT ISPC_VERSION)
|
||||
EXECUTE_PROCESS(COMMAND ${ISPC_EXECUTABLE} --version OUTPUT_VARIABLE ISPC_OUTPUT)
|
||||
STRING(REGEX MATCH " ([0-9]+[.][0-9]+[.][0-9]+)(dev|knl)? " DUMMY "${ISPC_OUTPUT}")
|
||||
SET(ISPC_VERSION ${CMAKE_MATCH_1})
|
||||
|
||||
IF (ISPC_VERSION VERSION_LESS ISPC_VERSION_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Need at least version ${ISPC_VERSION_REQUIRED} of Intel SPMD Compiler (ISPC).")
|
||||
IF (ISPC_VERSION VERSION_LESS ISPC_VERSION_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Need at least version ${ISPC_VERSION_REQUIRED} of Intel SPMD Compiler (ISPC).")
|
||||
ENDIF()
|
||||
|
||||
SET(ISPC_VERSION ${ISPC_VERSION} CACHE STRING "ISPC Version")
|
||||
MARK_AS_ADVANCED(ISPC_VERSION)
|
||||
MARK_AS_ADVANCED(ISPC_EXECUTABLE)
|
||||
ENDIF()
|
||||
|
||||
GET_FILENAME_COMPONENT(ISPC_DIR ${EMBREE_ISPC_EXECUTABLE} PATH)
|
||||
GET_FILENAME_COMPONENT(ISPC_DIR ${ISPC_EXECUTABLE} PATH)
|
||||
|
||||
SET(EMBREE_ISPC_ADDRESSING 32 CACHE INT "32vs64 bit addressing in ispc")
|
||||
MARK_AS_ADVANCED(EMBREE_ISPC_ADDRESSING)
|
||||
@@ -74,8 +68,14 @@ MARK_AS_ADVANCED(EMBREE_ISPC_ADDRESSING)
|
||||
MACRO (ISPC_COMPILE)
|
||||
SET(ISPC_ADDITIONAL_ARGS "")
|
||||
|
||||
SET(ISPC_TARGET_EXT ${CMAKE_CXX_OUTPUT_EXTENSION})
|
||||
STRING(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}")
|
||||
IF (NOT __XEON__)
|
||||
SET(ISPC_TARGET_EXT .cpp)
|
||||
SET(ISPC_TARGET_ARGS generic-16)
|
||||
SET(ISPC_ADDITIONAL_ARGS ${ISPC_ADDITIONAL_ARGS} --opt=force-aligned-memory --emit-c++ --c++-include-file=${ISPC_DIR}/examples/intrinsics/knc.h -D__XEON_PHI__)
|
||||
ELSE()
|
||||
SET(ISPC_TARGET_EXT ${CMAKE_CXX_OUTPUT_EXTENSION})
|
||||
STRING(REPLACE ";" "," ISPC_TARGET_ARGS "${ISPC_TARGETS}")
|
||||
ENDIF()
|
||||
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
SET(ISPC_ARCHITECTURE "x86-64")
|
||||
@@ -84,6 +84,7 @@ MACRO (ISPC_COMPILE)
|
||||
ENDIF()
|
||||
|
||||
SET(ISPC_TARGET_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${ISPC_TARGET_DIR})
|
||||
|
||||
IF(ISPC_INCLUDE_DIR)
|
||||
STRING(REPLACE ";" ";-I;" ISPC_INCLUDE_DIR_PARMS "${ISPC_INCLUDE_DIR}")
|
||||
@@ -127,26 +128,21 @@ MACRO (ISPC_COMPILE)
|
||||
SET(results "${outdir}/${fname}.dev${ISPC_TARGET_EXT}")
|
||||
|
||||
# if we have multiple targets add additional object files
|
||||
LIST(LENGTH ISPC_TARGETS NUM_TARGETS)
|
||||
IF (NUM_TARGETS GREATER 1)
|
||||
FOREACH(target ${ISPC_TARGETS})
|
||||
# in v1.9.0 ISPC changed the ISA suffix of avx512knl-i32x16 to just 'avx512knl'
|
||||
IF (${target} STREQUAL "avx512knl-i32x16" AND NOT ISPC_VERSION VERSION_LESS "1.9.0")
|
||||
SET(target "avx512knl")
|
||||
ELSEIF (${target} STREQUAL "avx512skx-i32x16")
|
||||
SET(target "avx512skx")
|
||||
ENDIF()
|
||||
SET(results ${results} "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}")
|
||||
ENDFOREACH()
|
||||
IF (__XEON__)
|
||||
LIST(LENGTH ISPC_TARGETS NUM_TARGETS)
|
||||
IF (NUM_TARGETS GREATER 1)
|
||||
FOREACH(target ${ISPC_TARGETS})
|
||||
SET(results ${results} "${outdir}/${fname}.dev_${target}${ISPC_TARGET_EXT}")
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${results} ${ISPC_TARGET_DIR}/${fname}_ispc.h
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${outdir}
|
||||
COMMAND ${EMBREE_ISPC_EXECUTABLE}
|
||||
COMMAND ${ISPC_EXECUTABLE}
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${ISPC_INCLUDE_DIR_PARMS}
|
||||
${ISPC_DEFINITIONS}
|
||||
--arch=${ISPC_ARCHITECTURE}
|
||||
--addressing=${EMBREE_ISPC_ADDRESSING}
|
||||
${ISPC_OPT_FLAGS}
|
||||
@@ -166,7 +162,7 @@ MACRO (ISPC_COMPILE)
|
||||
ENDFOREACH()
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
|
||||
MACRO (ADD_ISPC_EXECUTABLE name)
|
||||
SET(ISPC_SOURCES "")
|
||||
SET(OTHER_SOURCES "")
|
||||
FOREACH(src ${ARGN})
|
||||
@@ -179,6 +175,12 @@ MACRO (ADD_EMBREE_ISPC_EXECUTABLE name)
|
||||
ENDFOREACH()
|
||||
ISPC_COMPILE(${ISPC_SOURCES})
|
||||
ADD_EXECUTABLE(${name} ${ISPC_OBJECTS} ${OTHER_SOURCES})
|
||||
|
||||
IF (NOT __XEON__)
|
||||
FOREACH(src ${ISPC_OBJECTS})
|
||||
SET_SOURCE_FILES_PROPERTIES( ${src} PROPERTIES COMPILE_FLAGS -std=gnu++98 )
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_ISPC_LIBRARY name type)
|
||||
@@ -194,9 +196,15 @@ MACRO (ADD_ISPC_LIBRARY name type)
|
||||
ENDFOREACH()
|
||||
ISPC_COMPILE(${ISPC_SOURCES})
|
||||
ADD_LIBRARY(${name} ${type} ${ISPC_OBJECTS} ${OTHER_SOURCES})
|
||||
|
||||
IF (NOT __XEON__)
|
||||
FOREACH(src ${ISPC_OBJECTS})
|
||||
SET_SOURCE_FILES_PROPERTIES( ${src} PROPERTIES COMPILE_FLAGS -std=gnu++98 )
|
||||
ENDFOREACH()
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
ELSE (EMBREE_ISPC_SUPPORT)
|
||||
ELSE (ENABLE_ISPC_SUPPORT)
|
||||
|
||||
MACRO (ADD_ISPC_LIBRARY name type)
|
||||
SET(ISPC_SOURCES "")
|
||||
@@ -212,4 +220,4 @@ MACRO (ADD_ISPC_LIBRARY name type)
|
||||
ADD_LIBRARY(${name} ${type} ${OTHER_SOURCES})
|
||||
ENDMACRO()
|
||||
|
||||
ENDIF (EMBREE_ISPC_SUPPORT)
|
||||
ENDIF (ENABLE_ISPC_SUPPORT)
|
||||
|
||||
+30
-40
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,49 +14,39 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
SET(FLAGS_SSE2 "/D__SSE__ /D__SSE2__")
|
||||
SET(FLAGS_SSE42 "${FLAGS_SSE2} /D__SSE3__ /D__SSSE3__ /D__SSE4_1__ /D__SSE4_2__")
|
||||
SET(FLAGS_AVX "${FLAGS_SSE42} /arch:AVX")
|
||||
SET(FLAGS_AVX2 "${FLAGS_SSE42} /arch:AVX2")
|
||||
|
||||
SET(COMMON_CXX_FLAGS "")
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /EHsc") # catch C++ exceptions only and extern "C" functions never throw a C++ exception
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /MP") # compile source files in parallel
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GR") # enable runtime type information (on by default)
|
||||
IF (EMBREE_STACK_PROTECTOR)
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS") # protects against return address overrides
|
||||
# the /QxXXX flags are meant for the Intel Compiler, MSVC ignores them
|
||||
SET(FLAGS_SSE2 "/QxSSE2")
|
||||
SET(FLAGS_SSE3 "/QxSSE3")
|
||||
SET(FLAGS_SSSE3 "/QxSSSE3")
|
||||
SET(FLAGS_SSE41 "/DCONFIG_SSE41 /QxSSE4.1")
|
||||
SET(FLAGS_SSE42 "/DCONFIG_SSE42 /QxSSE4.2")
|
||||
SET(FLAGS_AVX "/arch:AVX /DCONFIG_AVX")
|
||||
# Intel Compiler 15, Update 1 unfortunately cannot handle /arch:AVX2
|
||||
IF (COMPILER STREQUAL "ICC") # for scripts/regression.py to work with ICC
|
||||
SET(FLAGS_AVX2 "/DCONFIG_AVX2 /QxCORE-AVX2")
|
||||
ELSE()
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} /GS-") # do not protect against return address overrides
|
||||
SET(FLAGS_AVX2 "/arch:AVX2 /DCONFIG_AVX2 /QxCORE-AVX2")
|
||||
ENDIF()
|
||||
SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} ${FLAGS_SSE2}")
|
||||
SET(FLAGS_AVX512 "")
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG") # generate debug information
|
||||
SET(COMMON_CXX_FLAGS "/EHsc /MP /GR ")
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Gy") # package individual functions
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ")
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS}")
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox") # enable full optimizations
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi") # inline intrinsic functions
|
||||
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Gy") # package individual functions
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG") # generate debug information
|
||||
|
||||
SET(SECURE_LINKER_FLAGS "")
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /NXCompat") # compatible with data execution prevention (on by default)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /DynamicBase") # random rebase of executable at load time
|
||||
IF (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
SET(SECURE_LINKER_FLAGS "${SECURE_LINKER_FLAGS} /SafeSEH") # invoke known exception handlers (Win32 only, x64 exception handlers are safe by design)
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:4000000")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /STACK:4000000")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG")
|
||||
|
||||
# optionally use static runtime library
|
||||
OPTION(USE_STATIC_RUNTIME "Use the static version of the C/C++ runtime library." ON)
|
||||
IF (USE_STATIC_RUNTIME)
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
ENDIF()
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SECURE_LINKER_FLAGS}")
|
||||
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4217") # locally defined symbol XXX imported in function YYY (happens as the ISPC API layer uses exported library functions)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4049") # warning LNK4049: locally defined symbol _rtcOccluded1M imported
|
||||
|
||||
INCLUDE(msvc_post)
|
||||
|
||||
# remove define NDEBUG and instead set define DEBUG for config RelWithDebInfo
|
||||
STRING(REPLACE "NDEBUG" "DEBUG" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
# optionally use static runtime library
|
||||
OPTION(EMBREE_STATIC_RUNTIME "Use the static version of the C/C++ runtime library." ON)
|
||||
IF (EMBREE_STATIC_RUNTIME)
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
ENDIF()
|
||||
|
||||
# remove define NDEBUG and instead set define DEBUG for config RelWithDebInfo
|
||||
STRING(REPLACE "NDEBUG" "DEBUG" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
+82
-95
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,112 +14,113 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
INCLUDE(GNUInstallDirs)
|
||||
OPTION(ENABLE_INSTALLER "Switches between installer or ZIP file creation for 'make package'" ON)
|
||||
MARK_AS_ADVANCED(ENABLE_INSTALLER)
|
||||
|
||||
if (NOT DEFINED EMBREE_ZIP_MODE)
|
||||
set(EMBREE_ZIP_MODE OFF)
|
||||
endif()
|
||||
|
||||
IF (NOT EMBREE_ZIP_MODE AND NOT WIN32 AND NOT APPLE)
|
||||
SET(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}/embree${EMBREE_VERSION_MAJOR})
|
||||
SET(CMAKE_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_FULL_BINDIR}/embree${EMBREE_VERSION_MAJOR})
|
||||
IF (ENABLE_INSTALLER AND APPLE)
|
||||
#SET(CMAKE_MACOSX_RPATH ON)
|
||||
#SET(CMAKE_SKIP_INSTALL_RPATH OFF)
|
||||
#SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
#SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
#SET(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
|
||||
ELSE()
|
||||
SET(CMAKE_SKIP_INSTALL_RPATH ON)
|
||||
ENDIF()
|
||||
|
||||
# use full absolute path as install name
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
|
||||
IF (NOT ENABLE_INSTALLER)
|
||||
SET(DOC_INSTALL_DIR doc)
|
||||
SET(TUTORIALS_INSTALL_DIR bin)
|
||||
SET(UTILITIES_INSTALL_DIR bin)
|
||||
ELSEIF (WIN32)
|
||||
SET(DOC_INSTALL_DIR doc)
|
||||
SET(TUTORIALS_INSTALL_DIR bin)
|
||||
SET(UTILITIES_INSTALL_DIR bin)
|
||||
ELSEIF (APPLE)
|
||||
SET(DOC_INSTALL_DIR ../../Applications/Embree2/documentation)
|
||||
SET(APPLICATION_INSTALL_DIR ../../Applications/Embree2)
|
||||
SET(TUTORIALS_INSTALL_DIR ../../Applications/Embree2/tutorials)
|
||||
SET(UTILITIES_INSTALL_DIR ../../Applications/Embree2/tutorials)
|
||||
ELSE()
|
||||
IF(APPLE)
|
||||
SET(CMAKE_INSTALL_RPATH "@loader_path/../lib")
|
||||
ELSE()
|
||||
SET(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
|
||||
ENDIF()
|
||||
SET(DOC_INSTALL_DIR share/doc/embree-${EMBREE_VERSION})
|
||||
SET(TUTORIALS_INSTALL_DIR bin/embree-${EMBREE_VERSION})
|
||||
SET(UTILITIES_INSTALL_DIR bin/embree-${EMBREE_VERSION})
|
||||
ENDIF()
|
||||
|
||||
##############################################################
|
||||
# Install Headers
|
||||
##############################################################
|
||||
INSTALL(DIRECTORY include/embree2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel)
|
||||
INSTALL(DIRECTORY include/embree2 DESTINATION include COMPONENT devel)
|
||||
CONFIGURE_FILE(include/embree2/rtcore.h rtcore.h @ONLY)
|
||||
CONFIGURE_FILE(include/embree2/rtcore.isph rtcore.isph @ONLY)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/rtcore.h DESTINATION include/embree2 COMPONENT devel)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/rtcore.isph DESTINATION include/embree2 COMPONENT devel)
|
||||
|
||||
##############################################################
|
||||
# Install Models
|
||||
##############################################################
|
||||
INSTALL(DIRECTORY tutorials/models DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT examples)
|
||||
INSTALL(DIRECTORY tutorials/models DESTINATION "${TUTORIALS_INSTALL_DIR}" COMPONENT examples)
|
||||
|
||||
##############################################################
|
||||
# Install Documentation
|
||||
##############################################################
|
||||
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib)
|
||||
#FILE(GLOB DOC_FILES ${PROJECT_SOURCE_DIR}/embree-doc/docbin/*)
|
||||
#INSTALL(FILES ${DOC_FILES} OPTIONAL DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/CHANGELOG.md DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${DOC_INSTALL_DIR} COMPONENT lib)
|
||||
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/LICENSE.txt" "LICENSE")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/CHANGELOG.txt" "CHANGELOG")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/README.md" "README.md")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_DOCDIR}/readme.pdf" "readme.pdf")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/LICENSE.txt" "LICENSE")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/CHANGELOG.txt" "CHANGELOG")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/README.md" "README.md")
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${DOC_INSTALL_DIR}/readme.pdf" "readme.pdf")
|
||||
|
||||
# currently CMake does not support solution folders without projects
|
||||
# SOURCE_GROUP("Documentation" FILES README.md CHANGELOG.md LICENSE.txt readme.pdf)
|
||||
|
||||
##############################################################
|
||||
# Install scripts to set embree paths
|
||||
##############################################################
|
||||
|
||||
IF (EMBREE_ZIP_MODE)
|
||||
IF (NOT ENABLE_INSTALLER)
|
||||
IF (WIN32)
|
||||
ELSEIF(APPLE)
|
||||
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh embree-vars.sh @ONLY)
|
||||
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh embree-vars.csh @ONLY)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.sh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_macosx/embree-vars.csh DESTINATION "." COMPONENT lib)
|
||||
ELSE()
|
||||
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh embree-vars.sh @ONLY)
|
||||
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh embree-vars.csh @ONLY)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.sh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_BINARY_DIR}/embree-vars.csh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.sh DESTINATION "." COMPONENT lib)
|
||||
INSTALL(FILES ${PROJECT_SOURCE_DIR}/scripts/install_linux/embree-vars.csh DESTINATION "." COMPONENT lib)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
##############################################################
|
||||
# Install Embree CMake Configuration
|
||||
##############################################################
|
||||
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
IF (ENABLE_INSTALLER)
|
||||
SET(EMBREE_CONFIG_VERSION ${EMBREE_VERSION})
|
||||
ELSE()
|
||||
SET(EMBREE_CONFIG_VERSION ${EMBREE_VERSION_MAJOR})
|
||||
ENDIF()
|
||||
|
||||
IF (APPLE AND NOT EMBREE_ZIP_MODE)
|
||||
CONFIGURE_FILE(scripts/install_macosx/uninstall.command uninstall.command @ONLY)
|
||||
INSTALL(PROGRAMS "${PROJECT_BINARY_DIR}/uninstall.command" DESTINATION ${CMAKE_INSTALL_BINDIR}/.. COMPONENT lib)
|
||||
ENDIF()
|
||||
|
||||
# why does this have to be so complicated...
|
||||
IF (WIN32)
|
||||
SET(EMBREE_LIBRARY_NAME ${CMAKE_IMPORT_LIBRARY_PREFIX}embree${CMAKE_IMPORT_LIBRARY_SUFFIX})
|
||||
CONFIGURE_FILE(common/cmake/embree-config-windows.cmake embree-config.cmake @ONLY)
|
||||
ELSEIF (APPLE)
|
||||
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree.${EMBREE_CONFIG_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
CONFIGURE_FILE(common/cmake/embree-config-macosx.cmake embree-config.cmake @ONLY)
|
||||
IF (ENABLE_INSTALLER)
|
||||
CONFIGURE_FILE(scripts/install_macosx/uninstall.command uninstall.command @ONLY)
|
||||
INSTALL(PROGRAMS "${PROJECT_BINARY_DIR}/uninstall.command" DESTINATION ${APPLICATION_INSTALL_DIR} COMPONENT lib)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(EMBREE_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}embree${CMAKE_SHARED_LIBRARY_SUFFIX}.${EMBREE_CONFIG_VERSION})
|
||||
CONFIGURE_FILE(common/cmake/embree-config-linux.cmake embree-config.cmake @ONLY)
|
||||
ENDIF()
|
||||
|
||||
IF (WIN32 OR EMBREE_ZIP_MODE)
|
||||
# for local "installs" and on Windows we want the cmake config files placed
|
||||
# in the install root, such that users can point the CMake variable
|
||||
# embree_DIR just to the install folder
|
||||
SET(EMBREE_CMAKECONFIG_DIR ".")
|
||||
SET(EMBREE_RELATIV_ROOT_DIR ".")
|
||||
ELSE()
|
||||
SET(EMBREE_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/embree-${EMBREE_VERSION}")
|
||||
SET(EMBREE_RELATIV_ROOT_DIR "../../..")
|
||||
ENDIF()
|
||||
CONFIGURE_FILE(common/cmake/embree-config.cmake embree-config-install.cmake @ONLY)
|
||||
CONFIGURE_FILE(common/cmake/embree-config-version.cmake embree-config-version.cmake @ONLY)
|
||||
# create a config file for the build directory
|
||||
CONFIGURE_FILE(common/cmake/embree-config-builddir.cmake embree-config.cmake @ONLY)
|
||||
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-install.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} RENAME "embree-config.cmake" COMPONENT devel)
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION ${EMBREE_CMAKECONFIG_DIR} COMPONENT devel)
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config.cmake" DESTINATION "lib/cmake/embree-${EMBREE_VERSION}" COMPONENT devel)
|
||||
INSTALL(FILES "${PROJECT_BINARY_DIR}/embree-config-version.cmake" DESTINATION "lib/cmake/embree-${EMBREE_VERSION}" COMPONENT devel)
|
||||
|
||||
##############################################################
|
||||
# CPack specific stuff
|
||||
@@ -129,7 +130,6 @@ SET(CPACK_PACKAGE_NAME "Embree")
|
||||
SET(CPACK_PACKAGE_FILE_NAME "embree-${EMBREE_VERSION}")
|
||||
#SET(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/embree-doc/images/icon.png)
|
||||
#SET(CPACK_PACKAGE_RELOCATABLE TRUE)
|
||||
SET(CPACK_STRIP_FILES TRUE)
|
||||
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${EMBREE_VERSION_MAJOR})
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR ${EMBREE_VERSION_MINOR})
|
||||
@@ -141,16 +141,23 @@ SET(CPACK_PACKAGE_CONTACT embree_support@intel.com)
|
||||
SET(CPACK_COMPONENT_LIB_DISPLAY_NAME "Library")
|
||||
SET(CPACK_COMPONENT_LIB_DESCRIPTION "The Embree library including documentation.")
|
||||
|
||||
SET(XEONPHI_DESCRIPTION "For The Intel Xeon Phi coprocessor." )
|
||||
SET(CPACK_COMPONENT_LIB_XEONPHI_NAME "Xeon Phi Library")
|
||||
SET(CPACK_COMPONENT_LIB_XEONPHI_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION}\n${XEONPHI_DESCRIPTION}")
|
||||
|
||||
SET(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "Development")
|
||||
SET(CPACK_COMPONENT_DEVEL_DESCRIPTION "Header Files for C and ISPC required to develop applications with Embree.")
|
||||
|
||||
SET(CPACK_COMPONENT_EXAMPLES_DISPLAY_NAME "Examples")
|
||||
SET(CPACK_COMPONENT_EXAMPLES_DESCRIPTION "Tutorials demonstrating how to use Embree.")
|
||||
|
||||
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_NAME "Xeon Phi Examples")
|
||||
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_DESCRIPTION "${CPACK_COMPONENT_EXAMPLES_DESCRIPTION}\n${XEONPHI_DESCRIPTION}")
|
||||
|
||||
# dependencies between components
|
||||
SET(CPACK_COMPONENT_DEVEL_DEPENDS lib)
|
||||
SET(CPACK_COMPONENT_LIB_XEONPHI_DEPENDS lib)
|
||||
SET(CPACK_COMPONENT_EXAMPLES_DEPENDS lib)
|
||||
SET(CPACK_COMPONENT_LIB_REQUIRED ON) # always install the libs
|
||||
SET(CPACK_COMPONENT_EXAMPLES_XEONPHI_DEPENDS lib_xeonphi)
|
||||
|
||||
# point to readme and license files
|
||||
SET(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md)
|
||||
@@ -170,7 +177,7 @@ IF(WIN32)
|
||||
ENDIF()
|
||||
|
||||
# NSIS specific settings
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
IF (ENABLE_INSTALLER)
|
||||
SET(CPACK_GENERATOR NSIS)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}")
|
||||
SET(CPACK_COMPONENTS_ALL lib devel examples)
|
||||
@@ -188,16 +195,10 @@ IF(WIN32)
|
||||
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\documentation\\\"")
|
||||
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\tutorials\\\"")
|
||||
#SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS ${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS} "\n ${UNINSTALL_LIST}\n RMDir \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\"\n")
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CPACK_PACKAGE_FILE_NAME}.exe ${CMAKE_BUILD_TYPE})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_GENERATOR ZIP)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${ARCH}.windows")
|
||||
SET(CPACK_MONOLITHIC_INSTALL 1)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_win.bat ${CPACK_PACKAGE_FILE_NAME}.zip ${CMAKE_BUILD_TYPE})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# MacOSX specific settings
|
||||
@@ -206,8 +207,7 @@ ELSEIF(APPLE)
|
||||
CONFIGURE_FILE(README.md README.txt)
|
||||
SET(CPACK_RESOURCE_FILE_README ${PROJECT_BINARY_DIR}/README.txt)
|
||||
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
SET(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
IF (ENABLE_INSTALLER)
|
||||
SET(CPACK_GENERATOR PackageMaker)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64")
|
||||
#SET(CPACK_COMPONENTS_ALL lib devel examples)
|
||||
@@ -215,52 +215,39 @@ ELSEIF(APPLE)
|
||||
SET(CPACK_PACKAGE_NAME embree-${EMBREE_VERSION})
|
||||
SET(CPACK_PACKAGE_VENDOR "intel") # creates short name com.intel.embree2.xxx in pkgutil
|
||||
SET(CPACK_OSX_PACKAGE_VERSION 10.7)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.dmg)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(CPACK_GENERATOR TGZ)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.macosx")
|
||||
SET(CPACK_MONOLITHIC_INSTALL 1)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_macosx.sh ${CMAKE_BUILD_TYPE} ${CPACK_PACKAGE_FILE_NAME}.tgz)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Linux specific settings
|
||||
ELSE()
|
||||
|
||||
|
||||
IF (NOT EMBREE_ZIP_MODE)
|
||||
IF (ENABLE_INSTALLER)
|
||||
|
||||
SET(CPACK_GENERATOR RPM)
|
||||
SET(CPACK_COMPONENTS_ALL devel lib examples)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}.x86_64")
|
||||
SET(CPACK_COMPONENTS_ALL devel lib examples lib_xeonphi examples_xeonphi)
|
||||
SET(CPACK_RPM_COMPONENT_INSTALL ON)
|
||||
SET(CPACK_RPM_FILE_NAME RPM-DEFAULT)
|
||||
SET(CPACK_RPM_devel_PACKAGE_ARCHITECTURE noarch)
|
||||
SET(CPACK_RPM_PACKAGE_LICENSE "ASL 2.0") # Apache Software License, Version 2.0
|
||||
SET(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
|
||||
SET(CPACK_RPM_CHANGELOG_FILE ${CMAKE_BINARY_DIR}/rpm_changelog.txt) # ChangeLog of the RPM
|
||||
STRING(TIMESTAMP CHANGELOG_DATE "%a %b %d %Y")
|
||||
SET(RPM_CHANGELOG "* ${CHANGELOG_DATE} Johannes Günther <johannes.guenther@intel.com> - ${EMBREE_VERSION}-${CPACK_RPM_PACKAGE_RELEASE}\n- First package")
|
||||
FILE(WRITE ${CPACK_RPM_CHANGELOG_FILE} ${RPM_CHANGELOG})
|
||||
#SET(CPACK_RPM_CHANGELOG_FILE "") # ChangeLog of the RPM; also CHANGELOG.md is not in the required format
|
||||
SET(CPACK_RPM_PACKAGE_ARCHITECTURE x86_64)
|
||||
SET(CPACK_RPM_PACKAGE_URL http://embree.github.io/)
|
||||
SET(CPACK_RPM_DEFAULT_DIR_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # otherwise cmake directory has wrong 775 permissions
|
||||
|
||||
# post install and uninstall scripts
|
||||
SET(CPACK_RPM_lib_POST_INSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
|
||||
SET(CPACK_RPM_lib_POST_UNINSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_linux.sh ${EMBREE_ZIP_MODE} ${EMBREE_VERSION})
|
||||
ENDIF()
|
||||
SET(CPACK_RPM_lib_xeonphi_POST_INSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
|
||||
SET(CPACK_RPM_lib_xeonphi_POST_UNINSTALL_SCRIPT_FILE ${PROJECT_SOURCE_DIR}/common/cmake/rpm_ldconfig.sh)
|
||||
ELSE()
|
||||
|
||||
SET(CPACK_GENERATOR TGZ)
|
||||
SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.linux")
|
||||
SET(CPACK_MONOLITHIC_INSTALL 1)
|
||||
IF (EMBREE_TESTING_PACKAGE)
|
||||
ADD_TEST(NAME "BuildPackage" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/package_linux.sh ${EMBREE_ZIP_MODE} ${EMBREE_VERSION})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
ENDIF()
|
||||
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
## You may obtain a copy of the License at ##
|
||||
## ##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0 ##
|
||||
## ##
|
||||
## Unless required by applicable law or agreed to in writing, software ##
|
||||
## distributed under the License is distributed on an "AS IS" BASIS, ##
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##
|
||||
## See the License for the specific language governing permissions and ##
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
IF(NOT BUILD_TESTING)
|
||||
SET(BUILD_TESTING OFF CACHE BOOL "Build the testing tree.")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE(CTest)
|
||||
|
||||
IF (BUILD_TESTING)
|
||||
|
||||
CMAKE_HOST_SYSTEM_INFORMATION(RESULT memory QUERY TOTAL_PHYSICAL_MEMORY)
|
||||
|
||||
SET(EMBREE_TESTING_MODEL_DIR "${PROJECT_SOURCE_DIR}/models" CACHE PATH "Path to the folder containing the Embree models for regression testing.")
|
||||
SET(EMBREE_TESTING_INTENSIVE OFF CACHE BOOL "Turns intensive testing on.")
|
||||
SET(EMBREE_TESTING_MEMCHECK OFF CACHE BOOL "Turns on memory checking for some tests.")
|
||||
SET(EMBREE_TESTING_BENCHMARK OFF CACHE BOOL "Turns benchmarking on.")
|
||||
SET(EMBREE_TESTING_BENCHMARK_DATABASE "${PROJECT_BINARY_DIR}" CACHE PATH "Path to database for benchmarking.")
|
||||
SET(EMBREE_TESTING_PACKAGE OFF CACHE BOOL "Packages release as test.")
|
||||
SET(EMBREE_TESTING_KLOCWORK OFF CACHE BOOL "Runs Kocwork as test.")
|
||||
|
||||
SET(EMBREE_TESTING_SDE OFF CACHE STRING "Uses SDE to run tests for specified CPU.")
|
||||
SET_PROPERTY(CACHE EMBREE_TESTING_SDE PROPERTY STRINGS OFF pnr nhm wsm snb ivb hsw bdw knl skl skx cnl)
|
||||
|
||||
IF( NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-subdiv.txt"
|
||||
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-win32.txt"
|
||||
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-x64.txt"
|
||||
OR NOT EXISTS "${EMBREE_TESTING_MODEL_DIR}/embree-models-large.txt")
|
||||
MESSAGE(FATAL_ERROR "Invalid Embree testing model repository. Either disable BUILD_TESTING or properly set EMBREE_TESTING_MODEL_DIR.")
|
||||
ENDIF()
|
||||
|
||||
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-subdiv.txt" models_subdiv)
|
||||
STRING(REGEX REPLACE "\n" ";" models_subdiv "${models_subdiv}")
|
||||
|
||||
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-win32.txt" models_small_win32)
|
||||
STRING(REGEX REPLACE "\n" ";" models_small_win32 "${models_small_win32}")
|
||||
|
||||
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-small-x64.txt" models_small_x64)
|
||||
STRING(REGEX REPLACE "\n" ";" models_small_x64 "${models_small_x64}")
|
||||
|
||||
FILE(READ "${EMBREE_TESTING_MODEL_DIR}/embree-models-large.txt" models_large)
|
||||
STRING(REGEX REPLACE "\n" ";" models_large "${models_large}")
|
||||
|
||||
IF (EMBREE_TESTING_INTENSIVE)
|
||||
SET(models ${models_small_x64})
|
||||
IF (${memory} GREATER 10000)
|
||||
SET(models ${models} ${models_large})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(models ${models_small_win32})
|
||||
ENDIF()
|
||||
|
||||
IF (WIN32)
|
||||
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
|
||||
ELSE()
|
||||
SET(MY_PROJECT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
ENDIF()
|
||||
|
||||
MACRO (ADD_EMBREE_MODEL_TEST name reference executable args model)
|
||||
|
||||
ADD_TEST(NAME ${name}
|
||||
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
|
||||
COMMAND python ${PROJECT_SOURCE_DIR}/scripts/invoke_test.py
|
||||
--name ${name}
|
||||
--modeldir ${EMBREE_TESTING_MODEL_DIR}
|
||||
--reference ${reference}
|
||||
--model ${model}
|
||||
--sde ${EMBREE_TESTING_SDE}
|
||||
--execute ${MY_PROJECT_BINARY_DIR}/${executable} ${args})
|
||||
|
||||
IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
|
||||
ADD_TEST(NAME ${name}_ispc
|
||||
WORKING_DIRECTORY ${MY_PROJECT_BINARY_DIR}
|
||||
COMMAND python ${PROJECT_SOURCE_DIR}/scripts/invoke_test.py
|
||||
--name ${name}_ispc
|
||||
--modeldir ${EMBREE_TESTING_MODEL_DIR}
|
||||
--reference ${reference}
|
||||
--model ${model}
|
||||
--sde ${EMBREE_TESTING_SDE}
|
||||
--execute ${MY_PROJECT_BINARY_DIR}/${executable}_ispc ${args})
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_MODELS_TEST name reference executable)
|
||||
FOREACH (model ${models})
|
||||
STRING(REGEX REPLACE "/" "_" modelname "${model}")
|
||||
STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}")
|
||||
ADD_EMBREE_MODEL_TEST(${name}_${modelname} ${reference}_${modelname} ${executable} "${ARGN}" ${model})
|
||||
ENDFOREACH()
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_SUBDIV_MODELS_TEST name reference executable)
|
||||
FOREACH (model ${models_subdiv})
|
||||
STRING(REGEX REPLACE "/" "_" modelname "${model}")
|
||||
STRING(REGEX REPLACE ".ecs" "" modelname "${modelname}")
|
||||
ADD_EMBREE_MODEL_TEST(${name}_${modelname} ${reference}_${modelname} ${executable} "${ARGN}" ${model})
|
||||
ENDFOREACH()
|
||||
ENDMACRO()
|
||||
|
||||
IF (EMBREE_TESTING_KLOCWORK)
|
||||
ADD_TEST(NAME Klocwork WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${PROJECT_SOURCE_DIR}/scripts/klocwork.sh)
|
||||
SET_TESTS_PROPERTIES(Klocwork PROPERTIES TIMEOUT 2400)
|
||||
ENDIF()
|
||||
|
||||
ELSE()
|
||||
|
||||
MACRO (ADD_EMBREE_MODEL_TEST name reference executable args model)
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_SUBDIV_MODELS_TEST name reference executable)
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_MODELS_TEST name)
|
||||
ENDMACRO()
|
||||
|
||||
ENDIF()
|
||||
|
||||
MACRO (ADD_EMBREE_TEST name)
|
||||
ADD_EMBREE_MODEL_TEST(${name} ${name} ${name} "" "default")
|
||||
ENDMACRO()
|
||||
|
||||
MACRO (ADD_EMBREE_TEST2 name exe args)
|
||||
ADD_EMBREE_MODEL_TEST(${name} ${exe} ${exe} "${args}" "default")
|
||||
ENDMACRO()
|
||||
|
||||
IF (EMBREE_TESTING_MEMCHECK)
|
||||
find_program( EMBREE_MEMORYCHECK_COMMAND valgrind )
|
||||
set( EMBREE_MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=1" )
|
||||
|
||||
FUNCTION(ADD_MEMCHECK_TEST name binary)
|
||||
set(memcheck_command "${EMBREE_MEMORYCHECK_COMMAND} ${EMBREE_MEMORYCHECK_COMMAND_OPTIONS}")
|
||||
separate_arguments(memcheck_command)
|
||||
add_test(NAME ${name} COMMAND ${memcheck_command} ${MY_PROJECT_BINARY_DIR}/${binary} ${ARGN})
|
||||
ENDFUNCTION()
|
||||
ENDIF()
|
||||
+35
-13
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -19,20 +19,42 @@
|
||||
|
||||
MACRO (ADD_TUTORIAL TUTORIAL_NAME)
|
||||
|
||||
ADD_EXECUTABLE(${TUTORIAL_NAME} ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.cpp ${ARGN})
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME} embree tutorial image tutorial_device noise ${ADDITIONAL_LIBRARIES})
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME} PROPERTY FOLDER tutorials/single)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_BINDIR}/${TUTORIAL_NAME}" "${TUTORIAL_NAME}")
|
||||
IF (__XEON__)
|
||||
|
||||
IF (EMBREE_ISPC_SUPPORT AND EMBREE_RAY_PACKETS)
|
||||
ADD_EMBREE_ISPC_EXECUTABLE(${TUTORIAL_NAME}_ispc ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.ispc)
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_ispc embree tutorial image tutorial_device_ispc noise noise_ispc)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc PROPERTY FOLDER tutorials/ispc)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT examples)
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${CMAKE_INSTALL_BINDIR}/${TUTORIAL_NAME}_ispc" "${TUTORIAL_NAME}_ispc")
|
||||
ADD_EXECUTABLE(${TUTORIAL_NAME} ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.cpp ${ARGN})
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME} embree tutorial image transport tutorial_device ${ADDITIONAL_LIBRARIES})
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME} PROPERTY FOLDER tutorials/single)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME} DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples)
|
||||
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${TUTORIALS_INSTALL_DIR}/${TUTORIAL_NAME}" "${TUTORIAL_NAME}")
|
||||
|
||||
IF (ENABLE_ISPC_SUPPORT AND RTCORE_RAY_PACKETS)
|
||||
ADD_ISPC_EXECUTABLE(${TUTORIAL_NAME}_ispc ${TUTORIAL_NAME}.cpp ${TUTORIAL_NAME}_device.ispc)
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_ispc embree tutorial image transport tutorial_device_ispc)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_ispc PROPERTY FOLDER tutorials/ispc)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME}_ispc DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples)
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} "${TUTORIALS_INSTALL_DIR}/${TUTORIAL_NAME}_ispc" "${TUTORIAL_NAME}_ispc")
|
||||
ENDIF()
|
||||
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} PARENT_SCOPE)
|
||||
|
||||
ELSE (__XEON__)
|
||||
|
||||
IF (ENABLE_XEON_PHI_SUPPORT)
|
||||
IF (__HOST__)
|
||||
ADD_EXECUTABLE(${TUTORIAL_NAME}_xeonphi ${TUTORIAL_NAME}.cpp)
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_xeonphi tutorial image transport_host)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_xeonphi PROPERTY FOLDER tutorials/xeonphi)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME}_xeonphi DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples_xeonphi)
|
||||
ELSE()
|
||||
INCLUDE (icc_xeonphi)
|
||||
ADD_ISPC_EXECUTABLE(${TUTORIAL_NAME}_xeonphi_device ${TUTORIAL_NAME}_device.ispc)
|
||||
TARGET_LINK_LIBRARIES(${TUTORIAL_NAME}_xeonphi_device embree_xeonphi transport_device tutorial_xeonphi_device_ispc)
|
||||
SET_PROPERTY(TARGET ${TUTORIAL_NAME}_xeonphi_device PROPERTY FOLDER tutorials/xeonphi)
|
||||
INSTALL(TARGETS ${TUTORIAL_NAME}_xeonphi_device DESTINATION ${TUTORIALS_INSTALL_DIR} COMPONENT examples_xeonphi)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(CPACK_NSIS_MENU_LINKS ${CPACK_NSIS_MENU_LINKS} PARENT_SCOPE)
|
||||
ENDIF (__XEON__)
|
||||
|
||||
ENDMACRO ()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,9 +14,18 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
ADD_LIBRARY(lexers STATIC
|
||||
IF (__XEON__)
|
||||
SET(EXT)
|
||||
ELSE()
|
||||
INCLUDE(icc_xeonphi)
|
||||
SET(EXT _xeonphi)
|
||||
ENDIF()
|
||||
|
||||
|
||||
ADD_LIBRARY(lexers${EXT} STATIC
|
||||
stringstream.cpp
|
||||
tokenstream.cpp
|
||||
)
|
||||
TARGET_LINK_LIBRARIES(lexers sys math)
|
||||
SET_PROPERTY(TARGET lexers PROPERTY FOLDER common)
|
||||
|
||||
TARGET_LINK_LIBRARIES(lexers${EXT} sys${EXT})
|
||||
SET_PROPERTY(TARGET lexers${EXT} PROPERTY FOLDER common)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -21,7 +21,9 @@
|
||||
#include "../math/vec2.h"
|
||||
#include "../math/vec3.h"
|
||||
#include "../math/col3.h"
|
||||
#if !defined(__MIC__)
|
||||
#include "../math/color.h"
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
@@ -101,12 +103,14 @@ namespace embree
|
||||
return Col3f(x,y,z);
|
||||
}
|
||||
|
||||
#if !defined(__MIC__)
|
||||
Color getColor() {
|
||||
float r = (float)atof(get().c_str());
|
||||
float g = (float)atof(get().c_str());
|
||||
float b = (float)atof(get().c_str());
|
||||
return Color(r,g,b);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
Ref<Stream<std::string> > cin;
|
||||
|
||||
+45
-42
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -28,25 +28,31 @@
|
||||
|
||||
namespace embree
|
||||
{
|
||||
class String : public RefCount {
|
||||
public:
|
||||
String(std::string str) : str(str) {}
|
||||
std::string str;
|
||||
};
|
||||
|
||||
/*! stores the location of a stream element in the source */
|
||||
class ParseLocation
|
||||
{
|
||||
public:
|
||||
ParseLocation () : lineNumber(-1), colNumber(-1), charNumber(-1) {}
|
||||
ParseLocation (std::shared_ptr<std::string> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t charNumber)
|
||||
ParseLocation () : fileName(nullptr), lineNumber(-1), colNumber(-1), charNumber(-1) {}
|
||||
ParseLocation (Ref<String> fileName, ssize_t lineNumber, ssize_t colNumber, ssize_t charNumber)
|
||||
: fileName(fileName), lineNumber(lineNumber), colNumber(colNumber), charNumber(charNumber) {}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::string str = "unknown";
|
||||
if (fileName) str = *fileName;
|
||||
if (lineNumber >= 0) str += " line " + toString(lineNumber);
|
||||
if (lineNumber >= 0 && colNumber >= 0) str += " character " + toString(colNumber);
|
||||
if (fileName) str = fileName->str;
|
||||
if (lineNumber >= 0) str += " line " + std::to_string((long long)lineNumber);
|
||||
if (lineNumber >= 0 && colNumber >= 0) str += " character " + std::to_string((long long)colNumber);
|
||||
return str;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::string> fileName; /// name of the file (or stream) the token is from
|
||||
Ref<String> fileName; /// name of the file (or stream) the token is from
|
||||
ssize_t lineNumber; /// the line number the token is from
|
||||
ssize_t colNumber; /// the character number in the current line
|
||||
ssize_t charNumber; /// the character in the file
|
||||
@@ -56,33 +62,33 @@ namespace embree
|
||||
template<typename T> class Stream : public RefCount
|
||||
{
|
||||
enum { BUF_SIZE = 1024 };
|
||||
|
||||
|
||||
private:
|
||||
virtual T next() = 0;
|
||||
virtual ParseLocation location() = 0;
|
||||
__forceinline std::pair<T,ParseLocation> nextHelper() {
|
||||
ParseLocation l = location();
|
||||
T v = next();
|
||||
return std::pair<T,ParseLocation>(v,l);
|
||||
}
|
||||
__forceinline void push_back(const std::pair<T,ParseLocation>& v) {
|
||||
if (past+future == BUF_SIZE) pop_front();
|
||||
size_t end = (start+past+future++)%BUF_SIZE;
|
||||
buffer[end] = v;
|
||||
}
|
||||
__forceinline void pop_front() {
|
||||
if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
|
||||
start = (start+1)%BUF_SIZE; past--;
|
||||
}
|
||||
__forceinline std::pair<T,ParseLocation> nextHelper() {
|
||||
ParseLocation l = location();
|
||||
T v = next();
|
||||
return std::pair<T,ParseLocation>(v,l);
|
||||
}
|
||||
__forceinline void push_back(const std::pair<T,ParseLocation>& v) {
|
||||
if (past+future == BUF_SIZE) pop_front();
|
||||
int end = (start+past+future++)%BUF_SIZE;
|
||||
buffer[end] = v;
|
||||
}
|
||||
__forceinline void pop_front() {
|
||||
if (past == 0) THROW_RUNTIME_ERROR("stream buffer empty");
|
||||
start = (start+1)%BUF_SIZE; past--;
|
||||
}
|
||||
public:
|
||||
Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
|
||||
virtual ~Stream() {}
|
||||
|
||||
Stream () : start(0), past(0), future(0), buffer(BUF_SIZE) {}
|
||||
virtual ~Stream() {}
|
||||
|
||||
public:
|
||||
|
||||
const ParseLocation& loc() {
|
||||
if (future == 0) push_back(nextHelper());
|
||||
return buffer[(start+past)%BUF_SIZE].second;
|
||||
|
||||
const ParseLocation& loc() {
|
||||
if (future == 0) push_back(nextHelper());
|
||||
return buffer[(start+past)%BUF_SIZE].second;
|
||||
}
|
||||
T get() {
|
||||
if (future == 0) push_back(nextHelper());
|
||||
@@ -107,13 +113,13 @@ namespace embree
|
||||
size_t start,past,future;
|
||||
std::vector<std::pair<T,ParseLocation> > buffer;
|
||||
};
|
||||
|
||||
|
||||
/*! warps an iostream stream */
|
||||
class StdStream : public Stream<int>
|
||||
{
|
||||
public:
|
||||
StdStream (std::istream& cin, const std::string& name = "std::stream")
|
||||
: cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
|
||||
: cin(cin), lineNumber(1), colNumber(0), charNumber(0), name(new String(name)) {}
|
||||
~StdStream() {}
|
||||
ParseLocation location() {
|
||||
return ParseLocation(name,lineNumber,colNumber,charNumber);
|
||||
@@ -129,7 +135,7 @@ namespace embree
|
||||
ssize_t lineNumber; /// the line number the token is from
|
||||
ssize_t colNumber; /// the character number in the current line
|
||||
ssize_t charNumber; /// the character in the file
|
||||
std::shared_ptr<std::string> name; /// name of buffer
|
||||
Ref<String> name; /// name of buffer
|
||||
};
|
||||
|
||||
/*! creates a stream from a file */
|
||||
@@ -138,10 +144,10 @@ namespace embree
|
||||
public:
|
||||
|
||||
FileStream (FILE* file, const std::string& name = "file")
|
||||
: file(file), lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name))) {}
|
||||
: file(file), lineNumber(1), colNumber(0), charNumber(0), name(new String(name)) {}
|
||||
|
||||
FileStream (const FileName& fileName)
|
||||
: lineNumber(1), colNumber(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(fileName.str())))
|
||||
: lineNumber(1), colNumber(0), charNumber(0), name(new String(fileName.str()))
|
||||
{
|
||||
file = fopen(fileName.c_str(),"r");
|
||||
if (file == nullptr) THROW_RUNTIME_ERROR("cannot open file " + fileName.str());
|
||||
@@ -165,7 +171,7 @@ namespace embree
|
||||
ssize_t lineNumber; /// the line number the token is from
|
||||
ssize_t colNumber; /// the character number in the current line
|
||||
ssize_t charNumber; /// the character in the file
|
||||
std::shared_ptr<std::string> name; /// name of buffer
|
||||
Ref<String> name; /// name of buffer
|
||||
};
|
||||
|
||||
/*! creates a stream from a string */
|
||||
@@ -178,7 +184,7 @@ namespace embree
|
||||
|
||||
public:
|
||||
ParseLocation location() {
|
||||
return ParseLocation(std::shared_ptr<std::string>(),lineNumber,colNumber,charNumber);
|
||||
return ParseLocation(nullptr,lineNumber,colNumber,charNumber);
|
||||
}
|
||||
|
||||
int next() {
|
||||
@@ -201,12 +207,9 @@ namespace embree
|
||||
{
|
||||
public:
|
||||
CommandLineStream (int argc, char** argv, const std::string& name = "command line")
|
||||
: i(0), j(0), charNumber(0), name(std::shared_ptr<std::string>(new std::string(name)))
|
||||
: i(0), j(0), charNumber(0), name(new String(name))
|
||||
{
|
||||
if (argc > 0) {
|
||||
for (size_t i=0; argv[0][i] && i<1024; i++) charNumber++;
|
||||
charNumber++;
|
||||
}
|
||||
if (argc > 0) charNumber = strlen(argv[0])+1;
|
||||
for (ssize_t k=1; k<argc; k++) args.push_back(argv[k]);
|
||||
}
|
||||
~CommandLineStream() {}
|
||||
@@ -224,6 +227,6 @@ namespace embree
|
||||
size_t i,j;
|
||||
std::vector<std::string> args;
|
||||
ssize_t charNumber; /// the character in the file
|
||||
std::shared_ptr<std::string> name; /// name of buffer
|
||||
Ref<String> name; /// name of buffer
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -30,7 +30,7 @@ namespace embree
|
||||
ParseLocation location() { return cin->loc(); }
|
||||
std::string next();
|
||||
private:
|
||||
__forceinline bool isSeparator(int c) const { return c <= 256 && isSepMap[c]; }
|
||||
__forceinline bool isSeparator(int c) const { return isSepMap[c]; }
|
||||
private:
|
||||
Ref<Stream<int> > cin; /*! source character stream */
|
||||
bool isSepMap[256]; /*! map for fast classification of separators */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -86,10 +86,6 @@ namespace embree
|
||||
{
|
||||
bool ok = false;
|
||||
std::string str;
|
||||
if (trySymbol("nan")) {
|
||||
token = Token(float(nan));
|
||||
return true;
|
||||
}
|
||||
if (trySymbol("+inf")) {
|
||||
token = Token(float(pos_inf));
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -103,12 +103,12 @@ namespace embree
|
||||
friend std::ostream& operator<<(std::ostream& cout, const Token& t)
|
||||
{
|
||||
if (t.ty == TY_EOF) return cout << "eof";
|
||||
if (t.ty == TY_CHAR) return cout << "Char(" << t.c << ")";
|
||||
if (t.ty == TY_INT) return cout << "Int(" << t.i << ")";
|
||||
if (t.ty == TY_FLOAT) return cout << "Float(" << t.f << ")";
|
||||
if (t.ty == TY_IDENTIFIER) return cout << "Id(" << t.str << ")";
|
||||
if (t.ty == TY_STRING) return cout << "String(" << t.str << ")";
|
||||
if (t.ty == TY_SYMBOL) return cout << "Symbol(" << t.str << ")";
|
||||
if (t.ty == TY_CHAR) return cout << t.c;
|
||||
if (t.ty == TY_INT) return cout << t.i;
|
||||
if (t.ty == TY_FLOAT) return cout << t.f;
|
||||
if (t.ty == TY_IDENTIFIER) return cout << t.str;
|
||||
if (t.ty == TY_STRING) return cout << "\"" + t.str + "\"";
|
||||
if (t.ty == TY_SYMBOL) return cout << t.str;
|
||||
return cout << "unknown";
|
||||
}
|
||||
|
||||
@@ -160,13 +160,13 @@ namespace embree
|
||||
std::vector<std::string> symbols;
|
||||
|
||||
/*! checks if a character is a separator */
|
||||
__forceinline bool isSeparator(int c) const { return c<256 && isSepMap[c]; }
|
||||
__forceinline bool isSeparator(int c) const { return isSepMap[c]; }
|
||||
|
||||
/*! checks if a character is a number */
|
||||
__forceinline bool isDigit(int c) const { return c >= '0' && c <= '9';}
|
||||
|
||||
/*! checks if a character is legal for an identifier */
|
||||
__forceinline bool isAlpha(int c) const { return c<256 && isAlphaMap[c]; }
|
||||
__forceinline bool isAlpha(int c) const { return isAlphaMap[c]; }
|
||||
__forceinline bool isAlphaNum(int c) const { return isAlpha(c) || isDigit(c); }
|
||||
};
|
||||
}
|
||||
|
||||
+10
-33
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "linearspace2.h"
|
||||
#include "linearspace3.h"
|
||||
#include "quaternion.h"
|
||||
#include "bbox.h"
|
||||
@@ -48,7 +47,7 @@ namespace embree
|
||||
__forceinline AffineSpaceT( const VectorT& vx, const VectorT& vy, const VectorT& vz, const VectorT& p ) : l(vx,vy,vz), p(p) {}
|
||||
__forceinline AffineSpaceT( const L& l, const VectorT& p ) : l(l), p(p) {}
|
||||
|
||||
template<typename L1> __forceinline AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
|
||||
template<typename L1> __forceinline explicit AffineSpaceT( const AffineSpaceT<L1>& s ) : l(s.l), p(s.p) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
@@ -58,21 +57,18 @@ namespace embree
|
||||
__forceinline AffineSpaceT( OneTy ) : l(one), p(zero) {}
|
||||
|
||||
/*! return matrix for scaling */
|
||||
static __forceinline AffineSpaceT scale(const VectorT& s) { return L::scale(s); }
|
||||
static __forceinline AffineSpaceT scale(const VectorT& s) { return AffineSpaceT(L::scale(s),zero); }
|
||||
|
||||
/*! return matrix for translation */
|
||||
static __forceinline AffineSpaceT translate(const VectorT& p) { return AffineSpaceT(one,p); }
|
||||
|
||||
/*! return matrix for rotation, only in 2D */
|
||||
static __forceinline AffineSpaceT rotate(const ScalarT& r) { return L::rotate(r); }
|
||||
/*! return matrix for rotation around arbitrary axis */
|
||||
static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return AffineSpaceT(L::rotate(u,r),zero); }
|
||||
|
||||
/*! return matrix for rotation around arbitrary point (2D) or axis (3D) */
|
||||
static __forceinline AffineSpaceT rotate(const VectorT& u, const ScalarT& r) { return L::rotate(u,r); }
|
||||
|
||||
/*! return matrix for rotation around arbitrary axis and point, only in 3D */
|
||||
/*! return matrix for rotation around arbitrary axis and point */
|
||||
static __forceinline AffineSpaceT rotate(const VectorT& p, const VectorT& u, const ScalarT& r) { return translate(+p) * rotate(u,r) * translate(-p); }
|
||||
|
||||
/*! return matrix for looking at given point, only in 3D */
|
||||
/*! return matrix for looking at given point */
|
||||
static __forceinline AffineSpaceT lookat(const VectorT& eye, const VectorT& point, const VectorT& up) {
|
||||
VectorT Z = normalize(point-eye);
|
||||
VectorT U = normalize(cross(up,Z));
|
||||
@@ -107,9 +103,9 @@ namespace embree
|
||||
template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a = a / b; }
|
||||
template<typename L> __forceinline AffineSpaceT<L>& operator /=( AffineSpaceT<L>& a, const ScalarT & b ) { return a = a / b; }
|
||||
|
||||
template<typename L> __forceinline VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
|
||||
template<typename L> __forceinline VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
|
||||
template<typename L> __forceinline VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
|
||||
template<typename L> __forceinline const VectorT xfmPoint (const AffineSpaceT<L>& m, const VectorT& p) { return madd(VectorT(p.x),m.l.vx,madd(VectorT(p.y),m.l.vy,madd(VectorT(p.z),m.l.vz,m.p))); }
|
||||
template<typename L> __forceinline const VectorT xfmVector(const AffineSpaceT<L>& m, const VectorT& v) { return xfmVector(m.l,v); }
|
||||
template<typename L> __forceinline const VectorT xfmNormal(const AffineSpaceT<L>& m, const VectorT& n) { return xfmNormal(m.l,n); }
|
||||
|
||||
__forceinline const BBox<Vec3fa> xfmBounds(const AffineSpaceT<LinearSpace3<Vec3fa> >& m, const BBox<Vec3fa>& b)
|
||||
{
|
||||
@@ -132,20 +128,6 @@ namespace embree
|
||||
template<typename L> __forceinline bool operator ==( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l == b.l && a.p == b.p; }
|
||||
template<typename L> __forceinline bool operator !=( const AffineSpaceT<L>& a, const AffineSpaceT<L>& b ) { return a.l != b.l || a.p != b.p; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename L> __forceinline AffineSpaceT<L> select ( const typename L::Vector::Scalar::Bool& s, const AffineSpaceT<L>& t, const AffineSpaceT<L>& f ) {
|
||||
return AffineSpaceT<L>(select(s,t.l,f.l),select(s,t.p,f.p));
|
||||
}
|
||||
|
||||
/*! blending */
|
||||
template<typename T>
|
||||
__forceinline AffineSpaceT<T> lerp(const AffineSpaceT<T>& l0, const AffineSpaceT<T>& l1, const float t) {
|
||||
return AffineSpaceT<T>(lerp(l0.l,l1.l,t),lerp(l0.p,l1.p,t));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -158,15 +140,10 @@ namespace embree
|
||||
// Template Instantiations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef AffineSpaceT<LinearSpace2f> AffineSpace2f;
|
||||
typedef AffineSpaceT<LinearSpace3f> AffineSpace3f;
|
||||
typedef AffineSpaceT<LinearSpace3fa> AffineSpace3fa;
|
||||
typedef AffineSpaceT<Quaternion3f > OrthonormalSpace3f;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/*! Template Specialization for 2D: return matrix for rotation around point (rotation around arbitrarty vector is not meaningful in 2D) */
|
||||
template<> __forceinline AffineSpace2f AffineSpace2f::rotate(const Vec2f& p, const float& r) { return translate(+p) * AffineSpace2f(LinearSpace2f::rotate(r)) * translate(-p); }
|
||||
|
||||
#undef VectorT
|
||||
#undef ScalarT
|
||||
}
|
||||
|
||||
+11
-138
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -44,6 +44,15 @@ namespace embree
|
||||
__forceinline const BBox& extend(const BBox& other) { lower = min(lower,other.lower); upper = max(upper,other.upper); return *this; }
|
||||
__forceinline const BBox& extend(const T & other) { lower = min(lower,other ); upper = max(upper,other ); return *this; }
|
||||
|
||||
__forceinline void extend_atomic(const BBox& other) {
|
||||
atomic_min_f32(&lower.x,other.lower.x);
|
||||
atomic_min_f32(&lower.y,other.lower.y);
|
||||
atomic_min_f32(&lower.z,other.lower.z);
|
||||
atomic_max_f32(&upper.x,other.upper.x);
|
||||
atomic_max_f32(&upper.y,other.upper.y);
|
||||
atomic_max_f32(&upper.z,other.upper.z);
|
||||
}
|
||||
|
||||
/*! tests if box is empty */
|
||||
__forceinline bool empty() const { for (int i=0; i<T::N; i++) if (lower[i] > upper[i]) return true; return false; }
|
||||
|
||||
@@ -56,11 +65,6 @@ namespace embree
|
||||
/*! computes twice the center of the box */
|
||||
__forceinline T center2() const { return lower+upper; }
|
||||
|
||||
/*! merges two boxes */
|
||||
__forceinline static const BBox merge (const BBox& a, const BBox& b) {
|
||||
return BBox(min(a.lower, b.lower), max(a.upper, b.upper));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -73,10 +77,6 @@ namespace embree
|
||||
__forceinline BBox( PosInfTy ): lower(neg_inf), upper(pos_inf) {}
|
||||
};
|
||||
|
||||
template<> __forceinline bool BBox<float>::empty() const {
|
||||
return lower > upper;
|
||||
}
|
||||
|
||||
#if defined(__SSE__)
|
||||
template<> __forceinline bool BBox<Vec3fa>::empty() const {
|
||||
return !all(le_mask(lower,upper));
|
||||
@@ -97,8 +97,8 @@ namespace embree
|
||||
__forceinline bool inside ( const BBox<Vec3fa>& b, const Vec3fa& p ) { return all(ge_mask(p,b.lower) & le_mask(p,b.upper)); }
|
||||
|
||||
/*! computes the center of the box */
|
||||
template<typename T> __forceinline const T center (const BBox<T>& box) { return T(.5f)*(box.lower + box.upper); }
|
||||
template<typename T> __forceinline const T center2(const BBox<T>& box) { return box.lower + box.upper; }
|
||||
template<typename T> __forceinline const T center (const BBox<T>& box) { return T(0.5f)*center2(box); }
|
||||
|
||||
/*! computes the volume of a bounding box */
|
||||
__forceinline float volume ( const BBox<Vec3fa>& b ) { return reduce_mul(b.size()); }
|
||||
@@ -118,10 +118,6 @@ namespace embree
|
||||
|
||||
template<typename Vec> __forceinline float safeArea( const BBox<Vec>& b ) { if (b.empty()) return 0.0f; else return area(b); }
|
||||
|
||||
template<typename T> __forceinline float expectedApproxHalfArea(const BBox<T>& box) {
|
||||
return halfArea(box);
|
||||
}
|
||||
|
||||
/*! merges bounding boxes and points */
|
||||
template<typename T> __forceinline const BBox<T> merge( const BBox<T>& a, const T& b ) { return BBox<T>(min(a.lower, b ), max(a.upper, b )); }
|
||||
template<typename T> __forceinline const BBox<T> merge( const T& a, const BBox<T>& b ) { return BBox<T>(min(a , b.lower), max(a , b.upper)); }
|
||||
@@ -155,16 +151,6 @@ namespace embree
|
||||
/*! intersect bounding boxes */
|
||||
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b ) { return BBox<T>(max(a.lower, b.lower), min(a.upper, b.upper)); }
|
||||
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c ) { return intersect(a,intersect(b,c)); }
|
||||
template<typename T> __forceinline const BBox<T> intersect( const BBox<T>& a, const BBox<T>& b, const BBox<T>& c, const BBox<T>& d ) { return intersect(intersect(a,b),intersect(c,d)); }
|
||||
|
||||
/*! subtract bounds from each other */
|
||||
template<typename T> __forceinline void subtract(const BBox<T>& a, const BBox<T>& b, BBox<T>& c, BBox<T>& d)
|
||||
{
|
||||
c.lower = a.lower;
|
||||
c.upper = min(a.upper,b.lower);
|
||||
d.lower = max(a.lower,b.upper);
|
||||
d.upper = a.upper;
|
||||
}
|
||||
|
||||
/*! tests if bounding boxes (and points) are disjoint (empty intersection) */
|
||||
template<typename T> __inline bool disjoint( const BBox<T>& a, const BBox<T>& b ) { return intersect(a,b).empty(); }
|
||||
@@ -184,126 +170,13 @@ namespace embree
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! blending */
|
||||
template<typename T>
|
||||
__forceinline BBox<T> lerp(const BBox<T>& b0, const BBox<T>& b1, const float t) {
|
||||
return BBox<T>(lerp(b0.lower,b1.lower,t),lerp(b0.upper,b1.upper,t));
|
||||
}
|
||||
|
||||
/*! output operator */
|
||||
template<typename T> __forceinline std::ostream& operator<<(std::ostream& cout, const BBox<T>& box) {
|
||||
return cout << "[" << box.lower << "; " << box.upper << "]";
|
||||
}
|
||||
|
||||
/*! default template instantiations */
|
||||
typedef BBox<float> BBox1f;
|
||||
typedef BBox<Vec2f> BBox2f;
|
||||
typedef BBox<Vec3f> BBox3f;
|
||||
typedef BBox<Vec3fa> BBox3fa;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE / AVX / MIC specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined __SSE__
|
||||
#include "../simd/sse.h"
|
||||
#endif
|
||||
|
||||
#if defined __AVX__
|
||||
#include "../simd/avx.h"
|
||||
#endif
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
#include "../simd/avx512.h"
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
template<int N>
|
||||
__forceinline BBox<Vec3<vfloat<N>>> transpose(const BBox3fa* bounds);
|
||||
|
||||
template<>
|
||||
__forceinline BBox<Vec3<vfloat4>> transpose<4>(const BBox3fa* bounds)
|
||||
{
|
||||
BBox<Vec3<vfloat4>> dest;
|
||||
|
||||
transpose((vfloat4&)bounds[0].lower,
|
||||
(vfloat4&)bounds[1].lower,
|
||||
(vfloat4&)bounds[2].lower,
|
||||
(vfloat4&)bounds[3].lower,
|
||||
dest.lower.x,
|
||||
dest.lower.y,
|
||||
dest.lower.z);
|
||||
|
||||
transpose((vfloat4&)bounds[0].upper,
|
||||
(vfloat4&)bounds[1].upper,
|
||||
(vfloat4&)bounds[2].upper,
|
||||
(vfloat4&)bounds[3].upper,
|
||||
dest.upper.x,
|
||||
dest.upper.y,
|
||||
dest.upper.z);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<>
|
||||
__forceinline BBox<Vec3<vfloat8>> transpose<8>(const BBox3fa* bounds)
|
||||
{
|
||||
BBox<Vec3<vfloat8>> dest;
|
||||
|
||||
transpose((vfloat4&)bounds[0].lower,
|
||||
(vfloat4&)bounds[1].lower,
|
||||
(vfloat4&)bounds[2].lower,
|
||||
(vfloat4&)bounds[3].lower,
|
||||
(vfloat4&)bounds[4].lower,
|
||||
(vfloat4&)bounds[5].lower,
|
||||
(vfloat4&)bounds[6].lower,
|
||||
(vfloat4&)bounds[7].lower,
|
||||
dest.lower.x,
|
||||
dest.lower.y,
|
||||
dest.lower.z);
|
||||
|
||||
transpose((vfloat4&)bounds[0].upper,
|
||||
(vfloat4&)bounds[1].upper,
|
||||
(vfloat4&)bounds[2].upper,
|
||||
(vfloat4&)bounds[3].upper,
|
||||
(vfloat4&)bounds[4].upper,
|
||||
(vfloat4&)bounds[5].upper,
|
||||
(vfloat4&)bounds[6].upper,
|
||||
(vfloat4&)bounds[7].upper,
|
||||
dest.upper.x,
|
||||
dest.upper.y,
|
||||
dest.upper.z);
|
||||
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<int N>
|
||||
__forceinline BBox3fa merge(const BBox3fa* bounds);
|
||||
|
||||
template<>
|
||||
__forceinline BBox3fa merge<4>(const BBox3fa* bounds)
|
||||
{
|
||||
const Vec3fa lower = min(min(bounds[0].lower,bounds[1].lower),
|
||||
min(bounds[2].lower,bounds[3].lower));
|
||||
const Vec3fa upper = max(max(bounds[0].upper,bounds[1].upper),
|
||||
max(bounds[2].upper,bounds[3].upper));
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<>
|
||||
__forceinline BBox3fa merge<8>(const BBox3fa* bounds)
|
||||
{
|
||||
const Vec3fa lower = min(min(min(bounds[0].lower,bounds[1].lower),min(bounds[2].lower,bounds[3].lower)),
|
||||
min(min(bounds[4].lower,bounds[5].lower),min(bounds[6].lower,bounds[7].lower)));
|
||||
const Vec3fa upper = max(max(max(bounds[0].upper,bounds[1].upper),max(bounds[2].upper,bounds[3].upper)),
|
||||
max(max(bounds[4].upper,bounds[5].upper),max(bounds[6].upper,bounds[7].upper)));
|
||||
return BBox3fa(lower,upper);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
|
||||
+17
-23
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -53,8 +53,8 @@ namespace embree
|
||||
__forceinline Color4 ( const Color4& other ) : m128(other.m128) {}
|
||||
__forceinline Color4& operator=( const Color4& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline operator const __m128&() const { return m128; }
|
||||
__forceinline operator __m128&() { return m128; }
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator __m128&( void ) { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Set
|
||||
@@ -64,14 +64,14 @@ namespace embree
|
||||
__forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = a; }
|
||||
__forceinline void set(Col3uc& d) const
|
||||
{
|
||||
vfloat4 s = clamp(vfloat4(m128))*255.0f;
|
||||
float4 s = clamp(float4(m128))*255.0f;
|
||||
d.r = (unsigned char)(s[0]);
|
||||
d.g = (unsigned char)(s[1]);
|
||||
d.b = (unsigned char)(s[2]);
|
||||
}
|
||||
__forceinline void set(Col4uc& d) const
|
||||
{
|
||||
vfloat4 s = clamp(vfloat4(m128))*255.0f;
|
||||
float4 s = clamp(float4(m128))*255.0f;
|
||||
d.r = (unsigned char)(s[0]);
|
||||
d.g = (unsigned char)(s[1]);
|
||||
d.b = (unsigned char)(s[2]);
|
||||
@@ -115,8 +115,8 @@ namespace embree
|
||||
__forceinline Color ( const Color4& other ) : m128(other.m128) {}
|
||||
__forceinline Color& operator=( const Color4& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline operator const __m128&() const { return m128; }
|
||||
__forceinline operator __m128&() { return m128; }
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator __m128&( void ) { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Set
|
||||
@@ -126,18 +126,18 @@ namespace embree
|
||||
__forceinline void set(Col4f& d) const { d.r = r; d.g = g; d.b = b; d.a = 1.0f; }
|
||||
__forceinline void set(Col3uc& d) const
|
||||
{
|
||||
vfloat4 s = clamp(vfloat4(m128))*255.0f;
|
||||
float4 s = clamp(float4(m128))*255.0f;
|
||||
d.r = (unsigned char)(s[0]);
|
||||
d.g = (unsigned char)(s[1]);
|
||||
d.b = (unsigned char)(s[2]);
|
||||
}
|
||||
__forceinline void set(Col4uc& d) const
|
||||
{
|
||||
vfloat4 s = clamp(vfloat4(m128))*255.0f;
|
||||
float4 s = clamp(float4(m128))*255.0f;
|
||||
d.r = (unsigned char)(s[0]);
|
||||
d.g = (unsigned char)(s[1]);
|
||||
d.b = (unsigned char)(s[2]);
|
||||
d.a = 255;
|
||||
d.a = 1.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -163,22 +163,12 @@ namespace embree
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
|
||||
return _mm_and_ps(a.m128, mask);
|
||||
}
|
||||
__forceinline const Color rcp ( const Color& a )
|
||||
{
|
||||
#if defined(__AVX512VL__)
|
||||
const Color r = _mm_rcp14_ps(a.m128);
|
||||
#else
|
||||
__forceinline const Color rcp ( const Color& a ) {
|
||||
const Color r = _mm_rcp_ps(a.m128);
|
||||
#endif
|
||||
return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
|
||||
}
|
||||
__forceinline const Color rsqrt( const Color& a )
|
||||
{
|
||||
#if defined(__AVX512VL__)
|
||||
__m128 r = _mm_rsqrt14_ps(a.m128);
|
||||
#else
|
||||
__forceinline const Color rsqrt( const Color& a ) {
|
||||
__m128 r = _mm_rsqrt_ps(a.m128);
|
||||
#endif
|
||||
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
|
||||
}
|
||||
__forceinline const Color sqrt ( const Color& a ) { return _mm_sqrt_ps(a.m128); }
|
||||
@@ -245,7 +235,11 @@ namespace embree
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*! computes luminance of a color */
|
||||
__forceinline float luminance (const Color& a) { return madd(0.212671f,a.r,madd(0.715160f,a.g,0.072169f*a.b)); }
|
||||
__forceinline float luminance (const Color& a) { return 0.212671f*a.r + 0.715160f*a.g + 0.072169f*a.b; }
|
||||
|
||||
__forceinline Color exp (const Color& a) { return Color(exp_ps(a.m128)); }
|
||||
__forceinline Color log (const Color& a) { return Color(log_ps(a.m128)); }
|
||||
__forceinline Color pow (const Color& a, const float& b) { return Color(select(float4(a)<=float4(zero),float4(zero),float4(exp_ps(log(a)*b)))); }
|
||||
|
||||
/*! output operator */
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Color& a) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
TrueTy True;
|
||||
FalseTy False;
|
||||
ZeroTy zero;
|
||||
OneTy one;
|
||||
NegInfTy neg_inf;
|
||||
PosInfTy inf;
|
||||
PosInfTy pos_inf;
|
||||
NaNTy nan;
|
||||
UlpTy ulp;
|
||||
PiTy pi;
|
||||
OneOverPiTy one_over_pi;
|
||||
TwoPiTy two_pi;
|
||||
OneOverTwoPiTy one_over_two_pi;
|
||||
FourPiTy four_pi;
|
||||
OneOverFourPiTy one_over_four_pi;
|
||||
StepTy step;
|
||||
ReverseStepTy reverse_step;
|
||||
EmptyTy empty;
|
||||
UndefinedTy undefined;
|
||||
}
|
||||
+47
-92
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -32,19 +32,15 @@ namespace embree
|
||||
/* we consider floating point numbers in that range as valid input numbers */
|
||||
static float FLT_LARGE = 1.844E18f;
|
||||
|
||||
struct TrueTy {
|
||||
static struct TrueTy {
|
||||
__forceinline operator bool( ) const { return true; }
|
||||
};
|
||||
} True MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED TrueTy True;
|
||||
|
||||
struct FalseTy {
|
||||
static struct FalseTy {
|
||||
__forceinline operator bool( ) const { return false; }
|
||||
};
|
||||
|
||||
extern MAYBE_UNUSED FalseTy False;
|
||||
} False MAYBE_UNUSED;
|
||||
|
||||
struct ZeroTy
|
||||
static struct ZeroTy
|
||||
{
|
||||
__forceinline operator double ( ) const { return 0; }
|
||||
__forceinline operator float ( ) const { return 0; }
|
||||
@@ -58,11 +54,9 @@ namespace embree
|
||||
__forceinline operator unsigned short ( ) const { return 0; }
|
||||
__forceinline operator char ( ) const { return 0; }
|
||||
__forceinline operator unsigned char ( ) const { return 0; }
|
||||
};
|
||||
} zero MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED ZeroTy zero;
|
||||
|
||||
struct OneTy
|
||||
static struct OneTy
|
||||
{
|
||||
__forceinline operator double ( ) const { return 1; }
|
||||
__forceinline operator float ( ) const { return 1; }
|
||||
@@ -76,11 +70,9 @@ namespace embree
|
||||
__forceinline operator unsigned short ( ) const { return 1; }
|
||||
__forceinline operator char ( ) const { return 1; }
|
||||
__forceinline operator unsigned char ( ) const { return 1; }
|
||||
};
|
||||
} one MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED OneTy one;
|
||||
|
||||
struct NegInfTy
|
||||
static struct NegInfTy
|
||||
{
|
||||
__forceinline operator double ( ) const { return -std::numeric_limits<double>::infinity(); }
|
||||
__forceinline operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
|
||||
@@ -95,11 +87,9 @@ namespace embree
|
||||
__forceinline operator char ( ) const { return std::numeric_limits<char>::min(); }
|
||||
__forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::min(); }
|
||||
|
||||
};
|
||||
} neg_inf MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED NegInfTy neg_inf;
|
||||
|
||||
struct PosInfTy
|
||||
static struct PosInfTy
|
||||
{
|
||||
__forceinline operator double ( ) const { return std::numeric_limits<double>::infinity(); }
|
||||
__forceinline operator float ( ) const { return std::numeric_limits<float>::infinity(); }
|
||||
@@ -113,97 +103,62 @@ namespace embree
|
||||
__forceinline operator unsigned short ( ) const { return std::numeric_limits<unsigned short>::max(); }
|
||||
__forceinline operator char ( ) const { return std::numeric_limits<char>::max(); }
|
||||
__forceinline operator unsigned char ( ) const { return std::numeric_limits<unsigned char>::max(); }
|
||||
};
|
||||
} inf MAYBE_UNUSED, pos_inf MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED PosInfTy inf;
|
||||
extern MAYBE_UNUSED PosInfTy pos_inf;
|
||||
|
||||
struct NaNTy
|
||||
static struct NaNTy
|
||||
{
|
||||
__forceinline operator double( ) const { return std::numeric_limits<double>::quiet_NaN(); }
|
||||
__forceinline operator float ( ) const { return std::numeric_limits<float>::quiet_NaN(); }
|
||||
};
|
||||
} nan MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED NaNTy nan;
|
||||
|
||||
struct UlpTy
|
||||
static struct UlpTy
|
||||
{
|
||||
__forceinline operator double( ) const { return std::numeric_limits<double>::epsilon(); }
|
||||
__forceinline operator float ( ) const { return std::numeric_limits<float>::epsilon(); }
|
||||
};
|
||||
} ulp MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED UlpTy ulp;
|
||||
|
||||
struct PiTy
|
||||
static struct PiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(M_PI); }
|
||||
__forceinline operator float ( ) const { return float(M_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return M_PI; }
|
||||
__forceinline operator float ( ) const { return M_PI; }
|
||||
} pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED PiTy pi;
|
||||
|
||||
struct OneOverPiTy
|
||||
static struct OneOverPiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(M_1_PI); }
|
||||
__forceinline operator float ( ) const { return float(M_1_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return M_1_PI; }
|
||||
__forceinline operator float ( ) const { return M_1_PI; }
|
||||
} one_over_pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED OneOverPiTy one_over_pi;
|
||||
|
||||
struct TwoPiTy
|
||||
static struct TwoPiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(2.0*M_PI); }
|
||||
__forceinline operator float ( ) const { return float(2.0*M_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return 2.0*M_PI; }
|
||||
__forceinline operator float ( ) const { return 2.0*M_PI; }
|
||||
} two_pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED TwoPiTy two_pi;
|
||||
|
||||
struct OneOverTwoPiTy
|
||||
static struct OneOverTwoPiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(0.5*M_1_PI); }
|
||||
__forceinline operator float ( ) const { return float(0.5*M_1_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return 0.5*M_1_PI; }
|
||||
__forceinline operator float ( ) const { return 0.5*M_1_PI; }
|
||||
} one_over_two_pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED OneOverTwoPiTy one_over_two_pi;
|
||||
|
||||
struct FourPiTy
|
||||
static struct FourPiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(4.0*M_PI); }
|
||||
__forceinline operator float ( ) const { return float(4.0*M_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return 4.0*M_PI; }
|
||||
__forceinline operator float ( ) const { return 4.0*M_PI; }
|
||||
} four_pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED FourPiTy four_pi;
|
||||
|
||||
struct OneOverFourPiTy
|
||||
static struct OneOverFourPiTy
|
||||
{
|
||||
__forceinline operator double( ) const { return double(0.25*M_1_PI); }
|
||||
__forceinline operator float ( ) const { return float(0.25*M_1_PI); }
|
||||
};
|
||||
__forceinline operator double( ) const { return 0.25*M_1_PI; }
|
||||
__forceinline operator float ( ) const { return 0.25*M_1_PI; }
|
||||
} one_over_four_pi MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED OneOverFourPiTy one_over_four_pi;
|
||||
static struct StepTy {
|
||||
} step MAYBE_UNUSED;
|
||||
|
||||
struct StepTy {
|
||||
};
|
||||
static struct EmptyTy {
|
||||
} empty MAYBE_UNUSED;
|
||||
|
||||
extern MAYBE_UNUSED StepTy step;
|
||||
|
||||
struct ReverseStepTy {
|
||||
};
|
||||
|
||||
extern MAYBE_UNUSED ReverseStepTy reverse_step;
|
||||
|
||||
struct EmptyTy {
|
||||
};
|
||||
|
||||
extern MAYBE_UNUSED EmptyTy empty;
|
||||
|
||||
struct FullTy {
|
||||
};
|
||||
|
||||
extern MAYBE_UNUSED FullTy full;
|
||||
|
||||
struct UndefinedTy {
|
||||
};
|
||||
|
||||
extern MAYBE_UNUSED UndefinedTy undefined;
|
||||
static struct FullTy {
|
||||
} full MAYBE_UNUSED;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -34,7 +34,7 @@ namespace embree
|
||||
__forceinline LinearSpace2 ( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; }
|
||||
__forceinline LinearSpace2& operator=( const LinearSpace2& other ) { vx = other.vx; vy = other.vy; return *this; }
|
||||
|
||||
template<typename L1> __forceinline LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
|
||||
template<typename L1> __forceinline explicit LinearSpace2( const LinearSpace2<L1>& s ) : vx(s.vx), vy(s.vy) {}
|
||||
|
||||
/*! matrix construction from column vectors */
|
||||
__forceinline LinearSpace2(const Vector& vx, const Vector& vy)
|
||||
@@ -58,10 +58,10 @@ namespace embree
|
||||
__forceinline const LinearSpace2 transposed() const { return LinearSpace2(vx.x,vx.y,vy.x,vy.y); }
|
||||
|
||||
/*! returns first row of matrix */
|
||||
__forceinline Vector row0() const { return Vector(vx.x,vy.x); }
|
||||
__forceinline const Vector row0() const { return Vector(vx.x,vy.x); }
|
||||
|
||||
/*! returns second row of matrix */
|
||||
__forceinline Vector row1() const { return Vector(vx.y,vy.y); }
|
||||
__forceinline const Vector row1() const { return Vector(vx.y,vy.y); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
@@ -76,39 +76,6 @@ namespace embree
|
||||
0 , s.y);
|
||||
}
|
||||
|
||||
/*! return matrix for rotation */
|
||||
static __forceinline LinearSpace2 rotate(const Scalar& r) {
|
||||
Scalar s = sin(r), c = cos(r);
|
||||
return LinearSpace2(c, -s,
|
||||
s, c);
|
||||
}
|
||||
|
||||
/*! return closest orthogonal matrix (i.e. a general rotation including reflection) */
|
||||
LinearSpace2 orthogonal() const
|
||||
{
|
||||
LinearSpace2 m = *this;
|
||||
|
||||
// mirrored?
|
||||
Scalar mirror(one);
|
||||
if (m.det() < Scalar(zero)) {
|
||||
m.vx = -m.vx;
|
||||
mirror = -mirror;
|
||||
}
|
||||
|
||||
// rotation
|
||||
for (int i = 0; i < 99; i++) {
|
||||
const LinearSpace2 m_next = 0.5 * (m + m.transposed().inverse());
|
||||
const LinearSpace2 d = m_next - m;
|
||||
m = m_next;
|
||||
// norm^2 of difference small enough?
|
||||
if (max(dot(d.vx, d.vx), dot(d.vy, d.vy)) < 1e-8)
|
||||
break;
|
||||
}
|
||||
|
||||
// rotation * mirror_x
|
||||
return LinearSpace2(mirror*m.vx, m.vy);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/*! the column vectors of the matrix */
|
||||
|
||||
+12
-31
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -35,7 +35,7 @@ namespace embree
|
||||
__forceinline LinearSpace3 ( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; }
|
||||
__forceinline LinearSpace3& operator=( const LinearSpace3& other ) { vx = other.vx; vy = other.vy; vz = other.vz; return *this; }
|
||||
|
||||
template<typename L1> __forceinline LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
|
||||
template<typename L1> __forceinline explicit LinearSpace3( const LinearSpace3<L1>& s ) : vx(s.vx), vy(s.vy), vz(s.vz) {}
|
||||
|
||||
/*! matrix construction from column vectors */
|
||||
__forceinline LinearSpace3(const Vector& vx, const Vector& vy, const Vector& vz)
|
||||
@@ -66,13 +66,13 @@ namespace embree
|
||||
__forceinline const LinearSpace3 transposed() const { return LinearSpace3(vx.x,vx.y,vx.z,vy.x,vy.y,vy.z,vz.x,vz.y,vz.z); }
|
||||
|
||||
/*! returns first row of matrix */
|
||||
__forceinline Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
|
||||
__forceinline const Vector row0() const { return Vector(vx.x,vy.x,vz.x); }
|
||||
|
||||
/*! returns second row of matrix */
|
||||
__forceinline Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
|
||||
__forceinline const Vector row1() const { return Vector(vx.y,vy.y,vz.y); }
|
||||
|
||||
/*! returns third row of matrix */
|
||||
__forceinline Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
|
||||
__forceinline const Vector row2() const { return Vector(vx.z,vy.z,vz.z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
@@ -104,15 +104,12 @@ namespace embree
|
||||
};
|
||||
|
||||
/*! compute transposed matrix */
|
||||
#if !defined(__MIC__)
|
||||
template<> __forceinline const LinearSpace3<Vec3fa> LinearSpace3<Vec3fa>::transposed() const {
|
||||
vfloat4 rx,ry,rz; transpose((vfloat4&)vx,(vfloat4&)vy,(vfloat4&)vz,vfloat4(zero),rx,ry,rz);
|
||||
float4 rx,ry,rz; transpose((float4&)vx,(float4&)vy,(float4&)vz,float4(zero),rx,ry,rz);
|
||||
return LinearSpace3<Vec3fa>(Vec3fa(rx),Vec3fa(ry),Vec3fa(rz));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline const LinearSpace3<T> transposed(const LinearSpace3<T>& xfm) {
|
||||
return xfm.transposed();
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Unary Operators
|
||||
@@ -125,8 +122,8 @@ namespace embree
|
||||
/* constructs a coordinate frame form a normalized normal */
|
||||
template<typename T> __forceinline LinearSpace3<T> frame(const T& N)
|
||||
{
|
||||
const T dx0(0,N.z,-N.y);
|
||||
const T dx1(-N.z,0,N.x);
|
||||
const T dx0 = cross(T(one,zero,zero),N);
|
||||
const T dx1 = cross(T(zero,one,zero),N);
|
||||
const T dx = normalize(select(dot(dx0,dx0) > dot(dx1,dx1),dx0,dx1));
|
||||
const T dy = normalize(cross(N,dx));
|
||||
return LinearSpace3<T>(dx,dy,N);
|
||||
@@ -156,7 +153,7 @@ namespace embree
|
||||
template<typename T> __forceinline LinearSpace3<T> operator -( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return LinearSpace3<T>(a.vx-b.vx,a.vy-b.vy,a.vz-b.vz); }
|
||||
|
||||
template<typename T> __forceinline LinearSpace3<T> operator*(const typename T::Scalar & a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
|
||||
template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return madd(T(b.x),a.vx,madd(T(b.y),a.vy,T(b.z)*a.vz)); }
|
||||
template<typename T> __forceinline T operator*(const LinearSpace3<T>& a, const T & b) { return b.x*a.vx + b.y*a.vy + b.z*a.vz; }
|
||||
template<typename T> __forceinline LinearSpace3<T> operator*(const LinearSpace3<T>& a, const LinearSpace3<T>& b) { return LinearSpace3<T>(a*b.vx, a*b.vy, a*b.vz); }
|
||||
|
||||
template<typename T> __forceinline LinearSpace3<T> operator/(const LinearSpace3<T>& a, const typename T::Scalar & b) { return LinearSpace3<T>(a.vx/b, a.vy/b, a.vz/b); }
|
||||
@@ -176,23 +173,6 @@ namespace embree
|
||||
template<typename T> __forceinline bool operator ==( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx == b.vx && a.vy == b.vy && a.vz == b.vz; }
|
||||
template<typename T> __forceinline bool operator !=( const LinearSpace3<T>& a, const LinearSpace3<T>& b ) { return a.vx != b.vx || a.vy != b.vy || a.vz != b.vz; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline LinearSpace3<T> select ( const typename T::Scalar::Bool& s, const LinearSpace3<T>& t, const LinearSpace3<T>& f ) {
|
||||
return LinearSpace3<T>(select(s,t.vx,f.vx),select(s,t.vy,f.vy),select(s,t.vz,f.vz));
|
||||
}
|
||||
|
||||
/*! blending */
|
||||
template<typename T>
|
||||
__forceinline LinearSpace3<T> lerp(const LinearSpace3<T>& l0, const LinearSpace3<T>& l1, const float t)
|
||||
{
|
||||
return LinearSpace3<T>(lerp(l0.vx,l1.vx,t),
|
||||
lerp(l0.vy,l1.vy,t),
|
||||
lerp(l0.vz,l1.vz,t));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -204,4 +184,5 @@ namespace embree
|
||||
/*! Shortcuts for common linear spaces. */
|
||||
typedef LinearSpace3<Vec3f> LinearSpace3f;
|
||||
typedef LinearSpace3<Vec3fa> LinearSpace3fa;
|
||||
|
||||
}
|
||||
|
||||
+71
-131
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -17,21 +17,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "../sys/platform.h"
|
||||
#include "../sys/intrinsics.h"
|
||||
#include "constants.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <xmmintrin.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#if (__MSV_VER <= 1700)
|
||||
namespace std
|
||||
{
|
||||
__forceinline bool isinf ( const float x ) { return _finite(x) == 0; }
|
||||
__forceinline bool isnan ( const float x ) { return _isnan(x) != 0; }
|
||||
__forceinline bool isfinite (const float x) { return _finite(x) != 0; }
|
||||
__forceinline bool isinf ( const float x ) { return !_finite(x); }
|
||||
__forceinline bool isnan ( const float x ) { return _isnan(x); }
|
||||
__forceinline bool isfinite (const float x) { return _finite(x); }
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -45,7 +43,7 @@ namespace embree
|
||||
__forceinline int cast_f2i(float f) {
|
||||
union { float f; int i; } v; v.f = f; return v.i;
|
||||
}
|
||||
|
||||
|
||||
__forceinline float cast_i2f(int i) {
|
||||
union { float f; int i; } v; v.i = i; return v.f;
|
||||
}
|
||||
@@ -57,54 +55,43 @@ namespace embree
|
||||
__forceinline float sign ( const float x ) { return x<0?-1.0f:1.0f; }
|
||||
__forceinline float sqr ( const float x ) { return x*x; }
|
||||
|
||||
__forceinline float rcp ( const float x )
|
||||
#ifndef __MIC__
|
||||
__forceinline float rcp ( const float x )
|
||||
{
|
||||
const __m128 a = _mm_set_ss(x);
|
||||
|
||||
#if defined(__AVX512VL__)
|
||||
const __m128 r = _mm_rcp14_ss(_mm_set_ss(0.0f),a);
|
||||
#else
|
||||
const __m128 r = _mm_rcp_ss(a);
|
||||
#endif
|
||||
|
||||
const __m128 r = _mm_rcp_ps(a);
|
||||
#if defined(__AVX2__)
|
||||
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_fnmadd_ss(r, a, _mm_set_ss(2.0f))));
|
||||
return _mm_cvtss_f32(_mm_mul_ps(r,_mm_fnmadd_ps(r, a, _mm_set_ss(2.0f))));
|
||||
#else
|
||||
return _mm_cvtss_f32(_mm_mul_ss(r,_mm_sub_ss(_mm_set_ss(2.0f), _mm_mul_ss(r, a))));
|
||||
return _mm_cvtss_f32(_mm_mul_ps(r,_mm_sub_ps(_mm_set_ss(2.0f), _mm_mul_ps(r, a))));
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline float signmsk ( const float x ) {
|
||||
__forceinline float signmsk ( const float x ) {
|
||||
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
|
||||
}
|
||||
__forceinline float xorf( const float x, const float y ) {
|
||||
__forceinline float xorf( const float x, const float y ) {
|
||||
return _mm_cvtss_f32(_mm_xor_ps(_mm_set_ss(x),_mm_set_ss(y)));
|
||||
}
|
||||
__forceinline float andf( const float x, const unsigned y ) {
|
||||
__forceinline float andf( const float x, const unsigned y ) {
|
||||
return _mm_cvtss_f32(_mm_and_ps(_mm_set_ss(x),_mm_castsi128_ps(_mm_set1_epi32(y))));
|
||||
}
|
||||
__forceinline float rsqrt( const float x )
|
||||
{
|
||||
__forceinline float rsqrt( const float x ) {
|
||||
const __m128 a = _mm_set_ss(x);
|
||||
#if defined(__AVX512VL__)
|
||||
const __m128 r = _mm_rsqrt14_ss(_mm_set_ss(0.0f),a);
|
||||
#else
|
||||
const __m128 r = _mm_rsqrt_ss(a);
|
||||
#endif
|
||||
const __m128 c = _mm_add_ss(_mm_mul_ss(_mm_set_ss(1.5f), r),
|
||||
_mm_mul_ss(_mm_mul_ss(_mm_mul_ss(a, _mm_set_ss(-0.5f)), r), _mm_mul_ss(r, r)));
|
||||
const __m128 r = _mm_rsqrt_ps(a);
|
||||
const __m128 c = _mm_add_ps(_mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
|
||||
_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r), _mm_mul_ps(r, r)));
|
||||
return _mm_cvtss_f32(c);
|
||||
}
|
||||
|
||||
#if defined(__WIN32__) && (__MSC_VER <= 1700)
|
||||
__forceinline float nextafter(float x, float y) { if ((x<y) == (x>0)) return x*(1.1f+float(ulp)); else return x*(0.9f-float(ulp)); }
|
||||
__forceinline double nextafter(double x, double y) { return _nextafter(x, y); }
|
||||
__forceinline int roundf(float f) { return (int)(f + 0.5f); }
|
||||
#else
|
||||
__forceinline float nextafter(float x, float y) { return ::nextafterf(x, y); }
|
||||
__forceinline double nextafter(double x, double y) { return ::nextafter(x, y); }
|
||||
__forceinline float rcp ( const float x ) { return 1.0f/x; }
|
||||
__forceinline float signmsk ( const float x ) { return cast_i2f(cast_f2i(x)&0x80000000); }
|
||||
__forceinline float xorf( const float x, const float y ) { return cast_i2f(cast_f2i(x) ^ cast_f2i(y)); }
|
||||
__forceinline float andf( const float x, const float y ) { return cast_i2f(cast_f2i(x) & cast_f2i(y)); }
|
||||
__forceinline float rsqrt( const float x ) { return 1.0f/sqrtf(x); }
|
||||
#endif
|
||||
|
||||
#if !defined(__WIN32__)
|
||||
__forceinline float abs ( const float x ) { return ::fabsf(x); }
|
||||
__forceinline float acos ( const float x ) { return ::acosf (x); }
|
||||
__forceinline float asin ( const float x ) { return ::asinf (x); }
|
||||
@@ -124,6 +111,7 @@ namespace embree
|
||||
__forceinline float tanh ( const float x ) { return ::tanhf (x); }
|
||||
__forceinline float floor( const float x ) { return ::floorf (x); }
|
||||
__forceinline float ceil ( const float x ) { return ::ceilf (x); }
|
||||
#endif
|
||||
__forceinline float frac ( const float x ) { return x-floor(x); }
|
||||
|
||||
__forceinline double abs ( const double x ) { return ::fabs(x); }
|
||||
@@ -151,7 +139,7 @@ namespace embree
|
||||
__forceinline double ceil ( const double x ) { return ::ceil (x); }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float mini(float a, float b) {
|
||||
__forceinline float mini(float a, float b) {
|
||||
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
|
||||
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
|
||||
const __m128i ci = _mm_min_epi32(ai,bi);
|
||||
@@ -160,7 +148,7 @@ namespace embree
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float maxi(float a, float b) {
|
||||
__forceinline float maxi(float a, float b) {
|
||||
const __m128i ai = _mm_castps_si128(_mm_set_ss(a));
|
||||
const __m128i bi = _mm_castps_si128(_mm_set_ss(b));
|
||||
const __m128i ci = _mm_max_epi32(ai,bi);
|
||||
@@ -168,60 +156,31 @@ namespace embree
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
__forceinline T twice(const T& a) { return a+a; }
|
||||
|
||||
__forceinline int min(int a, int b) { return a<b ? a:b; }
|
||||
__forceinline unsigned min(unsigned a, unsigned b) { return a<b ? a:b; }
|
||||
__forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
|
||||
__forceinline float min(float a, float b) { return a<b ? a:b; }
|
||||
__forceinline double min(double a, double b) { return a<b ? a:b; }
|
||||
#if defined(__X86_64__)
|
||||
__forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
|
||||
#endif
|
||||
__forceinline int min(int a, int b) { return a<b ? a:b; }
|
||||
__forceinline int64_t min(int64_t a, int64_t b) { return a<b ? a:b; }
|
||||
__forceinline size_t min(size_t a, size_t b) { return a<b ? a:b; }
|
||||
__forceinline float min(float a, float b) { return a<b ? a:b; }
|
||||
__forceinline double min(double a, double b) { return a<b ? a:b; }
|
||||
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c) { return min(min(a,b),c); }
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d) { return min(min(a,b),min(c,d)); }
|
||||
template<typename T> __forceinline T min(const T& a, const T& b, const T& c, const T& d, const T& e) { return min(min(min(a,b),min(c,d)),e); }
|
||||
|
||||
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c) { return mini(mini(a,b),c); }
|
||||
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d) { return mini(mini(a,b),mini(c,d)); }
|
||||
template<typename T> __forceinline T mini(const T& a, const T& b, const T& c, const T& d, const T& e) { return mini(mini(mini(a,b),mini(c,d)),e); }
|
||||
|
||||
__forceinline int max(int a, int b) { return a<b ? b:a; }
|
||||
__forceinline unsigned max(unsigned a, unsigned b) { return a<b ? b:a; }
|
||||
__forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
|
||||
__forceinline float max(float a, float b) { return a<b ? b:a; }
|
||||
__forceinline double max(double a, double b) { return a<b ? b:a; }
|
||||
#if defined(__X86_64__)
|
||||
__forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
|
||||
#endif
|
||||
__forceinline int max(int a, int b) { return a<b ? b:a; }
|
||||
__forceinline int64_t max(int64_t a, int64_t b) { return a<b ? b:a; }
|
||||
__forceinline size_t max(size_t a, size_t b) { return a<b ? b:a; }
|
||||
__forceinline float max(float a, float b) { return a<b ? b:a; }
|
||||
__forceinline double max(double a, double b) { return a<b ? b:a; }
|
||||
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c) { return max(max(a,b),c); }
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d) { return max(max(a,b),max(c,d)); }
|
||||
template<typename T> __forceinline T max(const T& a, const T& b, const T& c, const T& d, const T& e) { return max(max(max(a,b),max(c,d)),e); }
|
||||
|
||||
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c) { return maxi(maxi(a,b),c); }
|
||||
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d) { return maxi(maxi(a,b),maxi(c,d)); }
|
||||
template<typename T> __forceinline T maxi(const T& a, const T& b, const T& c, const T& d, const T& e) { return maxi(maxi(maxi(a,b),maxi(c,d)),e); }
|
||||
|
||||
#if defined(__MACOSX__)
|
||||
__forceinline ssize_t min(ssize_t a, ssize_t b) { return a<b ? a:b; }
|
||||
__forceinline ssize_t max(ssize_t a, ssize_t b) { return a<b ? b:a; }
|
||||
#endif
|
||||
|
||||
#if defined(__MACOSX__) && !defined(__INTEL_COMPILER)
|
||||
__forceinline void sincosf(float x, float *sin, float *cos) {
|
||||
__sincosf(x,sin,cos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__) || defined(__FreeBSD__)
|
||||
__forceinline void sincosf(float x, float *s, float *c) {
|
||||
*s = sinf(x); *c = cosf(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T> __forceinline T clamp(const T& x, const T& lower = T(zero), const T& upper = T(one)) { return max(min(x,upper),lower); }
|
||||
template<typename T> __forceinline T clampz(const T& x, const T& upper) { return max(T(zero), min(x,upper)); }
|
||||
|
||||
@@ -251,8 +210,8 @@ namespace embree
|
||||
template<> __forceinline int random() { return int(rand()); }
|
||||
template<> __forceinline uint32_t random() { return uint32_t(rand()) ^ (uint32_t(rand()) << 16); }
|
||||
#endif
|
||||
template<> __forceinline float random() { return rand()/float(RAND_MAX); }
|
||||
template<> __forceinline double random() { return rand()/double(RAND_MAX); }
|
||||
template<> __forceinline float random() { return random<uint32_t>()/float(RAND_MAX); }
|
||||
template<> __forceinline double random() { return random<uint32_t>()/double(RAND_MAX); }
|
||||
|
||||
#if _WIN32
|
||||
__forceinline double drand48() {
|
||||
@@ -269,15 +228,9 @@ namespace embree
|
||||
__forceinline int select(bool s, int t, int f) { return s ? t : f; }
|
||||
__forceinline float select(bool s, float t, float f) { return s ? t : f; }
|
||||
|
||||
|
||||
template<typename V>
|
||||
__forceinline V lerp(const V& v0, const V& v1, const float t) {
|
||||
return madd(V(1.0f-t),v0,t*v1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline T lerp2(const float x0, const float x1, const float x2, const float x3, const T& u, const T& v) {
|
||||
return madd((1.0f-u),madd((1.0f-v),T(x0),v*T(x2)),u*madd((1.0f-v),T(x1),v*T(x3)));
|
||||
template<typename T>
|
||||
__forceinline T lerp2(const float x0, const float x1, const float x2, const float x3,const T &u, const T &v) {
|
||||
return (1.0f-u)*(1.0f-v)*x0 + u*(1.0f-v)*x1 + (1.0f-u)*v*x2 + u*v*x3;
|
||||
}
|
||||
|
||||
/*! exchange */
|
||||
@@ -301,60 +254,47 @@ namespace embree
|
||||
__forceinline T bitInterleave(const T& xin, const T& yin, const T& zin)
|
||||
{
|
||||
T x = xin, y = yin, z = zin;
|
||||
x = (x | (x << 16)) & 0x030000FF;
|
||||
x = (x | (x << 8)) & 0x0300F00F;
|
||||
x = (x | (x << 4)) & 0x030C30C3;
|
||||
x = (x | (x << 2)) & 0x09249249;
|
||||
|
||||
y = (y | (y << 16)) & 0x030000FF;
|
||||
y = (y | (y << 8)) & 0x0300F00F;
|
||||
y = (y | (y << 4)) & 0x030C30C3;
|
||||
y = (y | (y << 2)) & 0x09249249;
|
||||
|
||||
z = (z | (z << 16)) & 0x030000FF;
|
||||
z = (z | (z << 8)) & 0x0300F00F;
|
||||
z = (z | (z << 4)) & 0x030C30C3;
|
||||
z = (z | (z << 2)) & 0x09249249;
|
||||
|
||||
x = (x | (x << 16)) & 0x030000FF;
|
||||
x = (x | (x << 8)) & 0x0300F00F;
|
||||
x = (x | (x << 4)) & 0x030C30C3;
|
||||
x = (x | (x << 2)) & 0x09249249;
|
||||
|
||||
y = (y | (y << 16)) & 0x030000FF;
|
||||
y = (y | (y << 8)) & 0x0300F00F;
|
||||
y = (y | (y << 4)) & 0x030C30C3;
|
||||
y = (y | (y << 2)) & 0x09249249;
|
||||
|
||||
z = (z | (z << 16)) & 0x030000FF;
|
||||
z = (z | (z << 8)) & 0x0300F00F;
|
||||
z = (z | (z << 4)) & 0x030C30C3;
|
||||
z = (z | (z << 2)) & 0x09249249;
|
||||
|
||||
return x | (y << 1) | (z << 2);
|
||||
}
|
||||
|
||||
#if defined(__AVX2__)
|
||||
|
||||
template<>
|
||||
__forceinline unsigned int bitInterleave(const unsigned int &xi, const unsigned int& yi, const unsigned int& zi)
|
||||
{
|
||||
const unsigned int xx = pdep(xi,0x49249249 /* 0b01001001001001001001001001001001 */ );
|
||||
const unsigned int yy = pdep(yi,0x92492492 /* 0b10010010010010010010010010010010 */);
|
||||
const unsigned int zz = pdep(zi,0x24924924 /* 0b00100100100100100100100100100100 */);
|
||||
return xx | yy | zz;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*! bit interleave operation for 64bit data types*/
|
||||
template<class T>
|
||||
__forceinline T bitInterleave64(const T& xin, const T& yin, const T& zin){
|
||||
T x = xin & 0x1fffff;
|
||||
T y = yin & 0x1fffff;
|
||||
T z = zin & 0x1fffff;
|
||||
T x = xin & 0x1fffff;
|
||||
T y = yin & 0x1fffff;
|
||||
T z = zin & 0x1fffff;
|
||||
|
||||
x = (x | x << 32) & 0x1f00000000ffff;
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff;
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f;
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3;
|
||||
x = (x | x << 32) & 0x1f00000000ffff;
|
||||
x = (x | x << 16) & 0x1f0000ff0000ff;
|
||||
x = (x | x << 8) & 0x100f00f00f00f00f;
|
||||
x = (x | x << 4) & 0x10c30c30c30c30c3;
|
||||
x = (x | x << 2) & 0x1249249249249249;
|
||||
|
||||
y = (y | y << 32) & 0x1f00000000ffff;
|
||||
y = (y | y << 16) & 0x1f0000ff0000ff;
|
||||
y = (y | y << 8) & 0x100f00f00f00f00f;
|
||||
y = (y | y << 4) & 0x10c30c30c30c30c3;
|
||||
y = (y | y << 32) & 0x1f00000000ffff;
|
||||
y = (y | y << 16) & 0x1f0000ff0000ff;
|
||||
y = (y | y << 8) & 0x100f00f00f00f00f;
|
||||
y = (y | y << 4) & 0x10c30c30c30c30c3;
|
||||
y = (y | y << 2) & 0x1249249249249249;
|
||||
|
||||
z = (z | z << 32) & 0x1f00000000ffff;
|
||||
z = (z | z << 16) & 0x1f0000ff0000ff;
|
||||
z = (z | z << 8) & 0x100f00f00f00f00f;
|
||||
z = (z | z << 4) & 0x10c30c30c30c30c3;
|
||||
z = (z | z << 32) & 0x1f00000000ffff;
|
||||
z = (z | z << 16) & 0x1f0000ff0000ff;
|
||||
z = (z | z << 8) & 0x100f00f00f00f00f;
|
||||
z = (z | z << 4) & 0x10c30c30c30c30c3;
|
||||
z = (z | z << 2) & 0x1249249249249249;
|
||||
|
||||
return x | (y << 1) | (z << 2);
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -21,7 +21,7 @@
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Quaternion Struct
|
||||
// Quaterion Struct
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
@@ -33,13 +33,13 @@ namespace embree
|
||||
/// Construction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline QuaternionT () { }
|
||||
__forceinline QuaternionT ( void ) { }
|
||||
__forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
|
||||
__forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
|
||||
|
||||
__forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
|
||||
__forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
|
||||
__forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
|
||||
__forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
|
||||
__forceinline QuaternionT( const T& r, const T& i, const T& j , const T& k ) : r(r), i(i), j(j), k(k) {}
|
||||
__forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
|
||||
|
||||
__inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
|
||||
@@ -58,7 +58,7 @@ namespace embree
|
||||
}
|
||||
|
||||
/*! returns the rotation axis of the quaternion as a vector */
|
||||
__forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
|
||||
__forceinline const Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
|
||||
|
||||
public:
|
||||
T r, i, j, k;
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../sys/platform.h"
|
||||
#include "../math/math.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
template<typename Ty>
|
||||
struct range
|
||||
{
|
||||
__forceinline range() {}
|
||||
|
||||
__forceinline range(const Ty& begin)
|
||||
: _begin(begin), _end(begin+1) {}
|
||||
|
||||
__forceinline range(const Ty& begin, const Ty& end)
|
||||
: _begin(begin), _end(end) {}
|
||||
|
||||
__forceinline range(const range& other)
|
||||
: _begin(other._begin), _end(other._end) {}
|
||||
|
||||
template<typename T1>
|
||||
__forceinline range(const range<T1>& other)
|
||||
: _begin(Ty(other._begin)), _end(Ty(other._end)) {}
|
||||
|
||||
template<typename T1>
|
||||
__forceinline range& operator =(const range<T1>& other) {
|
||||
_begin = other._begin;
|
||||
_end = other._end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__forceinline Ty begin() const {
|
||||
return _begin;
|
||||
}
|
||||
|
||||
__forceinline Ty end() const {
|
||||
return _end;
|
||||
}
|
||||
|
||||
__forceinline range intersect(const range& r) const {
|
||||
return range (max(_begin,r._begin),min(_end,r._end));
|
||||
}
|
||||
|
||||
__forceinline Ty size() const {
|
||||
return _end - _begin;
|
||||
}
|
||||
|
||||
__forceinline bool empty() const {
|
||||
return _end <= _begin;
|
||||
}
|
||||
|
||||
__forceinline Ty center() const {
|
||||
return (_begin + _end)/2;
|
||||
}
|
||||
|
||||
__forceinline std::pair<range,range> split() const
|
||||
{
|
||||
const Ty _center = center();
|
||||
return std::make_pair(range(_begin,_center),range(_center,_end));
|
||||
}
|
||||
|
||||
__forceinline void split(range& left_o, range& right_o) const
|
||||
{
|
||||
const Ty _center = center();
|
||||
left_o = range(_begin,_center);
|
||||
right_o = range(_center,_end);
|
||||
}
|
||||
|
||||
__forceinline friend bool operator< (const range& r0, const range& r1) {
|
||||
return r0.size() < r1.size();
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& cout, const range& r) {
|
||||
return cout << "range [" << r.begin() << ", " << r.end() << "]";
|
||||
}
|
||||
|
||||
Ty _begin, _end;
|
||||
};
|
||||
|
||||
template<typename Ty>
|
||||
range<Ty> make_range(const Ty& begin, const Ty& end) {
|
||||
return range<Ty>(begin,end);
|
||||
}
|
||||
|
||||
template<typename Ty>
|
||||
struct extended_range : public range<Ty>
|
||||
{
|
||||
__forceinline extended_range () {}
|
||||
|
||||
__forceinline extended_range (const Ty& begin)
|
||||
: range<Ty>(begin), _ext_end(begin+1) {}
|
||||
|
||||
__forceinline extended_range (const Ty& begin, const Ty& end)
|
||||
: range<Ty>(begin,end), _ext_end(end) {}
|
||||
|
||||
__forceinline extended_range (const Ty& begin, const Ty& end, const Ty& ext_end)
|
||||
: range<Ty>(begin,end), _ext_end(ext_end) {}
|
||||
|
||||
__forceinline Ty ext_end() const {
|
||||
return _ext_end;
|
||||
}
|
||||
|
||||
__forceinline Ty ext_size() const {
|
||||
return _ext_end - range<Ty>::_begin;
|
||||
}
|
||||
|
||||
__forceinline Ty ext_range_size() const {
|
||||
return _ext_end - range<Ty>::_end;
|
||||
}
|
||||
|
||||
__forceinline bool has_ext_range() const {
|
||||
assert(_ext_end >= range<Ty>::_end);
|
||||
return (_ext_end - range<Ty>::_end) > 0;
|
||||
}
|
||||
|
||||
__forceinline void set_ext_range(const size_t ext_end){
|
||||
assert(ext_end >= range<Ty>::_end);
|
||||
_ext_end = ext_end;
|
||||
}
|
||||
|
||||
__forceinline void move_right(const size_t plus){
|
||||
range<Ty>::_begin += plus;
|
||||
range<Ty>::_end += plus;
|
||||
_ext_end += plus;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& cout, const extended_range& r) {
|
||||
return cout << "extended_range [" << r.begin() << ", " << r.end() << " (" << r.ext_end() << ")]";
|
||||
}
|
||||
|
||||
Ty _ext_end;
|
||||
};
|
||||
}
|
||||
+16
-27
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -35,14 +35,14 @@ namespace embree
|
||||
/// Construction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec2( ) {}
|
||||
__forceinline Vec2 ( ) { }
|
||||
__forceinline explicit Vec2( const T& a ) : x(a), y(a) {}
|
||||
__forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {}
|
||||
__forceinline explicit Vec2( const T& x, const T& y ) : x(x), y(y) {}
|
||||
|
||||
__forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; }
|
||||
__forceinline Vec2 ( const Vec2& other ) { x = other.x; y = other.y; }
|
||||
template<typename T1> __forceinline Vec2( const Vec2<T1>& a ) : x(T(a.x)), y(T(a.y)) {}
|
||||
template<typename T1> __forceinline Vec2& operator =( const Vec2<T1>& other ) { x = other.x; y = other.y; return *this; }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -66,18 +66,13 @@ namespace embree
|
||||
template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); }
|
||||
template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); }
|
||||
template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); }
|
||||
template<typename T> __forceinline Vec2<T> frac ( const Vec2<T>& a ) { return Vec2<T>(frac (a.x), frac (a.y)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x + b.x, a.y + b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x + b , a.y + b ); }
|
||||
template<typename T> __forceinline Vec2<T> operator +( const T& a, const Vec2<T>& b ) { return Vec2<T>(a + b.x, a + b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x - b.x, a.y - b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x - b , a.y - b ); }
|
||||
template<typename T> __forceinline Vec2<T> operator -( const T& a, const Vec2<T>& b ) { return Vec2<T>(a - b.x, a - b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x * b.x, a.y * b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator *( const T& a, const Vec2<T>& b ) { return Vec2<T>(a * b.x, a * b.y); }
|
||||
template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x * b , a.y * b ); }
|
||||
@@ -87,20 +82,15 @@ namespace embree
|
||||
|
||||
template<typename T> __forceinline Vec2<T> min(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(min(a.x, b.x), min(a.y, b.y)); }
|
||||
template<typename T> __forceinline Vec2<T> max(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(max(a.x, b.x), max(a.y, b.y)); }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
|
||||
|
||||
template<typename T> __forceinline Vec2<T> madd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a,b.x,c.x), madd(a,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> msub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a,b.x,c.x), msub(a,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> nmadd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y) ); }
|
||||
template<typename T> __forceinline Vec2<T> nmsub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y) ); }
|
||||
template<typename T> __forceinline const Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline const Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline const Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); }
|
||||
template<typename T> __forceinline const Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
@@ -135,7 +125,7 @@ namespace embree
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); }
|
||||
|
||||
template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); }
|
||||
@@ -143,7 +133,7 @@ namespace embree
|
||||
template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-b); }
|
||||
template<typename T> __forceinline T det ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.y - a.y*b.x; }
|
||||
|
||||
template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
|
||||
template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) {
|
||||
const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) );
|
||||
}
|
||||
|
||||
@@ -159,14 +149,13 @@ namespace embree
|
||||
return Vec2<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline Vec2<T> select ( const typename T::Bool& s, const Vec2<T>& t, const Vec2<T>& f ) {
|
||||
template<typename T> __forceinline Vec2<T> select ( const typename T::Mask& s, const Vec2<T>& t, const Vec2<T>& f ) {
|
||||
return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
|
||||
{
|
||||
const Vec2<T> b = abs(a);
|
||||
if (b.x > b.y) return 0;
|
||||
template<typename T> __forceinline int maxDim ( const Vec2<T>& a )
|
||||
{
|
||||
if (a.x > a.y) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
|
||||
+73
-101
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -37,12 +37,12 @@ namespace embree
|
||||
/// Construction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3( ) {}
|
||||
__forceinline explicit Vec3( const T& a ) : x(a), y(a), z(a) {}
|
||||
__forceinline Vec3( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
|
||||
__forceinline Vec3 ( ) {}
|
||||
__forceinline explicit Vec3 ( const T& a ) : x(a), y(a), z(a) {}
|
||||
__forceinline explicit Vec3 ( const T& x, const T& y, const T& z ) : x(x), y(y), z(z) {}
|
||||
|
||||
__forceinline Vec3( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
|
||||
__forceinline Vec3( const Vec3fa& other );
|
||||
__forceinline Vec3 ( const Vec3& other ) { x = other.x; y = other.y; z = other.z; }
|
||||
__forceinline Vec3 ( const Vec3fa& other );
|
||||
|
||||
template<typename T1> __forceinline Vec3( const Vec3<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)) {}
|
||||
template<typename T1> __forceinline Vec3& operator =(const Vec3<T1>& other) { x = other.x; y = other.y; z = other.z; return *this; }
|
||||
@@ -71,13 +71,13 @@ namespace embree
|
||||
template<typename T> __forceinline Vec3<T> rsqrt ( const Vec3<T>& a ) { return Vec3<T>(rsqrt(a.x), rsqrt(a.y), rsqrt(a.z)); }
|
||||
template<typename T> __forceinline Vec3<T> sqrt ( const Vec3<T>& a ) { return Vec3<T>(sqrt (a.x), sqrt (a.y), sqrt (a.z)); }
|
||||
|
||||
template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
|
||||
template<typename T> __forceinline Vec3<T> zero_fix( const Vec3<T>& a )
|
||||
{
|
||||
return Vec3<T>(select(abs(a.x)<min_rcp_input,T(min_rcp_input),a.x),
|
||||
select(abs(a.y)<min_rcp_input,T(min_rcp_input),a.y),
|
||||
select(abs(a.z)<min_rcp_input,T(min_rcp_input),a.z));
|
||||
}
|
||||
template<typename T> __forceinline Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
|
||||
template<typename T> __forceinline const Vec3<T> rcp_safe(const Vec3<T>& a) { return rcp(zero_fix(a)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
@@ -102,25 +102,20 @@ namespace embree
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
|
||||
template<typename T> __forceinline Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
|
||||
template<typename T> __forceinline Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
|
||||
template<typename T> __forceinline Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
|
||||
|
||||
template<typename T> __forceinline Vec3<T> madd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z)); }
|
||||
template<typename T> __forceinline Vec3<T> msub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z)); }
|
||||
template<typename T> __forceinline Vec3<T> nmadd ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z));}
|
||||
template<typename T> __forceinline Vec3<T> nmsub ( const T& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z)); }
|
||||
template<typename T> __forceinline const Vec3<T> madd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z)); }
|
||||
template<typename T> __forceinline const Vec3<T> msub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z)); }
|
||||
template<typename T> __forceinline const Vec3<T> nmadd ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z));}
|
||||
template<typename T> __forceinline const Vec3<T> nmsub ( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c) { return Vec3<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
|
||||
template<typename T> __forceinline Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
|
||||
template<typename T> __forceinline Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
|
||||
template<typename T> __forceinline Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
|
||||
template<typename T> __forceinline Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
|
||||
template<typename T> __forceinline const Vec3<T>& operator +=( Vec3<T>& a, const T b ) { a.x += b; a.y += b; a.z += b; return a; }
|
||||
template<typename T> __forceinline const Vec3<T>& operator +=( Vec3<T>& a, const Vec3<T>& b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
|
||||
template<typename T> __forceinline const Vec3<T>& operator -=( Vec3<T>& a, const Vec3<T>& b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
|
||||
template<typename T> __forceinline const Vec3<T>& operator *=( Vec3<T>& a, const T& b ) { a.x *= b ; a.y *= b ; a.z *= b ; return a; }
|
||||
template<typename T> __forceinline const Vec3<T>& operator /=( Vec3<T>& a, const T& b ) { a.x /= b ; a.y /= b ; a.z /= b ; return a; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operators
|
||||
@@ -156,22 +151,16 @@ namespace embree
|
||||
return Vec3<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline Vec3<T> select ( const typename T::Bool& s, const Vec3<T>& t, const Vec3<T>& f ) {
|
||||
template<typename T> __forceinline Vec3<T> select ( const typename T::Mask& s, const Vec3<T>& t, const Vec3<T>& f ) {
|
||||
return Vec3<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline Vec3<T> lerp(const Vec3<T>& v0, const Vec3<T>& v1, const T& t) {
|
||||
return madd(Vec3<T>(T(1.0f)-t),v0,t*v1);
|
||||
}
|
||||
|
||||
template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
|
||||
{
|
||||
const Vec3<T> b = abs(a);
|
||||
if (b.x > b.y) {
|
||||
if (b.x > b.z) return 0; else return 2;
|
||||
template<typename T> __forceinline int maxDim ( const Vec3<T>& a )
|
||||
{
|
||||
if (a.x > a.y) {
|
||||
if (a.x > a.z) return 0; else return 2;
|
||||
} else {
|
||||
if (b.y > b.z) return 1; else return 2;
|
||||
if (a.y > a.z) return 1; else return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,48 +181,34 @@ namespace embree
|
||||
|
||||
template<typename T> __forceinline T dot ( const Vec3<T>& a, const Vec3<T>& b ) { return madd(a.x,b.x,madd(a.y,b.y,a.z*b.z)); }
|
||||
template<typename T> __forceinline T length ( const Vec3<T>& a ) { return sqrt(dot(a,a)); }
|
||||
template<typename T> __forceinline T rcp_length( const Vec3<T>& a ) { return rsqrt(dot(a,a)); }
|
||||
template<typename T> __forceinline Vec3<T> normalize( const Vec3<T>& a ) { return a*rsqrt(dot(a,a)); }
|
||||
template<typename T> __forceinline T distance ( const Vec3<T>& a, const Vec3<T>& b ) { return length(a-b); }
|
||||
template<typename T> __forceinline Vec3<T> cross ( const Vec3<T>& a, const Vec3<T>& b ) { return Vec3<T>(msub(a.y,b.z,a.z*b.y), msub(a.z,b.x,a.x*b.z), msub(a.x,b.y,a.y*b.x)); }
|
||||
|
||||
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
|
||||
template<typename T> __forceinline Vec3<T> stable_triangle_normal( const Vec3<T>& a, const Vec3<T>& b, const Vec3<T>& c )
|
||||
{
|
||||
const T ab_x = a.z*b.y, ab_y = a.x*b.z, ab_z = a.y*b.x;
|
||||
const T bc_x = b.z*c.y, bc_y = b.x*c.z, bc_z = b.y*c.x;
|
||||
const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
|
||||
const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
|
||||
const Vec3<T> cross_ab(msub(a.y,b.z,ab_x), msub(a.z,b.x,ab_y), msub(a.x,b.y,ab_z));
|
||||
const Vec3<T> cross_bc(msub(b.y,c.z,bc_x), msub(b.z,c.x,bc_y), msub(b.x,c.y,bc_z));
|
||||
const auto sx = abs(ab_x) < abs(bc_x);
|
||||
const auto sy = abs(ab_y) < abs(bc_y);
|
||||
const auto sz = abs(ab_z) < abs(bc_z);
|
||||
return Vec3<T>(select(sx,cross_ab.x,cross_bc.x),
|
||||
select(sy,cross_ab.y,cross_bc.y),
|
||||
select(sz,cross_ab.z,cross_bc.z));
|
||||
select(sx,cross_ab.y,cross_bc.y),
|
||||
select(sx,cross_ab.z,cross_bc.z));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline T sum ( const Vec3<T>& a ) { return a.x+a.y+a.z; }
|
||||
|
||||
template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
|
||||
template<typename T> __forceinline T halfArea ( const Vec3<T>& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
|
||||
template<typename T> __forceinline T area ( const Vec3<T>& d ) { return 2.0f*halfArea(d); }
|
||||
template<typename T> __forceinline Vec3<T> reflect ( const Vec3<T>& V, const Vec3fa& N ) { return 2.0f*dot(V,N)*N-V; }
|
||||
|
||||
template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
|
||||
template<typename T> __forceinline Vec3<T> normalize_safe( const Vec3<T>& a ) {
|
||||
const T d = dot(a,a); return select(d == T( zero ), a , a*rsqrt(d) );
|
||||
}
|
||||
|
||||
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& P, const Vec3<T>& Q0, const Vec3<T>& Q1)
|
||||
{
|
||||
const Vec3<T> N = cross(P-Q0,Q1-Q0);
|
||||
const Vec3<T> D = Q1-Q0;
|
||||
return dot(N,N)*rcp(dot(D,D));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline T sqr_point_to_line_distance(const Vec3<T>& PmQ0, const Vec3<T>& Q1mQ0)
|
||||
{
|
||||
const Vec3<T> N = cross(PmQ0,Q1mQ0);
|
||||
const Vec3<T> D = Q1mQ0;
|
||||
return dot(N,N)*rcp(dot(D,D));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -247,9 +222,15 @@ namespace embree
|
||||
typedef Vec3<float> Vec3f;
|
||||
}
|
||||
|
||||
#include "vec3ba.h"
|
||||
#include "vec3ia.h"
|
||||
#include "vec3fa.h"
|
||||
#if defined(__MIC__)
|
||||
#include "vec3ba_mic.h"
|
||||
#include "vec3ia_mic.h"
|
||||
#include "vec3fa_mic.h"
|
||||
#else
|
||||
#include "vec3ba.h"
|
||||
#include "vec3ia.h"
|
||||
#include "vec3fa.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE / AVX / MIC specializations
|
||||
@@ -263,77 +244,68 @@ namespace embree
|
||||
#include "../simd/avx.h"
|
||||
#endif
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
#if defined (__MIC__) || defined(__AVX512F__)
|
||||
#include "../simd/avx512.h"
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace embree
|
||||
{
|
||||
template<typename Out, typename In>
|
||||
__forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
|
||||
return Vec3<Out>(Out(a.x[k]), Out(a.y[k]), Out(a.z[k]));
|
||||
__forceinline Vec3<Out> broadcast(const Vec3<In>& a, const size_t k) {
|
||||
return Vec3<Out>(Out(a.x[k]),Out(a.y[k]),Out(a.z[k]));
|
||||
}
|
||||
|
||||
template<> __forceinline Vec3<float>::Vec3(const Vec3fa& a) { x = a.x; y = a.y; z = a.z; }
|
||||
template<> __forceinline Vec3<float>::Vec3( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; }
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<> __forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
|
||||
x = a.x; y = a.y; z = a.z;
|
||||
#if defined (__SSE__)
|
||||
template<> __forceinline Vec3<float4>::Vec3( const Vec3fa& a ) {
|
||||
const float4 v = float4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
|
||||
}
|
||||
#elif defined(__SSE__)
|
||||
template<>
|
||||
__forceinline Vec3<vfloat4>::Vec3(const Vec3fa& a) {
|
||||
const vfloat4 v = vfloat4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE__)
|
||||
__forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat4>& a, const size_t k) {
|
||||
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float4> broadcast4f( const Vec3<float4>& a, const size_t k ) {
|
||||
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
|
||||
}
|
||||
|
||||
template<>
|
||||
__forceinline Vec3<vfloat4> broadcast<vfloat4,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
|
||||
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float4> broadcast<float4,float4>( const Vec3<float4>& a, const size_t k ) {
|
||||
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
|
||||
}
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline Vec3<vfloat4> shuffle(const Vec3<vfloat4>& b) {
|
||||
return Vec3<vfloat4>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const Vec3<float4> shuffle( const Vec3<float4>& b ) {
|
||||
return Vec3<float4>(shuffle<i0,i1,i2,i3>(b.x),shuffle<i0,i1,i2,i3>(b.y),shuffle<i0,i1,i2,i3>(b.z));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<>
|
||||
__forceinline Vec3<vfloat8>::Vec3(const Vec3fa& a) {
|
||||
x = a.x; y = a.y; z = a.z;
|
||||
template<> __forceinline Vec3<float8>::Vec3( const Vec3fa& a ) {
|
||||
x = a.x; y = a.y; z = a.z;
|
||||
}
|
||||
__forceinline Vec3<vfloat4> broadcast4f(const Vec3<vfloat8>& a, const size_t k) {
|
||||
return Vec3<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float4> broadcast4f( const Vec3<float8>& a, const size_t k ) {
|
||||
return Vec3<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]));
|
||||
}
|
||||
__forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat4>& a, const size_t k) {
|
||||
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float8> broadcast8f( const Vec3<float4>& a, const size_t k ) {
|
||||
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
|
||||
}
|
||||
__forceinline Vec3<vfloat8> broadcast8f(const Vec3<vfloat8>& a, const size_t k) {
|
||||
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float8> broadcast8f( const Vec3<float8>& a, const size_t k ) {
|
||||
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
|
||||
}
|
||||
|
||||
template<>
|
||||
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat4>(const Vec3<vfloat4>& a, const size_t k) {
|
||||
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float8> broadcast<float8,float4>( const Vec3<float4>& a, const size_t k ) {
|
||||
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
|
||||
}
|
||||
template<>
|
||||
__forceinline Vec3<vfloat8> broadcast<vfloat8,vfloat8>(const Vec3<vfloat8>& a, const size_t k) {
|
||||
return Vec3<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]));
|
||||
__forceinline Vec3<float8> broadcast<float8,float8>( const Vec3<float8>& a, const size_t k ) {
|
||||
return Vec3<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]));
|
||||
}
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline Vec3<vfloat8> shuffle(const Vec3<vfloat8>& b) {
|
||||
return Vec3<vfloat8>(shuffle<i0,i1,i2,i3>(b.x), shuffle<i0,i1,i2,i3>(b.y), shuffle<i0,i1,i2,i3>(b.z));
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const Vec3<float8> shuffle( const Vec3<float8>& b ) {
|
||||
return Vec3<float8>(shuffle<i0,i1,i2,i3>(b.x),shuffle<i0,i1,i2,i3>(b.y),shuffle<i0,i1,i2,i3>(b.z));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
template<> __forceinline Vec3<vfloat16>::Vec3(const Vec3fa& a) : x(a.x), y(a.y), z(a.z) {}
|
||||
#if defined (__MIC__) || defined(__AVX512F__)
|
||||
template<> __forceinline Vec3<float16>::Vec3( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
+12
-15
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
@@ -28,8 +27,6 @@ namespace embree
|
||||
|
||||
struct __aligned(16) Vec3ba
|
||||
{
|
||||
ALIGNED_STRUCT;
|
||||
|
||||
union {
|
||||
__m128 m128;
|
||||
struct { int x,y,z; int a; };
|
||||
@@ -47,13 +44,13 @@ namespace embree
|
||||
__forceinline Vec3ba( const Vec3ba& other ) : m128(other.m128) {}
|
||||
__forceinline Vec3ba& operator =(const Vec3ba& other) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3ba( bool a )
|
||||
__forceinline explicit Vec3ba ( bool a )
|
||||
: m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
|
||||
__forceinline Vec3ba( bool a, bool b, bool c)
|
||||
__forceinline explicit Vec3ba ( bool a, bool b, bool c)
|
||||
: m128(_mm_lookupmask_ps[(size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
|
||||
|
||||
__forceinline operator const __m128&() const { return m128; }
|
||||
__forceinline operator __m128&() { return m128; }
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator __m128&( void ) { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
@@ -75,23 +72,23 @@ namespace embree
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
|
||||
__forceinline const Vec3ba operator !( const Vec3ba& a ) { return _mm_xor_ps(a.m128, Vec3ba(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
|
||||
__forceinline Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
|
||||
__forceinline Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
|
||||
__forceinline const Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm_and_ps(a.m128, b.m128); }
|
||||
__forceinline const Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm_or_ps (a.m128, b.m128); }
|
||||
__forceinline const Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm_xor_ps(a.m128, b.m128); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba& operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
|
||||
__forceinline Vec3ba& operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
|
||||
__forceinline Vec3ba& operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
|
||||
__forceinline const Vec3ba operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
|
||||
__forceinline const Vec3ba operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
|
||||
__forceinline const Vec3ba operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math.h"
|
||||
#include "../simd/avx512.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// MIC Vec3ba Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*! 3-wide bool type emulated with 16-wide bit vectors. */
|
||||
struct Vec3ba
|
||||
{
|
||||
enum { N = 3 };
|
||||
__mmask16 v;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba( ) {}
|
||||
__forceinline Vec3ba ( const __mmask16 a ) : v(a) {}
|
||||
__forceinline Vec3ba ( const Vec3ba& a ) : v(a.v) {}
|
||||
__forceinline Vec3ba& operator =(const Vec3ba& a) { v = a.v; return *this; }
|
||||
|
||||
__forceinline explicit Vec3ba ( bool x ) : v(x ? 0xF : 0x0) {}
|
||||
__forceinline explicit Vec3ba ( bool x, bool y, bool z ) : v(1*__mmask16(x)+2*__mmask16(y)+4*__mmask16(z)) {}
|
||||
|
||||
__forceinline operator const __mmask16&( void ) const { return v; }
|
||||
__forceinline operator __mmask16&( void ) { return v; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ba( FalseTy ) : v(0x0) {}
|
||||
__forceinline Vec3ba( TrueTy ) : v(0xF) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator []( const size_t index ) const { assert(index < 3); return (v >> index) & 1; }
|
||||
//__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ba operator !( const Vec3ba& a ) { return _mm512_knot(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ba operator &( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kand(a.v, b.v); }
|
||||
__forceinline const Vec3ba operator |( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kor (a.v, b.v); }
|
||||
__forceinline const Vec3ba operator ^( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxor(a.v, b.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ba operator &=( Vec3ba& a, const Vec3ba& b ) { return a = a & b; }
|
||||
__forceinline const Vec3ba operator |=( Vec3ba& a, const Vec3ba& b ) { return a = a | b; }
|
||||
__forceinline const Vec3ba operator ^=( Vec3ba& a, const Vec3ba& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxnor(a, b); }
|
||||
__forceinline bool operator !=( const Vec3ba& a, const Vec3ba& b ) { return _mm512_kxor (a, b); }
|
||||
__forceinline bool operator < ( const Vec3ba& a, const Vec3ba& b ) {
|
||||
if (a[0] != b[0]) return a[0] < b[0];
|
||||
if (a[1] != b[1]) return a[1] < b[1];
|
||||
if (a[2] != b[2]) return a[2] < b[2];
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and( const Vec3ba& a ) { return (a.v & 0x7) == 0x7; }
|
||||
__forceinline bool reduce_or ( const Vec3ba& a ) { return (a.v & 0x7) != 0x0; }
|
||||
|
||||
__forceinline int all(const Vec3ba& a) { return (a.v & 0x7) == 0x7; }
|
||||
__forceinline int any(const Vec3ba& a) { return (a.v & 0x7) != 0x0; }
|
||||
__forceinline int none(const Vec3ba& a) { return (a.v & 0x7) == 0x0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3ba& a) {
|
||||
return cout << "(" << (a[0] ? "1" : "0") << ", " << (a[1] ? "1" : "0") << ", " << (a[2] ? "1" : "0") << ")";
|
||||
}
|
||||
}
|
||||
+81
-115
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
@@ -28,8 +27,6 @@ namespace embree
|
||||
|
||||
struct __aligned(16) Vec3fa
|
||||
{
|
||||
ALIGNED_STRUCT;
|
||||
|
||||
typedef float Scalar;
|
||||
enum { N = 3 };
|
||||
union {
|
||||
@@ -52,40 +49,40 @@ namespace embree
|
||||
__forceinline Vec3fa& operator =( const Vec3fa& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3fa( const float a ) : m128(_mm_set1_ps(a)) {}
|
||||
__forceinline Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(z, z, y, x)) {}
|
||||
__forceinline explicit Vec3fa( const float x, const float y, const float z) : m128(_mm_set_ps(z, z, y, x)) {}
|
||||
|
||||
__forceinline Vec3fa( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
|
||||
__forceinline Vec3fa( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
|
||||
__forceinline Vec3fa( const Vec3fa& other, const float w1) { m128 = other.m128; w = w1; }
|
||||
//__forceinline Vec3fa( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
|
||||
//__forceinline Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
|
||||
__forceinline Vec3fa( const float x, const float y, const float z, const float w) : m128(_mm_set_ps(w, z, y, x)) {}
|
||||
__forceinline explicit Vec3fa( const Vec3fa& other, const int a1) { m128 = other.m128; a = a1; }
|
||||
__forceinline explicit Vec3fa( const Vec3fa& other, const unsigned a1) { m128 = other.m128; u = a1; }
|
||||
__forceinline explicit Vec3fa( const Vec3fa& other, const float w1) { m128 = other.m128; w = w1; }
|
||||
//__forceinline explicit Vec3fa( const float x, const float y, const float z, const int a) : x(x), y(y), z(z), a(a) {} // not working properly!
|
||||
//__forceinline explicit Vec3fa( const float x, const float y, const float z, const unsigned a) : x(x), y(y), z(z), u(a) {} // not working properly!
|
||||
__forceinline explicit Vec3fa( const float x, const float y, const float z, const float w) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
__forceinline explicit Vec3fa( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
|
||||
|
||||
__forceinline operator const __m128&() const { return m128; }
|
||||
__forceinline operator __m128&() { return m128; }
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator __m128&( void ) { return m128; }
|
||||
|
||||
#if defined (__SSE4_1__)
|
||||
friend __forceinline Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { return _mm_insert_ps(a, b, (3 << 4) | (3 << 6)); }
|
||||
friend __forceinline const Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { return _mm_insert_ps(a, b, (3 << 4) | (3 << 6)); }
|
||||
#else
|
||||
friend __forceinline Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { Vec3fa c = a; c.a = b.a; return c; }
|
||||
friend __forceinline const Vec3fa copy_a( const Vec3fa& a, const Vec3fa& b ) { Vec3fa c = a; c.a = b.a; return c; }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline Vec3fa load( const void* const a ) {
|
||||
return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
|
||||
}
|
||||
static __forceinline Vec3fa load( const void* const a ) {
|
||||
return Vec3fa(_mm_and_ps(_mm_load_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
|
||||
}
|
||||
|
||||
static __forceinline Vec3fa loadu( const void* const a ) {
|
||||
return Vec3fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
|
||||
}
|
||||
|
||||
static __forceinline Vec3fa loadu( const void* const a ) {
|
||||
return Vec3fa(_mm_and_ps(_mm_loadu_ps((float*)a),_mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1))));
|
||||
}
|
||||
|
||||
static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
|
||||
_mm_storeu_ps((float*)ptr,v);
|
||||
static __forceinline void storeu ( void* ptr, const Vec3fa& v ) {
|
||||
_mm_storeu_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -104,66 +101,50 @@ namespace embree
|
||||
__forceinline const float& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
|
||||
__forceinline float& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa operator +( const Vec3fa& a ) { return a; }
|
||||
__forceinline Vec3fa operator -( const Vec3fa& a ) {
|
||||
__forceinline const Vec3fa operator +( const Vec3fa& a ) { return a; }
|
||||
__forceinline const Vec3fa operator -( const Vec3fa& a ) {
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
|
||||
return _mm_xor_ps(a.m128, mask);
|
||||
}
|
||||
__forceinline Vec3fa abs ( const Vec3fa& a ) {
|
||||
__forceinline const Vec3fa abs ( const Vec3fa& a ) {
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
|
||||
return _mm_and_ps(a.m128, mask);
|
||||
}
|
||||
__forceinline Vec3fa sign ( const Vec3fa& a ) {
|
||||
return blendv_ps(Vec3fa(one), -Vec3fa(one), _mm_cmplt_ps (a,Vec3fa(zero)));
|
||||
__forceinline const Vec3fa sign ( const Vec3fa& a ) {
|
||||
return blendv_ps(Vec3fa(one), -Vec3fa(one), _mm_cmplt_ps (a,Vec3fa(zero)));
|
||||
}
|
||||
|
||||
__forceinline Vec3fa rcp ( const Vec3fa& a )
|
||||
{
|
||||
#if defined(__AVX512VL__)
|
||||
const Vec3fa r = _mm_rcp14_ps(a.m128);
|
||||
#else
|
||||
__forceinline const Vec3fa rcp ( const Vec3fa& a ) {
|
||||
const Vec3fa r = _mm_rcp_ps(a.m128);
|
||||
#endif
|
||||
|
||||
#if defined(__AVX2__)
|
||||
const Vec3fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, vfloat4(2.0f)));
|
||||
const Vec3fa res = _mm_mul_ps(r,_mm_fnmadd_ps(r, a, float4(2.0f)));
|
||||
#else
|
||||
const Vec3fa res = _mm_mul_ps(r,_mm_sub_ps(vfloat4(2.0f), _mm_mul_ps(r, a)));
|
||||
const Vec3fa res = _mm_mul_ps(r,_mm_sub_ps(float4(2.0f), _mm_mul_ps(r, a)));
|
||||
//return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
__forceinline Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
|
||||
__forceinline Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a,a); }
|
||||
|
||||
__forceinline Vec3fa rsqrt( const Vec3fa& a )
|
||||
{
|
||||
#if defined(__AVX512VL__)
|
||||
__m128 r = _mm_rsqrt14_ps(a.m128);
|
||||
#else
|
||||
__forceinline const Vec3fa sqrt ( const Vec3fa& a ) { return _mm_sqrt_ps(a.m128); }
|
||||
__forceinline const Vec3fa sqr ( const Vec3fa& a ) { return _mm_mul_ps(a,a); }
|
||||
__forceinline const Vec3fa rsqrt( const Vec3fa& a ) {
|
||||
__m128 r = _mm_rsqrt_ps(a.m128);
|
||||
#endif
|
||||
return _mm_add_ps(_mm_mul_ps(_mm_set1_ps(1.5f),r), _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set1_ps(-0.5f)), r), _mm_mul_ps(r, r)));
|
||||
}
|
||||
|
||||
__forceinline Vec3fa zero_fix(const Vec3fa& a) {
|
||||
return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
|
||||
__forceinline const Vec3fa zero_fix(const Vec3fa& a) {
|
||||
return blendv_ps(a, _mm_set1_ps(min_rcp_input), _mm_cmplt_ps (abs(a).m128, _mm_set1_ps(min_rcp_input)));
|
||||
}
|
||||
__forceinline Vec3fa rcp_safe(const Vec3fa& a) {
|
||||
return rcp(zero_fix(a));
|
||||
__forceinline const Vec3fa rcp_safe(const Vec3fa& a) {
|
||||
return rcp(zero_fix(a));
|
||||
}
|
||||
__forceinline Vec3fa log ( const Vec3fa& a ) {
|
||||
__forceinline Vec3fa log ( const Vec3fa& a ) {
|
||||
return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
|
||||
}
|
||||
|
||||
__forceinline Vec3fa exp ( const Vec3fa& a ) {
|
||||
__forceinline Vec3fa exp ( const Vec3fa& a ) {
|
||||
return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
|
||||
}
|
||||
|
||||
@@ -171,37 +152,37 @@ namespace embree
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
|
||||
__forceinline Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
|
||||
__forceinline Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
|
||||
__forceinline Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
|
||||
__forceinline Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
|
||||
__forceinline Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
|
||||
__forceinline Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
|
||||
__forceinline Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
|
||||
__forceinline const Vec3fa operator +( const Vec3fa& a, const Vec3fa& b ) { return _mm_add_ps(a.m128, b.m128); }
|
||||
__forceinline const Vec3fa operator -( const Vec3fa& a, const Vec3fa& b ) { return _mm_sub_ps(a.m128, b.m128); }
|
||||
__forceinline const Vec3fa operator *( const Vec3fa& a, const Vec3fa& b ) { return _mm_mul_ps(a.m128, b.m128); }
|
||||
__forceinline const Vec3fa operator *( const Vec3fa& a, const float b ) { return a * Vec3fa(b); }
|
||||
__forceinline const Vec3fa operator *( const float a, const Vec3fa& b ) { return Vec3fa(a) * b; }
|
||||
__forceinline const Vec3fa operator /( const Vec3fa& a, const Vec3fa& b ) { return _mm_div_ps(a.m128,b.m128); }
|
||||
__forceinline const Vec3fa operator /( const Vec3fa& a, const float b ) { return _mm_div_ps(a.m128,_mm_set1_ps(b)); }
|
||||
__forceinline const Vec3fa operator /( const float a, const Vec3fa& b ) { return _mm_div_ps(_mm_set1_ps(a),b.m128); }
|
||||
|
||||
__forceinline Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
|
||||
__forceinline Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
|
||||
__forceinline const Vec3fa min( const Vec3fa& a, const Vec3fa& b ) { return _mm_min_ps(a.m128,b.m128); }
|
||||
__forceinline const Vec3fa max( const Vec3fa& a, const Vec3fa& b ) { return _mm_max_ps(a.m128,b.m128); }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3fa mini(const Vec3fa& a, const Vec3fa& b) {
|
||||
const vint4 ai = _mm_castps_si128(a);
|
||||
const vint4 bi = _mm_castps_si128(b);
|
||||
const vint4 ci = _mm_min_epi32(ai,bi);
|
||||
const int4 ai = _mm_castps_si128(a);
|
||||
const int4 bi = _mm_castps_si128(b);
|
||||
const int4 ci = _mm_min_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3fa maxi(const Vec3fa& a, const Vec3fa& b) {
|
||||
const vint4 ai = _mm_castps_si128(a);
|
||||
const vint4 bi = _mm_castps_si128(b);
|
||||
const vint4 ci = _mm_max_epi32(ai,bi);
|
||||
const int4 ai = _mm_castps_si128(a);
|
||||
const int4 bi = _mm_castps_si128(b);
|
||||
const int4 ci = _mm_max_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
|
||||
__forceinline Vec3fa pow ( const Vec3fa& a, const float& b ) {
|
||||
return Vec3fa(powf(a.x,b),powf(a.y,b),powf(a.z,b));
|
||||
}
|
||||
|
||||
@@ -221,11 +202,6 @@ namespace embree
|
||||
__forceinline Vec3fa nmsub ( const Vec3fa& a, const Vec3fa& b, const Vec3fa& c) { return -a*b-c; }
|
||||
#endif
|
||||
|
||||
__forceinline Vec3fa madd ( const float a, const Vec3fa& b, const Vec3fa& c) { return madd(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa msub ( const float a, const Vec3fa& b, const Vec3fa& c) { return msub(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa nmadd ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmadd(Vec3fa(a),b,c); }
|
||||
__forceinline Vec3fa nmsub ( const float a, const Vec3fa& b, const Vec3fa& c) { return nmsub(Vec3fa(a),b,c); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -264,7 +240,7 @@ namespace embree
|
||||
return all(gt_mask(v,Vec3fa(-FLT_LARGE)) & lt_mask(v,Vec3fa(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const Vec3fa& a ) {
|
||||
__forceinline bool is_finite ( const Vec3fa& a ) {
|
||||
return all(ge_mask(a,Vec3fa(-FLT_MAX)) & le_mask(a,Vec3fa(+FLT_MAX)));
|
||||
}
|
||||
|
||||
@@ -282,56 +258,46 @@ namespace embree
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
|
||||
__forceinline Vec3fa cross ( const Vec3fa& a, const Vec3fa& b )
|
||||
{
|
||||
vfloat4 a0 = vfloat4(a);
|
||||
vfloat4 b0 = shuffle<1,2,0,3>(vfloat4(b));
|
||||
vfloat4 a1 = shuffle<1,2,0,3>(vfloat4(a));
|
||||
vfloat4 b1 = vfloat4(b);
|
||||
float4 a0 = float4(a);
|
||||
float4 b0 = shuffle<1,2,0,3>(float4(b));
|
||||
float4 a1 = shuffle<1,2,0,3>(float4(a));
|
||||
float4 b1 = float4(b);
|
||||
return Vec3fa(shuffle<1,2,0,3>(msub(a0,b0,a1*b1)));
|
||||
}
|
||||
|
||||
__forceinline float sqr_length ( const Vec3fa& a ) { return dot(a,a); }
|
||||
__forceinline float rcp_length ( const Vec3fa& a ) { return rsqrt(dot(a,a)); }
|
||||
__forceinline float rcp_length2( const Vec3fa& a ) { return rcp(dot(a,a)); }
|
||||
__forceinline float sqr_length( const Vec3fa& a ) { return dot(a,a); }
|
||||
__forceinline float length ( const Vec3fa& a ) { return sqrt(dot(a,a)); }
|
||||
__forceinline Vec3fa normalize( const Vec3fa& a ) { return a*rsqrt(dot(a,a)); }
|
||||
__forceinline float distance ( const Vec3fa& a, const Vec3fa& b ) { return length(a-b); }
|
||||
__forceinline float halfArea ( const Vec3fa& d ) { return madd(d.x,(d.y+d.z),d.y*d.z); }
|
||||
__forceinline float halfArea ( const Vec3fa& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
|
||||
__forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
|
||||
__forceinline Vec3fa reflect ( const Vec3fa& V, const Vec3fa& N ) { return 2.0f*dot(V,N)*N-V; }
|
||||
|
||||
__forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
|
||||
__forceinline Vec3fa normalize_safe( const Vec3fa& a ) {
|
||||
const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
|
||||
}
|
||||
|
||||
/*! differentiated normalization */
|
||||
__forceinline Vec3fa dnormalize(const Vec3fa& p, const Vec3fa& dp)
|
||||
{
|
||||
const float pp = dot(p,p);
|
||||
const float pdp = dot(p,dp);
|
||||
return (pp*dp-pdp*p)*rcp(pp)*rsqrt(pp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
__forceinline const Vec3fa select( bool s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
__m128 mask = s ? _mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())) : _mm_setzero_ps();
|
||||
return blendv_ps(f, t, mask);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
__forceinline const Vec3fa select( const Vec3ba& s, const Vec3fa& t, const Vec3fa& f ) {
|
||||
return blendv_ps(f, t, s);
|
||||
}
|
||||
|
||||
__forceinline int maxDim ( const Vec3fa& a )
|
||||
{
|
||||
const Vec3fa b = abs(a);
|
||||
if (b.x > b.y) {
|
||||
if (b.x > b.z) return 0; else return 2;
|
||||
__forceinline int maxDim ( const Vec3fa& a )
|
||||
{
|
||||
if (a.x > a.y) {
|
||||
if (a.x > a.z) return 0; else return 2;
|
||||
} else {
|
||||
if (b.y > b.z) return 1; else return 2;
|
||||
if (a.y > a.z) return 1; else return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,13 +306,13 @@ namespace embree
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined (__SSE4_1__)
|
||||
//__forceinline Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
|
||||
__forceinline Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
|
||||
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
|
||||
//__forceinline const Vec3fa trunc( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
|
||||
__forceinline const Vec3fa floor( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
|
||||
__forceinline const Vec3fa ceil ( const Vec3fa& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
|
||||
#else
|
||||
//__forceinline Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
|
||||
__forceinline Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
|
||||
__forceinline Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
|
||||
//__forceinline const Vec3fa trunc( const Vec3fa& a ) { return Vec3fa(truncf(a.x),truncf(a.y),truncf(a.z)); }
|
||||
__forceinline const Vec3fa floor( const Vec3fa& a ) { return Vec3fa(floorf(a.x),floorf(a.y),floorf(a.z)); }
|
||||
__forceinline const Vec3fa ceil ( const Vec3fa& a ) { return Vec3fa(ceilf (a.x),ceilf (a.y),ceilf (a.z)); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -356,6 +322,6 @@ namespace embree
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa& a) {
|
||||
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
|
||||
}
|
||||
|
||||
|
||||
typedef Vec3fa Vec3fa_t;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math.h"
|
||||
#include "../simd/avx512.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// MIC Vec3fa Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Vec3fa_t;
|
||||
|
||||
/* 3 aligned floats as memory representation */
|
||||
struct __aligned(16) Vec3fa
|
||||
{
|
||||
typedef float Scalar;
|
||||
enum { N = 3 };
|
||||
float x,y,z; union { int a; unsigned u; float w; };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa () {}
|
||||
__forceinline Vec3fa ( float x ) : x(x), y(x), z(x), a(0) {}
|
||||
__forceinline Vec3fa ( float x, float y, float z ) : x(x), y(y), z(z), a(0) {}
|
||||
__forceinline Vec3fa ( float x, float y, float z, float w ) : x(x), y(y), z(z), w(w) {}
|
||||
__forceinline Vec3fa ( const Vec3f & o ) : x(o.x), y(o.y), z(o.z), a(0) {}
|
||||
__forceinline Vec3fa ( const Vec3fa& other, const int other_a ) : x(other.x), y(other.y), z(other.z), a(other_a) {}
|
||||
|
||||
__forceinline Vec3fa ( const Vec3ia_t& other );
|
||||
__forceinline Vec3fa ( const Vec3fa_t& other );
|
||||
__forceinline Vec3fa& operator=( const Vec3fa_t& other );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa( ZeroTy ) : x(0.0f), y(0.0f), z(0.0f), a(0) {}
|
||||
__forceinline Vec3fa( OneTy ) : x(1.0f), y(1.0f), z(1.0f), a(0) {}
|
||||
__forceinline Vec3fa( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), a(0) {}
|
||||
__forceinline Vec3fa( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), a(0) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float& operator []( const size_t index ) const { assert(index <= 3); return (&x)[index]; }
|
||||
__forceinline float& operator []( const size_t index ) { assert(index <= 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
/*! 3-wide vectors emulated with 16-wide vectors. */
|
||||
struct __aligned(64) Vec3fa_t
|
||||
{
|
||||
__m512 m512;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
__forceinline Vec3fa_t( ) { m512 = _mm512_undefined(); }
|
||||
|
||||
__forceinline Vec3fa_t( const __m512 a ) : m512(a) {}
|
||||
__forceinline Vec3fa_t ( const Vec3fa_t& other ) { m512 = other.m512; }
|
||||
__forceinline Vec3fa_t& operator =( const Vec3fa_t& other ) { m512 = other.m512; return *this; }
|
||||
|
||||
__forceinline operator const __m512&( void ) const { return m512; }
|
||||
__forceinline operator __m512&( void ) { return m512; }
|
||||
|
||||
__forceinline operator const float16( void ) const { return float16(m512); }
|
||||
__forceinline operator float16( void ) { return float16(m512); }
|
||||
|
||||
public:
|
||||
__forceinline explicit Vec3fa_t ( float a )
|
||||
: m512(_mm512_set1_ps(a)) {}
|
||||
|
||||
__forceinline Vec3fa_t( const Vec3fa& other ) {
|
||||
m512 = _mm512_extload_ps(&other,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loading
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline Vec3fa_t loadu( const void* const a ) {
|
||||
const bool16 m_4f = 0xf;
|
||||
return (__m512)permute<0,0,0,0>(uload16f(m_4f,(float*)a));
|
||||
}
|
||||
|
||||
static __forceinline void storeu( void* const ptr, const Vec3fa_t& v ) // FIXME: implement fast version
|
||||
{
|
||||
((float*)ptr)[0] = ((float*)&v)[0];
|
||||
((float*)ptr)[1] = ((float*)&v)[1];
|
||||
((float*)ptr)[2] = ((float*)&v)[2];
|
||||
((float*)ptr)[3] = ((float*)&v)[3];
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia::Vec3ia ( const Vec3fa_t& other ) {
|
||||
__m512i i = _mm512_cvtfxpnt_round_adjustps_epi32(other,_MM_ROUND_MODE_NEAREST,_MM_EXPADJ_NONE);
|
||||
_mm512_mask_extpackstorelo_epi32(this,0xf,i,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa::Vec3fa( const Vec3ia_t& v ) {
|
||||
__m512 f = _mm512_cvtfxpnt_round_adjustepi32_ps(v,_MM_ROUND_MODE_NEAREST,_MM_EXPADJ_NONE);
|
||||
_mm512_mask_extpackstorelo_ps(this,0xf,f,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa::Vec3fa ( const Vec3fa_t& other ) {
|
||||
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa& Vec3fa::operator=( const Vec3fa_t& other ) {
|
||||
_mm512_mask_extpackstorelo_ps(this,0xf,other.m512,_MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3fa_t operator +( const Vec3fa_t& a ) { return a; }
|
||||
__forceinline const Vec3fa_t operator -( const Vec3fa_t& a ) { return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a.m512), _mm512_set1_epi32(0x80000000))); }
|
||||
__forceinline const Vec3fa_t abs ( const Vec3fa_t& a ) { return _mm512_gmaxabs_ps(a.m512,a.m512); }
|
||||
__forceinline const Vec3fa_t sign ( const Vec3fa_t& a ) { return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a,_mm512_setzero_ps(),_MM_CMPINT_LT), _mm512_set1_ps(1.0f), _mm512_set1_ps(-1.0f)); }
|
||||
|
||||
__forceinline const Vec3fa_t rcp ( const Vec3fa_t& a ) { return _mm512_rcp23_ps(a); }
|
||||
__forceinline const Vec3fa_t sqr ( const Vec3fa_t& a ) { return _mm512_mul_ps(a,a); }
|
||||
__forceinline const Vec3fa_t sqrt ( const Vec3fa_t& a ) { return _mm512_sqrt_ps(a.m512); }
|
||||
__forceinline const Vec3fa_t rsqrt( const Vec3fa_t& a ) { return _mm512_invsqrt_ps(a.m512); }
|
||||
__forceinline const Vec3fa_t zero_fix( const Vec3fa_t& a ) { return _mm512_mask_blend_ps(_mm512_cmp_ps_mask(a.m512,_mm512_setzero_ps(),_MM_CMPINT_EQ), a, _mm512_set1_ps(1E-10f)); }
|
||||
__forceinline const Vec3fa_t rcp_safe(const Vec3fa_t& a) { return rcp(zero_fix(a)); }
|
||||
|
||||
__forceinline Vec3fa log ( const Vec3fa& a ) {
|
||||
return Vec3fa(logf(a.x),logf(a.y),logf(a.z));
|
||||
}
|
||||
|
||||
__forceinline Vec3fa exp ( const Vec3fa& a ) {
|
||||
return Vec3fa(expf(a.x),expf(a.y),expf(a.z));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3fa_t operator +( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_add_ps(a.m512, b.m512); }
|
||||
__forceinline const Vec3fa_t operator -( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_sub_ps(a.m512, b.m512); }
|
||||
__forceinline const Vec3fa_t operator *( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_mul_ps(a.m512, b.m512); }
|
||||
__forceinline const Vec3fa_t operator *( const Vec3fa_t& a, const float b ) { return a * Vec3fa_t(b); }
|
||||
__forceinline const Vec3fa_t operator *( const float a, const Vec3fa_t& b ) { return Vec3fa_t(a) * b; }
|
||||
__forceinline const Vec3fa_t operator /( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_div_ps(a.m512,b.m512); }
|
||||
__forceinline const Vec3fa_t operator /( const Vec3fa_t& a, const float b ) { return _mm512_div_ps(a.m512,_mm512_set1_ps(b)); }
|
||||
__forceinline const Vec3fa_t operator /( const float a, const Vec3fa_t& b ) { return _mm512_div_ps(_mm512_set1_ps(a),b.m512); }
|
||||
|
||||
__forceinline const Vec3fa_t min( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_gmin_ps(a.m512,b.m512); }
|
||||
__forceinline const Vec3fa_t max( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_gmax_ps(a.m512,b.m512); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa_t madd ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fmadd_ps(a,b,c); }
|
||||
__forceinline Vec3fa_t msub ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fmsub_ps(a,b,c); }
|
||||
__forceinline Vec3fa_t nmadd ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fnmadd_ps(a,b,c); }
|
||||
__forceinline Vec3fa_t nmsub ( const Vec3fa_t& a, const Vec3fa_t& b, const Vec3fa_t& c) { return _mm512_fnmsub_ps(a,b,c); }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3fa& operator +=( Vec3fa& a, const Vec3fa_t& b ) { return a = a + b; }
|
||||
__forceinline Vec3fa& operator -=( Vec3fa& a, const Vec3fa_t& b ) { return a = a - b; }
|
||||
__forceinline Vec3fa& operator *=( Vec3fa& a, const float b ) { return a = a * b; }
|
||||
__forceinline Vec3fa& operator /=( Vec3fa& a, const float b ) { return a = a / b; }
|
||||
|
||||
__forceinline Vec3fa_t& operator +=( Vec3fa_t& a, const Vec3fa_t& b ) { return a = a + b; }
|
||||
__forceinline Vec3fa_t& operator *=( Vec3fa_t& a, const float b ) { return a = a * b; }
|
||||
__forceinline Vec3fa_t& operator /=( Vec3fa_t& a, const float b ) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float reduce_add(const Vec3fa_t& a) {
|
||||
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(0.0f));
|
||||
__m512 c = _mm512_add_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
|
||||
__m512 d = _mm512_add_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
|
||||
return _mm512_cvtss_f32(d);
|
||||
}
|
||||
|
||||
__forceinline float reduce_mul(const Vec3fa_t& a) {
|
||||
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(1.0f));
|
||||
__m512 c = _mm512_mul_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
|
||||
__m512 d = _mm512_mul_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
|
||||
return _mm512_cvtss_f32(d);
|
||||
}
|
||||
|
||||
__forceinline float reduce_min(const Vec3fa_t& a) {
|
||||
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(pos_inf));
|
||||
__m512 c = _mm512_gmin_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
|
||||
__m512 d = _mm512_gmin_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
|
||||
return _mm512_cvtss_f32(d);
|
||||
}
|
||||
|
||||
__forceinline float reduce_max(const Vec3fa_t& a) {
|
||||
__m512 b = _mm512_mask_blend_ps(0x8,a.m512,_mm512_set1_ps(neg_inf));
|
||||
__m512 c = _mm512_gmax_ps(b, _mm512_swizzle_ps(b, _MM_SWIZ_REG_BADC));
|
||||
__m512 d = _mm512_gmax_ps(c, _mm512_swizzle_ps(c, _MM_SWIZ_REG_CDAB));
|
||||
return _mm512_cvtss_f32(d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3fa_t& a, const Vec3fa_t& b ) { return (_mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ) & 7) == 7; }
|
||||
__forceinline bool operator !=( const Vec3fa_t& a, const Vec3fa_t& b ) { return (_mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE) & 7) != 0; }
|
||||
|
||||
__forceinline Vec3ba eq_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
|
||||
__forceinline Vec3ba neq_mask(const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
|
||||
__forceinline Vec3ba lt_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
|
||||
__forceinline Vec3ba le_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
|
||||
__forceinline Vec3ba gt_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
|
||||
__forceinline Vec3ba ge_mask( const Vec3fa_t& a, const Vec3fa_t& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
|
||||
|
||||
__forceinline bool isvalid ( const Vec3fa& v ) {
|
||||
return all(gt_mask(v,Vec3fa_t(-FLT_LARGE)) & lt_mask(v,Vec3fa_t(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float dot ( const Vec3fa_t& a, const Vec3fa_t& b ) {
|
||||
return reduce_add(a*b);
|
||||
}
|
||||
|
||||
__forceinline Vec3fa_t cross ( const Vec3fa_t& a, const Vec3fa_t& b )
|
||||
{
|
||||
__m512 c = _mm512_mul_ps(b,_mm512_swizzle_ps(a,_MM_SWIZ_REG_DACB));
|
||||
c = _mm512_fmsub_ps(_mm512_swizzle_ps(b,_MM_SWIZ_REG_DACB),a,c);
|
||||
c = _mm512_swizzle_ps(c,_MM_SWIZ_REG_DACB);
|
||||
return c;
|
||||
}
|
||||
|
||||
__forceinline float length ( const Vec3fa_t& a ) { return sqrt(dot(a,a)); }
|
||||
__forceinline Vec3fa_t normalize( const Vec3fa_t& a ) { return a*rsqrt(dot(a,a)); }
|
||||
__forceinline float distance ( const Vec3fa_t& a, const Vec3fa_t& b ) { return length(a-b); }
|
||||
__forceinline float halfArea ( const Vec3fa& d ) { return d.x*(d.y+d.z)+d.y*d.z; }
|
||||
__forceinline float area ( const Vec3fa& d ) { return 2.0f*halfArea(d); }
|
||||
__forceinline Vec3fa_t reflect ( const Vec3fa_t& V, const Vec3fa_t& N ) { return 2.0f*dot(V,N)*N-V; }
|
||||
|
||||
__forceinline Vec3fa_t normalize_safe( const Vec3fa_t& a ) {
|
||||
const float d = dot(a,a); if (unlikely(d == 0.0f)) return a; else return a*rsqrt(d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3fa_t select( bool s, const Vec3fa_t& t, const Vec3fa_t& f ) {
|
||||
return _mm512_mask_blend_ps(s ? 0xF : 0x0, f, t);
|
||||
}
|
||||
|
||||
__forceinline const Vec3fa_t select( const Vec3ba& s, const Vec3fa_t& t, const Vec3fa_t& f ) {
|
||||
return _mm512_mask_blend_ps(s, f, t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa& a) {
|
||||
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ", " << a.w << ")";
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3fa_t& a) {
|
||||
const float * const f = (float*)&a.m512;
|
||||
return cout << "(" << f[0] << ", " << f[1] << ", " << f[2] << ", " << f[3] << ")";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+34
-38
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../sys/alloc.h"
|
||||
#include "math.h"
|
||||
#include "../simd/sse.h"
|
||||
|
||||
@@ -28,8 +27,6 @@ namespace embree
|
||||
|
||||
struct __aligned(16) Vec3ia
|
||||
{
|
||||
ALIGNED_STRUCT;
|
||||
|
||||
union {
|
||||
__m128i m128;
|
||||
struct { int x,y,z; int a; };
|
||||
@@ -48,11 +45,11 @@ namespace embree
|
||||
__forceinline Vec3ia& operator =(const Vec3ia& other) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline explicit Vec3ia( const int a ) : m128(_mm_set1_epi32(a)) {}
|
||||
__forceinline Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
|
||||
__forceinline explicit Vec3ia( const int x, const int y, const int z) : m128(_mm_set_epi32(z, z, y, x)) {}
|
||||
__forceinline explicit Vec3ia( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
|
||||
|
||||
__forceinline operator const __m128i&() const { return m128; }
|
||||
__forceinline operator __m128i&() { return m128; }
|
||||
__forceinline operator const __m128i&( void ) const { return m128; }
|
||||
__forceinline operator __m128i&( void ) { return m128; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
@@ -76,48 +73,47 @@ namespace embree
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a ) { return a; }
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
|
||||
__forceinline const Vec3ia operator +( const Vec3ia& a ) { return a; }
|
||||
__forceinline const Vec3ia operator -( const Vec3ia& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
|
||||
#if defined(__SSSE3__)
|
||||
__forceinline Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
|
||||
__forceinline const Vec3ia abs ( const Vec3ia& a ) { return _mm_abs_epi32(a.m128); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
|
||||
__forceinline Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
|
||||
__forceinline const Vec3ia operator +( const Vec3ia& a, const Vec3ia& b ) { return _mm_add_epi32(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator +( const Vec3ia& a, const int b ) { return a+Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator +( const int a, const Vec3ia& b ) { return Vec3ia(a)+b; }
|
||||
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
|
||||
__forceinline Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
|
||||
__forceinline const Vec3ia operator -( const Vec3ia& a, const Vec3ia& b ) { return _mm_sub_epi32(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator -( const Vec3ia& a, const int b ) { return a-Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator -( const int a, const Vec3ia& b ) { return Vec3ia(a)-b; }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
|
||||
__forceinline Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
|
||||
__forceinline const Vec3ia operator *( const Vec3ia& a, const Vec3ia& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator *( const Vec3ia& a, const int b ) { return a * Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator *( const int a, const Vec3ia& b ) { return Vec3ia(a) * b; }
|
||||
#endif
|
||||
|
||||
__forceinline Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
|
||||
__forceinline Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
|
||||
__forceinline const Vec3ia operator &( const Vec3ia& a, const Vec3ia& b ) { return _mm_and_si128(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator &( const Vec3ia& a, const int b ) { return a & Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator &( const int a, const Vec3ia& b ) { return Vec3ia(a) & b; }
|
||||
|
||||
__forceinline Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
|
||||
__forceinline Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
|
||||
__forceinline const Vec3ia operator |( const Vec3ia& a, const Vec3ia& b ) { return _mm_or_si128(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator |( const Vec3ia& a, const int b ) { return a | Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator |( const int a, const Vec3ia& b ) { return Vec3ia(a) | b; }
|
||||
|
||||
__forceinline Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
|
||||
__forceinline Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
|
||||
__forceinline Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
|
||||
__forceinline const Vec3ia operator ^( const Vec3ia& a, const Vec3ia& b ) { return _mm_xor_si128(a.m128, b.m128); }
|
||||
__forceinline const Vec3ia operator ^( const Vec3ia& a, const int b ) { return a ^ Vec3ia(b); }
|
||||
__forceinline const Vec3ia operator ^( const int a, const Vec3ia& b ) { return Vec3ia(a) ^ b; }
|
||||
|
||||
__forceinline Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
|
||||
__forceinline Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
|
||||
__forceinline const Vec3ia operator <<( const Vec3ia& a, const int n ) { return _mm_slli_epi32(a.m128, n); }
|
||||
__forceinline const Vec3ia operator >>( const Vec3ia& a, const int n ) { return _mm_srai_epi32(a.m128, n); }
|
||||
|
||||
__forceinline Vec3ia sll ( const Vec3ia& a, const int b ) { return _mm_slli_epi32(a.m128, b); }
|
||||
__forceinline Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
|
||||
__forceinline Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
|
||||
__forceinline const Vec3ia sra ( const Vec3ia& a, const int b ) { return _mm_srai_epi32(a.m128, b); }
|
||||
__forceinline const Vec3ia srl ( const Vec3ia& a, const int b ) { return _mm_srli_epi32(a.m128, b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
@@ -173,7 +169,7 @@ namespace embree
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
|
||||
__forceinline const Vec3ia select( const Vec3ba& m, const Vec3ia& t, const Vec3ia& f ) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
|
||||
#else
|
||||
@@ -182,11 +178,11 @@ namespace embree
|
||||
}
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
|
||||
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
|
||||
__forceinline const Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return _mm_min_epi32(a.m128,b.m128); }
|
||||
__forceinline const Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return _mm_max_epi32(a.m128,b.m128); }
|
||||
#else
|
||||
__forceinline Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
|
||||
__forceinline Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
|
||||
__forceinline const Vec3ia min( const Vec3ia& a, const Vec3ia& b ) { return select(lt_mask(a,b),a,b); }
|
||||
__forceinline const Vec3ia max( const Vec3ia& a, const Vec3ia& b ) { return select(gt_mask(a,b),a,b); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "math.h"
|
||||
#include "../simd/avx512.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// MIC Vec3ia Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Vec3ia_t;
|
||||
struct Vec3fa_t;
|
||||
|
||||
/* 3 aligned ints as memory representation */
|
||||
struct __aligned(16) Vec3ia
|
||||
{
|
||||
typedef int Scalar;
|
||||
enum { N = 3 };
|
||||
struct { int x,y,z; int a; };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia ( ) {}
|
||||
__forceinline Vec3ia ( int x ) : x(x), y(x), z(x), a(0) {}
|
||||
__forceinline Vec3ia ( int x, int y, int z ) : x(x), y(y), z(z), a(0) {}
|
||||
|
||||
__forceinline Vec3ia ( const Vec3fa_t& other );
|
||||
__forceinline Vec3ia ( const Vec3ia_t& other );
|
||||
__forceinline Vec3ia& operator=( const Vec3ia_t& other );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia( ZeroTy ) : x(0), y(0), z(0), a(0) {}
|
||||
__forceinline Vec3ia( OneTy ) : x(1), y(1), z(1), a(1) {}
|
||||
__forceinline Vec3ia( PosInfTy ) : x(pos_inf), y(pos_inf), z(pos_inf), a(pos_inf) {}
|
||||
__forceinline Vec3ia( NegInfTy ) : x(neg_inf), y(neg_inf), z(neg_inf), a(neg_inf) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int& operator []( const size_t index ) const { assert(index < 3); return (&x)[index]; }
|
||||
__forceinline int& operator []( const size_t index ) { assert(index < 3); return (&x)[index]; }
|
||||
};
|
||||
|
||||
/*! 3-wide vectors emulated with 16-wide vectors. */
|
||||
struct __aligned(64) Vec3ia_t
|
||||
{
|
||||
__m512i m512;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia_t ( const __m512i a ) : m512(a) {}
|
||||
__forceinline Vec3ia_t ( const Vec3ia_t& other ) { m512 = other.m512; }
|
||||
__forceinline Vec3ia_t& operator =( const Vec3ia_t& other ) { m512 = other.m512; return *this; }
|
||||
|
||||
__forceinline operator const __m512i&( void ) const { return m512; }
|
||||
__forceinline operator __m512i&( void ) { return m512; }
|
||||
|
||||
public:
|
||||
__forceinline explicit Vec3ia_t ( int a )
|
||||
: m512(_mm512_set1_epi32(a)) {}
|
||||
|
||||
__forceinline Vec3ia_t( const Vec3ia& other ) {
|
||||
m512 = _mm512_extload_epi32(&other,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia::Vec3ia ( const Vec3ia_t& other ) {
|
||||
_mm512_mask_extpackstorelo_epi32(this,0xf,other.m512,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline Vec3ia& Vec3ia::operator=( const Vec3ia_t& other ) {
|
||||
_mm512_mask_extpackstorelo_epi32(this,0xf,other.m512,_MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a ) { return a; }
|
||||
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a ) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a.m512); }
|
||||
//__forceinline const Vec3ia_t abs ( const Vec3ia_t& a ) { return _mm512_abs_epi32(a.m512); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_add_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator +( const Vec3ia_t& a, const int b ) { return a+Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator +( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a)+b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_sub_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator -( const Vec3ia_t& a, const int b ) { return a-Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator -( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a)-b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator *( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_mullo_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator *( const Vec3ia_t& a, const int b ) { return a * Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator *( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) * b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator &( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_and_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator &( const Vec3ia_t& a, const int b ) { return a & Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator &( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) & b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator |( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_or_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator |( const Vec3ia_t& a, const int b ) { return a | Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator |( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) | b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator ^( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_xor_epi32(a.m512, b.m512); }
|
||||
__forceinline const Vec3ia_t operator ^( const Vec3ia_t& a, const int b ) { return a ^ Vec3ia_t(b); }
|
||||
__forceinline const Vec3ia_t operator ^( const int a, const Vec3ia_t& b ) { return Vec3ia_t(a) ^ b; }
|
||||
|
||||
__forceinline const Vec3ia_t operator <<( const Vec3ia_t& a, const int n ) { return _mm512_slli_epi32(a.m512, n); }
|
||||
__forceinline const Vec3ia_t operator >>( const Vec3ia_t& a, const int n ) { return _mm512_srai_epi32(a.m512, n); }
|
||||
|
||||
__forceinline const Vec3ia_t sra ( const Vec3ia_t& a, const int b ) { return _mm512_srai_epi32(a.m512, b); }
|
||||
__forceinline const Vec3ia_t srl ( const Vec3ia_t& a, const int b ) { return _mm512_srli_epi32(a.m512, b); }
|
||||
|
||||
__forceinline const Vec3ia_t min( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_min_epi32(a.m512,b.m512); }
|
||||
__forceinline const Vec3ia_t max( const Vec3ia_t& a, const Vec3ia_t& b ) { return _mm512_max_epi32(a.m512,b.m512); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3ia& operator +=( Vec3ia& a, const Vec3ia_t& b ) { return a = a + b; }
|
||||
__forceinline Vec3ia& operator +=( Vec3ia& a, const int& b ) { return a = a + b; }
|
||||
|
||||
__forceinline Vec3ia& operator -=( Vec3ia& a, const Vec3ia_t& b ) { return a = a - b; }
|
||||
__forceinline Vec3ia& operator -=( Vec3ia& a, const int& b ) { return a = a - b; }
|
||||
|
||||
__forceinline Vec3ia& operator *=( Vec3ia& a, const Vec3ia_t& b ) { return a = a * b; }
|
||||
__forceinline Vec3ia& operator *=( Vec3ia& a, const int& b ) { return a = a * b; }
|
||||
|
||||
__forceinline Vec3ia& operator &=( Vec3ia& a, const Vec3ia_t& b ) { return a = a & b; }
|
||||
__forceinline Vec3ia& operator &=( Vec3ia& a, const int& b ) { return a = a & b; }
|
||||
|
||||
__forceinline Vec3ia& operator |=( Vec3ia& a, const Vec3ia_t& b ) { return a = a | b; }
|
||||
__forceinline Vec3ia& operator |=( Vec3ia& a, const int& b ) { return a = a | b; }
|
||||
|
||||
__forceinline Vec3ia& operator <<=( Vec3ia& a, const int& b ) { return a = a << b; }
|
||||
__forceinline Vec3ia& operator >>=( Vec3ia& a, const int& b ) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int reduce_add(const Vec3ia_t& a) {
|
||||
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(0));
|
||||
__m512i c = _mm512_add_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
|
||||
__m512i d = _mm512_add_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
|
||||
return *(int*)&d;
|
||||
}
|
||||
|
||||
__forceinline int reduce_mul(const Vec3ia_t& a) {
|
||||
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(1));
|
||||
__m512i c = _mm512_mullo_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
|
||||
__m512i d = _mm512_mullo_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
|
||||
return *(int*)&d;
|
||||
}
|
||||
|
||||
__forceinline int reduce_min(const Vec3ia_t& a) {
|
||||
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(pos_inf));
|
||||
__m512i c = _mm512_min_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
|
||||
__m512i d = _mm512_min_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
|
||||
return *(int*)&d;
|
||||
}
|
||||
|
||||
__forceinline int reduce_max(const Vec3ia_t& a) {
|
||||
__m512i b = _mm512_mask_blend_epi32(0x8,a.m512,_mm512_set1_epi32(neg_inf));
|
||||
__m512i c = _mm512_max_epi32(b, _mm512_swizzle_epi32(b, _MM_SWIZ_REG_BADC));
|
||||
__m512i d = _mm512_max_epi32(c, _mm512_swizzle_epi32(c, _MM_SWIZ_REG_CDAB));
|
||||
return *(int*)&d;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator ==( const Vec3ia_t& a, const Vec3ia_t& b ) { return (_mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ) & 7) == 7; }
|
||||
__forceinline bool operator !=( const Vec3ia_t& a, const Vec3ia_t& b ) { return (_mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE) & 7) != 0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const Vec3ia_t select( bool s, const Vec3ia_t& t, const Vec3ia_t& f ) {
|
||||
return _mm512_mask_blend_epi32(s ? 0xF : 0x0, f, t);
|
||||
}
|
||||
|
||||
__forceinline const Vec3ia_t select( const Vec3ba& s, const Vec3ia_t& t, const Vec3ia_t& f ) {
|
||||
return _mm512_mask_blend_epi32(s, f, t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const Vec3ia& a) {
|
||||
return cout << "(" << a.x << ", " << a.y << ", " << a.z << ")";
|
||||
}
|
||||
}
|
||||
+33
-78
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -17,7 +17,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "math.h"
|
||||
#include "vec3.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
@@ -36,19 +35,16 @@ namespace embree
|
||||
/// Construction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec4( ) {}
|
||||
__forceinline Vec4 ( ) { }
|
||||
__forceinline explicit Vec4( const T& a ) : x(a), y(a), z(a), w(a) {}
|
||||
__forceinline Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
|
||||
__forceinline Vec4( const Vec3<T>& xyz, const T& w ) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
|
||||
__forceinline explicit Vec4( const T& x, const T& y, const T& z, const T& w ) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
__forceinline Vec4( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
|
||||
__forceinline Vec4( const Vec3fa& other );
|
||||
__forceinline Vec4 ( const Vec4& other ) { x = other.x; y = other.y; z = other.z; w = other.w; }
|
||||
__forceinline Vec4 ( const Vec3fa& other );
|
||||
|
||||
template<typename T1> __forceinline Vec4( const Vec4<T1>& a ) : x(T(a.x)), y(T(a.y)), z(T(a.z)), w(T(a.w)) {}
|
||||
template<typename T1> __forceinline Vec4& operator =(const Vec4<T1>& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
|
||||
|
||||
__forceinline operator Vec3<T> () const { return Vec3<T>(x,y,z); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -60,12 +56,6 @@ namespace embree
|
||||
|
||||
__forceinline const T& operator []( const size_t axis ) const { assert(axis < 4); return (&x)[axis]; }
|
||||
__forceinline T& operator []( const size_t axis ) { assert(axis < 4); return (&x)[axis]; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Swizzles
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline Vec3<T> xyz() const { return Vec3<T>(x, y, z); }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -95,20 +85,6 @@ namespace embree
|
||||
template<typename T> __forceinline Vec4<T> min(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w)); }
|
||||
template<typename T> __forceinline Vec4<T> max(const Vec4<T>& a, const Vec4<T>& b) { return Vec4<T>(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec4<T> madd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y), madd(a.z,b.z,c.z), madd(a.w,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> msub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y), msub(a.z,b.z,c.z), msub(a.w,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> nmadd ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y),nmadd(a.z,b.z,c.z),nmadd(a.w,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> nmsub ( const Vec4<T>& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y),nmsub(a.z,b.z,c.z),nmsub(a.w,b.w,c.w)); }
|
||||
|
||||
template<typename T> __forceinline Vec4<T> madd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( madd(a,b.x,c.x), madd(a,b.y,c.y), madd(a,b.z,c.z), madd(a,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> msub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>( msub(a,b.x,c.x), msub(a,b.y,c.y), msub(a,b.z,c.z), msub(a,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> nmadd ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y),nmadd(a,b.z,c.z),nmadd(a,b.w,c.w)); }
|
||||
template<typename T> __forceinline Vec4<T> nmsub ( const T& a, const Vec4<T>& b, const Vec4<T>& c) { return Vec4<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y),nmsub(a,b.z,c.z),nmsub(a,b.w,c.w)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -141,14 +117,6 @@ namespace embree
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Shift Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> __forceinline Vec4<T> shift_right_1( const Vec4<T>& a ) {
|
||||
return Vec4<T>(shift_right_1(a.x),shift_right_1(a.y),shift_right_1(a.z),shift_right_1(a.w));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -167,19 +135,6 @@ namespace embree
|
||||
return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline Vec4<T> select ( const Vec4<bool>& s, const Vec4<T>& t, const Vec4<T>& f ) {
|
||||
return Vec4<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y),select(s.z,t.z,f.z),select(s.w,t.w,f.w));
|
||||
}
|
||||
|
||||
template<typename T> __forceinline Vec4<T> select ( const typename T::Bool& s, const Vec4<T>& t, const Vec4<T>& f ) {
|
||||
return Vec4<T>(select(s,t.x,f.x),select(s,t.y,f.y),select(s,t.z,f.z),select(s,t.w,f.w));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
__forceinline Vec4<T> lerp(const Vec4<T>& v0, const Vec4<T>& v1, const T& t) {
|
||||
return madd(Vec4<T>(T(1.0f)-t),v0,t*v1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -198,9 +153,15 @@ namespace embree
|
||||
typedef Vec4<float > Vec4f;
|
||||
}
|
||||
|
||||
#include "vec3ba.h"
|
||||
#include "vec3ia.h"
|
||||
#include "vec3fa.h"
|
||||
#if defined(__MIC__)
|
||||
#include "vec3ba_mic.h"
|
||||
#include "vec3ia_mic.h"
|
||||
#include "vec3fa_mic.h"
|
||||
#else
|
||||
#include "vec3ba.h"
|
||||
#include "vec3ia.h"
|
||||
#include "vec3fa.h"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// SSE / AVX / MIC specializations
|
||||
@@ -214,46 +175,40 @@ namespace embree
|
||||
#include "../simd/avx.h"
|
||||
#endif
|
||||
|
||||
#if defined __AVX512F__
|
||||
#if defined __MIC__
|
||||
#include "../simd/avx512.h"
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace embree
|
||||
{
|
||||
template<> __forceinline Vec4<float>::Vec4( const Vec3fa& a ) { x = a.x; y = a.y; z = a.z; w = a.w; }
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fa& a ) {
|
||||
x = a.x; y = a.y; z = a.z; w = a.w;
|
||||
#if defined (__SSE__)
|
||||
template<> __forceinline Vec4<float4>::Vec4( const Vec3fa& a ) {
|
||||
const float4 v = float4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
|
||||
}
|
||||
#elif defined(__SSE__)
|
||||
template<> __forceinline Vec4<vfloat4>::Vec4( const Vec3fa& a ) {
|
||||
const vfloat4 v = vfloat4(a); x = shuffle<0,0,0,0>(v); y = shuffle<1,1,1,1>(v); z = shuffle<2,2,2,2>(v); w = shuffle<3,3,3,3>(v);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE__)
|
||||
__forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat4>& a, const size_t k ) {
|
||||
return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
|
||||
__forceinline Vec4<float4> broadcast4f( const Vec4<float4>& a, const size_t k ) {
|
||||
return Vec4<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]), float4::broadcast(&a.w[k]));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__AVX__)
|
||||
template<> __forceinline Vec4<vfloat8>::Vec4( const Vec3fa& a ) {
|
||||
x = a.x; y = a.y; z = a.z; w = a.w;
|
||||
template<> __forceinline Vec4<float8>::Vec4( const Vec3fa& a ) {
|
||||
x = a.x; y = a.y; z = a.z; w = a.w;
|
||||
}
|
||||
__forceinline Vec4<vfloat4> broadcast4f( const Vec4<vfloat8>& a, const size_t k ) {
|
||||
return Vec4<vfloat4>(vfloat4::broadcast(&a.x[k]), vfloat4::broadcast(&a.y[k]), vfloat4::broadcast(&a.z[k]), vfloat4::broadcast(&a.w[k]));
|
||||
__forceinline Vec4<float4> broadcast4f( const Vec4<float8>& a, const size_t k ) {
|
||||
return Vec4<float4>(float4::broadcast(&a.x[k]), float4::broadcast(&a.y[k]), float4::broadcast(&a.z[k]), float4::broadcast(&a.w[k]));
|
||||
}
|
||||
__forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat4>& a, const size_t k ) {
|
||||
return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
|
||||
__forceinline Vec4<float8> broadcast8f( const Vec4<float4>& a, const size_t k ) {
|
||||
return Vec4<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]), float8::broadcast(&a.w[k]));
|
||||
}
|
||||
__forceinline Vec4<vfloat8> broadcast8f( const Vec4<vfloat8>& a, const size_t k ) {
|
||||
return Vec4<vfloat8>(vfloat8::broadcast(&a.x[k]), vfloat8::broadcast(&a.y[k]), vfloat8::broadcast(&a.z[k]), vfloat8::broadcast(&a.w[k]));
|
||||
__forceinline Vec4<float8> broadcast8f( const Vec4<float8>& a, const size_t k ) {
|
||||
return Vec4<float8>(float8::broadcast(&a.x[k]), float8::broadcast(&a.y[k]), float8::broadcast(&a.z[k]), float8::broadcast(&a.w[k]));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
template<> __forceinline Vec4<vfloat16>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
|
||||
#if defined(__MIC__)
|
||||
//template<> __forceinline Vec4<float4>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
|
||||
template<> __forceinline Vec4<float16>::Vec4( const Vec3fa& a ) : x(a.x), y(a.y), z(a.z), w(a.w) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## ======================================================================== ##
|
||||
## Copyright 2009-2017 Intel Corporation ##
|
||||
## Copyright 2009-2015 Intel Corporation ##
|
||||
## ##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License"); ##
|
||||
## you may not use this file except in compliance with the License. ##
|
||||
@@ -14,6 +14,11 @@
|
||||
## limitations under the License. ##
|
||||
## ======================================================================== ##
|
||||
|
||||
ADD_LIBRARY(simd STATIC sse.cpp)
|
||||
SET_PROPERTY(TARGET simd PROPERTY FOLDER common)
|
||||
IF (__XEON__)
|
||||
ADD_LIBRARY(simd STATIC sse.cpp)
|
||||
SET_PROPERTY(TARGET simd PROPERTY FOLDER common)
|
||||
ELSE ()
|
||||
INCLUDE(icc_xeonphi)
|
||||
ADD_LIBRARY(simd_xeonphi STATIC bool16_avx512.cpp)
|
||||
ENDIF ()
|
||||
|
||||
|
||||
+13
-19
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -18,28 +18,22 @@
|
||||
|
||||
#include "sse.h"
|
||||
|
||||
#if defined(__AVX512VL__)
|
||||
#include "vboolf8_avx512.h"
|
||||
#include "vboold4_avx512.h"
|
||||
#else
|
||||
#include "vboolf8_avx.h"
|
||||
#include "vboold4_avx.h"
|
||||
#endif
|
||||
namespace embree
|
||||
{
|
||||
struct bool8;
|
||||
struct int8;
|
||||
struct float8;
|
||||
}
|
||||
|
||||
#if defined(__AVX2__)
|
||||
#include "vint8_avx2.h"
|
||||
#if defined(__X86_64__)
|
||||
#include "vllong4_avx2.h"
|
||||
#endif
|
||||
#include "bool8_avx.h"
|
||||
#if defined (__AVX2__)
|
||||
#include "int8_avx2.h"
|
||||
#else
|
||||
#include "vint8_avx.h"
|
||||
#endif
|
||||
#include "vfloat8_avx.h"
|
||||
#if defined(__X86_64__)
|
||||
#include "vdouble4_avx.h"
|
||||
#include "int8_avx.h"
|
||||
#endif
|
||||
#include "float8_avx.h"
|
||||
|
||||
#if defined(__AVX512F__)
|
||||
#if defined (__AVX512F__)
|
||||
#include "avx512.h"
|
||||
#endif
|
||||
|
||||
|
||||
+89
-9
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -19,16 +19,25 @@
|
||||
#include "../sys/platform.h"
|
||||
#include "../sys/intrinsics.h"
|
||||
#include "../math/constants.h"
|
||||
#include "varying.h"
|
||||
//#include "sse_mic.h"
|
||||
|
||||
#include "vboolf16_avx512.h"
|
||||
#include "vint16_avx512.h"
|
||||
#include "vfloat16_avx512.h"
|
||||
#include <zmmintrin.h>
|
||||
|
||||
#include "vuint16_avx512.h"
|
||||
#include "vboold8_avx512.h"
|
||||
#include "vllong8_avx512.h"
|
||||
#include "vdouble8_avx512.h"
|
||||
#define _MM_SHUF_PERM(e3, e2, e1, e0) \
|
||||
((_MM_PERM_ENUM)((e3)*64 + (e2)*16 + (e1)*4 + (e0)))
|
||||
|
||||
#define _MM_SHUF_PERM_NONE _MM_SHUF_PERM(3,2,1,0)
|
||||
|
||||
namespace embree
|
||||
{
|
||||
class bool16;
|
||||
class int16;
|
||||
class float16;
|
||||
}
|
||||
|
||||
#include "bool16_avx512.h"
|
||||
#include "int16_avx512.h"
|
||||
#include "float16_avx512.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
@@ -39,6 +48,9 @@ namespace embree
|
||||
#define PFHINT_L1 0
|
||||
#define PFHINT_L2 1
|
||||
#define PFHINT_NT 2
|
||||
#define PFHINT_L1EX 3
|
||||
#define PFHINT_L2EX 4
|
||||
#define PFHINT_NTEX 5
|
||||
|
||||
template<const unsigned int mode>
|
||||
__forceinline void prefetch(const void * __restrict__ const m)
|
||||
@@ -49,5 +61,73 @@ namespace embree
|
||||
_mm_prefetch((const char*)m,_MM_HINT_T1);
|
||||
else if (mode == PFHINT_NT)
|
||||
_mm_prefetch((const char*)m,_MM_HINT_NTA);
|
||||
else if (mode == PFHINT_L1EX)
|
||||
_mm_prefetch((const char*)m,_MM_HINT_ET0);
|
||||
else if (mode == PFHINT_L2EX)
|
||||
_mm_prefetch((const char*)m,_MM_HINT_ET2);
|
||||
else if (mode == PFHINT_NTEX)
|
||||
_mm_prefetch((const char*)m,_MM_HINT_ENTA);
|
||||
}
|
||||
|
||||
__forceinline void gather_prefetch(const bool16 &m_active,
|
||||
const void *const ptr,
|
||||
const int16 index,
|
||||
const int mode = _MM_HINT_T2,
|
||||
const _MM_INDEX_SCALE_ENUM scale = _MM_SCALE_4,
|
||||
const _MM_UPCONV_PS_ENUM up = _MM_UPCONV_PS_NONE)
|
||||
{
|
||||
_mm512_mask_prefetch_i32extgather_ps(index,m_active,ptr,up,scale,mode);
|
||||
}
|
||||
|
||||
__forceinline void scatter_prefetch(const bool16 &m_active,
|
||||
void *const ptr,
|
||||
const int16 index,
|
||||
const int mode = _MM_HINT_ET2,
|
||||
const _MM_INDEX_SCALE_ENUM scale = _MM_SCALE_4,
|
||||
const _MM_UPCONV_PS_ENUM up = _MM_UPCONV_PS_NONE)
|
||||
{
|
||||
_mm512_mask_prefetch_i32extscatter_ps(ptr,m_active,index,up,scale,mode);
|
||||
}
|
||||
|
||||
|
||||
#if !defined(_MM_SHUF_PERM)
|
||||
#define _MM_SHUF_PERM(e3, e2, e1, e0) ((_MM_PERM_ENUM)((e3)*64 + (e2)*16 + (e1)*4 + (e0)))
|
||||
#define _MM_SHUF_PERM_NONE _MM_SHUF_PERM(3,2,1,0)
|
||||
#endif
|
||||
|
||||
template<const int D, const int C, const int B, const int A>
|
||||
__forceinline float16 lshuf(const float16 &in)
|
||||
{
|
||||
return _mm512_permute4f128_ps(in,(_MM_PERM_ENUM)_MM_SHUF_PERM(D,C,B,A));
|
||||
}
|
||||
|
||||
|
||||
template<const int D, const int C, const int B, const int A>
|
||||
__forceinline float16 lshuf(const bool16 &mask, float16 &dest, const float16 &in)
|
||||
{
|
||||
return _mm512_mask_permute4f128_ps(dest,mask,in,(_MM_PERM_ENUM) _MM_SHUF_PERM(D,C,B,A));
|
||||
}
|
||||
|
||||
template<const int lane>
|
||||
__forceinline float16 lane_shuffle_gather(const float16 &v0,const float16 &v1,const float16 &v2,const float16 &v3)
|
||||
{
|
||||
float16 t = lshuf<lane,lane,lane,lane>(v0);
|
||||
t = lshuf<lane,lane,lane,lane>(0xf0,t,v1);
|
||||
t = lshuf<lane,lane,lane,lane>(0xf00,t,v2);
|
||||
t = lshuf<lane,lane,lane,lane>(0xf000,t,v3);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* __forceinline float16 convert(const float4 &v) */
|
||||
/* { */
|
||||
/* return broadcast4to16f(&v); */
|
||||
/* } */
|
||||
|
||||
__forceinline int16 mul_uint64_t( const int16& a, const int16& b) {
|
||||
const int16 low = _mm512_mullo_epi32(a, b);
|
||||
const int16 high = _mm512_mulhi_epu32(a, b);
|
||||
return select(0x5555,low,high);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#include "avx512.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
|
||||
__aligned(64) unsigned int bool16::shift1[32] = {
|
||||
((unsigned int)1 << 0),
|
||||
((unsigned int)1 << 1),
|
||||
((unsigned int)1 << 2),
|
||||
((unsigned int)1 << 3),
|
||||
((unsigned int)1 << 4),
|
||||
((unsigned int)1 << 5),
|
||||
((unsigned int)1 << 6),
|
||||
((unsigned int)1 << 7),
|
||||
((unsigned int)1 << 8),
|
||||
((unsigned int)1 << 9),
|
||||
((unsigned int)1 << 10),
|
||||
((unsigned int)1 << 11),
|
||||
((unsigned int)1 << 12),
|
||||
((unsigned int)1 << 13),
|
||||
((unsigned int)1 << 14),
|
||||
((unsigned int)1 << 15),
|
||||
((unsigned int)1 << 16),
|
||||
((unsigned int)1 << 17),
|
||||
((unsigned int)1 << 18),
|
||||
((unsigned int)1 << 19),
|
||||
((unsigned int)1 << 20),
|
||||
((unsigned int)1 << 21),
|
||||
((unsigned int)1 << 22),
|
||||
((unsigned int)1 << 23),
|
||||
((unsigned int)1 << 24),
|
||||
((unsigned int)1 << 25),
|
||||
((unsigned int)1 << 26),
|
||||
((unsigned int)1 << 27),
|
||||
((unsigned int)1 << 28),
|
||||
((unsigned int)1 << 29),
|
||||
((unsigned int)1 << 30),
|
||||
((unsigned int)1 << 31)
|
||||
};
|
||||
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 16-wide MIC bool type. */
|
||||
class bool16
|
||||
{
|
||||
public:
|
||||
__mmask v;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool16 () {};
|
||||
__forceinline bool16 (const bool16 &t) { v = t.v; };
|
||||
__forceinline bool16& operator=(const bool16 &f) { v = f.v; return *this; };
|
||||
|
||||
__forceinline bool16 (const __mmask &t) { v = t; };
|
||||
__forceinline operator __mmask () const { return v; };
|
||||
|
||||
__forceinline bool16(bool b) { v = b ? 0xFFFF : 0x0000; };
|
||||
__forceinline bool16(int t ) { v = (__mmask)t; };
|
||||
__forceinline bool16(unsigned int t ) { v = (__mmask)t; };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool16( FalseTy ) : v(0x0000) {}
|
||||
__forceinline bool16( TrueTy ) : v(0xffff) {}
|
||||
|
||||
static unsigned int shift1[32];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool16 operator!(const bool16 &a) { return _mm512_knot(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool16 operator&(const bool16 &a, const bool16 &b) { return _mm512_kand(a,b); };
|
||||
__forceinline bool16 operator|(const bool16 &a, const bool16 &b) { return _mm512_kor(a,b); };
|
||||
__forceinline bool16 operator^(const bool16 &a, const bool16 &b) { return _mm512_kxor(a,b); };
|
||||
|
||||
__forceinline bool16 andn(const bool16 &a, const bool16 &b) { return _mm512_kandn(b,a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool16 operator &=( bool16& a, const bool16& b ) { return a = a & b; }
|
||||
__forceinline const bool16 operator |=( bool16& a, const bool16& b ) { return a = a | b; }
|
||||
__forceinline const bool16 operator ^=( bool16& a, const bool16& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool16 operator !=( const bool16& a, const bool16& b ) { return _mm512_kxor(a, b); }
|
||||
__forceinline const bool16 operator ==( const bool16& a, const bool16& b ) { return _mm512_kxnor(a, b); }
|
||||
|
||||
__forceinline bool16 select (const bool16 &s, const bool16 &a, const bool16 &b) {
|
||||
return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all(const bool16 &a) { return _mm512_kortestc(a,a) != 0; }
|
||||
__forceinline int any(const bool16 &a) { return _mm512_kortestz(a,a) == 0; }
|
||||
__forceinline int none(const bool16 &a) { return _mm512_kortestz(a,a) != 0; }
|
||||
|
||||
__forceinline int all ( const bool16& valid, const bool16& b ) { return all(!valid | b); }
|
||||
__forceinline int any ( const bool16& valid, const bool16& b ) { return any( valid & b); }
|
||||
__forceinline int none ( const bool16& valid, const bool16& b ) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask( const bool16& a ) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt ( const bool16& a ) { return _mm_countbits_32(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Convertion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt (const bool16 &a) { return _mm512_mask2int(a); };
|
||||
__forceinline bool16 toMask(const int &a) { return _mm512_int2mask(a); };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const bool16& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<16; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 4-wide SSE bool type. */
|
||||
struct bool4
|
||||
{
|
||||
typedef bool4 Mask; // mask type
|
||||
typedef int4 Int; // int type
|
||||
typedef float4 Float; // float type
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { __m128 m128; int v[4]; }; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool4 ( ) {}
|
||||
__forceinline bool4 ( const bool4& other ) { m128 = other.m128; }
|
||||
__forceinline bool4& operator=( const bool4& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline bool4( const __m128 input ) : m128(input) {}
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator const __m128i( void ) const { return _mm_castps_si128(m128); }
|
||||
__forceinline operator const __m128d( void ) const { return _mm_castps_pd(m128); }
|
||||
|
||||
__forceinline bool4 ( bool a )
|
||||
: m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
|
||||
__forceinline bool4 ( bool a, bool b)
|
||||
: m128(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
|
||||
__forceinline bool4 ( bool a, bool b, bool c, bool d)
|
||||
: m128(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
|
||||
__forceinline bool4(int mask) {
|
||||
assert(mask >= 0 && mask < 16);
|
||||
m128 = _mm_lookupmask_ps[mask];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool4( FalseTy ) : m128(_mm_setzero_ps()) {}
|
||||
__forceinline bool4( TrueTy ) : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator []( const size_t i ) const { assert(i < 4); return (_mm_movemask_ps(m128) >> i) & 1; }
|
||||
__forceinline int& operator []( const size_t i ) { assert(i < 4); return v[i]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator !( const bool4& a ) { return _mm_xor_ps(a, bool4(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator &( const bool4& a, const bool4& b ) { return _mm_and_ps(a, b); }
|
||||
__forceinline const bool4 operator |( const bool4& a, const bool4& b ) { return _mm_or_ps (a, b); }
|
||||
__forceinline const bool4 operator ^( const bool4& a, const bool4& b ) { return _mm_xor_ps(a, b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator &=( bool4& a, const bool4& b ) { return a = a & b; }
|
||||
__forceinline const bool4 operator |=( bool4& a, const bool4& b ) { return a = a | b; }
|
||||
__forceinline const bool4 operator ^=( bool4& a, const bool4& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator !=( const bool4& a, const bool4& b ) { return _mm_xor_ps(a, b); }
|
||||
__forceinline const bool4 operator ==( const bool4& a, const bool4& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
|
||||
|
||||
__forceinline const bool4 select( const bool4& m, const bool4& t, const bool4& f ) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_blendv_ps(f, t, m);
|
||||
#else
|
||||
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 unpacklo( const bool4& a, const bool4& b ) { return _mm_unpacklo_ps(a, b); }
|
||||
__forceinline const bool4 unpackhi( const bool4& a, const bool4& b ) { return _mm_unpackhi_ps(a, b); }
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool4 shuffle( const bool4& a ) {
|
||||
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool4 shuffle( const bool4& a, const bool4& b ) {
|
||||
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
#if defined(__SSE3__)
|
||||
template<> __forceinline const bool4 shuffle<0, 0, 2, 2>( const bool4& a ) { return _mm_moveldup_ps(a); }
|
||||
template<> __forceinline const bool4 shuffle<1, 1, 3, 3>( const bool4& a ) { return _mm_movehdup_ps(a); }
|
||||
template<> __forceinline const bool4 shuffle<0, 1, 0, 1>( const bool4& a ) { return _mm_castpd_ps(_mm_movedup_pd (a)); }
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
template<size_t dst, size_t src, size_t clr> __forceinline const bool4 insert( const bool4& a, const bool4& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
|
||||
template<size_t dst, size_t src> __forceinline const bool4 insert( const bool4& a, const bool4& b ) { return insert<dst, src, 0>(a, b); }
|
||||
template<size_t dst> __forceinline const bool4 insert( const bool4& a, const bool b ) { return insert<dst,0>(a, bool4(b)); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and( const bool4& a ) { return _mm_movemask_ps(a) == 0xf; }
|
||||
__forceinline bool reduce_or ( const bool4& a ) { return _mm_movemask_ps(a) != 0x0; }
|
||||
|
||||
__forceinline bool all ( const bool4& b ) { return _mm_movemask_ps(b) == 0xf; }
|
||||
__forceinline bool any ( const bool4& b ) { return _mm_movemask_ps(b) != 0x0; }
|
||||
__forceinline bool none ( const bool4& b ) { return _mm_movemask_ps(b) == 0x0; }
|
||||
|
||||
__forceinline bool all ( const bool4& valid, const bool4& b ) { return all(!valid | b); }
|
||||
__forceinline bool any ( const bool4& valid, const bool4& b ) { return any( valid & b); }
|
||||
__forceinline bool none ( const bool4& valid, const bool4& b ) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask( const bool4& a ) { return _mm_movemask_ps(a); }
|
||||
#if defined(__SSE4_2__)
|
||||
__forceinline size_t popcnt( const bool4& a ) { return __popcnt(_mm_movemask_ps(a)); }
|
||||
#else
|
||||
__forceinline size_t popcnt( const bool4& a ) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const bool4& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 8-wide AVX bool type. */
|
||||
struct bool8
|
||||
{
|
||||
typedef bool8 Mask; // mask type for us
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256 m256;
|
||||
struct { __m128 l,h; };
|
||||
int v[8];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool8 () {}
|
||||
__forceinline bool8 ( const bool8& a ) { m256 = a.m256; }
|
||||
__forceinline bool8& operator=( const bool8& a ) { m256 = a.m256; return *this; }
|
||||
|
||||
__forceinline bool8( const __m256 a ) : m256(a) {}
|
||||
__forceinline operator const __m256&( void ) const { return m256; }
|
||||
__forceinline operator const __m256i( void ) const { return _mm256_castps_si256(m256); }
|
||||
__forceinline operator const __m256d( void ) const { return _mm256_castps_pd(m256); }
|
||||
|
||||
__forceinline bool8 ( const int a )
|
||||
{
|
||||
assert(a >= 0 && a <= 255);
|
||||
#if defined (__AVX2__)
|
||||
const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
|
||||
const __m256i b = _mm256_set1_epi32(a);
|
||||
const __m256i c = _mm256_and_si256(b,mask);
|
||||
m256 = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
|
||||
#else
|
||||
l = _mm_lookupmask_ps[a & 0xF];
|
||||
h = _mm_lookupmask_ps[a >> 4];
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline bool8 ( const bool4& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
|
||||
__forceinline bool8 ( const bool4& a, const bool4& b) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
|
||||
__forceinline bool8 ( const __m128 a, const __m128 b) : l(a), h(b) {}
|
||||
|
||||
__forceinline bool8 ( bool a ) : m256(bool8(bool4(a), bool4(a))) {}
|
||||
__forceinline bool8 ( bool a, bool b) : m256(bool8(bool4(a), bool4(b))) {}
|
||||
__forceinline bool8 ( bool a, bool b, bool c, bool d) : m256(bool8(bool4(a,b), bool4(c,d))) {}
|
||||
__forceinline bool8 ( bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h ) : m256(bool8(bool4(a,b,c,d), bool4(e,f,g,h))) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool8( FalseTy ) : m256(_mm256_setzero_ps()) {}
|
||||
__forceinline bool8( TrueTy ) : m256(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator []( const size_t i ) const { assert(i < 8); return (_mm256_movemask_ps(m256) >> i) & 1; }
|
||||
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator !( const bool8& a ) { return _mm256_xor_ps(a, bool8(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator &( const bool8& a, const bool8& b ) { return _mm256_and_ps(a, b); }
|
||||
__forceinline const bool8 operator |( const bool8& a, const bool8& b ) { return _mm256_or_ps (a, b); }
|
||||
__forceinline const bool8 operator ^( const bool8& a, const bool8& b ) { return _mm256_xor_ps(a, b); }
|
||||
|
||||
__forceinline bool8 operator &=( bool8& a, const bool8& b ) { return a = a & b; }
|
||||
__forceinline bool8 operator |=( bool8& a, const bool8& b ) { return a = a | b; }
|
||||
__forceinline bool8 operator ^=( bool8& a, const bool8& b ) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator !=( const bool8& a, const bool8& b ) { return _mm256_xor_ps(a, b); }
|
||||
__forceinline const bool8 operator ==( const bool8& a, const bool8& b ) { return _mm256_xor_ps(_mm256_xor_ps(a,b),bool8(embree::True)); }
|
||||
|
||||
__forceinline const bool8 select( const bool8& mask, const bool8& t, const bool8& f ) {
|
||||
return _mm256_blendv_ps(f, t, mask);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool8 unpacklo( const bool8& a, const bool8& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
|
||||
__forceinline bool8 unpackhi( const bool8& a, const bool8& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
|
||||
|
||||
template<size_t i> __forceinline const bool8 shuffle( const bool8& a ) {
|
||||
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const bool8 shuffle( const bool8& a ) {
|
||||
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const bool8 shuffle( const bool8& a, const bool8& b) {
|
||||
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool8 shuffle( const bool8& a ) {
|
||||
return _mm256_permute_ps(a, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const bool8 shuffle( const bool8& a, const bool8& b ) {
|
||||
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<> __forceinline const bool8 shuffle<0, 0, 2, 2>( const bool8& b ) { return _mm256_moveldup_ps(b); }
|
||||
template<> __forceinline const bool8 shuffle<1, 1, 3, 3>( const bool8& b ) { return _mm256_movehdup_ps(b); }
|
||||
template<> __forceinline const bool8 shuffle<0, 1, 0, 1>( const bool8& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
|
||||
|
||||
template<size_t i> __forceinline const bool8 insert (const bool8& a, const bool4& b) { return _mm256_insertf128_ps (a,b,i); }
|
||||
template<size_t i> __forceinline const bool4 extract(const bool8& a ) { return _mm256_extractf128_ps(a ,i); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and( const bool8& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
|
||||
__forceinline bool reduce_or ( const bool8& a ) { return !_mm256_testz_ps(a,a); }
|
||||
|
||||
__forceinline bool all ( const bool8& a ) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
|
||||
__forceinline bool any ( const bool8& a ) { return !_mm256_testz_ps(a,a); }
|
||||
__forceinline bool none ( const bool8& a ) { return _mm256_testz_ps(a,a) != 0; }
|
||||
|
||||
__forceinline bool all ( const bool8& valid, const bool8& b ) { return all(!valid | b); }
|
||||
__forceinline bool any ( const bool8& valid, const bool8& b ) { return any( valid & b); }
|
||||
__forceinline bool none ( const bool8& valid, const bool8& b ) { return none(valid & b); }
|
||||
|
||||
__forceinline unsigned int movemask( const bool8& a ) { return _mm256_movemask_ps(a); }
|
||||
__forceinline size_t popcnt ( const bool8& a ) { return __popcnt(_mm256_movemask_ps(a)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const bool8& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
|
||||
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,971 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 16-wide MIC float type. */
|
||||
class float16
|
||||
{
|
||||
public:
|
||||
typedef bool16 Mask; // mask type for us
|
||||
|
||||
enum { size = 16 }; // number of SIMD elements
|
||||
|
||||
union {
|
||||
__m512 v;
|
||||
float f[16];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16() {}
|
||||
__forceinline float16(const float16& t) { v = t; };
|
||||
__forceinline float16& operator=(const float16& f) { v = f.v; return *this; };
|
||||
|
||||
__forceinline float16(const __m512& t) { v = t; };
|
||||
__forceinline operator __m512 () const { return v; };
|
||||
|
||||
__forceinline float16(const float& f) {
|
||||
v = _mm512_set_1to16_ps(f);
|
||||
}
|
||||
__forceinline float16(const float& a, const float& b, const float& c, const float& d) {
|
||||
v = _mm512_set_4to16_ps(a,b,c,d);
|
||||
}
|
||||
|
||||
__forceinline explicit float16(const __m512i& a) {
|
||||
#if defined(__AVX512F__)
|
||||
v = _mm512_cvt_roundepi32_ps(a,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
|
||||
#else
|
||||
v = _mm512_cvtfxpnt_round_adjustepi32_ps(a, _MM_FROUND_NO_EXC,_MM_EXPADJ_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void store(void* addr, const float16& v2) {
|
||||
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_NONE,0);
|
||||
}
|
||||
|
||||
static __forceinline void store(const bool16& mask, void* addr, const float16& v2) {
|
||||
_mm512_mask_extstore_ps(addr,mask,v2,_MM_DOWNCONV_PS_NONE,0);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(float* ptr, const float16& f ) {
|
||||
#if defined(__AVX512F__)
|
||||
_mm512_storeu_ps(ptr,f);
|
||||
#else
|
||||
_mm512_extpackstorelo_ps(ptr+0 ,f, _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_extpackstorehi_ps(ptr+16 ,f, _MM_DOWNCONV_PS_NONE , 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void storeu(const bool16& mask, float* ptr, const float16& f ) {
|
||||
#if defined(__AVX512F__)
|
||||
_mm512_mask_storeu_ps(ptr,mask,f);
|
||||
#else
|
||||
float16 r = float16::undefined();
|
||||
r = _mm512_extloadunpacklo_ps(r, ptr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_extloadunpackhi_ps(r, ptr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_mask_blend_ps(mask,r,f);
|
||||
_mm512_extpackstorelo_ps(ptr, r, _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_extpackstorehi_ps(ptr+16 ,r, _MM_DOWNCONV_PS_NONE , 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16( ZeroTy ) : v(_mm512_setzero_ps()) {}
|
||||
__forceinline float16( OneTy ) : v(_mm512_set_1to16_ps(1.0f)) {}
|
||||
__forceinline float16( PosInfTy ) : v(_mm512_set_1to16_ps(pos_inf)) {}
|
||||
__forceinline float16( NegInfTy ) : v(_mm512_set_1to16_ps(neg_inf)) {}
|
||||
__forceinline float16( StepTy ) : v(_mm512_set_16to16_ps(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
|
||||
__forceinline float16( NaNTy ) : v(_mm512_set_1to16_ps(nan)) {}
|
||||
|
||||
__forceinline static float16 undefined() { return _mm512_undefined(); }
|
||||
__forceinline static float16 zero() { return _mm512_setzero_ps(); }
|
||||
__forceinline static float16 one () { return _mm512_set_1to16_ps(1.0f); }
|
||||
__forceinline static float16 ulp () { return _mm512_set_1to16_ps(embree::ulp); }
|
||||
__forceinline static float16 inf () { return _mm512_set_1to16_ps((float)pos_inf); }
|
||||
__forceinline static float16 minus_inf () { return _mm512_set_1to16_ps((float)neg_inf); }
|
||||
|
||||
static __forceinline float16 loadu(const void* addr)
|
||||
{
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_loadu_ps(addr);
|
||||
#else
|
||||
float16 r = float16::undefined();
|
||||
r =_mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
return _mm512_extloadunpackhi_ps(r, (float*)addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline float16 load(const void *f) {
|
||||
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float& operator[](const size_t index) { return f[index]; };
|
||||
__forceinline const float& operator[](const size_t index) const { return f[index]; };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float16 cast (const __m512i& a) { return _mm512_castsi512_ps(a); }
|
||||
__forceinline const float16 operator +( const float16& a ) { return a; }
|
||||
__forceinline const float16 operator -( const float16& a ) { return _mm512_mul_ps(a,float16(-1)); }
|
||||
__forceinline const float16 abs ( const float16& a ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_abs_ps(a);
|
||||
#else
|
||||
return _mm512_gmaxabs_ps(a,a);
|
||||
#endif
|
||||
}
|
||||
__forceinline const float16 signmsk ( const float16& a ) { return _mm512_castsi512_ps(_mm512_and_epi32(_mm512_castps_si512(a),_mm512_set1_epi32(0x80000000))); }
|
||||
|
||||
__forceinline const float16 rcp ( const float16& a ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_rcp28_ps(a);
|
||||
#else
|
||||
return _mm512_rcp23_ps(a);
|
||||
#endif
|
||||
};
|
||||
|
||||
__forceinline const float16 sqr ( const float16& a ) { return _mm512_mul_ps(a,a); }
|
||||
__forceinline const float16 sqrt ( const float16& a ) { return _mm512_sqrt_ps(a); }
|
||||
__forceinline const float16 rsqrt( const float16& a ) { return _mm512_invsqrt_ps(a); }
|
||||
|
||||
__forceinline float16 exp(const float16& a) { return _mm512_exp_ps(a); }
|
||||
__forceinline float16 exp2(const float16& a) { return _mm512_exp2_ps(a); }
|
||||
__forceinline float16 pow(const float16& a, float16 b) { return _mm512_pow_ps(a,b); }
|
||||
|
||||
__forceinline float16 log(const float16& a) { return _mm512_log_ps(a); }
|
||||
__forceinline float16 log2(const float16& a) { return _mm512_log2_ps(a); }
|
||||
__forceinline float16 log10(const float16& a) { return _mm512_log10_ps(a); }
|
||||
|
||||
__forceinline float16 sin(const float16& a) { return _mm512_sin_ps(a); }
|
||||
__forceinline float16 cos(const float16& a) { return _mm512_cos_ps(a); }
|
||||
__forceinline float16 tan(const float16& a) { return _mm512_tan_ps(a); }
|
||||
|
||||
__forceinline float16 asin(const float16& a) { return _mm512_asin_ps(a); }
|
||||
__forceinline float16 acos(const float16& a) { return _mm512_acos_ps(a); }
|
||||
__forceinline float16 atan(const float16& a) { return _mm512_atan_ps(a); }
|
||||
__forceinline float16 atan2(const float16& a, float16 b) { return _mm512_atan2_ps(a,b); }
|
||||
|
||||
__forceinline float16 sinh(const float16& a) { return _mm512_sinh_ps(a); }
|
||||
__forceinline float16 cosh(const float16& a) { return _mm512_cosh_ps(a); }
|
||||
__forceinline float16 tanh(const float16& a) { return _mm512_tan_ps(a); }
|
||||
|
||||
__forceinline float16 asinh(const float16& a) { return _mm512_asinh_ps(a); }
|
||||
__forceinline float16 acosh(const float16& a) { return _mm512_acosh_ps(a); }
|
||||
__forceinline float16 atanh(const float16& a) { return _mm512_atanh_ps(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float16 operator +( const float16& a, const float16& b ) { return _mm512_add_ps(a, b); }
|
||||
__forceinline const float16 operator +( const float16& a, const float& b ) { return a + float16(b); }
|
||||
__forceinline const float16 operator +( const float& a, const float16& b ) { return float16(a) + b; }
|
||||
|
||||
__forceinline const float16 operator -( const float16& a, const float16& b ) { return _mm512_sub_ps(a, b); }
|
||||
__forceinline const float16 operator -( const float16& a, const float& b ) { return a - float16(b); }
|
||||
__forceinline const float16 operator -( const float& a, const float16& b ) { return float16(a) - b; }
|
||||
|
||||
__forceinline const float16 operator *( const float16& a, const float16& b ) { return _mm512_mul_ps(a, b); }
|
||||
__forceinline const float16 operator *( const float16& a, const float& b ) { return a * float16(b); }
|
||||
__forceinline const float16 operator *( const float& a, const float16& b ) { return float16(a) * b; }
|
||||
|
||||
__forceinline const float16 operator /( const float16& a, const float16& b ) { return _mm512_div_ps(a,b); }
|
||||
__forceinline const float16 operator /( const float16& a, const float& b ) { return a/float16(b); }
|
||||
__forceinline const float16 operator /( const float& a, const float16& b ) { return float16(a)/b; }
|
||||
|
||||
__forceinline const float16 operator^(const float16& a, const float16& b) {
|
||||
return _mm512_castsi512_ps(_mm512_xor_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b)));
|
||||
}
|
||||
|
||||
__forceinline const float16 min( const float16& a, const float16& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_min_ps(a,b);
|
||||
#else
|
||||
return _mm512_gmin_ps(a,b);
|
||||
#endif
|
||||
}
|
||||
__forceinline const float16 min( const float16& a, const float& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_min_ps(a,float16(b));
|
||||
#else
|
||||
return _mm512_gmin_ps(a,float16(b));
|
||||
#endif
|
||||
}
|
||||
__forceinline const float16 min( const float& a, const float16& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_min_ps(float16(a),b);
|
||||
#else
|
||||
return _mm512_gmin_ps(float16(a),b);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline const float16 max( const float16& a, const float16& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_max_ps(a,b);
|
||||
#else
|
||||
return _mm512_gmax_ps(a,b);
|
||||
#endif
|
||||
}
|
||||
__forceinline const float16 max( const float16& a, const float& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_max_ps(a,float16(b));
|
||||
#else
|
||||
return _mm512_gmax_ps(a,float16(b));
|
||||
#endif
|
||||
}
|
||||
__forceinline const float16 max( const float& a, const float16& b ) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_max_ps(float16(a),b);
|
||||
#else
|
||||
return _mm512_gmax_ps(float16(a),b);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline float16 mask_add(const bool16& mask, const float16& c, const float16& a, const float16& b) { return _mm512_mask_add_ps (c,mask,a,b); };
|
||||
__forceinline float16 mask_min(const bool16& mask, const float16& c, const float16& a, const float16& b) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_mask_min_ps(c,mask,a,b);
|
||||
#else
|
||||
return _mm512_mask_gmin_ps(c,mask,a,b);
|
||||
#endif
|
||||
};
|
||||
__forceinline float16 mask_max(const bool16& mask, const float16& c, const float16& a, const float16& b) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_mask_max_ps(c,mask,a,b);
|
||||
#else
|
||||
return _mm512_mask_gmax_ps(c,mask,a,b);
|
||||
#endif
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 madd (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_ps(a,b,c); }
|
||||
|
||||
__forceinline float16 msub (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(a,b,c); }
|
||||
__forceinline float16 nmadd (const float16& a, const float16& b, const float16& c) { return _mm512_fnmadd_ps(a,b,c); }
|
||||
__forceinline float16 nmsub (const float16& a, const float16& b, const float16& c) { return _mm512_fnmsub_ps(a,b,c); }
|
||||
|
||||
__forceinline float16 mask_msub (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_ps(a,mask,b,c); }
|
||||
|
||||
__forceinline float16 madd231 (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_ps(c,b,a); }
|
||||
__forceinline float16 msub213 (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(a,b,c); }
|
||||
__forceinline float16 msub231 (const float16& a, const float16& b, const float16& c) { return _mm512_fmsub_ps(c,b,a); }
|
||||
__forceinline float16 msubr231(const float16& a, const float16& b, const float16& c) { return _mm512_fnmadd_ps(c,b,a); }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Operators with rounding
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 madd_round_down (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_NEG_INF); }
|
||||
|
||||
__forceinline float16 madd_round_up (const float16& a, const float16& b, const float16& c) { return _mm512_fmadd_round_ps(a,b,c,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 mul_round_down (const float16& a, const float16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 mul_round_up (const float16& a, const float16& b) { return _mm512_mul_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 add_round_down (const float16& a, const float16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 add_round_up (const float16& a, const float16& b) { return _mm512_add_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 sub_round_down (const float16& a, const float16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 sub_round_up (const float16& a, const float16& b) { return _mm512_sub_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 div_round_down (const float16& a, const float16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 div_round_up (const float16& a, const float16& b) { return _mm512_div_round_ps(a,b,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 mask_msub_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 mask_msub_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_fmsub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 mask_mul_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 mask_mul_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_mul_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
__forceinline float16 mask_sub_round_down (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_NEG_INF); }
|
||||
__forceinline float16 mask_sub_round_up (const bool16& mask,const float16& a, const float16& b, const float16& c) { return _mm512_mask_sub_round_ps(a,mask,b,c,_MM_FROUND_TO_POS_INF); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16& operator +=( float16& a, const float16& b ) { return a = a + b; }
|
||||
__forceinline float16& operator +=( float16& a, const float& b ) { return a = a + b; }
|
||||
|
||||
__forceinline float16& operator -=( float16& a, const float16& b ) { return a = a - b; }
|
||||
__forceinline float16& operator -=( float16& a, const float& b ) { return a = a - b; }
|
||||
|
||||
__forceinline float16& operator *=( float16& a, const float16& b ) { return a = a * b; }
|
||||
__forceinline float16& operator *=( float16& a, const float& b ) { return a = a * b; }
|
||||
|
||||
__forceinline float16& operator /=( float16& a, const float16& b ) { return a = a / b; }
|
||||
__forceinline float16& operator /=( float16& a, const float& b ) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool16 operator ==( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
|
||||
__forceinline const bool16 operator ==( const float16& a, const float& b ) { return a == float16(b); }
|
||||
__forceinline const bool16 operator ==( const float& a, const float16& b ) { return float16(a) == b; }
|
||||
|
||||
__forceinline const bool16 operator !=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
|
||||
__forceinline const bool16 operator !=( const float16& a, const float& b ) { return a != float16(b); }
|
||||
__forceinline const bool16 operator !=( const float& a, const float16& b ) { return float16(a) != b; }
|
||||
|
||||
__forceinline const bool16 operator < ( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
|
||||
__forceinline const bool16 operator < ( const float16& a, const float& b ) { return a < float16(b); }
|
||||
__forceinline const bool16 operator < ( const float& a, const float16& b ) { return float16(a) < b; }
|
||||
|
||||
__forceinline const bool16 operator >=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
|
||||
__forceinline const bool16 operator >=( const float16& a, const float& b ) { return a >= float16(b); }
|
||||
__forceinline const bool16 operator >=( const float& a, const float16& b ) { return float16(a) >= b; }
|
||||
|
||||
__forceinline const bool16 operator > ( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
|
||||
__forceinline const bool16 operator > ( const float16& a, const float& b ) { return a > float16(b); }
|
||||
__forceinline const bool16 operator > ( const float& a, const float16& b ) { return float16(a) > b; }
|
||||
|
||||
__forceinline const bool16 operator <=( const float16& a, const float16& b ) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
|
||||
__forceinline const bool16 operator <=( const float16& a, const float& b ) { return a <= float16(b); }
|
||||
__forceinline const bool16 operator <=( const float& a, const float16& b ) { return float16(a) <= b; }
|
||||
|
||||
__forceinline bool16 eq( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_EQ); }
|
||||
__forceinline bool16 eq(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_EQ); }
|
||||
|
||||
__forceinline bool16 ne( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_NE); }
|
||||
__forceinline bool16 ne(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_NE); }
|
||||
|
||||
__forceinline bool16 lt( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LT); }
|
||||
__forceinline bool16 lt(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LT); }
|
||||
|
||||
__forceinline bool16 ge( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GE); }
|
||||
__forceinline bool16 ge(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GE); }
|
||||
|
||||
__forceinline bool16 gt( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_GT); }
|
||||
__forceinline bool16 gt(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_GT); }
|
||||
|
||||
__forceinline bool16 le( const float16& a, const float16& b) { return _mm512_cmp_ps_mask(a,b,_MM_CMPINT_LE); }
|
||||
__forceinline bool16 le(const bool16& mask, const float16& a, const float16& b) { return _mm512_mask_cmp_ps_mask(mask,a,b,_MM_CMPINT_LE); }
|
||||
|
||||
__forceinline const float16 select( const bool16& s, const float16& t, const float16& f ) {
|
||||
return _mm512_mask_blend_ps(s, f, t);
|
||||
}
|
||||
|
||||
__forceinline float16 lerp(const float16& a, const float16& b, const float16& t) {
|
||||
return madd(t, b, madd(-t, a, a));
|
||||
}
|
||||
|
||||
__forceinline void xchg(bool16 m, float16& a, float16& b)
|
||||
{
|
||||
float16 c = a;
|
||||
a = select(m,b,a);
|
||||
b = select(m,c,b);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Rounding Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 vround(const float16& f,
|
||||
const _MM_ROUND_MODE_ENUM mode,
|
||||
const _MM_EXP_ADJ_ENUM exp = _MM_EXPADJ_NONE)
|
||||
{
|
||||
return _mm512_round_ps(f,mode,exp);
|
||||
}
|
||||
|
||||
__forceinline float16 floor(const float16& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_DOWN, _MM_EXPADJ_NONE); }
|
||||
__forceinline float16 ceil (const float16& a) { return _mm512_round_ps(a,_MM_ROUND_MODE_UP , _MM_EXPADJ_NONE); }
|
||||
__forceinline float16 trunc(const float16& a) { return _mm512_trunc_ps(a); }
|
||||
__forceinline float16 frac( const float16& a ) { return a-trunc(a); }
|
||||
|
||||
__forceinline const float16 rcp_nr ( const float16& a ) {
|
||||
const float16 ra = _mm512_rcp23_ps(a);
|
||||
return (ra+ra) - (ra * a * ra);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 swizzle(const float16& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_ps(x,perm32); }
|
||||
__forceinline float16 permute(const float16& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_ps(x,perm128); }
|
||||
|
||||
template<int D, int C, int B, int A> __forceinline float16 swizzle (const float16& v) { return _mm512_shuffle_ps(v,_MM_SHUF_PERM(D,C,B,A)); }
|
||||
template<int A> __forceinline float16 swizzle (const float16& x) { return swizzle<A,A,A,A>(v); }
|
||||
template<> __forceinline float16 swizzle<0>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
|
||||
template<> __forceinline float16 swizzle<1>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
|
||||
template<> __forceinline float16 swizzle<2>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
|
||||
template<> __forceinline float16 swizzle<3>(const float16& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
|
||||
|
||||
template<int D, int C, int B, int A> __forceinline float16 permute(const float16& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
|
||||
template<int A> __forceinline float16 permute(const float16& x) { return permute<A,A,A,A>(x); }
|
||||
|
||||
__forceinline float16 shuffle(const float16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
|
||||
|
||||
__forceinline float16 shuffle(const bool16& mask, float16& v, const float16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) {
|
||||
return _mm512_mask_swizzle_ps(_mm512_mask_permute4f128_ps(v,mask,x,perm128),mask,x,perm32);
|
||||
}
|
||||
|
||||
__forceinline float16 swAAAA(const float16 &x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_AAAA);
|
||||
}
|
||||
|
||||
__forceinline float16 swBBBB(const float16 &x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_BBBB);
|
||||
}
|
||||
|
||||
__forceinline float16 swCCCC(const float16 &x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_CCCC);
|
||||
}
|
||||
|
||||
__forceinline float16 swDDDD(const float16 &x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_DDDD);
|
||||
}
|
||||
|
||||
__forceinline float16 _mm512_permutev_ps(__m512i index, float16 v)
|
||||
{
|
||||
return _mm512_castsi512_ps(_mm512_permutev_epi32(index,_mm512_castps_si512(v)));
|
||||
}
|
||||
|
||||
__forceinline float16 permute16f(__m512i index, float16 v)
|
||||
{
|
||||
return _mm512_castsi512_ps(_mm512_permutev_epi32(index,_mm512_castps_si512(v)));
|
||||
}
|
||||
|
||||
template<int i>
|
||||
__forceinline float16 align_shift_right(const float16 &a, const float16 &b)
|
||||
{
|
||||
return _mm512_castsi512_ps(_mm512_alignr_epi32(_mm512_castps_si512(a),_mm512_castps_si512(b),i));
|
||||
};
|
||||
|
||||
template<int i>
|
||||
__forceinline float16 mask_align_shift_right(const bool16 &mask,float16 &c,const float16 &a, const float16 &b)
|
||||
{
|
||||
return _mm512_castsi512_ps(_mm512_mask_alignr_epi32(_mm512_castps_si512(c),mask,_mm512_castps_si512(a),_mm512_castps_si512(b),i));
|
||||
};
|
||||
|
||||
__forceinline float16 shl1_zero_extend(const float16 &a)
|
||||
{
|
||||
float16 z = float16::zero();
|
||||
return mask_align_shift_right<15>(0xfffe,z,a,a);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float reduce_add(float16 a) { return _mm512_reduce_add_ps(a); }
|
||||
__forceinline float reduce_mul(float16 a) { return _mm512_reduce_mul_ps(a); }
|
||||
__forceinline float reduce_min(float16 a) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_reduce_min_ps(a);
|
||||
#else
|
||||
return _mm512_reduce_gmin_ps(a);
|
||||
#endif
|
||||
}
|
||||
__forceinline float reduce_max(float16 a) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_reduce_max_ps(a);
|
||||
#else
|
||||
return _mm512_reduce_gmax_ps(a);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__forceinline float16 vreduce_min2(float16 x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
|
||||
__forceinline float16 vreduce_min4(float16 x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
|
||||
__forceinline float16 vreduce_min8(float16 x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
|
||||
__forceinline float16 vreduce_min (float16 x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
|
||||
|
||||
__forceinline float16 vreduce_max2(float16 x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
|
||||
__forceinline float16 vreduce_max4(float16 x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
|
||||
__forceinline float16 vreduce_max8(float16 x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
|
||||
__forceinline float16 vreduce_max (float16 x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
|
||||
|
||||
__forceinline float16 vreduce_add2(float16 x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
|
||||
__forceinline float16 vreduce_add4(float16 x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
|
||||
__forceinline float16 vreduce_add8(float16 x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
|
||||
__forceinline float16 vreduce_add (float16 x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
|
||||
|
||||
__forceinline size_t select_min(const float16& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const float16& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool16& valid, const float16& v, const float16 &max_value) { const float16 a = select(valid,v,max_value); return __bsf(movemask(a == vreduce_min(a))); }
|
||||
|
||||
__forceinline size_t select_max(const bool16& valid, const float16& v, const float16 &min_value) { const float16 a = select(valid,v,min_value); return __bsf(movemask(a == vreduce_max(a))); }
|
||||
|
||||
__forceinline size_t select_max(const bool16& valid, const float16& v) { const float16 a = select(valid,v,float16(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
__forceinline size_t select_min(const bool16& valid, const float16& v) { const float16 a = select(valid,v,float16(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
|
||||
__forceinline float16 prefix_sum(const float16& a)
|
||||
{
|
||||
float16 v = a;
|
||||
v = mask_add(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
|
||||
v = mask_add(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
|
||||
const float16 shuf_v0 = shuffle(v,_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_add(0xf0f0,v,v,shuf_v0);
|
||||
const float16 shuf_v1 = shuffle(v,_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_add(0xff00,v,v,shuf_v1);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 prefix_min(const float16& a)
|
||||
{
|
||||
float16 v = a;
|
||||
v = mask_min(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
|
||||
v = mask_min(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
|
||||
const float16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_min(0xf0f0,v,v,shuf_v0);
|
||||
const float16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_min(0xff00,v,v,shuf_v1);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 prefix_max(const float16& a)
|
||||
{
|
||||
float16 v = a;
|
||||
v = mask_max(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
|
||||
v = mask_max(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
|
||||
const float16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_max(0xf0f0,v,v,shuf_v0);
|
||||
const float16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_max(0xff00,v,v,shuf_v1);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 set_min4(float16 x) {
|
||||
x = min(x,swizzle(x,_MM_SWIZ_REG_BADC));
|
||||
x = min(x,swizzle(x,_MM_SWIZ_REG_CDAB));
|
||||
return x;
|
||||
}
|
||||
|
||||
__forceinline float16 set_min_lanes(float16 x) {
|
||||
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
|
||||
x = min(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
|
||||
return x;
|
||||
}
|
||||
|
||||
__forceinline float16 set_max_lanes(float16 x) {
|
||||
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_CDAB));
|
||||
x = max(x,_mm512_permute4f128_ps(x, _MM_PERM_BADC));
|
||||
return x;
|
||||
}
|
||||
|
||||
__forceinline float16 set_min16(float16 x) {
|
||||
return set_min_lanes(set_min4(x));
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 load1f(const void *f) {
|
||||
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 load16f(const void *f) {
|
||||
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 load16f(const float16 d, const bool16 valid, const void *f) {
|
||||
return _mm512_mask_extload_ps(d,valid,f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 broadcast1to16f(const void *f) {
|
||||
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 broadcast4to16f(const void *f) {
|
||||
return _mm512_extload_ps(f,_MM_UPCONV_PS_NONE,_MM_BROADCAST_4X16,0);
|
||||
}
|
||||
|
||||
__forceinline float16 broadcast8to16f(const void *f) {
|
||||
return _mm512_castpd_ps(_mm512_extload_pd(f,_MM_UPCONV_PD_NONE,_MM_BROADCAST_4X8,0));
|
||||
}
|
||||
|
||||
__forceinline float16 load16f_uint8(const unsigned char *const ptr) {
|
||||
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_UINT8,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/255.0f));
|
||||
}
|
||||
|
||||
__forceinline float16 load16f_uint16(const unsigned short *const ptr) {
|
||||
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_UINT16,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/65535.0f));
|
||||
}
|
||||
|
||||
#if !defined(__AVX512F__)
|
||||
__forceinline float16 uload16f_low_uint8(const bool16& mask, const void* addr, const float16& v1) {
|
||||
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_UINT8, _MM_HINT_NONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline float16 load16f_int8(const char *const ptr) {
|
||||
return _mm512_mul_ps(_mm512_extload_ps(ptr,_MM_UPCONV_PS_SINT8,_MM_BROADCAST_16X16,_MM_HINT_NONE),float16(1.0f/127.0f));
|
||||
}
|
||||
|
||||
|
||||
__forceinline float16 gather16f_4f(const float *__restrict__ const ptr0,
|
||||
const float *__restrict__ const ptr1,
|
||||
const float *__restrict__ const ptr2,
|
||||
const float *__restrict__ const ptr3)
|
||||
{
|
||||
float16 v = broadcast4to16f(ptr0);
|
||||
v = select((bool16)0x00f0,broadcast4to16f(ptr1),v);
|
||||
v = select((bool16)0x0f00,broadcast4to16f(ptr2),v);
|
||||
v = select((bool16)0xf000,broadcast4to16f(ptr3),v);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 gather16f_4f(const float16& v0,
|
||||
const float16& v1,
|
||||
const float16& v2,
|
||||
const float16& v3)
|
||||
{
|
||||
float16 v = v0;
|
||||
v = select((bool16)0xf0 ,v1,v);
|
||||
v = select((bool16)0xf00 ,v2,v);
|
||||
v = select((bool16)0xf000,v3,v);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 gather_4f_zlc(const int16 &v_mask,
|
||||
const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1,
|
||||
const void *__restrict__ const ptr2,
|
||||
const void *__restrict__ const ptr3)
|
||||
{
|
||||
const bool16 m_00f0 = 0x00f0;
|
||||
const bool16 m_0f00 = 0x0f00;
|
||||
const bool16 m_f000 = 0xf000;
|
||||
|
||||
int16 v = v_mask & broadcast4to16i((const int*)ptr0);
|
||||
v = mask_and(m_00f0,v,v_mask, broadcast4to16i((const int*)ptr1));
|
||||
v = mask_and(m_0f00,v,v_mask, broadcast4to16i((const int*)ptr2));
|
||||
v = mask_and(m_f000,v,v_mask, broadcast4to16i((const int*)ptr3));
|
||||
return cast(v);
|
||||
}
|
||||
|
||||
__forceinline float16 gather_2f_zlc(const int16 &v_mask,
|
||||
const bool16 &mask,
|
||||
const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1)
|
||||
{
|
||||
int16 v = v_mask & broadcast4to16i((const int*)ptr0);
|
||||
v = mask_and(mask,v,v_mask, broadcast4to16i((const int*)ptr1));
|
||||
return cast(v);
|
||||
}
|
||||
|
||||
|
||||
__forceinline float16 gather16f_4f_align(const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1,
|
||||
const void *__restrict__ const ptr2,
|
||||
const void *__restrict__ const ptr3)
|
||||
{
|
||||
float16 v = broadcast4to16f(ptr3);
|
||||
v = align_shift_right<12>(v,broadcast4to16f(ptr2));
|
||||
v = align_shift_right<12>(v,broadcast4to16f(ptr1));
|
||||
v = align_shift_right<12>(v,broadcast4to16f(ptr0));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
__forceinline float16 gather16f_4f_align(const float16& v0,
|
||||
const float16& v1,
|
||||
const float16& v2,
|
||||
const float16& v3)
|
||||
{
|
||||
float16 v = v3;
|
||||
v = align_shift_right<12>(v,v2);
|
||||
v = align_shift_right<12>(v,v1);
|
||||
v = align_shift_right<12>(v,v0);
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 gather_4f_zlc_align(const int16 &v_mask,
|
||||
const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1,
|
||||
const void *__restrict__ const ptr2,
|
||||
const void *__restrict__ const ptr3)
|
||||
{
|
||||
float16 v = gather16f_4f_align(ptr0,ptr1,ptr2,ptr3);
|
||||
return cast(cast(v) & v_mask);
|
||||
}
|
||||
|
||||
|
||||
__forceinline float16 uload16f(const bool16& mask,const float *const addr) {
|
||||
float16 r = float16::undefined();
|
||||
r =_mm512_mask_extloadunpacklo_ps(r, mask,addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_mask_extloadunpackhi_ps(r, mask, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
return r;
|
||||
}
|
||||
|
||||
__forceinline float16 uload16f(float16 &r, const bool16& mask, const float *const addr) {
|
||||
r =_mm512_mask_extloadunpacklo_ps(r, mask,addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_mask_extloadunpackhi_ps(r, mask, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
return r;
|
||||
}
|
||||
|
||||
__forceinline float16 uload16f(const float *const addr) {
|
||||
float16 r = float16::undefined();
|
||||
r =_mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
return _mm512_extloadunpackhi_ps(r, addr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 uload16f_low(const float *const addr) {
|
||||
float16 r = float16::undefined();
|
||||
return _mm512_extloadunpacklo_ps(r, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 uload16f_low(const bool16& mask, const void* addr, const float16& v1) {
|
||||
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 uload16f_low(const bool16& mask, const void* addr) {
|
||||
float16 v1 = float16::undefined();
|
||||
return _mm512_mask_extloadunpacklo_ps(v1, mask, addr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void ustore16f(float *addr, const float16& reg) {
|
||||
#if defined(__AVX512F__)
|
||||
_mm512_storeu_ps(addr,reg);
|
||||
#else
|
||||
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_extpackstorehi_ps(addr+16 ,reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* pass by value to avoid compiler generating inefficient code */
|
||||
__forceinline void compactustore16f(const bool16& mask, float *addr, const float16 reg) {
|
||||
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_mask_extpackstorehi_ps(addr+16 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void compactustore16f_low(const bool16& mask, float * addr, const float16 ®) {
|
||||
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void compactustore16f_low_uint8(const bool16& mask, void * addr, const float16 ®) {
|
||||
_mm512_mask_extpackstorelo_ps(addr+0 ,mask, reg, _MM_DOWNCONV_PS_UINT8 , 0);
|
||||
}
|
||||
|
||||
__forceinline void ustore16f_low(float * addr, const float16& reg) {
|
||||
_mm512_extpackstorelo_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void compactustore16f_high(const bool16& mask, float *addr, const float16& reg) {
|
||||
_mm512_extpackstorehi_ps(addr+0 ,reg, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void store16f(const bool16& mask, void* addr, const float16& v2) {
|
||||
_mm512_mask_extstore_ps(addr,mask,v2,_MM_DOWNCONV_PS_NONE,0);
|
||||
}
|
||||
|
||||
|
||||
__forceinline void store16f(void* addr, const float16& v2) {
|
||||
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_NONE,0);
|
||||
}
|
||||
|
||||
__forceinline void store16f_int8(void* addr, const float16& v2) {
|
||||
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_SINT8,0);
|
||||
}
|
||||
|
||||
__forceinline void store16f_uint16(void* addr, const float16& v2) {
|
||||
_mm512_extstore_ps(addr,v2,_MM_DOWNCONV_PS_UINT16,0);
|
||||
}
|
||||
|
||||
__forceinline void store4f_int8(void* addr, const float16& v1) {
|
||||
assert((unsigned long)addr % 4 == 0);
|
||||
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_SINT8 , 0);
|
||||
}
|
||||
|
||||
__forceinline void store4f(void* addr, const float16& v1) {
|
||||
assert((unsigned long)addr % 16 == 0);
|
||||
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void store3f(void* addr, const float16& v1) {
|
||||
assert((unsigned long)addr % 16 == 0);
|
||||
_mm512_mask_extpackstorelo_ps(addr,0x7, v1, _MM_DOWNCONV_PS_NONE , 0);
|
||||
}
|
||||
|
||||
__forceinline void store4f_nt(void* addr, const float16& v1) {
|
||||
assert((unsigned long)addr % 16 == 0);
|
||||
_mm512_mask_extpackstorelo_ps(addr,0xf, v1, _MM_DOWNCONV_PS_NONE , _MM_HINT_NT);
|
||||
}
|
||||
|
||||
__forceinline void store16f_nt(void *__restrict__ ptr, const float16& a) {
|
||||
_mm512_storenr_ps(ptr,a);
|
||||
}
|
||||
|
||||
__forceinline void store16f_ngo(void *__restrict__ ptr, const float16& a) {
|
||||
_mm512_storenrngo_ps(ptr,a);
|
||||
}
|
||||
|
||||
__forceinline void store1f(void *addr, const float16& reg) {
|
||||
_mm512_mask_extpackstorelo_ps((float*)addr+0 ,(bool16)1, reg, _MM_DOWNCONV_PS_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline float16 gather16f(const bool16& mask, const float *const ptr, __m512i index, const _MM_INDEX_SCALE_ENUM scale) {
|
||||
float16 r = float16::undefined();
|
||||
return _mm512_mask_i32extgather_ps(r,mask,index,ptr,_MM_UPCONV_PS_NONE,scale,0);
|
||||
}
|
||||
|
||||
__forceinline void scatter16f(const bool16& mask,const float *const ptr, const __m512i index,const float16 v, const _MM_INDEX_SCALE_ENUM scale) {
|
||||
_mm512_mask_i32extscatter_ps((void*)ptr,mask,index,v,_MM_DOWNCONV_PS_NONE,scale,0);
|
||||
}
|
||||
|
||||
__forceinline float16 loadAOS4to16f(const float& x,const float& y, const float& z)
|
||||
{
|
||||
float16 f = float16::zero();
|
||||
f = select(0x1111,broadcast1to16f(&x),f);
|
||||
f = select(0x2222,broadcast1to16f(&y),f);
|
||||
f = select(0x4444,broadcast1to16f(&z),f);
|
||||
return f;
|
||||
}
|
||||
|
||||
__forceinline float16 loadAOS4to16f(const unsigned int index,
|
||||
const float16 &x,
|
||||
const float16 &y,
|
||||
const float16 &z)
|
||||
{
|
||||
float16 f = float16::zero();
|
||||
f = select(0x1111,broadcast1to16f((float*)&x + index),f);
|
||||
f = select(0x2222,broadcast1to16f((float*)&y + index),f);
|
||||
f = select(0x4444,broadcast1to16f((float*)&z + index),f);
|
||||
return f;
|
||||
}
|
||||
|
||||
__forceinline float16 loadAOS4to16f(const unsigned int index,
|
||||
const float16 &x,
|
||||
const float16 &y,
|
||||
const float16 &z,
|
||||
const float16 &fill)
|
||||
{
|
||||
float16 f = fill;
|
||||
f = select(0x1111,broadcast1to16f((float*)&x + index),f);
|
||||
f = select(0x2222,broadcast1to16f((float*)&y + index),f);
|
||||
f = select(0x4444,broadcast1to16f((float*)&z + index),f);
|
||||
return f;
|
||||
}
|
||||
|
||||
__forceinline float16 gather16f_4f_unalign(const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1,
|
||||
const void *__restrict__ const ptr2,
|
||||
const void *__restrict__ const ptr3)
|
||||
{
|
||||
float16 v = permute<0>(uload16f((float*)ptr3));
|
||||
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr2)));
|
||||
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr1)));
|
||||
v = align_shift_right<12>(v,permute<0>(uload16f((float*)ptr0)));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
__forceinline float16 rcp_safe( const float16& a ) { return select(a != float16::zero(),_mm512_rcp23_ps(a),float16(1E-10f)); };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float16 lcross_zxy(const float16 &ao, const float16 &bo) {
|
||||
float16 ao_bo = bo * swizzle(ao,_MM_SWIZ_REG_DACB);
|
||||
ao_bo = msub231(ao_bo,ao,swizzle(bo,_MM_SWIZ_REG_DACB));
|
||||
return ao_bo;
|
||||
}
|
||||
|
||||
__forceinline float16 ldot16_zxy(const float16 &a,const float16 &v0, const float16 &v1, const float16 &v2)
|
||||
{
|
||||
float16 v = v0 * swizzle(a,_MM_SWIZ_REG_BBBB);
|
||||
v = madd231(v,v1,swizzle(a,_MM_SWIZ_REG_CCCC));
|
||||
v = madd231(v,v2,swizzle(a,_MM_SWIZ_REG_AAAA));
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 ldot16_xyz(const float16 &a,const float16 &v0, const float16 &v1, const float16 &v2)
|
||||
{
|
||||
float16 v = v0 * swizzle(a,_MM_SWIZ_REG_AAAA);
|
||||
v = madd231(v, v1,swizzle(a,_MM_SWIZ_REG_BBBB));
|
||||
v = madd231(v, v2,swizzle(a,_MM_SWIZ_REG_CCCC));
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline float16 lcross_xyz(const float16 &a, const float16 &b)
|
||||
{
|
||||
float16 c = b * swizzle(a,_MM_SWIZ_REG_DACB);
|
||||
c = msub231(c,a,swizzle(b,_MM_SWIZ_REG_DACB));
|
||||
c = swizzle(c,_MM_SWIZ_REG_DACB);
|
||||
return c;
|
||||
}
|
||||
|
||||
__forceinline float16 ldot3_xyz(const float16 &ao, const float16 &normal)
|
||||
{
|
||||
float16 vv = ao * normal;
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
|
||||
return vv;
|
||||
}
|
||||
|
||||
__forceinline float16 lsum3_xyz(const float16 &v)
|
||||
{
|
||||
float16 vv = v;
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
|
||||
return vv;
|
||||
}
|
||||
|
||||
__forceinline float16 ldot3_xyz(const bool16 &m_mask, const float16 &ao, const float16 &normal)
|
||||
{
|
||||
float16 vv = _mm512_mask_mul_ps(ao,m_mask,ao,normal);
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
|
||||
return vv;
|
||||
}
|
||||
|
||||
__forceinline float16 ldot3_zxy(const float16 &ao, const float16 &normal)
|
||||
{
|
||||
float16 vv = ao * swizzle(normal,_MM_SWIZ_REG_DACB);
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_CDAB));
|
||||
vv = _mm512_add_ps(vv,swizzle(vv,_MM_SWIZ_REG_BADC));
|
||||
return vv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline std::ostream &operator<<(std::ostream& cout, const float16& v)
|
||||
{
|
||||
cout << "<" << v[0];
|
||||
for (int i=1; i<16; i++) cout << ", " << v[i];
|
||||
cout << ">";
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,539 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#define EMBREE_FLOAT4
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 4-wide SSE float type. */
|
||||
struct float4
|
||||
{
|
||||
typedef bool4 Mask; // mask type
|
||||
typedef int4 Int; // int type
|
||||
typedef float4 Float; // float type
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { __m128 m128; float f[4]; int i[4]; }; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float4 ( ) {}
|
||||
__forceinline float4 ( const float4& other ) { m128 = other.m128; }
|
||||
__forceinline float4& operator=( const float4& other ) { m128 = other.m128; return *this; }
|
||||
|
||||
__forceinline float4( const __m128 a ) : m128(a) {}
|
||||
__forceinline operator const __m128&( void ) const { return m128; }
|
||||
__forceinline operator __m128&( void ) { return m128; }
|
||||
|
||||
__forceinline float4 ( float a ) : m128(_mm_set1_ps(a)) {}
|
||||
__forceinline float4 ( float a, float b, float c, float d) : m128(_mm_set_ps(d, c, b, a)) {}
|
||||
|
||||
__forceinline explicit float4( const __m128i a ) : m128(_mm_cvtepi32_ps(a)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float4( ZeroTy ) : m128(_mm_setzero_ps()) {}
|
||||
__forceinline float4( OneTy ) : m128(_mm_set1_ps(1.0f)) {}
|
||||
__forceinline float4( PosInfTy ) : m128(_mm_set1_ps(pos_inf)) {}
|
||||
__forceinline float4( NegInfTy ) : m128(_mm_set1_ps(neg_inf)) {}
|
||||
__forceinline float4( StepTy ) : m128(_mm_set_ps(3.0f, 2.0f, 1.0f, 0.0f)) {}
|
||||
__forceinline float4( NaNTy ) : m128(_mm_set1_ps(nan)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__AVX__)
|
||||
static __forceinline float4 broadcast( const void* const a ) { return _mm_broadcast_ss((float*)a); }
|
||||
|
||||
#else
|
||||
static __forceinline float4 broadcast( const void* const a ) { return _mm_set1_ps(*(float*)a); }
|
||||
#endif
|
||||
|
||||
static __forceinline float4 load( const float* const a ) {
|
||||
return _mm_load_ps(a);
|
||||
}
|
||||
|
||||
static __forceinline float4 loadu( const void* const a ) {
|
||||
return _mm_loadu_ps((float*)a);
|
||||
}
|
||||
|
||||
static __forceinline float4 load_nt ( const float* ptr ) {
|
||||
#if defined (__SSE4_1__)
|
||||
return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
|
||||
#else
|
||||
return _mm_load_ps(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
static __forceinline float4 load( const unsigned char* const ptr ) {
|
||||
return _mm_cvtepi32_ps(_mm_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
}
|
||||
#else
|
||||
static __forceinline float4 load( const unsigned char* const ptr ) {
|
||||
//return _mm_cvtpu8_ps(*(__m64*)ptr); // don't enable, will use MMX instructions
|
||||
return float4(ptr[0],ptr[1],ptr[2],ptr[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline float4 load(const unsigned short* const ptr) {
|
||||
return _mm_mul_ps(float4(int4::load(ptr)),float4(1.0f/65535.0f));
|
||||
}
|
||||
|
||||
static __forceinline void store ( void* ptr, const float4& v ) {
|
||||
_mm_store_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline void storeu ( void* ptr, const float4& v ) {
|
||||
_mm_storeu_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline void storeu ( float* ptr, const float4& v, size_t n) // FIXME: is there a better way of implementing this
|
||||
{
|
||||
if (n >= 1) ptr[0] = v[0];
|
||||
if (n >= 2) ptr[1] = v[1];
|
||||
if (n >= 3) ptr[2] = v[2];
|
||||
if (n >= 4) ptr[3] = v[3];
|
||||
}
|
||||
|
||||
static __forceinline void store_nt ( float4* ptr, const float4& v)
|
||||
{
|
||||
#if defined (__SSE4_1__)
|
||||
_mm_stream_ps((float*)ptr,v);
|
||||
#else
|
||||
_mm_store_ps((float*)ptr,v);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void store ( const bool4& mask, void* ptr, const float4& f )
|
||||
{
|
||||
#if defined (__AVX__)
|
||||
_mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
|
||||
#else
|
||||
*(float4*)ptr = select(mask,f,*(float4*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void storeu( const bool4& mask, void* ptr, const float4& f ) {
|
||||
return _mm_storeu_ps((float*)ptr,select(mask,f,_mm_loadu_ps((float*)ptr)));
|
||||
}
|
||||
|
||||
static __forceinline void store ( const bool4& mask, void* ptr, const int4& ofs, const float4& v, const int scale = 1 )
|
||||
{
|
||||
if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
|
||||
if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
|
||||
if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
|
||||
if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
|
||||
}
|
||||
static __forceinline void store ( const bool4& mask, char* ptr, const int4& ofs, const float4& v ) {
|
||||
store(mask,ptr,ofs,v,1);
|
||||
}
|
||||
static __forceinline void store ( const bool4& mask, float* ptr, const int4& ofs, const float4& v ) {
|
||||
store(mask,ptr,ofs,v,4);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float& operator []( const size_t i ) const { assert(i < 4); return f[i]; }
|
||||
__forceinline float& operator []( const size_t i ) { assert(i < 4); return f[i]; }
|
||||
|
||||
friend __forceinline const float4 select( const bool4& m, const float4& t, const float4& f ) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_blendv_ps(f, t, m);
|
||||
#else
|
||||
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float4 cast (const __m128i& a) { return _mm_castsi128_ps(a); }
|
||||
__forceinline const float4 operator +( const float4& a ) { return a; }
|
||||
__forceinline const float4 operator -( const float4& a ) { return _mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
|
||||
__forceinline const float4 abs ( const float4& a ) { return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
|
||||
__forceinline const float4 sign ( const float4& a ) { return blendv_ps(float4(one), -float4(one), _mm_cmplt_ps (a,float4(zero))); }
|
||||
__forceinline const float4 signmsk ( const float4& a ) { return _mm_and_ps(a.m128,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
|
||||
|
||||
__forceinline const float4 rcp ( const float4& a ) {
|
||||
const float4 r = _mm_rcp_ps(a.m128);
|
||||
#if defined(__AVX2__)
|
||||
return _mm_mul_ps(r,_mm_fnmadd_ps(r, a, float4(2.0f)));
|
||||
#else
|
||||
return _mm_mul_ps(r,_mm_sub_ps(float4(2.0f), _mm_mul_ps(r, a)));
|
||||
#endif
|
||||
}
|
||||
__forceinline const float4 sqr ( const float4& a ) { return _mm_mul_ps(a,a); }
|
||||
__forceinline const float4 sqrt ( const float4& a ) { return _mm_sqrt_ps(a.m128); }
|
||||
__forceinline const float4 rsqrt( const float4& a ) {
|
||||
const float4 r = _mm_rsqrt_ps(a.m128);
|
||||
return _mm_add_ps(_mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
|
||||
_mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r), _mm_mul_ps(r, r)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float4 operator +( const float4& a, const float4& b ) { return _mm_add_ps(a.m128, b.m128); }
|
||||
__forceinline const float4 operator +( const float4& a, const float& b ) { return a + float4(b); }
|
||||
__forceinline const float4 operator +( const float& a, const float4& b ) { return float4(a) + b; }
|
||||
|
||||
__forceinline const float4 operator -( const float4& a, const float4& b ) { return _mm_sub_ps(a.m128, b.m128); }
|
||||
__forceinline const float4 operator -( const float4& a, const float& b ) { return a - float4(b); }
|
||||
__forceinline const float4 operator -( const float& a, const float4& b ) { return float4(a) - b; }
|
||||
|
||||
__forceinline const float4 operator *( const float4& a, const float4& b ) { return _mm_mul_ps(a.m128, b.m128); }
|
||||
__forceinline const float4 operator *( const float4& a, const float& b ) { return a * float4(b); }
|
||||
__forceinline const float4 operator *( const float& a, const float4& b ) { return float4(a) * b; }
|
||||
|
||||
__forceinline const float4 operator /( const float4& a, const float4& b ) { return _mm_div_ps(a.m128,b.m128); }
|
||||
__forceinline const float4 operator /( const float4& a, const float& b ) { return a/float4(b); }
|
||||
__forceinline const float4 operator /( const float& a, const float4& b ) { return float4(a)/b; }
|
||||
|
||||
__forceinline const float4 operator^( const float4& a, const float4& b ) { return _mm_xor_ps(a.m128,b.m128); }
|
||||
__forceinline const float4 operator^( const float4& a, const int4& b ) { return _mm_xor_ps(a.m128,_mm_castsi128_ps(b.m128)); }
|
||||
|
||||
__forceinline const float4 min( const float4& a, const float4& b ) { return _mm_min_ps(a.m128,b.m128); }
|
||||
__forceinline const float4 min( const float4& a, const float& b ) { return _mm_min_ps(a.m128,float4(b)); }
|
||||
__forceinline const float4 min( const float& a, const float4& b ) { return _mm_min_ps(float4(a),b.m128); }
|
||||
|
||||
__forceinline const float4 max( const float4& a, const float4& b ) { return _mm_max_ps(a.m128,b.m128); }
|
||||
__forceinline const float4 max( const float4& a, const float& b ) { return _mm_max_ps(a.m128,float4(b)); }
|
||||
__forceinline const float4 max( const float& a, const float4& b ) { return _mm_max_ps(float4(a),b.m128); }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float4 mini(const float4& a, const float4& b) {
|
||||
const int4 ai = _mm_castps_si128(a);
|
||||
const int4 bi = _mm_castps_si128(b);
|
||||
const int4 ci = _mm_min_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline float4 maxi(const float4& a, const float4& b) {
|
||||
const int4 ai = _mm_castps_si128(a);
|
||||
const int4 bi = _mm_castps_si128(b);
|
||||
const int4 ci = _mm_max_epi32(ai,bi);
|
||||
return _mm_castsi128_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__AVX2__)
|
||||
__forceinline const float4 madd ( const float4& a, const float4& b, const float4& c) { return _mm_fmadd_ps(a,b,c); }
|
||||
__forceinline const float4 msub ( const float4& a, const float4& b, const float4& c) { return _mm_fmsub_ps(a,b,c); }
|
||||
__forceinline const float4 nmadd ( const float4& a, const float4& b, const float4& c) { return _mm_fnmadd_ps(a,b,c); }
|
||||
__forceinline const float4 nmsub ( const float4& a, const float4& b, const float4& c) { return _mm_fnmsub_ps(a,b,c); }
|
||||
#else
|
||||
__forceinline const float4 madd ( const float4& a, const float4& b, const float4& c) { return a*b+c; }
|
||||
__forceinline const float4 msub ( const float4& a, const float4& b, const float4& c) { return a*b-c; }
|
||||
__forceinline const float4 nmadd ( const float4& a, const float4& b, const float4& c) { return -a*b+c;}
|
||||
__forceinline const float4 nmsub ( const float4& a, const float4& b, const float4& c) { return -a*b-c; }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float4& operator +=( float4& a, const float4& b ) { return a = a + b; }
|
||||
__forceinline float4& operator +=( float4& a, const float& b ) { return a = a + b; }
|
||||
|
||||
__forceinline float4& operator -=( float4& a, const float4& b ) { return a = a - b; }
|
||||
__forceinline float4& operator -=( float4& a, const float& b ) { return a = a - b; }
|
||||
|
||||
__forceinline float4& operator *=( float4& a, const float4& b ) { return a = a * b; }
|
||||
__forceinline float4& operator *=( float4& a, const float& b ) { return a = a * b; }
|
||||
|
||||
__forceinline float4& operator /=( float4& a, const float4& b ) { return a = a / b; }
|
||||
__forceinline float4& operator /=( float4& a, const float& b ) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator ==( const float4& a, const float4& b ) { return _mm_cmpeq_ps (a.m128, b.m128); }
|
||||
__forceinline const bool4 operator ==( const float4& a, const float& b ) { return a == float4(b); }
|
||||
__forceinline const bool4 operator ==( const float& a, const float4& b ) { return float4(a) == b; }
|
||||
|
||||
__forceinline const bool4 operator !=( const float4& a, const float4& b ) { return _mm_cmpneq_ps(a.m128, b.m128); }
|
||||
__forceinline const bool4 operator !=( const float4& a, const float& b ) { return a != float4(b); }
|
||||
__forceinline const bool4 operator !=( const float& a, const float4& b ) { return float4(a) != b; }
|
||||
|
||||
__forceinline const bool4 operator < ( const float4& a, const float4& b ) { return _mm_cmplt_ps (a.m128, b.m128); }
|
||||
__forceinline const bool4 operator < ( const float4& a, const float& b ) { return a < float4(b); }
|
||||
__forceinline const bool4 operator < ( const float& a, const float4& b ) { return float4(a) < b; }
|
||||
|
||||
__forceinline const bool4 operator >=( const float4& a, const float4& b ) { return _mm_cmpnlt_ps(a.m128, b.m128); }
|
||||
__forceinline const bool4 operator >=( const float4& a, const float& b ) { return a >= float4(b); }
|
||||
__forceinline const bool4 operator >=( const float& a, const float4& b ) { return float4(a) >= b; }
|
||||
|
||||
__forceinline const bool4 operator > ( const float4& a, const float4& b ) { return _mm_cmpnle_ps(a.m128, b.m128); }
|
||||
__forceinline const bool4 operator > ( const float4& a, const float& b ) { return a > float4(b); }
|
||||
__forceinline const bool4 operator > ( const float& a, const float4& b ) { return float4(a) > b; }
|
||||
|
||||
__forceinline const bool4 operator <=( const float4& a, const float4& b ) { return _mm_cmple_ps (a.m128, b.m128); }
|
||||
__forceinline const bool4 operator <=( const float4& a, const float& b ) { return a <= float4(b); }
|
||||
__forceinline const bool4 operator <=( const float& a, const float4& b ) { return float4(a) <= b; }
|
||||
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
#if defined(__clang__) || defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || defined(_DEBUG))
|
||||
__forceinline const float4 select(const int mask, const float4& t, const float4& f) {
|
||||
return select(bool4(mask), t, f);
|
||||
}
|
||||
#else
|
||||
__forceinline const float4 select(const int mask, const float4& t, const float4& f) {
|
||||
return _mm_blend_ps(f, t, mask);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
__forceinline float4 lerp(const float4& a, const float4& b, const float4& t) {
|
||||
#if defined(__AVX2__)
|
||||
return madd(t, b, madd(-t, a, a));
|
||||
#else
|
||||
return a + t*(b-a);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline bool isvalid ( const float4& v ) {
|
||||
return all((v > float4(-FLT_LARGE)) & (v < float4(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const float4& a ) {
|
||||
return all((a >= float4(-FLT_MAX) & (a <= float4(+FLT_MAX))));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const bool4& valid, const float4& a ) {
|
||||
return all(valid, a >= float4(-FLT_MAX) & (a <= float4(+FLT_MAX)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Rounding Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined (__SSE4_1__)
|
||||
__forceinline const float4 floor ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
|
||||
__forceinline const float4 ceil ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
|
||||
__forceinline const float4 trunc ( const float4& a ) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
|
||||
#else
|
||||
__forceinline const float4 floor ( const float4& a ) { return float4(floorf(a[0]),floorf(a[1]),floorf(a[2]),floorf(a[3])); }
|
||||
__forceinline const float4 ceil ( const float4& a ) { return float4(ceilf (a[0]),ceilf (a[1]),ceilf (a[2]),ceilf (a[3])); }
|
||||
//__forceinline const float4 trunc ( const float4& a ) { return float4(truncf(a[0]),truncf(a[1]),truncf(a[2]),truncf(a[3])); }
|
||||
#endif
|
||||
__forceinline const float4 frac ( const float4& a ) { return a-floor(a); }
|
||||
|
||||
__forceinline int4 floori (const float4& a) {
|
||||
#if defined (__SSE4_1__)
|
||||
return int4(floor(a));
|
||||
#else
|
||||
return int4(a-float4(0.5f));
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float4 unpacklo( const float4& a, const float4& b ) { return _mm_unpacklo_ps(a.m128, b.m128); }
|
||||
__forceinline float4 unpackhi( const float4& a, const float4& b ) { return _mm_unpackhi_ps(a.m128, b.m128); }
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float4 shuffle( const float4& b ) {
|
||||
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float4 shuffle( const float4& a, const float4& b ) {
|
||||
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
#if defined (__SSSE3__)
|
||||
__forceinline const float4 shuffle8(const float4& a, const int4& shuf) {
|
||||
return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__SSE3__)
|
||||
template<> __forceinline const float4 shuffle<0, 0, 2, 2>( const float4& b ) { return _mm_moveldup_ps(b); }
|
||||
template<> __forceinline const float4 shuffle<1, 1, 3, 3>( const float4& b ) { return _mm_movehdup_ps(b); }
|
||||
template<> __forceinline const float4 shuffle<0, 1, 0, 1>( const float4& b ) { return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))); }
|
||||
#endif
|
||||
|
||||
template<size_t i0> __forceinline const float4 shuffle( const float4& b ) {
|
||||
return shuffle<i0,i0,i0,i0>(b);
|
||||
}
|
||||
|
||||
#if defined (__SSE4_1__) && !defined(__GNUC__)
|
||||
template<size_t i> __forceinline float extract ( const float4& a ) { return _mm_cvtss_f32(_mm_extract_ps(a,i)); }
|
||||
#else
|
||||
template<size_t i> __forceinline float extract ( const float4& a ) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
|
||||
#endif
|
||||
template<> __forceinline float extract<0>( const float4& a ) { return _mm_cvtss_f32(a); }
|
||||
|
||||
#if defined (__SSE4_1__)
|
||||
template<size_t dst, size_t src, size_t clr> __forceinline const float4 insert( const float4& a, const float4& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
|
||||
template<size_t dst, size_t src> __forceinline const float4 insert( const float4& a, const float4& b ) { return insert<dst, src, 0>(a, b); }
|
||||
template<size_t dst> __forceinline const float4 insert( const float4& a, const float b ) { return insert<dst, 0>(a, _mm_set_ss(b)); }
|
||||
#else
|
||||
template<size_t dst, size_t src> __forceinline const float4 insert( const float4& a, const float4& b ) { float4 c = a; c[dst] = b[src]; return c; }
|
||||
template<size_t dst> __forceinline const float4 insert( const float4& a, const float b ) { float4 c = a; c[dst] = b; return c; }
|
||||
#endif
|
||||
|
||||
__forceinline float4 broadcast4f( const float4& a, const size_t k ) {
|
||||
return float4::broadcast(&a[k]);
|
||||
}
|
||||
|
||||
#if defined (__AVX2__)
|
||||
__forceinline float4 permute(const float4 &a, const __m128i &index) {
|
||||
return _mm_permutevar_ps(a,index);
|
||||
}
|
||||
|
||||
__forceinline float4 broadcast1f( const void* const a ) { return _mm_broadcast_ss((float*)a); }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Transpose
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline void transpose(const float4& r0, const float4& r1, const float4& r2, const float4& r3, float4& c0, float4& c1, float4& c2, float4& c3)
|
||||
{
|
||||
float4 l02 = unpacklo(r0,r2);
|
||||
float4 h02 = unpackhi(r0,r2);
|
||||
float4 l13 = unpacklo(r1,r3);
|
||||
float4 h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
c3 = unpackhi(h02,h13);
|
||||
}
|
||||
|
||||
__forceinline void transpose(const float4& r0, const float4& r1, const float4& r2, const float4& r3, float4& c0, float4& c1, float4& c2)
|
||||
{
|
||||
float4 l02 = unpacklo(r0,r2);
|
||||
float4 h02 = unpackhi(r0,r2);
|
||||
float4 l13 = unpacklo(r1,r3);
|
||||
float4 h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float4 vreduce_min(const float4& v) { float4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
|
||||
__forceinline const float4 vreduce_max(const float4& v) { float4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
|
||||
__forceinline const float4 vreduce_add(const float4& v) { float4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
|
||||
|
||||
__forceinline float reduce_min(const float4& v) { return _mm_cvtss_f32(vreduce_min(v)); }
|
||||
__forceinline float reduce_max(const float4& v) { return _mm_cvtss_f32(vreduce_max(v)); }
|
||||
__forceinline float reduce_add(const float4& v) { return _mm_cvtss_f32(vreduce_add(v)); }
|
||||
|
||||
__forceinline size_t select_min(const float4& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const float4& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool4& valid, const float4& v) { const float4 a = select(valid,v,float4(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
__forceinline size_t select_max(const bool4& valid, const float4& v) { const float4 a = select(valid,v,float4(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float4 load4f( const void* const a ) {
|
||||
return _mm_load_ps((float*)a);
|
||||
}
|
||||
|
||||
__forceinline void store4f ( void* ptr, const float4& v ) {
|
||||
_mm_store_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
__forceinline float4 loadu4f( const void* const a ) {
|
||||
return _mm_loadu_ps((float*)a);
|
||||
}
|
||||
|
||||
__forceinline void storeu4f ( void* ptr, const float4& v ) {
|
||||
_mm_storeu_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
__forceinline void store4f ( const bool4& mask, void* ptr, const float4& f ) {
|
||||
#if defined (__AVX__)
|
||||
_mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
|
||||
#else
|
||||
*(float4*)ptr = select(mask,f,*(float4*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline float4 load4f_nt (void* ptr) {
|
||||
#if defined (__SSE4_1__)
|
||||
return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
|
||||
#else
|
||||
return _mm_load_ps((float*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void store4f_nt (void* ptr, const float4& v) {
|
||||
#if defined (__SSE4_1__)
|
||||
_mm_stream_ps((float*)ptr,v);
|
||||
#else
|
||||
_mm_store_ps((float*)ptr,v);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float dot ( const float4& a, const float4& b ) {
|
||||
return reduce_add(a*b);
|
||||
}
|
||||
|
||||
__forceinline float4 cross ( const float4& a, const float4& b )
|
||||
{
|
||||
const float4 a0 = a;
|
||||
const float4 b0 = shuffle<1,2,0,3>(b);
|
||||
const float4 a1 = shuffle<1,2,0,3>(a);
|
||||
const float4 b1 = b;
|
||||
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const float4& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,540 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#define EMBREE_FLOAT8
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 8-wide AVX float type. */
|
||||
struct float8
|
||||
{
|
||||
typedef bool8 Mask; // mask type for us
|
||||
typedef int8 Int ; // int type for us
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
union { __m256 m256; float v[8]; }; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float8 ( ) {}
|
||||
__forceinline float8 ( const float8& other ) { m256 = other.m256; }
|
||||
__forceinline float8& operator=( const float8& other ) { m256 = other.m256; return *this; }
|
||||
|
||||
__forceinline float8( const __m256 a ) : m256(a) {}
|
||||
__forceinline operator const __m256&( void ) const { return m256; }
|
||||
__forceinline operator __m256&( void ) { return m256; }
|
||||
|
||||
__forceinline explicit float8( const float4& a ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
|
||||
__forceinline float8( const float4& a, const float4& b ) : m256(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
|
||||
|
||||
__forceinline explicit float8( const char* const a ) : m256(_mm256_loadu_ps((const float*)a)) {}
|
||||
__forceinline float8( const float& a ) : m256(_mm256_broadcast_ss(&a)) {}
|
||||
__forceinline float8( float a, float b) : m256(_mm256_set_ps(b, a, b, a, b, a, b, a)) {}
|
||||
__forceinline float8( float a, float b, float c, float d ) : m256(_mm256_set_ps(d, c, b, a, d, c, b, a)) {}
|
||||
__forceinline float8( float a, float b, float c, float d, float e, float f, float g, float h ) : m256(_mm256_set_ps(h, g, f, e, d, c, b, a)) {}
|
||||
|
||||
__forceinline explicit float8( const __m256i a ) : m256(_mm256_cvtepi32_ps(a)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float8( ZeroTy ) : m256(_mm256_setzero_ps()) {}
|
||||
__forceinline float8( OneTy ) : m256(_mm256_set1_ps(1.0f)) {}
|
||||
__forceinline float8( PosInfTy ) : m256(_mm256_set1_ps(pos_inf)) {}
|
||||
__forceinline float8( NegInfTy ) : m256(_mm256_set1_ps(neg_inf)) {}
|
||||
__forceinline float8( StepTy ) : m256(_mm256_set_ps(7.0f, 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 1.0f, 0.0f)) {}
|
||||
__forceinline float8( NaNTy ) : m256(_mm256_set1_ps(nan)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline float8 broadcast( const void* const a ) {
|
||||
return _mm256_broadcast_ss((float*)a);
|
||||
}
|
||||
|
||||
static __forceinline const float8 broadcast4f(const void* ptr) { // FIXME: float4 input type?
|
||||
return _mm256_broadcast_ps((__m128*)ptr);
|
||||
}
|
||||
|
||||
static __forceinline float8 load( const unsigned char* const ptr ) {
|
||||
#if defined(__AVX2__)
|
||||
return _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_loadu_si128((__m128i*)ptr)));
|
||||
#else
|
||||
return float8(float4::load(ptr),float4::load(ptr+4));
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline float8 load( const float* const a) {
|
||||
return _mm256_load_ps(a);
|
||||
}
|
||||
|
||||
static __forceinline void store(void* ptr, const float8& f ) {
|
||||
return _mm256_store_ps((float*)ptr,f);
|
||||
}
|
||||
|
||||
static __forceinline float8 loadu( const void* const a) {
|
||||
return _mm256_loadu_ps((float*)a);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const float8& f ) {
|
||||
return _mm256_storeu_ps((float*)ptr,f);
|
||||
}
|
||||
|
||||
static __forceinline void store( const bool8& mask, void* ptr, const float8& f ) {
|
||||
return _mm256_maskstore_ps((float*)ptr,(__m256i)mask,f);
|
||||
}
|
||||
|
||||
static __forceinline void storeu( const bool8& mask, void* ptr, const float8& f ) {
|
||||
return _mm256_storeu_ps((float*)ptr,_mm256_blendv_ps(_mm256_loadu_ps((float*)ptr),f,mask));
|
||||
}
|
||||
|
||||
#if defined (__AVX2__)
|
||||
static __forceinline float8 load_nt(void* ptr) {
|
||||
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline void store_nt(float* ptr, const float8& v) {
|
||||
_mm256_stream_ps(ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline void store ( const bool8& mask, void* ptr, const int8& ofs, const float8& v, const int scale = 1 )
|
||||
{
|
||||
if (likely(mask[0])) *(float*)(((char*)ptr)+scale*ofs[0]) = v[0];
|
||||
if (likely(mask[1])) *(float*)(((char*)ptr)+scale*ofs[1]) = v[1];
|
||||
if (likely(mask[2])) *(float*)(((char*)ptr)+scale*ofs[2]) = v[2];
|
||||
if (likely(mask[3])) *(float*)(((char*)ptr)+scale*ofs[3]) = v[3];
|
||||
if (likely(mask[4])) *(float*)(((char*)ptr)+scale*ofs[4]) = v[4];
|
||||
if (likely(mask[5])) *(float*)(((char*)ptr)+scale*ofs[5]) = v[5];
|
||||
if (likely(mask[6])) *(float*)(((char*)ptr)+scale*ofs[6]) = v[6];
|
||||
if (likely(mask[7])) *(float*)(((char*)ptr)+scale*ofs[7]) = v[7];
|
||||
}
|
||||
static __forceinline void store ( const bool8& mask, char* ptr, const int8& ofs, const float8& v ) {
|
||||
store(mask,ptr,ofs,v,1);
|
||||
}
|
||||
static __forceinline void store ( const bool8& mask, float* ptr, const int8& ofs, const float8& v ) {
|
||||
store(mask,ptr,ofs,v,4);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
|
||||
__forceinline float& operator []( const size_t i ) { assert(i < 8); return v[i]; }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float8 cast (const int8& a ) { return _mm256_castsi256_ps(a); }
|
||||
__forceinline const int8 cast (const float8& a ) { return _mm256_castps_si256(a); }
|
||||
__forceinline const float8 operator +( const float8& a ) { return a; }
|
||||
__forceinline const float8 operator -( const float8& a ) {
|
||||
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x80000000));
|
||||
return _mm256_xor_ps(a.m256, mask);
|
||||
}
|
||||
__forceinline const float8 abs ( const float8& a ) {
|
||||
const __m256 mask = _mm256_castsi256_ps(_mm256_set1_epi32(0x7fffffff));
|
||||
return _mm256_and_ps(a.m256, mask);
|
||||
}
|
||||
__forceinline const float8 sign ( const float8& a ) { return _mm256_blendv_ps(float8(one), -float8(one), _mm256_cmp_ps(a, float8(zero), _CMP_NGE_UQ )); }
|
||||
__forceinline const float8 signmsk ( const float8& a ) { return _mm256_and_ps(a.m256,_mm256_castsi256_ps(_mm256_set1_epi32(0x80000000))); }
|
||||
|
||||
__forceinline const float8 rcp ( const float8& a ) {
|
||||
const float8 r = _mm256_rcp_ps(a.m256);
|
||||
#if defined(__AVX2__)
|
||||
return _mm256_mul_ps(r,_mm256_fnmadd_ps(r, a, float8(2.0f)));
|
||||
#else
|
||||
return _mm256_mul_ps(r,_mm256_sub_ps(float8(2.0f), _mm256_mul_ps(r, a)));
|
||||
#endif
|
||||
}
|
||||
__forceinline const float8 sqr ( const float8& a ) { return _mm256_mul_ps(a,a); }
|
||||
__forceinline const float8 sqrt ( const float8& a ) { return _mm256_sqrt_ps(a.m256); }
|
||||
__forceinline const float8 rsqrt( const float8& a ) {
|
||||
const float8 r = _mm256_rsqrt_ps(a.m256);
|
||||
return _mm256_add_ps(_mm256_mul_ps(_mm256_set1_ps(1.5f), r), _mm256_mul_ps(_mm256_mul_ps(_mm256_mul_ps(a, _mm256_set1_ps(-0.5f)), r), _mm256_mul_ps(r, r)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float8 operator +( const float8& a, const float8& b ) { return _mm256_add_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 operator +( const float8& a, const float b ) { return a + float8(b); }
|
||||
__forceinline const float8 operator +( const float a, const float8& b ) { return float8(a) + b; }
|
||||
|
||||
__forceinline const float8 operator -( const float8& a, const float8& b ) { return _mm256_sub_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 operator -( const float8& a, const float b ) { return a - float8(b); }
|
||||
__forceinline const float8 operator -( const float a, const float8& b ) { return float8(a) - b; }
|
||||
|
||||
__forceinline const float8 operator *( const float8& a, const float8& b ) { return _mm256_mul_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 operator *( const float8& a, const float b ) { return a * float8(b); }
|
||||
__forceinline const float8 operator *( const float a, const float8& b ) { return float8(a) * b; }
|
||||
|
||||
__forceinline const float8 operator /( const float8& a, const float8& b ) { return _mm256_div_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 operator /( const float8& a, const float b ) { return a / float8(b); }
|
||||
__forceinline const float8 operator /( const float a, const float8& b ) { return float8(a) / b; }
|
||||
|
||||
__forceinline const float8 operator^( const float8& a, const float8& b ) { return _mm256_xor_ps(a.m256,b.m256); }
|
||||
__forceinline const float8 operator^( const float8& a, const int8& b ) { return _mm256_xor_ps(a.m256,_mm256_castsi256_ps(b.m256)); }
|
||||
|
||||
__forceinline const float8 operator&( const float8& a, const float8& b ) { return _mm256_and_ps(a.m256,b.m256); }
|
||||
|
||||
__forceinline const float8 min( const float8& a, const float8& b ) { return _mm256_min_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 min( const float8& a, const float b ) { return _mm256_min_ps(a.m256, float8(b)); }
|
||||
__forceinline const float8 min( const float a, const float8& b ) { return _mm256_min_ps(float8(a), b.m256); }
|
||||
|
||||
__forceinline const float8 max( const float8& a, const float8& b ) { return _mm256_max_ps(a.m256, b.m256); }
|
||||
__forceinline const float8 max( const float8& a, const float b ) { return _mm256_max_ps(a.m256, float8(b)); }
|
||||
__forceinline const float8 max( const float a, const float8& b ) { return _mm256_max_ps(float8(a), b.m256); }
|
||||
|
||||
#if defined (__AVX2__)
|
||||
__forceinline float8 mini(const float8& a, const float8& b) {
|
||||
const int8 ai = _mm256_castps_si256(a);
|
||||
const int8 bi = _mm256_castps_si256(b);
|
||||
const int8 ci = _mm256_min_epi32(ai,bi);
|
||||
return _mm256_castsi256_ps(ci);
|
||||
}
|
||||
__forceinline float8 maxi(const float8& a, const float8& b) {
|
||||
const int8 ai = _mm256_castps_si256(a);
|
||||
const int8 bi = _mm256_castps_si256(b);
|
||||
const int8 ci = _mm256_max_epi32(ai,bi);
|
||||
return _mm256_castsi256_ps(ci);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Ternary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__AVX2__)
|
||||
__forceinline const float8 madd ( const float8& a, const float8& b, const float8& c) { return _mm256_fmadd_ps(a,b,c); }
|
||||
__forceinline const float8 msub ( const float8& a, const float8& b, const float8& c) { return _mm256_fmsub_ps(a,b,c); }
|
||||
__forceinline const float8 nmadd ( const float8& a, const float8& b, const float8& c) { return _mm256_fnmadd_ps(a,b,c); }
|
||||
__forceinline const float8 nmsub ( const float8& a, const float8& b, const float8& c) { return _mm256_fnmsub_ps(a,b,c); }
|
||||
#else
|
||||
__forceinline const float8 madd ( const float8& a, const float8& b, const float8& c) { return a*b+c; }
|
||||
__forceinline const float8 msub ( const float8& a, const float8& b, const float8& c) { return a*b-c; }
|
||||
__forceinline const float8 nmadd ( const float8& a, const float8& b, const float8& c) { return -a*b+c;}
|
||||
__forceinline const float8 nmsub ( const float8& a, const float8& b, const float8& c) { return -a*b-c; }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float8& operator +=( float8& a, const float8& b ) { return a = a + b; }
|
||||
__forceinline float8& operator +=( float8& a, const float b ) { return a = a + b; }
|
||||
|
||||
__forceinline float8& operator -=( float8& a, const float8& b ) { return a = a - b; }
|
||||
__forceinline float8& operator -=( float8& a, const float b ) { return a = a - b; }
|
||||
|
||||
__forceinline float8& operator *=( float8& a, const float8& b ) { return a = a * b; }
|
||||
__forceinline float8& operator *=( float8& a, const float b ) { return a = a * b; }
|
||||
|
||||
__forceinline float8& operator /=( float8& a, const float8& b ) { return a = a / b; }
|
||||
__forceinline float8& operator /=( float8& a, const float b ) { return a = a / b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator ==( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_EQ_OQ ); }
|
||||
__forceinline const bool8 operator ==( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_EQ_OQ ); }
|
||||
__forceinline const bool8 operator ==( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_EQ_OQ ); }
|
||||
|
||||
__forceinline const bool8 operator !=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_NEQ_OQ); }
|
||||
__forceinline const bool8 operator !=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_NEQ_OQ); }
|
||||
__forceinline const bool8 operator !=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_NEQ_OQ); }
|
||||
|
||||
__forceinline const bool8 operator < ( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LT_OQ ); }
|
||||
__forceinline const bool8 operator < ( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_LT_OQ ); }
|
||||
__forceinline const bool8 operator < ( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_LT_OQ ); }
|
||||
|
||||
__forceinline const bool8 operator >=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GE_OQ); }
|
||||
__forceinline const bool8 operator >=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_GE_OQ); }
|
||||
__forceinline const bool8 operator >=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_GE_OQ); }
|
||||
|
||||
__forceinline const bool8 operator > ( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_GT_OQ); }
|
||||
__forceinline const bool8 operator > ( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_GT_OQ); }
|
||||
__forceinline const bool8 operator > ( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_GT_OQ); }
|
||||
|
||||
__forceinline const bool8 operator <=( const float8& a, const float8& b ) { return _mm256_cmp_ps(a.m256, b.m256, _CMP_LE_OQ ); }
|
||||
__forceinline const bool8 operator <=( const float8& a, const float b ) { return _mm256_cmp_ps(a.m256, float8(b), _CMP_LE_OQ ); }
|
||||
__forceinline const bool8 operator <=( const float a, const float8& b ) { return _mm256_cmp_ps(float8(a), b.m256, _CMP_LE_OQ ); }
|
||||
|
||||
__forceinline const float8 select( const bool8& m, const float8& t, const float8& f ) {
|
||||
return _mm256_blendv_ps(f, t, m);
|
||||
}
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
__forceinline const float8 select(const int m, const float8& t, const float8& f) {
|
||||
return select(bool8(m), t, f); // workaround for clang and Microsoft compiler bugs
|
||||
}
|
||||
#else
|
||||
__forceinline const float8 select( const int m, const float8& t, const float8& f ) {
|
||||
return _mm256_blend_ps(f, t, m);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline float8 lerp(const float8& a, const float8& b, const float8& t) {
|
||||
#if defined(__AVX2__)
|
||||
return madd(t, b, madd(-t, a, a));
|
||||
#else
|
||||
return a + t*(b-a);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline bool isvalid ( const float8& v ) {
|
||||
return all((v > float8(-FLT_LARGE)) & (v < float8(+FLT_LARGE)));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const float8& a ) {
|
||||
return all((a >= float8(-FLT_MAX) & (a <= float8(+FLT_MAX))));
|
||||
}
|
||||
|
||||
__forceinline bool is_finite ( const bool8& valid, const float8& a ) {
|
||||
return all(valid, (a >= float8(-FLT_MAX) & (a <= float8(+FLT_MAX))));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Rounding Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float8 floor ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
|
||||
__forceinline const float8 ceil ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_POS_INF ); }
|
||||
__forceinline const float8 trunc ( const float8& a ) { return _mm256_round_ps(a, _MM_FROUND_TO_ZERO ); }
|
||||
__forceinline const float8 frac ( const float8& a ) { return a-floor(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float8 unpacklo( const float8& a, const float8& b ) { return _mm256_unpacklo_ps(a.m256, b.m256); }
|
||||
__forceinline float8 unpackhi( const float8& a, const float8& b ) { return _mm256_unpackhi_ps(a.m256, b.m256); }
|
||||
|
||||
template<size_t i> __forceinline const float8 shuffle( const float8& a ) {
|
||||
return _mm256_permute_ps(a, _MM_SHUFFLE(i, i, i, i));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const float8 shuffle( const float8& a ) {
|
||||
return _mm256_permute2f128_ps(a, a, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const float8 shuffle( const float8& a, const float8& b) {
|
||||
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float8 shuffle( const float8& a ) {
|
||||
return _mm256_permute_ps(a, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const float8 shuffle( const float8& a, const float8& b ) {
|
||||
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<> __forceinline const float8 shuffle<0, 0, 2, 2>( const float8& b ) { return _mm256_moveldup_ps(b); }
|
||||
template<> __forceinline const float8 shuffle<1, 1, 3, 3>( const float8& b ) { return _mm256_movehdup_ps(b); }
|
||||
template<> __forceinline const float8 shuffle<0, 1, 0, 1>( const float8& b ) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(b))); }
|
||||
|
||||
__forceinline const float8 broadcast(const float* ptr) { return _mm256_broadcast_ss(ptr); }
|
||||
template<size_t i> __forceinline const float8 insert (const float8& a, const float4& b) { return _mm256_insertf128_ps (a,b,i); }
|
||||
template<size_t i> __forceinline const float4 extract (const float8& a ) { return _mm256_extractf128_ps(a ,i); }
|
||||
template<> __forceinline const float4 extract<0>(const float8& a ) { return _mm256_castps256_ps128(a); }
|
||||
|
||||
template<size_t i> __forceinline float fextract (const float8& a ) { return _mm_cvtss_f32(_mm256_extractf128_ps(a ,i)); }
|
||||
|
||||
__forceinline float8 assign( const float4& a ) { return _mm256_castps128_ps256(a); }
|
||||
|
||||
#if defined (__AVX2__)
|
||||
__forceinline float8 permute(const float8 &a, const __m256i &index) {
|
||||
return _mm256_permutevar8x32_ps(a,index);
|
||||
}
|
||||
|
||||
template<int i>
|
||||
__forceinline float8 alignr(const float8 &a, const float8 &b) {
|
||||
return _mm256_castsi256_ps(_mm256_alignr_epi8(_mm256_castps_si256(a), _mm256_castps_si256(b), i));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (__AVX_I__)
|
||||
template<const int mode>
|
||||
__forceinline int4 convert_to_hf16(const float8 &a) {
|
||||
return _mm256_cvtps_ph(a,mode);
|
||||
}
|
||||
|
||||
__forceinline float8 convert_from_hf16(const int4 &a) {
|
||||
return _mm256_cvtph_ps(a);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline float4 broadcast4f( const float8& a, const size_t k ) {
|
||||
return float4::broadcast(&a[k]);
|
||||
}
|
||||
|
||||
__forceinline float8 broadcast8f( const float8& a, const size_t k ) {
|
||||
return float8::broadcast(&a[k]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Transpose
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, float8& c0, float8& c1, float8& c2, float8& c3)
|
||||
{
|
||||
float8 l02 = unpacklo(r0,r2);
|
||||
float8 h02 = unpackhi(r0,r2);
|
||||
float8 l13 = unpacklo(r1,r3);
|
||||
float8 h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
c3 = unpackhi(h02,h13);
|
||||
}
|
||||
|
||||
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, float8& c0, float8& c1, float8& c2)
|
||||
{
|
||||
float8 l02 = unpacklo(r0,r2);
|
||||
float8 h02 = unpackhi(r0,r2);
|
||||
float8 l13 = unpacklo(r1,r3);
|
||||
float8 h13 = unpackhi(r1,r3);
|
||||
c0 = unpacklo(l02,l13);
|
||||
c1 = unpackhi(l02,l13);
|
||||
c2 = unpacklo(h02,h13);
|
||||
}
|
||||
|
||||
__forceinline void transpose(const float8& r0, const float8& r1, const float8& r2, const float8& r3, const float8& r4, const float8& r5, const float8& r6, const float8& r7,
|
||||
float8& c0, float8& c1, float8& c2, float8& c3, float8& c4, float8& c5, float8& c6, float8& c7)
|
||||
{
|
||||
float8 h0,h1,h2,h3; transpose(r0,r1,r2,r3,h0,h1,h2,h3);
|
||||
float8 h4,h5,h6,h7; transpose(r4,r5,r6,r7,h4,h5,h6,h7);
|
||||
c0 = shuffle<0,2>(h0,h4);
|
||||
c1 = shuffle<0,2>(h1,h5);
|
||||
c2 = shuffle<0,2>(h2,h6);
|
||||
c3 = shuffle<0,2>(h3,h7);
|
||||
c4 = shuffle<1,3>(h0,h4);
|
||||
c5 = shuffle<1,3>(h1,h5);
|
||||
c6 = shuffle<1,3>(h2,h6);
|
||||
c7 = shuffle<1,3>(h3,h7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const float8 vreduce_min2(const float8& v) { return min(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const float8 vreduce_min4(const float8& v) { float8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const float8 vreduce_min (const float8& v) { float8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const float8 vreduce_max2(const float8& v) { return max(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const float8 vreduce_max4(const float8& v) { float8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const float8 vreduce_max (const float8& v) { float8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const float8 vreduce_add2(const float8& v) { return v + shuffle<1,0,3,2>(v); }
|
||||
__forceinline const float8 vreduce_add4(const float8& v) { float8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
|
||||
__forceinline const float8 vreduce_add (const float8& v) { float8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
|
||||
|
||||
__forceinline float reduce_min(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_min(v))); }
|
||||
__forceinline float reduce_max(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_max(v))); }
|
||||
__forceinline float reduce_add(const float8& v) { return _mm_cvtss_f32(extract<0>(vreduce_add(v))); }
|
||||
|
||||
__forceinline size_t select_min(const float8& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const float8& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool8& valid, const float8& v) { const float8 a = select(valid,v,float8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
__forceinline size_t select_max(const bool8& valid, const float8& v) { const float8 a = select(valid,v,float8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline float8 load8f( const void* const a) {
|
||||
return _mm256_load_ps((const float*)a);
|
||||
}
|
||||
|
||||
__forceinline void store8f(void *ptr, const float8& f ) {
|
||||
return _mm256_store_ps((float*)ptr,f);
|
||||
}
|
||||
|
||||
__forceinline void storeu8f(void *ptr, const float8& f ) {
|
||||
return _mm256_storeu_ps((float*)ptr,f);
|
||||
}
|
||||
|
||||
__forceinline void store8f( const bool8& mask, void *ptr, const float8& f ) {
|
||||
return _mm256_maskstore_ps((float*)ptr,(__m256i)mask,f);
|
||||
}
|
||||
|
||||
#if defined (__AVX2__)
|
||||
__forceinline float8 load8f_nt(void* ptr) {
|
||||
return _mm256_castsi256_ps(_mm256_stream_load_si256((__m256i*)ptr));
|
||||
}
|
||||
|
||||
#if 0 // FIXME: not compiling under VS2013
|
||||
__forceinline float8 merge2x4(const float& a, const float& b)
|
||||
{
|
||||
const float8 va = broadcast(&a);
|
||||
const float8 vb = broadcast(&b);
|
||||
return select(0b00001111,va,vb);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
__forceinline void store8f_nt(void* ptr, const float8& v) {
|
||||
_mm256_stream_ps((float*)ptr,v);
|
||||
}
|
||||
|
||||
__forceinline const float8 broadcast4f(const void* ptr) {
|
||||
return _mm256_broadcast_ps((__m128*)ptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Euclidian Space Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//__forceinline float8 dot ( const float8& a, const float8& b ) {
|
||||
// return vreduce_add4(a*b);
|
||||
//}
|
||||
|
||||
__forceinline float8 dot ( const float8& a, const float8& b ) {
|
||||
return _mm256_dp_ps(a,b,0x7F);
|
||||
}
|
||||
|
||||
__forceinline float8 cross ( const float8& a, const float8& b )
|
||||
{
|
||||
const float8 a0 = a;
|
||||
const float8 b0 = shuffle<1,2,0,3>(b);
|
||||
const float8 a1 = shuffle<1,2,0,3>(a);
|
||||
const float8 b1 = b;
|
||||
return shuffle<1,2,0,3>(msub(a0,b0,a1*b1));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const float8& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,537 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 16-wide MIC integer type. */
|
||||
class int16
|
||||
{
|
||||
public:
|
||||
|
||||
union {
|
||||
__m512i v;
|
||||
int i[16];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int16() {};
|
||||
__forceinline int16(const int16& t) { v = t.v; };
|
||||
__forceinline int16& operator=(const int16& f) { v = f.v; return *this; };
|
||||
|
||||
__forceinline int16(const __m512i& t) { v = t; };
|
||||
__forceinline operator __m512i () const { return v; };
|
||||
|
||||
__forceinline int16(const int i) {
|
||||
v = _mm512_set_1to16_epi32(i);
|
||||
}
|
||||
|
||||
__forceinline int16(const int a, const int b, const int c, const int d) {
|
||||
v = _mm512_set_4to16_epi32(a,b,c,d);
|
||||
}
|
||||
|
||||
__forceinline explicit int16(const __m512 f) {
|
||||
#if defined(__AVX512F__)
|
||||
v = _mm512_cvt_roundps_epi32(f,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
|
||||
#else
|
||||
v = _mm512_cvtfxpnt_round_adjustps_epi32(f,_MM_FROUND_FLOOR,_MM_EXPADJ_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int16( ZeroTy ) : v(_mm512_setzero_epi32()) {}
|
||||
__forceinline int16( OneTy ) : v(_mm512_set_1to16_epi32(1)) {}
|
||||
__forceinline int16( PosInfTy ) : v(_mm512_set_1to16_epi32(pos_inf)) {}
|
||||
__forceinline int16( NegInfTy ) : v(_mm512_set_1to16_epi32(neg_inf)) {}
|
||||
__forceinline int16( StepTy ) : v(_mm512_set_16to16_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) {}
|
||||
|
||||
__forceinline static int16 zero() { return _mm512_setzero_epi32(); }
|
||||
__forceinline static int16 one () { return _mm512_set_1to16_epi32(1); }
|
||||
__forceinline static int16 neg_one () { return _mm512_set_1to16_epi32(-1); }
|
||||
|
||||
|
||||
static __forceinline int16 loadu(const void* addr)
|
||||
{
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_loadu_si512(addr);
|
||||
#else
|
||||
int16 r = _mm512_undefined_epi32();
|
||||
r =_mm512_extloadunpacklo_epi32(r, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
return _mm512_extloadunpackhi_epi32(r, (int*)addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline int16 load(const void* addr) {
|
||||
return _mm512_load_si512(addr);
|
||||
}
|
||||
|
||||
static __forceinline void store(void* addr, const int16& v2) {
|
||||
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const int16& f ) {
|
||||
#if defined(__AVX512F__)
|
||||
_mm512_storeu_si512(ptr,f);
|
||||
#else
|
||||
_mm512_extpackstorelo_ps((int*)ptr+0 ,_mm512_castsi512_ps(f), _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_extpackstorehi_ps((int*)ptr+16 ,_mm512_castsi512_ps(f), _MM_DOWNCONV_PS_NONE , 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void storeu(const bool16& mask, int* ptr, const int16& f ) {
|
||||
#if defined(__AVX512F__)
|
||||
_mm512_mask_storeu_epi32(ptr,mask,f);
|
||||
#else
|
||||
__m512 r = _mm512_undefined();
|
||||
r = _mm512_extloadunpacklo_ps(r, ptr, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_extloadunpackhi_ps(r, ptr+16, _MM_UPCONV_PS_NONE, _MM_HINT_NONE);
|
||||
r = _mm512_mask_blend_ps(mask,r,_mm512_castsi512_ps(f));
|
||||
_mm512_extpackstorelo_ps(ptr, r, _MM_DOWNCONV_PS_NONE , 0);
|
||||
_mm512_extpackstorehi_ps(ptr+16 ,r, _MM_DOWNCONV_PS_NONE , 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void store(const bool16& mask, void* addr, const int16& v2) {
|
||||
_mm512_mask_store_epi32(addr,mask,v2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int& operator[](const size_t index) { return i[index]; };
|
||||
__forceinline const int& operator[](const size_t index) const { return i[index]; };
|
||||
|
||||
__forceinline unsigned int uint(const size_t index) const { assert(index < 16); return ((unsigned int*)i)[index]; };
|
||||
__forceinline size_t& uint64_t(const size_t index) const { assert(index < 8); return ((size_t*)i)[index]; };
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int16 cast ( const __m512& a) { return _mm512_castps_si512(a); }
|
||||
__forceinline const int16 operator +( const int16& a ) { return a; }
|
||||
__forceinline const int16 operator -( const int16& a ) { return _mm512_sub_epi32(_mm512_setzero_epi32(), a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int16 operator +( const int16& a, const int16& b ) { return _mm512_add_epi32(a, b); }
|
||||
__forceinline const int16 operator +( const int16& a, const int b ) { return a + int16(b); }
|
||||
__forceinline const int16 operator +( const int a, const int16& b ) { return int16(a) + b; }
|
||||
|
||||
__forceinline const int16 operator -( const int16& a, const int16& b ) { return _mm512_sub_epi32(a, b); }
|
||||
__forceinline const int16 operator -( const int16& a, const int b ) { return a - int16(b); }
|
||||
__forceinline const int16 operator -( const int a, const int16& b ) { return int16(a) - b; }
|
||||
|
||||
__forceinline const int16 operator *( const int16& a, const int16& b ) { return _mm512_mullo_epi32(a, b); }
|
||||
__forceinline const int16 operator *( const int16& a, const int b ) { return a * int16(b); }
|
||||
__forceinline const int16 operator *( const int a, const int16& b ) { return int16(a) * b; }
|
||||
|
||||
__forceinline const int16 operator &( const int16& a, const int16& b ) { return _mm512_and_epi32(a, b); }
|
||||
__forceinline const int16 operator &( const int16& a, const int b ) { return a & int16(b); }
|
||||
__forceinline const int16 operator &( const int a, const int16& b ) { return int16(a) & b; }
|
||||
|
||||
__forceinline const int16 operator |( const int16& a, const int16& b ) { return _mm512_or_epi32(a, b); }
|
||||
__forceinline const int16 operator |( const int16& a, const int b ) { return a | int16(b); }
|
||||
__forceinline const int16 operator |( const int a, const int16& b ) { return int16(a) | b; }
|
||||
|
||||
__forceinline const int16 operator ^( const int16& a, const int16& b ) { return _mm512_xor_epi32(a, b); }
|
||||
__forceinline const int16 operator ^( const int16& a, const int b ) { return a ^ int16(b); }
|
||||
__forceinline const int16 operator ^( const int a, const int16& b ) { return int16(a) ^ b; }
|
||||
|
||||
__forceinline const int16 operator <<( const int16& a, const int n ) { return _mm512_slli_epi32(a, n); }
|
||||
__forceinline const int16 operator >>( const int16& a, const int n ) { return _mm512_srai_epi32(a, n); }
|
||||
|
||||
__forceinline const int16 operator <<( const int16& a, const int16& n ) { return _mm512_sllv_epi32(a, n); }
|
||||
__forceinline const int16 operator >>( const int16& a, const int16& n ) { return _mm512_srav_epi32(a, n); }
|
||||
|
||||
__forceinline const int16 sra ( const int16& a, const int b ) { return _mm512_srai_epi32(a, b); }
|
||||
__forceinline const int16 srl ( const int16& a, const int b ) { return _mm512_srli_epi32(a, b); }
|
||||
|
||||
__forceinline const int16 min( const int16& a, const int16& b ) { return _mm512_min_epi32(a, b); }
|
||||
__forceinline const int16 min( const int16& a, const int b ) { return min(a,int16(b)); }
|
||||
__forceinline const int16 min( const int a, const int16& b ) { return min(int16(a),b); }
|
||||
|
||||
__forceinline const int16 max( const int16& a, const int16& b ) { return _mm512_max_epi32(a, b); }
|
||||
__forceinline const int16 max( const int16& a, const int b ) { return max(a,int16(b)); }
|
||||
__forceinline const int16 max( const int a, const int16& b ) { return max(int16(a),b); }
|
||||
|
||||
__forceinline const int16 mask_add(const bool16& mask, int16& c, const int16& a, const int16& b) { return _mm512_mask_add_epi32(c,mask,a,b); };
|
||||
__forceinline const int16 mask_sub(const bool16& mask, int16& c, const int16& a, const int16& b) { return _mm512_mask_sub_epi32(c,mask,a,b); };
|
||||
|
||||
__forceinline const int16 mask_and(const bool16& m,int16& c, const int16& a, const int16& b) { return _mm512_mask_and_epi32(c,m,a,b); };
|
||||
__forceinline const int16 mask_or (const bool16& m,int16& c, const int16& a, const int16& b) { return _mm512_mask_or_epi32(c,m,a,b); };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int16& operator +=( int16& a, const int16& b ) { return a = a + b; }
|
||||
__forceinline int16& operator +=( int16& a, const int b ) { return a = a + b; }
|
||||
|
||||
__forceinline int16& operator -=( int16& a, const int16& b ) { return a = a - b; }
|
||||
__forceinline int16& operator -=( int16& a, const int b ) { return a = a - b; }
|
||||
|
||||
__forceinline int16& operator *=( int16& a, const int16& b ) { return a = a * b; }
|
||||
__forceinline int16& operator *=( int16& a, const int b ) { return a = a * b; }
|
||||
|
||||
__forceinline int16& operator &=( int16& a, const int16& b ) { return a = a & b; }
|
||||
__forceinline int16& operator &=( int16& a, const int b ) { return a = a & b; }
|
||||
|
||||
__forceinline int16& operator |=( int16& a, const int16& b ) { return a = a | b; }
|
||||
__forceinline int16& operator |=( int16& a, const int b ) { return a = a | b; }
|
||||
|
||||
__forceinline int16& operator <<=( int16& a, const int b ) { return a = a << b; }
|
||||
__forceinline int16& operator >>=( int16& a, const int b ) { return a = a >> b; }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool16 operator ==( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); }
|
||||
__forceinline const bool16 operator ==( const int16& a, const int b ) { return a == int16(b); }
|
||||
__forceinline const bool16 operator ==( const int a, const int16& b ) { return int16(a) == b; }
|
||||
|
||||
__forceinline const bool16 operator !=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); }
|
||||
__forceinline const bool16 operator !=( const int16& a, const int b ) { return a != int16(b); }
|
||||
__forceinline const bool16 operator !=( const int a, const int16& b ) { return int16(a) != b; }
|
||||
|
||||
__forceinline const bool16 operator < ( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); }
|
||||
__forceinline const bool16 operator < ( const int16& a, const int b ) { return a < int16(b); }
|
||||
__forceinline const bool16 operator < ( const int a, const int16& b ) { return int16(a) < b; }
|
||||
|
||||
__forceinline const bool16 operator >=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); }
|
||||
__forceinline const bool16 operator >=( const int16& a, const int b ) { return a >= int16(b); }
|
||||
__forceinline const bool16 operator >=( const int a, const int16& b ) { return int16(a) >= b; }
|
||||
|
||||
__forceinline const bool16 operator > ( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); }
|
||||
__forceinline const bool16 operator > ( const int16& a, const int b ) { return a > int16(b); }
|
||||
__forceinline const bool16 operator > ( const int a, const int16& b ) { return int16(a) > b; }
|
||||
|
||||
__forceinline const bool16 operator <=( const int16& a, const int16& b ) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); }
|
||||
__forceinline const bool16 operator <=( const int16& a, const int b ) { return a <= int16(b); }
|
||||
__forceinline const bool16 operator <=( const int a, const int16& b ) { return int16(a) <= b; }
|
||||
|
||||
__forceinline bool16 eq( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_EQ); };
|
||||
__forceinline bool16 eq(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_EQ); };
|
||||
|
||||
__forceinline bool16 ne( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_NE); };
|
||||
__forceinline bool16 ne(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_NE); };
|
||||
|
||||
__forceinline bool16 lt( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LT); };
|
||||
__forceinline bool16 lt(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LT); };
|
||||
|
||||
__forceinline bool16 ge( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GE); };
|
||||
__forceinline bool16 ge(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GE); };
|
||||
|
||||
__forceinline bool16 gt( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_GT); };
|
||||
__forceinline bool16 gt(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_GT); };
|
||||
|
||||
__forceinline bool16 le( const int16& a, const int16& b) { return _mm512_cmp_epi32_mask(a,b,_MM_CMPINT_LE); };
|
||||
__forceinline bool16 le(const bool16 mask, const int16& a, const int16& b) { return _mm512_mask_cmp_epi32_mask(mask,a,b,_MM_CMPINT_LE); };
|
||||
|
||||
|
||||
__forceinline const int16 select( const bool16& m, const int16& t, const int16& f ) {
|
||||
return _mm512_mask_or_epi32(f,m,t,t);
|
||||
}
|
||||
|
||||
__forceinline void xchg(const bool16& m, int16& a, int16& b) {
|
||||
const int16 c = a; a = select(m,b,a); b = select(m,c,b);
|
||||
}
|
||||
|
||||
__forceinline bool16 test(const bool16& m, const int16& a, const int16& b) {
|
||||
return _mm512_mask_test_epi32_mask(m,a,b);
|
||||
}
|
||||
|
||||
__forceinline bool16 test(const int16& a, const int16& b) {
|
||||
return _mm512_test_epi32_mask(a,b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int16 swizzle(const int16& x,_MM_SWIZZLE_ENUM perm32 ) { return _mm512_swizzle_epi32(x,perm32); }
|
||||
__forceinline int16 permute(const int16& x,_MM_PERM_ENUM perm128) { return _mm512_permute4f128_epi32(x,perm128); }
|
||||
|
||||
template<int D, int C, int B, int A> __forceinline int16 swizzle (const int16& v) { return _mm512_shuffle_epi32(v,_MM_SHUF_PERM(D,C,B,A)); }
|
||||
template<int A> __forceinline int16 swizzle (const int16& x) { return swizzle<A,A,A,A>(v); }
|
||||
template<> __forceinline int16 swizzle<0>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_AAAA); }
|
||||
template<> __forceinline int16 swizzle<1>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_BBBB); }
|
||||
template<> __forceinline int16 swizzle<2>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_CCCC); }
|
||||
template<> __forceinline int16 swizzle<3>(const int16& x) { return swizzle(x,_MM_SWIZ_REG_DDDD); }
|
||||
|
||||
template<int D, int C, int B, int A> __forceinline int16 permute(const int16& v) { return permute(v,_MM_SHUF_PERM(D,C,B,A)); }
|
||||
template<int A> __forceinline int16 permute(const int16& x) { return permute<A,A,A,A>(x); }
|
||||
|
||||
__forceinline int16 shuffle(const int16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) { return swizzle(permute(x,perm128),perm32); }
|
||||
|
||||
__forceinline int16 shuffle(const bool16& mask, int16& v, const int16& x,_MM_PERM_ENUM perm128, _MM_SWIZZLE_ENUM perm32) {
|
||||
return _mm512_mask_swizzle_epi32(_mm512_mask_permute4f128_epi32(v,mask,x,perm128),mask,x,perm32);
|
||||
}
|
||||
|
||||
__forceinline int16 swAAAA(const int16& x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_AAAA);
|
||||
}
|
||||
|
||||
__forceinline int16 swBBBB(const int16& x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_BBBB);
|
||||
}
|
||||
|
||||
__forceinline int16 swCCCC(const int16& x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_CCCC);
|
||||
}
|
||||
|
||||
__forceinline int16 swDDDD(const int16& x) {
|
||||
return swizzle(x,_MM_SWIZ_REG_DDDD);
|
||||
}
|
||||
|
||||
template<int i>
|
||||
__forceinline int16 align_shift_right(const int16& a, const int16& b)
|
||||
{
|
||||
return _mm512_alignr_epi32(a,b,i);
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int reduce_add(int16 a) { return _mm512_reduce_add_epi32(a); }
|
||||
__forceinline int reduce_mul(int16 a) { return _mm512_reduce_mul_epi32(a); }
|
||||
__forceinline int reduce_min(int16 a) { return _mm512_reduce_min_epi32(a); }
|
||||
__forceinline int reduce_max(int16 a) { return _mm512_reduce_max_epi32(a); }
|
||||
__forceinline int reduce_and(int16 a) { return _mm512_reduce_and_epi32(a); }
|
||||
|
||||
__forceinline int16 vreduce_min2(int16 x) { return min(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
|
||||
__forceinline int16 vreduce_min4(int16 x) { x = vreduce_min2(x); return min(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
|
||||
__forceinline int16 vreduce_min8(int16 x) { x = vreduce_min4(x); return min(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
|
||||
__forceinline int16 vreduce_min (int16 x) { x = vreduce_min8(x); return min(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
|
||||
|
||||
__forceinline int16 vreduce_max2(int16 x) { return max(x,swizzle(x,_MM_SWIZ_REG_BADC)); }
|
||||
__forceinline int16 vreduce_max4(int16 x) { x = vreduce_max2(x); return max(x,swizzle(x,_MM_SWIZ_REG_CDAB)); }
|
||||
__forceinline int16 vreduce_max8(int16 x) { x = vreduce_max4(x); return max(x,permute(x,_MM_SHUF_PERM(2,3,0,1))); }
|
||||
__forceinline int16 vreduce_max (int16 x) { x = vreduce_max8(x); return max(x,permute(x,_MM_SHUF_PERM(1,0,3,2))); }
|
||||
|
||||
__forceinline int16 vreduce_and2(int16 x) { return x & swizzle(x,_MM_SWIZ_REG_BADC); }
|
||||
__forceinline int16 vreduce_and4(int16 x) { x = vreduce_and2(x); return x & swizzle(x,_MM_SWIZ_REG_CDAB); }
|
||||
__forceinline int16 vreduce_and8(int16 x) { x = vreduce_and4(x); return x & permute(x,_MM_SHUF_PERM(2,3,0,1)); }
|
||||
__forceinline int16 vreduce_and (int16 x) { x = vreduce_and8(x); return x & permute(x,_MM_SHUF_PERM(1,0,3,2)); }
|
||||
|
||||
__forceinline int16 vreduce_or2(int16 x) { return x | swizzle(x,_MM_SWIZ_REG_BADC); }
|
||||
__forceinline int16 vreduce_or4(int16 x) { x = vreduce_or2(x); return x | swizzle(x,_MM_SWIZ_REG_CDAB); }
|
||||
__forceinline int16 vreduce_or8(int16 x) { x = vreduce_or4(x); return x | permute(x,_MM_SHUF_PERM(2,3,0,1)); }
|
||||
__forceinline int16 vreduce_or (int16 x) { x = vreduce_or8(x); return x | permute(x,_MM_SHUF_PERM(1,0,3,2)); }
|
||||
|
||||
__forceinline int16 vreduce_add2(int16 x) { return x + swizzle(x,_MM_SWIZ_REG_BADC); }
|
||||
__forceinline int16 vreduce_add4(int16 x) { x = vreduce_add2(x); return x + swizzle(x,_MM_SWIZ_REG_CDAB); }
|
||||
__forceinline int16 vreduce_add8(int16 x) { x = vreduce_add4(x); return x + permute(x,_MM_SHUF_PERM(2,3,0,1)); }
|
||||
__forceinline int16 vreduce_add (int16 x) { x = vreduce_add8(x); return x + permute(x,_MM_SHUF_PERM(1,0,3,2)); }
|
||||
|
||||
__forceinline int16 prefix_sum(const int16& a)
|
||||
{
|
||||
int16 v = a;
|
||||
v = mask_add(0xaaaa,v,v,swizzle(v,_MM_SWIZ_REG_CDAB));
|
||||
v = mask_add(0xcccc,v,v,swizzle(v,_MM_SWIZ_REG_BBBB));
|
||||
const int16 shuf_v0 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(2,2,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_add(0xf0f0,v,v,shuf_v0);
|
||||
const int16 shuf_v1 = shuffle(v,(_MM_PERM_ENUM)_MM_SHUF_PERM(1,1,0,0),_MM_SWIZ_REG_DDDD);
|
||||
v = mask_add(0xff00,v,v,shuf_v1);
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int16 load1i(const int *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 load16i(const int *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_16X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 load1i_uint8(const unsigned char *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST_1X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 load16i_uint8(const unsigned char *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_UINT8,_MM_BROADCAST32_NONE,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 broadcast4to16i(const int *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_4X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 broadcast1to16i(const int *const ptr) {
|
||||
return _mm512_extload_epi32(ptr,_MM_UPCONV_EPI32_NONE,_MM_BROADCAST_1X16,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 uload16i(const int *const addr) {
|
||||
int16 r = _mm512_undefined_epi32();
|
||||
r =_mm512_extloadunpacklo_epi32(r, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
return _mm512_extloadunpackhi_epi32(r, addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 uload16i_low(const bool16& mask, const void* addr) {
|
||||
int16 v = _mm512_undefined_epi32();
|
||||
return _mm512_mask_extloadunpacklo_epi32(v, mask, addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 uload16i(const bool16& mask,const int *const addr) {
|
||||
int16 r = _mm512_undefined_epi32();
|
||||
r =_mm512_mask_extloadunpacklo_epi32(r, mask,addr, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
return _mm512_mask_extloadunpackhi_epi32(r, mask,addr+16, _MM_UPCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
|
||||
__forceinline int16 gather16i_4i(const int *__restrict__ const ptr0,
|
||||
const int *__restrict__ const ptr1,
|
||||
const int *__restrict__ const ptr2,
|
||||
const int *__restrict__ const ptr3)
|
||||
{
|
||||
int16 v = broadcast4to16i(ptr0);
|
||||
v = select((bool16)0xf0 , broadcast4to16i(ptr1),v);
|
||||
v = select((bool16)0xf00 , broadcast4to16i(ptr2),v);
|
||||
v = select((bool16)0xf000, broadcast4to16i(ptr3),v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
__forceinline int16 gather16i_4i_align(const void *__restrict__ const ptr0,
|
||||
const void *__restrict__ const ptr1,
|
||||
const void *__restrict__ const ptr2,
|
||||
const void *__restrict__ const ptr3)
|
||||
{
|
||||
int16 v = broadcast4to16i((const int*)ptr3);
|
||||
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr2));
|
||||
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr1));
|
||||
v = align_shift_right<12>(v,broadcast4to16i((const int*)ptr0));
|
||||
return v;
|
||||
}
|
||||
|
||||
__forceinline int16 gather16i_4i_align(const int16& v0,
|
||||
const int16& v1,
|
||||
const int16& v2,
|
||||
const int16& v3)
|
||||
{
|
||||
int16 v = v3;
|
||||
v = align_shift_right<12>(v,v2);
|
||||
v = align_shift_right<12>(v,v1);
|
||||
v = align_shift_right<12>(v,v0);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
__forceinline int16 gather16i(const bool16& mask, const int *const ptr, const int16& index,const _MM_INDEX_SCALE_ENUM scale) {
|
||||
return _mm512_mask_i32extgather_epi32(_mm512_undefined_epi32(),mask,index,ptr,_MM_UPCONV_EPI32_NONE,scale,0);
|
||||
}
|
||||
|
||||
__forceinline int16 gather16i(const bool16& mask, int16& dest, const int *const ptr, const int16& index,const _MM_INDEX_SCALE_ENUM scale) {
|
||||
return _mm512_mask_i32extgather_epi32(dest,mask,index,ptr,_MM_UPCONV_EPI32_NONE,scale,0);
|
||||
}
|
||||
|
||||
__forceinline void scatter16i(const bool16& mask,int *const ptr, const int16& index,const int16& v, const _MM_INDEX_SCALE_ENUM scale) {
|
||||
_mm512_mask_i32extscatter_epi32((int*)ptr,mask,index,v,_MM_DOWNCONV_EPI32_NONE,scale,0);
|
||||
}
|
||||
|
||||
__forceinline void ustore16i(void *addr, const int16& reg) {
|
||||
_mm512_extpackstorelo_epi32((int*)addr+0 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
_mm512_extpackstorehi_epi32((int*)addr+16 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
/* pass by value to avoid compiler generating inefficient code */
|
||||
__forceinline void compactustore16i(const bool16 mask,void * addr, const int16 reg) {
|
||||
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
_mm512_mask_extpackstorehi_epi32((int*)addr+16 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
|
||||
__forceinline void compactustore16i_low(const bool16 mask, void *addr, const int16& reg) {
|
||||
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void store1i(void *addr, const int16& reg) {
|
||||
_mm512_mask_extpackstorelo_epi32((int*)addr+0 ,(bool16)1, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void ustore16i_low(void *addr, const int16& reg) {
|
||||
_mm512_extpackstorelo_epi32((int*)addr+0 ,reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void compactustore16i_high(const bool16 mask, int *addr, const int16& reg) {
|
||||
_mm512_mask_extpackstorehi_epi32((int*)addr+16 ,mask, reg, _MM_DOWNCONV_EPI32_NONE, _MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void store16i_nr(void *__restrict__ ptr, const int16& a) {
|
||||
_mm512_storenr_ps(ptr,_mm512_castsi512_ps(a));
|
||||
}
|
||||
|
||||
__forceinline void store16i_ngo(void *__restrict__ ptr, const int16& a) {
|
||||
_mm512_storenrngo_ps(ptr,_mm512_castsi512_ps(a));
|
||||
}
|
||||
|
||||
__forceinline void store16i(const bool16& mask, void* __restrict__ addr, const int16& v2) {
|
||||
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
|
||||
__forceinline void store16i_nt(void* __restrict__ addr, const int16& v2) {
|
||||
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NT);
|
||||
}
|
||||
|
||||
__forceinline void store16i(void* __restrict__ addr, const int16& v2) {
|
||||
_mm512_extstore_epi32(addr,v2,_MM_DOWNCONV_EPI32_NONE,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline void store16i_uint8(const bool16& mask, void* __restrict__ addr, const int16& v2) {
|
||||
_mm512_mask_extstore_epi32(addr,mask,v2,_MM_DOWNCONV_EPI32_UINT8,_MM_HINT_NONE);
|
||||
}
|
||||
|
||||
__forceinline int16 convert_uint32_t(const __m512 f) {
|
||||
#if defined(__AVX512F__)
|
||||
return _mm512_cvt_roundps_epu32(f,_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // FIXME: round down as default?
|
||||
#else
|
||||
return _mm512_cvtfxpnt_round_adjustps_epu32(f,_MM_FROUND_TO_ZERO,_MM_EXPADJ_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline std::ostream& operator<<(std::ostream& cout, const int16& v)
|
||||
{
|
||||
cout << "<" << v[0];
|
||||
for (int i=1; i<16; i++) cout << ", " << v[i];
|
||||
cout << ">";
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../math/math.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 4-wide SSE integer type. */
|
||||
struct int4
|
||||
{
|
||||
typedef bool4 Mask; // mask type
|
||||
typedef int4 Int; // int type
|
||||
typedef float4 Float; // float type
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { __m128i m128; int i[4]; }; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int4 ( ) {}
|
||||
__forceinline int4 ( const int4& a ) { m128 = a.m128; }
|
||||
__forceinline int4& operator=( const int4& a ) { m128 = a.m128; return *this; }
|
||||
|
||||
__forceinline int4( const __m128i a ) : m128(a) {}
|
||||
__forceinline operator const __m128i&( void ) const { return m128; }
|
||||
__forceinline operator __m128i&( void ) { return m128; }
|
||||
|
||||
__forceinline int4 ( const int& a ) : m128(_mm_shuffle_epi32(_mm_castps_si128(_mm_load_ss((float*)&a)), _MM_SHUFFLE(0, 0, 0, 0))) {}
|
||||
__forceinline int4 ( const uint32_t& a ) : m128(_mm_shuffle_epi32(_mm_castps_si128(_mm_load_ss((float*)&a)), _MM_SHUFFLE(0, 0, 0, 0))) {}
|
||||
#if defined(__X86_64__)
|
||||
__forceinline int4 ( const size_t a ) : m128(_mm_set1_epi32((int)a)) {}
|
||||
#endif
|
||||
__forceinline int4 ( int a, int b, int c, int d) : m128(_mm_set_epi32(d, c, b, a)) {}
|
||||
|
||||
__forceinline explicit int4( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int4( ZeroTy ) : m128(_mm_setzero_si128()) {}
|
||||
__forceinline int4( OneTy ) : m128(_mm_set_epi32(1, 1, 1, 1)) {}
|
||||
__forceinline int4( PosInfTy ) : m128(_mm_set_epi32(pos_inf, pos_inf, pos_inf, pos_inf)) {}
|
||||
__forceinline int4( NegInfTy ) : m128(_mm_set_epi32(neg_inf, neg_inf, neg_inf, neg_inf)) {}
|
||||
__forceinline int4( StepTy ) : m128(_mm_set_epi32(3, 2, 1, 0)) {}
|
||||
__forceinline int4( TrueTy ) { m128 = _mm_cmpeq_epi32(m128,m128); }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
static __forceinline int4 load( const unsigned char* const ptr ) {
|
||||
return _mm_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr));
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline int4 load(const unsigned short* const ptr)
|
||||
{
|
||||
#if defined (__SSE4_1__)
|
||||
return _mm_cvtepu16_epi32(_mm_loadu_si128((__m128i*)ptr));
|
||||
#else
|
||||
return int4(ptr[0],ptr[1],ptr[2],ptr[3]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline int4 load( const void* const a ) {
|
||||
return _mm_load_si128((__m128i*)a);
|
||||
}
|
||||
|
||||
static __forceinline int4 loadu( const void* const a ) {
|
||||
return _mm_loadu_si128((__m128i*)a);
|
||||
}
|
||||
|
||||
static __forceinline void store(void* ptr, const int4& v) {
|
||||
_mm_store_si128((__m128i*)ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const int4& v) {
|
||||
_mm_storeu_si128((__m128i*)ptr,v);
|
||||
}
|
||||
|
||||
static __forceinline void store( const bool4& mask, void* ptr, const int4& i ) {
|
||||
#if defined (__AVX__)
|
||||
_mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i));
|
||||
#else
|
||||
*(int4*)ptr = select(mask,i,*(int4*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline int4 load_nt (void* ptr) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_stream_load_si128((__m128i*)ptr);
|
||||
#else
|
||||
return _mm_load_si128((__m128i*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline void store_nt(void* ptr, const int4& v) {
|
||||
#if defined(__SSE4_1__)
|
||||
_mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
|
||||
#else
|
||||
_mm_store_si128((__m128i*)ptr,v);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int& operator []( const size_t index ) const { assert(index < 4); return i[index]; }
|
||||
__forceinline int& operator []( const size_t index ) { assert(index < 4); return i[index]; }
|
||||
|
||||
friend __forceinline const int4 select( const bool4& m, const int4& t, const int4& f ) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
|
||||
#else
|
||||
return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int4 cast ( const __m128& a ) { return _mm_castps_si128(a); }
|
||||
__forceinline const int4 operator +( const int4& a ) { return a; }
|
||||
__forceinline const int4 operator -( const int4& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
|
||||
#if defined(__SSSE3__)
|
||||
__forceinline const int4 abs ( const int4& a ) { return _mm_abs_epi32(a.m128); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int4 operator +( const int4& a, const int4& b ) { return _mm_add_epi32(a.m128, b.m128); }
|
||||
__forceinline const int4 operator +( const int4& a, const int& b ) { return a + int4(b); }
|
||||
__forceinline const int4 operator +( const int& a, const int4& b ) { return int4(a) + b; }
|
||||
|
||||
__forceinline const int4 operator -( const int4& a, const int4& b ) { return _mm_sub_epi32(a.m128, b.m128); }
|
||||
__forceinline const int4 operator -( const int4& a, const int& b ) { return a - int4(b); }
|
||||
__forceinline const int4 operator -( const int& a, const int4& b ) { return int4(a) - b; }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline const int4 operator *( const int4& a, const int4& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
|
||||
#else
|
||||
__forceinline const int4 operator *( const int4& a, const int4& b ) { return int4(a[0]*b[0],a[1]*b[1],a[2]*b[2],a[3]*b[3]); }
|
||||
#endif
|
||||
__forceinline const int4 operator *( const int4& a, const int& b ) { return a * int4(b); }
|
||||
__forceinline const int4 operator *( const int& a, const int4& b ) { return int4(a) * b; }
|
||||
|
||||
__forceinline const int4 operator &( const int4& a, const int4& b ) { return _mm_and_si128(a.m128, b.m128); }
|
||||
__forceinline const int4 operator &( const int4& a, const int& b ) { return a & int4(b); }
|
||||
__forceinline const int4 operator &( const int& a, const int4& b ) { return int4(a) & b; }
|
||||
|
||||
__forceinline const int4 operator |( const int4& a, const int4& b ) { return _mm_or_si128(a.m128, b.m128); }
|
||||
__forceinline const int4 operator |( const int4& a, const int& b ) { return a | int4(b); }
|
||||
__forceinline const int4 operator |( const int& a, const int4& b ) { return int4(a) | b; }
|
||||
|
||||
__forceinline const int4 operator ^( const int4& a, const int4& b ) { return _mm_xor_si128(a.m128, b.m128); }
|
||||
__forceinline const int4 operator ^( const int4& a, const int& b ) { return a ^ int4(b); }
|
||||
__forceinline const int4 operator ^( const int& a, const int4& b ) { return int4(a) ^ b; }
|
||||
|
||||
__forceinline const int4 operator <<( const int4& a, const int& n ) { return _mm_slli_epi32(a.m128, n); }
|
||||
__forceinline const int4 operator >>( const int4& a, const int& n ) { return _mm_srai_epi32(a.m128, n); }
|
||||
|
||||
__forceinline const int4 sra ( const int4& a, const int& b ) { return _mm_srai_epi32(a.m128, b); }
|
||||
__forceinline const int4 srl ( const int4& a, const int& b ) { return _mm_srli_epi32(a.m128, b); }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline const int4 min( const int4& a, const int4& b ) { return _mm_min_epi32(a.m128, b.m128); }
|
||||
__forceinline const int4 max( const int4& a, const int4& b ) { return _mm_max_epi32(a.m128, b.m128); }
|
||||
|
||||
__forceinline const int4 umin( const int4& a, const int4& b ) { return _mm_min_epu32(a.m128, b.m128); }
|
||||
__forceinline const int4 umax( const int4& a, const int4& b ) { return _mm_max_epu32(a.m128, b.m128); }
|
||||
|
||||
#else
|
||||
__forceinline const int4 min( const int4& a, const int4& b ) { return int4(min(a[0],b[0]),min(a[1],b[1]),min(a[2],b[2]),min(a[3],b[3])); }
|
||||
__forceinline const int4 max( const int4& a, const int4& b ) { return int4(max(a[0],b[0]),max(a[1],b[1]),max(a[2],b[2]),max(a[3],b[3])); }
|
||||
#endif
|
||||
|
||||
__forceinline const int4 min( const int4& a, const int& b ) { return min(a,int4(b)); }
|
||||
__forceinline const int4 min( const int& a, const int4& b ) { return min(int4(a),b); }
|
||||
__forceinline const int4 max( const int4& a, const int& b ) { return max(a,int4(b)); }
|
||||
__forceinline const int4 max( const int& a, const int4& b ) { return max(int4(a),b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int4& operator +=( int4& a, const int4& b ) { return a = a + b; }
|
||||
__forceinline int4& operator +=( int4& a, const int& b ) { return a = a + b; }
|
||||
|
||||
__forceinline int4& operator -=( int4& a, const int4& b ) { return a = a - b; }
|
||||
__forceinline int4& operator -=( int4& a, const int& b ) { return a = a - b; }
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline int4& operator *=( int4& a, const int4& b ) { return a = a * b; }
|
||||
__forceinline int4& operator *=( int4& a, const int& b ) { return a = a * b; }
|
||||
#endif
|
||||
|
||||
__forceinline int4& operator &=( int4& a, const int4& b ) { return a = a & b; }
|
||||
__forceinline int4& operator &=( int4& a, const int& b ) { return a = a & b; }
|
||||
|
||||
__forceinline int4& operator |=( int4& a, const int4& b ) { return a = a | b; }
|
||||
__forceinline int4& operator |=( int4& a, const int& b ) { return a = a | b; }
|
||||
|
||||
__forceinline int4& operator <<=( int4& a, const int& b ) { return a = a << b; }
|
||||
__forceinline int4& operator >>=( int4& a, const int& b ) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool4 operator ==( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m128, b.m128)); }
|
||||
__forceinline const bool4 operator ==( const int4& a, const int& b ) { return a == int4(b); }
|
||||
__forceinline const bool4 operator ==( const int& a, const int4& b ) { return int4(a) == b; }
|
||||
|
||||
__forceinline const bool4 operator !=( const int4& a, const int4& b ) { return !(a == b); }
|
||||
__forceinline const bool4 operator !=( const int4& a, const int& b ) { return a != int4(b); }
|
||||
__forceinline const bool4 operator !=( const int& a, const int4& b ) { return int4(a) != b; }
|
||||
|
||||
__forceinline const bool4 operator < ( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
|
||||
__forceinline const bool4 operator < ( const int4& a, const int& b ) { return a < int4(b); }
|
||||
__forceinline const bool4 operator < ( const int& a, const int4& b ) { return int4(a) < b; }
|
||||
|
||||
__forceinline const bool4 operator >=( const int4& a, const int4& b ) { return !(a < b); }
|
||||
__forceinline const bool4 operator >=( const int4& a, const int& b ) { return a >= int4(b); }
|
||||
__forceinline const bool4 operator >=( const int& a, const int4& b ) { return int4(a) >= b; }
|
||||
|
||||
__forceinline const bool4 operator > ( const int4& a, const int4& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
|
||||
__forceinline const bool4 operator > ( const int4& a, const int& b ) { return a > int4(b); }
|
||||
__forceinline const bool4 operator > ( const int& a, const int4& b ) { return int4(a) > b; }
|
||||
|
||||
__forceinline const bool4 operator <=( const int4& a, const int4& b ) { return !(a > b); }
|
||||
__forceinline const bool4 operator <=( const int4& a, const int& b ) { return a <= int4(b); }
|
||||
__forceinline const bool4 operator <=( const int& a, const int4& b ) { return int4(a) <= b; }
|
||||
|
||||
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER) // FIXME: can this get removed?
|
||||
__forceinline const int4 select(const int mask, const int4& t, const int4& f) {
|
||||
return select(bool4(mask), t, f);
|
||||
}
|
||||
#else
|
||||
__forceinline const int4 select(const int m, const int4& t, const int4& f) {
|
||||
return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int4 unpacklo( const int4& a, const int4& b ) { return _mm_castps_si128(_mm_unpacklo_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
|
||||
__forceinline int4 unpackhi( const int4& a, const int4& b ) { return _mm_castps_si128(_mm_unpackhi_ps(_mm_castsi128_ps(a.m128), _mm_castsi128_ps(b.m128))); }
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int4 shuffle( const int4& a ) {
|
||||
return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int4 shuffle( const int4& a, const int4& b ) {
|
||||
return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
#if defined(__SSE3__)
|
||||
template<> __forceinline const int4 shuffle<0, 0, 2, 2>( const int4& a ) { return _mm_castps_si128(_mm_moveldup_ps(_mm_castsi128_ps(a))); }
|
||||
template<> __forceinline const int4 shuffle<1, 1, 3, 3>( const int4& a ) { return _mm_castps_si128(_mm_movehdup_ps(_mm_castsi128_ps(a))); }
|
||||
template<> __forceinline const int4 shuffle<0, 1, 0, 1>( const int4& a ) { return _mm_castpd_si128(_mm_movedup_pd (_mm_castsi128_pd(a))); }
|
||||
#endif
|
||||
|
||||
template<size_t i0> __forceinline const int4 shuffle( const int4& b ) {
|
||||
return shuffle<i0,i0,i0,i0>(b);
|
||||
}
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
template<size_t src> __forceinline int extract( const int4& b ) { return _mm_extract_epi32(b, src); }
|
||||
template<size_t dst> __forceinline const int4 insert( const int4& a, const int b ) { return _mm_insert_epi32(a, b, dst); }
|
||||
#else
|
||||
template<size_t src> __forceinline int extract( const int4& b ) { return b[src]; }
|
||||
template<size_t dst> __forceinline const int4 insert( const int4& a, const int b ) { int4 c = a; c[dst] = b; return c; }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline const int4 vreduce_min(const int4& v) { int4 h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
|
||||
__forceinline const int4 vreduce_max(const int4& v) { int4 h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
|
||||
__forceinline const int4 vreduce_add(const int4& v) { int4 h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
|
||||
|
||||
__forceinline int reduce_min(const int4& v) { return extract<0>(vreduce_min(v)); }
|
||||
__forceinline int reduce_max(const int4& v) { return extract<0>(vreduce_max(v)); }
|
||||
__forceinline int reduce_add(const int4& v) { return extract<0>(vreduce_add(v)); }
|
||||
|
||||
__forceinline size_t select_min(const int4& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const int4& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool4& valid, const int4& v) { const int4 a = select(valid,v,int4(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
__forceinline size_t select_max(const bool4& valid, const int4& v) { const int4 a = select(valid,v,int4(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
#else
|
||||
|
||||
__forceinline int reduce_min(const int4& v) { return min(v[0],v[1],v[2],v[3]); }
|
||||
__forceinline int reduce_max(const int4& v) { return max(v[0],v[1],v[2],v[3]); }
|
||||
__forceinline int reduce_add(const int4& v) { return v[0]+v[1]+v[2]+v[3]; }
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int4 load4i( const void* const a ) {
|
||||
return _mm_load_si128((__m128i*)a);
|
||||
}
|
||||
|
||||
__forceinline int4 loadu4i( const void* const a ) {
|
||||
return _mm_loadu_si128((__m128i*)a);
|
||||
}
|
||||
|
||||
__forceinline void store4i(void* ptr, const int4& v) {
|
||||
_mm_store_si128((__m128i*)ptr,v);
|
||||
}
|
||||
|
||||
__forceinline void storeu4i(void* ptr, const int4& v) {
|
||||
_mm_storeu_si128((__m128i*)ptr,v);
|
||||
}
|
||||
|
||||
__forceinline void store4i( const bool4& mask, void* ptr, const int4& i ) {
|
||||
#if defined (__AVX__)
|
||||
_mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i));
|
||||
#else
|
||||
*(int4*)ptr = select(mask,i,*(int4*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline int4 load4i_nt (void* ptr) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_stream_load_si128((__m128i*)ptr);
|
||||
#else
|
||||
return _mm_load_si128((__m128i*)ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void store4i_nt(void* ptr, const int4& v) {
|
||||
#if defined(__SSE4_1__)
|
||||
_mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
|
||||
#else
|
||||
_mm_store_si128((__m128i*)ptr,v);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0 // FIXME: not compiling under VS2013
|
||||
#if defined (__AVX2__)
|
||||
|
||||
__forceinline int4 networkSort(const int4 &v)
|
||||
{
|
||||
const int4 a0 = v;
|
||||
const int4 b0 = shuffle<1,0,3,2>(a0);
|
||||
const int4 c0 = umin(a0,b0);
|
||||
const int4 d0 = umax(a0,b0);
|
||||
const int4 a1 = select(0b0101,c0,d0);
|
||||
const int4 b1 = shuffle<2,3,0,1>(a1);
|
||||
const int4 c1 = umin(a1,b1);
|
||||
//const unsigned int min_dist_index = extract<0>(c1) & 3;
|
||||
// 2 case border?
|
||||
//assert(min_dist_index < 4);
|
||||
const int4 d1 = umax(a1,b1);
|
||||
const int4 a2 = select(0b0011,c1,d1);
|
||||
const int4 b2 = shuffle<0,2,1,3>(a2);
|
||||
const int4 c2 = umin(a2,b2);
|
||||
const int4 d2 = umax(a2,b2);
|
||||
const int4 a3 = select(0b0010,c2,d2);
|
||||
return a3;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const int4& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 8-wide AVX integer type. */
|
||||
struct int8
|
||||
{
|
||||
typedef bool8 Mask; // mask type for us
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256i m256;
|
||||
struct { __m128i l,h; };
|
||||
int v[8];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8 ( ) {}
|
||||
__forceinline int8 ( const int8& a ) { m256 = a.m256; }
|
||||
__forceinline int8& operator=( const int8& a ) { m256 = a.m256; return *this; }
|
||||
|
||||
__forceinline int8( const __m256i a ) : m256(a) {}
|
||||
__forceinline operator const __m256i&( void ) const { return m256; }
|
||||
__forceinline operator __m256i&( void ) { return m256; }
|
||||
|
||||
__forceinline explicit int8( const int4& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
|
||||
__forceinline int8( const int4& a, const int4& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
|
||||
__forceinline int8( const __m128i& a, const __m128i& b ) : l(a), h(b) {}
|
||||
|
||||
__forceinline explicit int8 ( const int* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
|
||||
__forceinline int8 ( int a ) : m256(_mm256_set1_epi32(a)) {}
|
||||
__forceinline int8 ( int a, int b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
|
||||
__forceinline int8 ( int a, int b, int c, int d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
|
||||
__forceinline int8 ( int a, int b, int c, int d, int e, int f, int g, int h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
|
||||
|
||||
__forceinline explicit int8( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8( ZeroTy ) : m256(_mm256_setzero_si256()) {}
|
||||
__forceinline int8( OneTy ) : m256(_mm256_set_epi32(1,1,1,1,1,1,1,1)) {}
|
||||
__forceinline int8( PosInfTy ) : m256(_mm256_set_epi32(pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf,pos_inf)) {}
|
||||
__forceinline int8( NegInfTy ) : m256(_mm256_set_epi32(neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf,neg_inf)) {}
|
||||
__forceinline int8( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline int8 load( const void* const a) {
|
||||
return _mm256_castps_si256(_mm256_load_ps((float*)a));
|
||||
}
|
||||
|
||||
static __forceinline int8 loadu( const void* const a) {
|
||||
return _mm256_castps_si256(_mm256_loadu_ps((float*)a));
|
||||
}
|
||||
|
||||
static __forceinline void store(void* ptr, const int8& f ) {
|
||||
_mm256_store_ps((float*)ptr,_mm256_castsi256_ps(f));
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const int8& f ) {
|
||||
_mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f));
|
||||
}
|
||||
|
||||
static __forceinline void store( const bool8& mask, void* ptr, const int8& f ) {
|
||||
_mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(f));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
|
||||
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 operator +( const int8& a ) { return a; }
|
||||
__forceinline const int8 operator -( const int8& a ) { return int8(_mm_sub_epi32(_mm_setzero_si128(), a.l), _mm_sub_epi32(_mm_setzero_si128(), a.h)); }
|
||||
__forceinline const int8 abs ( const int8& a ) { return int8(_mm_abs_epi32(a.l), _mm_abs_epi32(a.h)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 operator +( const int8& a, const int8& b ) { return int8(_mm_add_epi32(a.l, b.l), _mm_add_epi32(a.h, b.h)); }
|
||||
__forceinline const int8 operator +( const int8& a, const int b ) { return a + int8(b); }
|
||||
__forceinline const int8 operator +( const int a, const int8& b ) { return int8(a) + b; }
|
||||
|
||||
__forceinline const int8 operator -( const int8& a, const int8& b ) { return int8(_mm_sub_epi32(a.l, b.l), _mm_sub_epi32(a.h, b.h)); }
|
||||
__forceinline const int8 operator -( const int8& a, const int b ) { return a - int8(b); }
|
||||
__forceinline const int8 operator -( const int a, const int8& b ) { return int8(a) - b; }
|
||||
|
||||
__forceinline const int8 operator *( const int8& a, const int8& b ) { return int8(_mm_mullo_epi32(a.l, b.l), _mm_mullo_epi32(a.h, b.h)); }
|
||||
__forceinline const int8 operator *( const int8& a, const int b ) { return a * int8(b); }
|
||||
__forceinline const int8 operator *( const int a, const int8& b ) { return int8(a) * b; }
|
||||
|
||||
__forceinline const int8 operator &( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
|
||||
__forceinline const int8 operator &( const int8& a, const int b ) { return a & int8(b); }
|
||||
__forceinline const int8 operator &( const int a, const int8& b ) { return int8(a) & b; }
|
||||
|
||||
__forceinline const int8 operator |( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_or_ps (_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
|
||||
__forceinline const int8 operator |( const int8& a, const int b ) { return a | int8(b); }
|
||||
__forceinline const int8 operator |( const int a, const int8& b ) { return int8(a) | b; }
|
||||
|
||||
__forceinline const int8 operator ^( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
|
||||
__forceinline const int8 operator ^( const int8& a, const int b ) { return a ^ int8(b); }
|
||||
__forceinline const int8 operator ^( const int a, const int8& b ) { return int8(a) ^ b; }
|
||||
|
||||
__forceinline const int8 operator <<( const int8& a, const int n ) { return int8(_mm_slli_epi32(a.l, n), _mm_slli_epi32(a.h, n)); }
|
||||
__forceinline const int8 operator >>( const int8& a, const int n ) { return int8(_mm_srai_epi32(a.l, n), _mm_srai_epi32(a.h, n)); }
|
||||
|
||||
__forceinline const int8 sra ( const int8& a, const int b ) { return int8(_mm_srai_epi32(a.l, b), _mm_srai_epi32(a.h, b)); }
|
||||
__forceinline const int8 srl ( const int8& a, const int b ) { return int8(_mm_srli_epi32(a.l, b), _mm_srli_epi32(a.h, b)); }
|
||||
|
||||
__forceinline const int8 min( const int8& a, const int8& b ) { return int8(_mm_min_epi32(a.l, b.l), _mm_min_epi32(a.h, b.h)); }
|
||||
__forceinline const int8 min( const int8& a, const int b ) { return min(a,int8(b)); }
|
||||
__forceinline const int8 min( const int a, const int8& b ) { return min(int8(a),b); }
|
||||
|
||||
__forceinline const int8 max( const int8& a, const int8& b ) { return int8(_mm_max_epi32(a.l, b.l), _mm_max_epi32(a.h, b.h)); }
|
||||
__forceinline const int8 max( const int8& a, const int b ) { return max(a,int8(b)); }
|
||||
__forceinline const int8 max( const int a, const int8& b ) { return max(int8(a),b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8& operator +=( int8& a, const int8& b ) { return a = a + b; }
|
||||
__forceinline int8& operator +=( int8& a, const int b ) { return a = a + b; }
|
||||
|
||||
__forceinline int8& operator -=( int8& a, const int8& b ) { return a = a - b; }
|
||||
__forceinline int8& operator -=( int8& a, const int b ) { return a = a - b; }
|
||||
|
||||
__forceinline int8& operator *=( int8& a, const int8& b ) { return a = a * b; }
|
||||
__forceinline int8& operator *=( int8& a, const int b ) { return a = a * b; }
|
||||
|
||||
__forceinline int8& operator &=( int8& a, const int8& b ) { return a = a & b; }
|
||||
__forceinline int8& operator &=( int8& a, const int b ) { return a = a & b; }
|
||||
|
||||
__forceinline int8& operator |=( int8& a, const int8& b ) { return a = a | b; }
|
||||
__forceinline int8& operator |=( int8& a, const int b ) { return a = a | b; }
|
||||
|
||||
__forceinline int8& operator <<=( int8& a, const int b ) { return a = a << b; }
|
||||
__forceinline int8& operator >>=( int8& a, const int b ) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator ==( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmpeq_epi32 (a.l, b.l)),
|
||||
_mm_castsi128_ps(_mm_cmpeq_epi32 (a.h, b.h))); }
|
||||
__forceinline const bool8 operator ==( const int8& a, const int b ) { return a == int8(b); }
|
||||
__forceinline const bool8 operator ==( const int a, const int8& b ) { return int8(a) == b; }
|
||||
|
||||
__forceinline const bool8 operator !=( const int8& a, const int8& b ) { return !(a == b); }
|
||||
__forceinline const bool8 operator !=( const int8& a, const int b ) { return a != int8(b); }
|
||||
__forceinline const bool8 operator !=( const int a, const int8& b ) { return int8(a) != b; }
|
||||
|
||||
__forceinline const bool8 operator < ( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmplt_epi32 (a.l, b.l)),
|
||||
_mm_castsi128_ps(_mm_cmplt_epi32 (a.h, b.h))); }
|
||||
__forceinline const bool8 operator < ( const int8& a, const int b ) { return a < int8(b); }
|
||||
__forceinline const bool8 operator < ( const int a, const int8& b ) { return int8(a) < b; }
|
||||
|
||||
__forceinline const bool8 operator >=( const int8& a, const int8& b ) { return !(a < b); }
|
||||
__forceinline const bool8 operator >=( const int8& a, const int b ) { return a >= int8(b); }
|
||||
__forceinline const bool8 operator >=( const int a, const int8& b ) { return int8(a) >= b; }
|
||||
|
||||
__forceinline const bool8 operator > ( const int8& a, const int8& b ) { return bool8(_mm_castsi128_ps(_mm_cmpgt_epi32 (a.l, b.l)),
|
||||
_mm_castsi128_ps(_mm_cmpgt_epi32 (a.h, b.h))); }
|
||||
__forceinline const bool8 operator > ( const int8& a, const int b ) { return a > int8(b); }
|
||||
__forceinline const bool8 operator > ( const int a, const int8& b ) { return int8(a) > b; }
|
||||
|
||||
__forceinline const bool8 operator <=( const int8& a, const int8& b ) { return !(a > b); }
|
||||
__forceinline const bool8 operator <=( const int8& a, const int b ) { return a <= int8(b); }
|
||||
__forceinline const bool8 operator <=( const int a, const int8& b ) { return int8(a) <= b; }
|
||||
|
||||
__forceinline const int8 select( const bool8& m, const int8& t, const int8& f ) {
|
||||
return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8 unpacklo( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_unpacklo_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
|
||||
__forceinline int8 unpackhi( const int8& a, const int8& b ) { return _mm256_castps_si256(_mm256_unpackhi_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b))); }
|
||||
|
||||
template<size_t i> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i, i, i, i)));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a, const int8& b) {
|
||||
return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a, const int8& b ) {
|
||||
return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
template<> __forceinline const int8 shuffle<0, 0, 2, 2>( const int8& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
|
||||
template<> __forceinline const int8 shuffle<1, 1, 3, 3>( const int8& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
|
||||
template<> __forceinline const int8 shuffle<0, 1, 0, 1>( const int8& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
|
||||
|
||||
__forceinline const int8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
|
||||
template<size_t i> __forceinline const int8 insert (const int8& a, const int4& b) { return _mm256_insertf128_si256 (a,b,i); }
|
||||
template<size_t i> __forceinline const int4 extract(const int8& a ) { return _mm256_extractf128_si256(a ,i); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 vreduce_min2(const int8& v) { return min(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const int8 vreduce_min4(const int8& v) { int8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const int8 vreduce_min (const int8& v) { int8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const int8 vreduce_max2(const int8& v) { return max(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const int8 vreduce_max4(const int8& v) { int8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const int8 vreduce_max (const int8& v) { int8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const int8 vreduce_add2(const int8& v) { return v + shuffle<1,0,3,2>(v); }
|
||||
__forceinline const int8 vreduce_add4(const int8& v) { int8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
|
||||
__forceinline const int8 vreduce_add (const int8& v) { int8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
|
||||
|
||||
__forceinline int reduce_min(const int8& v) { return extract<0>(extract<0>(vreduce_min(v))); }
|
||||
__forceinline int reduce_max(const int8& v) { return extract<0>(extract<0>(vreduce_max(v))); }
|
||||
__forceinline int reduce_add(const int8& v) { return extract<0>(extract<0>(vreduce_add(v))); }
|
||||
|
||||
__forceinline size_t select_min(const int8& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const int8& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
__forceinline size_t select_max(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// New stuff
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline void store8i(void* ptr, const int8& i) {
|
||||
_mm256_store_ps((float*)ptr,_mm256_castsi256_ps(i));
|
||||
}
|
||||
|
||||
__forceinline void store8i( const bool8 &mask, void *ptr, const int8& i ) {
|
||||
_mm256_maskstore_ps((float*)ptr,(__m256i)mask,_mm256_castsi256_ps(i));
|
||||
}
|
||||
|
||||
__forceinline void store8i_nt(void* ptr, const int8& v) {
|
||||
store4i_nt((int*)ptr+0,v.l);
|
||||
store4i_nt((int*)ptr+4,v.h);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const int8& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/*! 8-wide AVX integer type. */
|
||||
struct int8
|
||||
{
|
||||
typedef bool8 Mask; // mask type for us
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256i m256;
|
||||
int v[8];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8 ( ) {}
|
||||
__forceinline int8 ( const int8& a ) { m256 = a.m256; }
|
||||
__forceinline int8& operator=( const int8& a ) { m256 = a.m256; return *this; }
|
||||
|
||||
__forceinline int8( const __m256i a ) : m256(a) {}
|
||||
__forceinline operator const __m256i&( void ) const { return m256; }
|
||||
__forceinline operator __m256i&( void ) { return m256; }
|
||||
|
||||
__forceinline explicit int8( const int4& a ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),a,1)) {}
|
||||
__forceinline int8( const int4& a, const int4& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
|
||||
__forceinline int8( const __m128i& a, const __m128i& b ) : m256(_mm256_insertf128_si256(_mm256_castsi128_si256(a),b,1)) {}
|
||||
|
||||
__forceinline explicit int8 ( const int* const a ) : m256(_mm256_castps_si256(_mm256_loadu_ps((const float*)a))) {}
|
||||
__forceinline int8 ( int a ) : m256(_mm256_set1_epi32(a)) {}
|
||||
__forceinline int8 ( int a, int b) : m256(_mm256_set_epi32(b, a, b, a, b, a, b, a)) {}
|
||||
__forceinline int8 ( int a, int b, int c, int d) : m256(_mm256_set_epi32(d, c, b, a, d, c, b, a)) {}
|
||||
__forceinline int8 ( int a, int b, int c, int d, int e, int f, int g, int h) : m256(_mm256_set_epi32(h, g, f, e, d, c, b, a)) {}
|
||||
|
||||
__forceinline explicit int8( const __m256 a ) : m256(_mm256_cvtps_epi32(a)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8( ZeroTy ) : m256(_mm256_setzero_si256()) {}
|
||||
__forceinline int8( OneTy ) : m256(_mm256_set1_epi32(1)) {}
|
||||
__forceinline int8( PosInfTy ) : m256(_mm256_set1_epi32(pos_inf)) {}
|
||||
__forceinline int8( NegInfTy ) : m256(_mm256_set1_epi32(neg_inf)) {}
|
||||
__forceinline int8( StepTy ) : m256(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)) {}
|
||||
__forceinline int8( TrueTy ) { /* m256 = _mm256_undefined_si256(); */ m256 = _mm256_cmpeq_epi32(m256,m256); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline int8 load( const unsigned char* const ptr ) {
|
||||
return _mm256_cvtepu8_epi32(_mm_load_si128((__m128i*)ptr));
|
||||
}
|
||||
|
||||
static __forceinline const int8 load(const int* const i) {
|
||||
return _mm256_load_si256((__m256i*)i);
|
||||
}
|
||||
|
||||
static __forceinline const int8 uload(const int* const i) {
|
||||
return _mm256_loadu_si256((__m256i*)i);
|
||||
}
|
||||
|
||||
static __forceinline void store(void* ptr, const int8& i ) {
|
||||
_mm256_store_si256((__m256i*)ptr,i);
|
||||
}
|
||||
|
||||
static __forceinline void store( const bool8& mask, void *ptr, const int8& i ) {
|
||||
_mm256_maskstore_epi32((int*)ptr,mask,i);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(void* ptr, const int8& f ) {
|
||||
_mm256_storeu_ps((float*)ptr,_mm256_castsi256_ps(f));
|
||||
}
|
||||
|
||||
#if defined (__AVX2__)
|
||||
static __forceinline int8 load_nt(void* ptr) {
|
||||
return _mm256_stream_load_si256((__m256i*)ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline void store_nt(void* ptr, const int8& v) {
|
||||
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int& operator []( const size_t i ) const { assert(i < 8); return v[i]; }
|
||||
__forceinline int& operator []( const size_t i ) { assert(i < 8); return v[i]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 operator +( const int8& a ) { return a; }
|
||||
__forceinline const int8 operator -( const int8& a ) { return _mm256_sub_epi32(_mm256_setzero_si256(), a.m256); }
|
||||
__forceinline const int8 abs ( const int8& a ) { return _mm256_abs_epi32(a.m256); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 operator +( const int8& a, const int8& b ) { return _mm256_add_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 operator +( const int8& a, const int b ) { return a + int8(b); }
|
||||
__forceinline const int8 operator +( const int a, const int8& b ) { return int8(a) + b; }
|
||||
|
||||
__forceinline const int8 operator -( const int8& a, const int8& b ) { return _mm256_sub_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 operator -( const int8& a, const int b ) { return a - int8(b); }
|
||||
__forceinline const int8 operator -( const int a, const int8& b ) { return int8(a) - b; }
|
||||
|
||||
__forceinline const int8 operator *( const int8& a, const int8& b ) { return _mm256_mullo_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 operator *( const int8& a, const int b ) { return a * int8(b); }
|
||||
__forceinline const int8 operator *( const int a, const int8& b ) { return int8(a) * b; }
|
||||
|
||||
__forceinline const int8 operator &( const int8& a, const int8& b ) { return _mm256_and_si256(a.m256, b.m256); }
|
||||
__forceinline const int8 operator &( const int8& a, const int b ) { return a & int8(b); }
|
||||
__forceinline const int8 operator &( const int a, const int8& b ) { return int8(a) & b; }
|
||||
|
||||
__forceinline const int8 operator |( const int8& a, const int8& b ) { return _mm256_or_si256(a.m256, b.m256); }
|
||||
__forceinline const int8 operator |( const int8& a, const int b ) { return a | int8(b); }
|
||||
__forceinline const int8 operator |( const int a, const int8& b ) { return int8(a) | b; }
|
||||
|
||||
__forceinline const int8 operator ^( const int8& a, const int8& b ) { return _mm256_xor_si256(a.m256, b.m256); }
|
||||
__forceinline const int8 operator ^( const int8& a, const int b ) { return a ^ int8(b); }
|
||||
__forceinline const int8 operator ^( const int a, const int8& b ) { return int8(a) ^ b; }
|
||||
|
||||
__forceinline const int8 operator <<( const int8& a, const int n ) { return _mm256_slli_epi32(a.m256, n); }
|
||||
__forceinline const int8 operator >>( const int8& a, const int n ) { return _mm256_srai_epi32(a.m256, n); }
|
||||
|
||||
__forceinline const int8 sra ( const int8& a, const int b ) { return _mm256_srai_epi32(a.m256, b); }
|
||||
__forceinline const int8 srl ( const int8& a, const int b ) { return _mm256_srli_epi32(a.m256, b); }
|
||||
|
||||
__forceinline const int8 sra ( const int8& a, const int8 &b ) { return _mm256_srav_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 srl ( const int8& a, const int8 &b ) { return _mm256_srlv_epi32(a.m256, b.m256); }
|
||||
|
||||
__forceinline const int8 min( const int8& a, const int8& b ) { return _mm256_min_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 min( const int8& a, const int b ) { return min(a,int8(b)); }
|
||||
__forceinline const int8 min( const int a, const int8& b ) { return min(int8(a),b); }
|
||||
|
||||
__forceinline const int8 max( const int8& a, const int8& b ) { return _mm256_max_epi32(a.m256, b.m256); }
|
||||
__forceinline const int8 max( const int8& a, const int b ) { return max(a,int8(b)); }
|
||||
__forceinline const int8 max( const int a, const int8& b ) { return max(int8(a),b); }
|
||||
|
||||
__forceinline const int8 umin( const int8& a, const int8& b ) { return _mm256_min_epu32(a.m256, b.m256); }
|
||||
__forceinline const int8 umax( const int8& a, const int8& b ) { return _mm256_max_epu32(a.m256, b.m256); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8& operator +=( int8& a, const int8& b ) { return a = a + b; }
|
||||
__forceinline int8& operator +=( int8& a, const int b ) { return a = a + b; }
|
||||
|
||||
__forceinline int8& operator -=( int8& a, const int8& b ) { return a = a - b; }
|
||||
__forceinline int8& operator -=( int8& a, const int b ) { return a = a - b; }
|
||||
|
||||
__forceinline int8& operator *=( int8& a, const int8& b ) { return a = a * b; }
|
||||
__forceinline int8& operator *=( int8& a, const int b ) { return a = a * b; }
|
||||
|
||||
__forceinline int8& operator &=( int8& a, const int8& b ) { return a = a & b; }
|
||||
__forceinline int8& operator &=( int8& a, const int b ) { return a = a & b; }
|
||||
|
||||
__forceinline int8& operator |=( int8& a, const int8& b ) { return a = a | b; }
|
||||
__forceinline int8& operator |=( int8& a, const int b ) { return a = a | b; }
|
||||
|
||||
__forceinline int8& operator <<=( int8& a, const int b ) { return a = a << b; }
|
||||
__forceinline int8& operator >>=( int8& a, const int b ) { return a = a >> b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const bool8 operator ==( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32 (a.m256, b.m256)); }
|
||||
__forceinline const bool8 operator ==( const int8& a, const int b ) { return a == int8(b); }
|
||||
__forceinline const bool8 operator ==( const int a, const int8& b ) { return int8(a) == b; }
|
||||
|
||||
__forceinline const bool8 operator !=( const int8& a, const int8& b ) { return !(a == b); }
|
||||
__forceinline const bool8 operator !=( const int8& a, const int b ) { return a != int8(b); }
|
||||
__forceinline const bool8 operator !=( const int a, const int8& b ) { return int8(a) != b; }
|
||||
|
||||
__forceinline const bool8 operator < ( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (b.m256, a.m256)); }
|
||||
__forceinline const bool8 operator < ( const int8& a, const int b ) { return a < int8(b); }
|
||||
__forceinline const bool8 operator < ( const int a, const int8& b ) { return int8(a) < b; }
|
||||
|
||||
__forceinline const bool8 operator >=( const int8& a, const int8& b ) { return !(a < b); }
|
||||
__forceinline const bool8 operator >=( const int8& a, const int b ) { return a >= int8(b); }
|
||||
__forceinline const bool8 operator >=( const int a, const int8& b ) { return int8(a) >= b; }
|
||||
|
||||
__forceinline const bool8 operator > ( const int8& a, const int8& b ) { return _mm256_castsi256_ps(_mm256_cmpgt_epi32 (a.m256, b.m256)); }
|
||||
__forceinline const bool8 operator > ( const int8& a, const int b ) { return a > int8(b); }
|
||||
__forceinline const bool8 operator > ( const int a, const int8& b ) { return int8(a) > b; }
|
||||
|
||||
__forceinline const bool8 operator <=( const int8& a, const int8& b ) { return !(a > b); }
|
||||
__forceinline const bool8 operator <=( const int8& a, const int b ) { return a <= int8(b); }
|
||||
__forceinline const bool8 operator <=( const int a, const int8& b ) { return int8(a) <= b; }
|
||||
|
||||
__forceinline const int8 select( const bool8& m, const int8& t, const int8& f ) {
|
||||
return _mm256_castps_si256(_mm256_blendv_ps(_mm256_castsi256_ps(f), _mm256_castsi256_ps(t), m));
|
||||
}
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
__forceinline const int8 select(const int m, const int8& t, const int8& f) {
|
||||
return select(bool8(m), t, f); // workaround for clang and Microsoft compiler bugs
|
||||
}
|
||||
#else
|
||||
__forceinline const int8 select(const int m, const int8& t, const int8& f) {
|
||||
return _mm256_blend_epi32(f, t, m);
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int8 unpacklo( const int8& a, const int8& b ) { return _mm256_unpacklo_epi32(a.m256, b.m256); }
|
||||
__forceinline int8 unpackhi( const int8& a, const int8& b ) { return _mm256_unpackhi_epi32(a.m256, b.m256); }
|
||||
|
||||
template<size_t i> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i, i, i, i)));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_permute2f128_si256(a, a, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1> __forceinline const int8 shuffle( const int8& a, const int8& b) {
|
||||
return _mm256_permute2f128_si256(a, b, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a ) {
|
||||
return _mm256_castps_si256(_mm256_permute_ps(_mm256_castsi256_ps(a), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const int8 shuffle( const int8& a, const int8& b ) {
|
||||
return _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
|
||||
}
|
||||
|
||||
template<> __forceinline const int8 shuffle<0, 0, 2, 2>( const int8& b ) { return _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(b))); }
|
||||
template<> __forceinline const int8 shuffle<1, 1, 3, 3>( const int8& b ) { return _mm256_castps_si256(_mm256_movehdup_ps(_mm256_castsi256_ps(b))); }
|
||||
template<> __forceinline const int8 shuffle<0, 1, 0, 1>( const int8& b ) { return _mm256_castps_si256(_mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(_mm256_castsi256_ps(b))))); }
|
||||
|
||||
__forceinline const int8 broadcast(const int* ptr) { return _mm256_castps_si256(_mm256_broadcast_ss((const float*)ptr)); }
|
||||
template<size_t i> __forceinline const int8 insert (const int8& a, const int4& b) { return _mm256_insertf128_si256 (a,b,i); }
|
||||
template<size_t i> __forceinline const int4 extract(const int8& a ) { return _mm256_extractf128_si256(a ,i); }
|
||||
|
||||
__forceinline int8 permute(const int8& a, const __m256i& index) {
|
||||
return _mm256_permutevar8x32_epi32(a,index);
|
||||
}
|
||||
|
||||
__forceinline int8 permute4x32(const int8& a, const __m256i& index) {
|
||||
return _mm256_castps_si256(_mm256_permutevar_ps(_mm256_castsi256_ps(a),index));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 vreduce_min2(const int8& v) { return min(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const int8 vreduce_min4(const int8& v) { int8 v1 = vreduce_min2(v); return min(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const int8 vreduce_min (const int8& v) { int8 v1 = vreduce_min4(v); return min(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const int8 vreduce_max2(const int8& v) { return max(v,shuffle<1,0,3,2>(v)); }
|
||||
__forceinline const int8 vreduce_max4(const int8& v) { int8 v1 = vreduce_max2(v); return max(v1,shuffle<2,3,0,1>(v1)); }
|
||||
__forceinline const int8 vreduce_max (const int8& v) { int8 v1 = vreduce_max4(v); return max(v1,shuffle<1,0>(v1)); }
|
||||
|
||||
__forceinline const int8 vreduce_add2(const int8& v) { return v + shuffle<1,0,3,2>(v); }
|
||||
__forceinline const int8 vreduce_add4(const int8& v) { int8 v1 = vreduce_add2(v); return v1 + shuffle<2,3,0,1>(v1); }
|
||||
__forceinline const int8 vreduce_add (const int8& v) { int8 v1 = vreduce_add4(v); return v1 + shuffle<1,0>(v1); }
|
||||
|
||||
__forceinline int reduce_min(const int8& v) { return extract<0>(extract<0>(vreduce_min(v))); }
|
||||
__forceinline int reduce_max(const int8& v) { return extract<0>(extract<0>(vreduce_max(v))); }
|
||||
__forceinline int reduce_add(const int8& v) { return extract<0>(extract<0>(vreduce_add(v))); }
|
||||
|
||||
__forceinline size_t select_min(const int8& v) { return __bsf(movemask(v == vreduce_min(v))); }
|
||||
__forceinline size_t select_max(const int8& v) { return __bsf(movemask(v == vreduce_max(v))); }
|
||||
|
||||
__forceinline size_t select_min(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
|
||||
__forceinline size_t select_max(const bool8& valid, const int8& v) { const int8 a = select(valid,v,int8(neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
|
||||
|
||||
|
||||
__forceinline int8 assign( const int4& a ) { return _mm256_castsi128_si256(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline const int8 load8i(const int* const i) {
|
||||
return _mm256_load_si256((__m256i*)i);
|
||||
}
|
||||
|
||||
__forceinline const int8 uload8i(const int* const i) {
|
||||
return _mm256_loadu_si256((__m256i*)i);
|
||||
}
|
||||
|
||||
__forceinline void store8i(void *ptr, const int8& i ) {
|
||||
_mm256_store_si256((__m256i*)ptr,i);
|
||||
}
|
||||
|
||||
__forceinline void store8i( const bool8& mask, void *ptr, const int8& i ) {
|
||||
_mm256_maskstore_epi32((int*)ptr,mask,i);
|
||||
}
|
||||
|
||||
#if defined (__AVX2__)
|
||||
__forceinline int8 load8i_nt(void* ptr) {
|
||||
return _mm256_stream_load_si256((__m256i*)ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
__forceinline void store8i_nt(void* ptr, const int8& v) {
|
||||
_mm256_stream_ps((float*)ptr,_mm256_castsi256_ps(v));
|
||||
}
|
||||
|
||||
#if 0 // FIXME: not compiling under VS2013
|
||||
__forceinline int8 sortNetwork2x4(const int8& v)
|
||||
{
|
||||
const int8 a0 = v;
|
||||
const int8 b0 = shuffle<1,0,3,2>(a0);
|
||||
const int8 c0 = umin(a0,b0);
|
||||
const int8 d0 = umax(a0,b0);
|
||||
const int8 a1 = (0b01010101,c0,d0);
|
||||
const int8 b1 = shuffle<2,3,0,1>(a1);
|
||||
const int8 c1 = umin(a1,b1);
|
||||
const int8 d1 = umax(a1,b1);
|
||||
const int8 a2 = (0b00110011,c1,d1);
|
||||
const int8 b2 = shuffle<0,2,1,3>(a2);
|
||||
const int8 c2 = umin(a2,b2);
|
||||
const int8 d2 = umax(a2,b2);
|
||||
const int8 a3 = select(0b00100010,c2,d2);
|
||||
return a3;
|
||||
}
|
||||
|
||||
__forceinline int8 sortNetwork(const int8& v)
|
||||
{
|
||||
const int8 a0 = v;
|
||||
const int8 b0 = shuffle<1,0,3,2>(a0);
|
||||
const int8 c0 = umin(a0,b0);
|
||||
const int8 d0 = umax(a0,b0);
|
||||
const int8 a1 = select(0b10011001,c0,d0);
|
||||
const int8 b1 = shuffle<2,3,0,1>(a1);
|
||||
const int8 c1 = umin(a1,b1);
|
||||
const int8 d1 = umax(a1,b1);
|
||||
const int8 a2 = select(0b11000011,c1,d1);
|
||||
const int8 b2 = shuffle<1,0,3,2>(a2);
|
||||
const int8 c2 = umin(a2,b2);
|
||||
const int8 d2 = umax(a2,b2);
|
||||
const int8 a3 = select(0b10100101,c2,d2);
|
||||
const int8 b3 = shuffle<1,0>(a3);
|
||||
const int8 c3 = umin(a3,b3);
|
||||
const int8 d3 = umax(a3,b3);
|
||||
const int8 a4 = select(0b00001111,c3,d3);
|
||||
const int8 b4 = shuffle<2,3,0,1>(a4);
|
||||
const int8 c4 = umin(a4,b4);
|
||||
const int8 d4 = umax(a4,b4);
|
||||
const int8 a5 = select(0b00110011,c4,d4);
|
||||
const int8 b5 = shuffle<1,0,3,2>(a5);
|
||||
const int8 c5 = umin(a5,b5);
|
||||
const int8 d5 = umax(a5,b5);
|
||||
const int8 a6 = select(0b01010101,c5,d5);
|
||||
return a6;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& cout, const int8& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
+40
-24
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -25,31 +25,47 @@
|
||||
|
||||
/* include AVX wrapper classes */
|
||||
#if defined(__AVX__)
|
||||
# include "avx.h"
|
||||
#include "avx.h"
|
||||
#endif
|
||||
|
||||
/* include AVX512 wrapper classes */
|
||||
#if defined (__AVX512F__)
|
||||
#if defined (__MIC__)
|
||||
# include "avx512.h"
|
||||
#endif
|
||||
|
||||
#if defined (__AVX__)
|
||||
#if defined(__AVX512F__)
|
||||
# define AVX_ZERO_UPPER()
|
||||
#elif defined (__AVX__)
|
||||
# define AVX_ZERO_UPPER() _mm256_zeroupper()
|
||||
#define AVX_ZERO_UPPER()
|
||||
#else
|
||||
# define AVX_ZERO_UPPER()
|
||||
#define AVX_ZERO_UPPER() _mm256_zeroupper()
|
||||
#endif
|
||||
#else
|
||||
#define AVX_ZERO_UPPER()
|
||||
#endif
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined (__AVX512F__) || defined (__MIC__)
|
||||
typedef bool16 vbool;
|
||||
typedef int16 vint;
|
||||
typedef float16 vfloat;
|
||||
#elif defined(__AVX__)
|
||||
typedef bool8 vbool;
|
||||
typedef int8 vint;
|
||||
typedef float8 vfloat;
|
||||
#else
|
||||
typedef bool4 vbool;
|
||||
typedef int4 vint;
|
||||
typedef float4 vfloat;
|
||||
#endif
|
||||
|
||||
/* foreach unique */
|
||||
template<typename vbool, typename vint, typename Closure>
|
||||
__forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
|
||||
__forceinline void foreach_unique(const vbool& valid0, const vint& vi, const Closure& closure)
|
||||
{
|
||||
vbool valid1 = valid0;
|
||||
while (any(valid1)) {
|
||||
const int j = int(__bsf(movemask(valid1)));
|
||||
const int j = __bsf(movemask(valid1));
|
||||
const int i = vi[j];
|
||||
const vbool valid2 = valid1 & (i == vi);
|
||||
valid1 = valid1 & !valid2;
|
||||
@@ -59,11 +75,11 @@ namespace embree
|
||||
|
||||
/* foreach unique */
|
||||
template<typename vbool, typename vint, typename Closure>
|
||||
__forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
|
||||
__forceinline void foreach_unique_index(const vbool& valid0, const vint& vi, const Closure& closure)
|
||||
{
|
||||
vbool valid1 = valid0;
|
||||
while (any(valid1)) {
|
||||
const int j = (int) __bsf(movemask(valid1));
|
||||
const int j = __bsf(movemask(valid1));
|
||||
const int i = vi[j];
|
||||
const vbool valid2 = valid1 & (i == vi);
|
||||
valid1 = valid1 & !valid2;
|
||||
@@ -74,24 +90,24 @@ namespace embree
|
||||
template<typename Closure>
|
||||
__forceinline void foreach2(int x0, int x1, int y0, int y1, const Closure& closure)
|
||||
{
|
||||
__aligned(64) int U[2*VSIZEX];
|
||||
__aligned(64) int V[2*VSIZEX];
|
||||
__aligned(64) int U[128];
|
||||
__aligned(64) int V[128];
|
||||
int index = 0;
|
||||
for (int y=y0; y<y1; y++) {
|
||||
const bool lasty = y+1>=y1;
|
||||
const vintx vy = y;
|
||||
for (int x=x0; x<x1; ) { //x+=VSIZEX) {
|
||||
const bool lastx = x+VSIZEX >= x1;
|
||||
vintx vx = x+vintx(step);
|
||||
vintx::storeu(&U[index],vx);
|
||||
vintx::storeu(&V[index],vy);
|
||||
const int dx = min(x1-x,VSIZEX);
|
||||
const vint vy = y;
|
||||
for (int x=x0; x<x1; ) { //x+=vfloat::size) {
|
||||
const bool lastx = x+vfloat::size >= x1;
|
||||
vint vx = x+vint(step);
|
||||
vint::storeu(&U[index],vx);
|
||||
vint::storeu(&V[index],vy);
|
||||
const int dx = min(x1-x,vfloat::size);
|
||||
index += dx;
|
||||
x += dx;
|
||||
if (index >= VSIZEX || (lastx && lasty)) {
|
||||
const vboolx valid = vintx(step) < vintx(index);
|
||||
closure(valid,vintx::load(U),vintx::load(V));
|
||||
x-= max(0,index-VSIZEX);
|
||||
if (index >= vfloat::size || (lastx && lasty)) {
|
||||
const vbool valid = vint(step) < vint(index);
|
||||
closure(valid,vint::load(U),vint::load(V));
|
||||
x-= max(0,index-vfloat::size);
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once // FIXME: remove this file?
|
||||
|
||||
#ifndef __GNUC__
|
||||
#pragma message (" --- Intel remark: SSE4 intrinsics are emulated with SSE3 ---")
|
||||
#endif
|
||||
|
||||
#define _MM_FROUND_TO_NEAREST_INT 0x00
|
||||
#define _MM_FROUND_TO_NEG_INF 0x01
|
||||
#define _MM_FROUND_TO_POS_INF 0x02
|
||||
#define _MM_FROUND_TO_ZERO 0x03
|
||||
#define _MM_FROUND_CUR_DIRECTION 0x04
|
||||
|
||||
#define _mm_blendv_ps __emu_mm_blendv_ps
|
||||
__forceinline __m128 _mm_blendv_ps( __m128 value, __m128 input, __m128 mask ) {
|
||||
return _mm_or_ps(_mm_and_ps(mask, input), _mm_andnot_ps(mask, value));
|
||||
}
|
||||
|
||||
#define _mm_blend_ps __emu_mm_blend_ps
|
||||
__forceinline __m128 _mm_blend_ps( __m128 value, __m128 input, const int mask ) {
|
||||
assert(mask < 0x10); return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]);
|
||||
}
|
||||
|
||||
#define _mm_blendv_epi8 __emu_mm_blendv_epi8
|
||||
__forceinline __m128i _mm_blendv_epi8( __m128i value, __m128i input, __m128i mask ) {
|
||||
return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value));
|
||||
}
|
||||
|
||||
#define _mm_mullo_epi32 __emu_mm_mullo_epi32
|
||||
__forceinline __m128i _mm_mullo_epi32( __m128i value, __m128i input ) {
|
||||
__m128i rvalue;
|
||||
char* _r = (char*)(&rvalue + 1);
|
||||
char* _v = (char*)(& value + 1);
|
||||
char* _i = (char*)(& input + 1);
|
||||
for ( ssize_t i = -16 ; i != 0 ; i += 4 ) *((int32_t*)(_r + i)) = *((int32_t*)(_v + i))* *((int32_t*)(_i + i));
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
|
||||
#define _mm_min_epi32 __emu_mm_min_epi32
|
||||
__forceinline __m128i _mm_min_epi32( __m128i value, __m128i input ) {
|
||||
return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input));
|
||||
}
|
||||
|
||||
#define _mm_max_epi32 __emu_mm_max_epi32
|
||||
__forceinline __m128i _mm_max_epi32( __m128i value, __m128i input ) {
|
||||
return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input));
|
||||
}
|
||||
|
||||
#define _mm_extract_epi32 __emu_mm_extract_epi32
|
||||
__forceinline int _mm_extract_epi32( __m128i input, const int index ) {
|
||||
switch ( index ) {
|
||||
case 0: return _mm_cvtsi128_si32(input);
|
||||
case 1: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
|
||||
case 2: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
|
||||
case 3: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(3, 3, 3, 3)));
|
||||
default: assert(false); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define _mm_insert_epi32 __emu_mm_insert_epi32
|
||||
__forceinline __m128i _mm_insert_epi32( __m128i value, int input, const int index ) {
|
||||
assert(index >= 0 && index < 4); ((int*)&value)[index] = input; return value;
|
||||
}
|
||||
|
||||
#define _mm_extract_ps __emu_mm_extract_ps
|
||||
__forceinline int _mm_extract_ps( __m128 input, const int index ) {
|
||||
int32_t* ptr = (int32_t*)&input; return ptr[index];
|
||||
}
|
||||
|
||||
#define _mm_insert_ps __emu_mm_insert_ps
|
||||
__forceinline __m128 _mm_insert_ps( __m128 value, __m128 input, const int index )
|
||||
{ assert(index < 0x100); ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6]; return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value); }
|
||||
|
||||
#define _mm_round_ps __emu_mm_round_ps
|
||||
__forceinline __m128 _mm_round_ps( __m128 value, const int flags )
|
||||
{
|
||||
switch ( flags )
|
||||
{
|
||||
case _MM_FROUND_TO_NEAREST_INT: return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
|
||||
case _MM_FROUND_TO_NEG_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
|
||||
case _MM_FROUND_TO_POS_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps( 0.5f))));
|
||||
case _MM_FROUND_TO_ZERO : return _mm_cvtepi32_ps(_mm_cvttps_epi32(value));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef _M_X64
|
||||
#define _mm_insert_epi64 __emu_mm_insert_epi64
|
||||
__forceinline __m128i _mm_insert_epi64( __m128i value, int64_t input, const int index ) {
|
||||
assert(size_t(index) < 4); ((int64_t*)&value)[index] = input; return value;
|
||||
}
|
||||
|
||||
#define _mm_extract_epi64 __emu_mm_extract_epi64
|
||||
__forceinline int64_t _mm_extract_epi64( __m128i input, const int index ) {
|
||||
assert(size_t(index) < 2);
|
||||
return index == 0 ? _mm_cvtsi128_si64x(input) : _mm_cvtsi128_si64x(_mm_unpackhi_epi64(input, input));
|
||||
}
|
||||
#endif
|
||||
+2
-11
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
#include "sse.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
namespace embree {
|
||||
const __m128 _mm_lookupmask_ps[16] = {
|
||||
_mm_castsi128_ps(_mm_set_epi32( 0, 0, 0, 0)),
|
||||
_mm_castsi128_ps(_mm_set_epi32( 0, 0, 0,-1)),
|
||||
@@ -36,12 +35,4 @@ namespace embree
|
||||
_mm_castsi128_ps(_mm_set_epi32(-1,-1,-1, 0)),
|
||||
_mm_castsi128_ps(_mm_set_epi32(-1,-1,-1,-1))
|
||||
};
|
||||
|
||||
const __m128d _mm_lookupmask_pd[4] = {
|
||||
_mm_castsi128_pd(_mm_set_epi32( 0, 0, 0, 0)),
|
||||
_mm_castsi128_pd(_mm_set_epi32( 0, 0,-1,-1)),
|
||||
_mm_castsi128_pd(_mm_set_epi32(-1,-1, 0, 0)),
|
||||
_mm_castsi128_pd(_mm_set_epi32(-1,-1,-1,-1))
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+12
-14
@@ -1,5 +1,5 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// Copyright 2009-2015 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
@@ -19,29 +19,27 @@
|
||||
#include "../sys/platform.h"
|
||||
#include "../sys/intrinsics.h"
|
||||
#include "../math/constants.h"
|
||||
#include "varying.h"
|
||||
#include "sse_special.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
#if defined(__SSE4_1__)
|
||||
__forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
|
||||
__forceinline __m128 blendv_ps( __m128 f, __m128 t, __m128 mask ) {
|
||||
return _mm_blendv_ps(f,t,mask);
|
||||
}
|
||||
#else
|
||||
__forceinline __m128 blendv_ps(__m128 f, __m128 t, __m128 mask) {
|
||||
__forceinline __m128 blendv_ps( __m128 f, __m128 t, __m128 mask ) {
|
||||
return _mm_or_ps(_mm_and_ps(mask, t), _mm_andnot_ps(mask, f));
|
||||
}
|
||||
#endif
|
||||
|
||||
extern const __m128 _mm_lookupmask_ps[16];
|
||||
extern const __m128d _mm_lookupmask_pd[4];
|
||||
extern const __m128 _mm_lookupmask_ps[16];
|
||||
|
||||
struct bool4;
|
||||
struct int4;
|
||||
struct float4;
|
||||
}
|
||||
|
||||
#if defined(__AVX512VL__)
|
||||
#include "vboolf4_avx512.h"
|
||||
#else
|
||||
#include "vboolf4_sse2.h"
|
||||
#endif
|
||||
#include "vint4_sse2.h"
|
||||
#include "vuint4_sse2.h"
|
||||
#include "vfloat4_sse2.h"
|
||||
#include "bool4_sse2.h"
|
||||
#include "int4_sse2.h"
|
||||
#include "float4_sse2.h"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../sys/platform.h"
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* Varying numeric types */
|
||||
template<int N>
|
||||
struct vfloat
|
||||
{
|
||||
union { float f[N]; int i[N]; };
|
||||
__forceinline const float& operator [](size_t index) const { assert(index < N); return f[index]; }
|
||||
__forceinline float& operator [](size_t index) { assert(index < N); return f[index]; }
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct vdouble
|
||||
{
|
||||
union { double f[N]; long long i[N]; };
|
||||
__forceinline const double& operator [](size_t index) const { assert(index < N); return f[index]; }
|
||||
__forceinline double& operator [](size_t index) { assert(index < N); return f[index]; }
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct vint
|
||||
{
|
||||
int i[N];
|
||||
__forceinline const int& operator [](size_t index) const { assert(index < N); return i[index]; }
|
||||
__forceinline int& operator [](size_t index) { assert(index < N); return i[index]; }
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct vuint
|
||||
{
|
||||
unsigned int i[N];
|
||||
__forceinline const unsigned int& operator [](size_t index) const { assert(index < N); return i[index]; }
|
||||
__forceinline unsigned int& operator [](size_t index) { assert(index < N); return i[index]; }
|
||||
};
|
||||
|
||||
template<int N>
|
||||
struct vllong
|
||||
{
|
||||
long long i[N];
|
||||
__forceinline const long long& operator [](size_t index) const { assert(index < N); return i[index]; }
|
||||
__forceinline long long& operator [](size_t index) { assert(index < N); return i[index]; }
|
||||
};
|
||||
|
||||
/* Varying bool types */
|
||||
template<int N> struct vboolf { int i[N]; }; // for float/int
|
||||
template<int N> struct vboold { long long i[N]; }; // for double/long long
|
||||
|
||||
/* Aliases to default types */
|
||||
template<int N> using vreal = vfloat<N>;
|
||||
template<int N> using vbool = vboolf<N>;
|
||||
|
||||
/* Maximum supported varying size */
|
||||
#if defined(__AVX512F__)
|
||||
const int VSIZEX = 16;
|
||||
#elif defined(__AVX__)
|
||||
const int VSIZEX = 8;
|
||||
#else
|
||||
const int VSIZEX = 4;
|
||||
#endif
|
||||
|
||||
/* Extends varying size N to optimal or up to max(N, N2) */
|
||||
template<int N, int N2 = VSIZEX>
|
||||
struct vextend
|
||||
{
|
||||
#if defined(__AVX512F__) && !defined(__AVX512VL__) // KNL
|
||||
/* use 16-wide SIMD calculations on KNL even for 4 and 8 wide SIMD */
|
||||
static const int size = (N2 == VSIZEX) ? VSIZEX : N;
|
||||
#define SIMD_MODE(N) N, 16
|
||||
#else
|
||||
/* calculate with same SIMD width otherwise */
|
||||
static const int size = N;
|
||||
#define SIMD_MODE(N) N, N
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 4-wide shortcuts */
|
||||
typedef vfloat<4> vfloat4;
|
||||
typedef vdouble<4> vdouble4;
|
||||
typedef vreal<4> vreal4;
|
||||
typedef vint<4> vint4;
|
||||
typedef vuint<4> vuint4;
|
||||
typedef vllong<4> vllong4;
|
||||
typedef vbool<4> vbool4;
|
||||
typedef vboolf<4> vboolf4;
|
||||
typedef vboold<4> vboold4;
|
||||
|
||||
/* 8-wide shortcuts */
|
||||
typedef vfloat<8> vfloat8;
|
||||
typedef vdouble<8> vdouble8;
|
||||
typedef vreal<8> vreal8;
|
||||
typedef vint<8> vint8;
|
||||
typedef vllong<8> vllong8;
|
||||
typedef vbool<8> vbool8;
|
||||
typedef vboolf<8> vboolf8;
|
||||
typedef vboold<8> vboold8;
|
||||
|
||||
/* 16-wide shortcuts */
|
||||
typedef vfloat<16> vfloat16;
|
||||
typedef vdouble<16> vdouble16;
|
||||
typedef vreal<16> vreal16;
|
||||
typedef vint<16> vint16;
|
||||
typedef vuint<16> vuint16;
|
||||
typedef vllong<16> vllong16;
|
||||
typedef vbool<16> vbool16;
|
||||
typedef vboolf<16> vboolf16;
|
||||
typedef vboold<16> vboold16;
|
||||
|
||||
/* Maximum shortcuts */
|
||||
typedef vfloat<VSIZEX> vfloatx;
|
||||
typedef vdouble<VSIZEX> vdoublex;
|
||||
typedef vreal<VSIZEX> vrealx;
|
||||
typedef vint<VSIZEX> vintx;
|
||||
typedef vllong<VSIZEX> vllongx;
|
||||
typedef vbool<VSIZEX> vboolx;
|
||||
typedef vboolf<VSIZEX> vboolfx;
|
||||
typedef vboold<VSIZEX> vbooldx;
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide AVX bool type for 64bit data types*/
|
||||
template<>
|
||||
struct vboold<4>
|
||||
{
|
||||
typedef vboold4 Bool;
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256d v;
|
||||
struct { __m128d vl,vh; };
|
||||
long long i[4];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold() {}
|
||||
__forceinline vboold(const vboold4& a) { v = a.v; }
|
||||
__forceinline vboold4& operator =(const vboold4& a) { v = a.v; return *this; }
|
||||
|
||||
__forceinline vboold(__m256d a) : v(a) {}
|
||||
__forceinline vboold(__m256i a) : v(_mm256_castsi256_pd(a)) {}
|
||||
|
||||
__forceinline operator const __m256() const { return _mm256_castpd_ps(v); }
|
||||
__forceinline operator const __m256i() const { return _mm256_castpd_si256(v); }
|
||||
__forceinline operator const __m256d() const { return v; }
|
||||
|
||||
__forceinline vboold(int a)
|
||||
{
|
||||
assert(a >= 0 && a <= 255);
|
||||
#if defined (__AVX2__)
|
||||
const __m256i mask = _mm256_set_epi64x(0x8, 0x4, 0x2, 0x1);
|
||||
const __m256i b = _mm256_set1_epi64x(a);
|
||||
const __m256i c = _mm256_and_si256(b,mask);
|
||||
v = _mm256_castsi256_pd(_mm256_cmpeq_epi64(c,mask));
|
||||
#else
|
||||
vl = _mm_lookupmask_pd[a & 0x3];
|
||||
vh = _mm_lookupmask_pd[a >> 2];
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline vboold(__m128d a, __m128d b) : vl(a), vh(b) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold(FalseTy) : v(_mm256_setzero_pd()) {}
|
||||
__forceinline vboold(TrueTy) : v(_mm256_cmp_pd(_mm256_setzero_pd(), _mm256_setzero_pd(), _CMP_EQ_OQ)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm256_movemask_pd(v) >> index) & 1; }
|
||||
__forceinline long long& operator [](size_t index) { assert(index < 4); return i[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator !(const vboold4& a) { return _mm256_xor_pd(a, vboold4(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm256_and_pd(a, b); }
|
||||
__forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm256_or_pd (a, b); }
|
||||
__forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
|
||||
|
||||
__forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
|
||||
__forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
|
||||
__forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(a, b); }
|
||||
__forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm256_xor_pd(_mm256_xor_pd(a,b),vboold4(embree::True)); }
|
||||
|
||||
__forceinline vboold4 select(const vboold4& mask, const vboold4& t, const vboold4& f) {
|
||||
return _mm256_blendv_pd(f, t, mask);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 unpacklo(const vboold4& a, const vboold4& b) { return _mm256_unpacklo_pd(a, b); }
|
||||
__forceinline vboold4 unpackhi(const vboold4& a, const vboold4& b) { return _mm256_unpackhi_pd(a, b); }
|
||||
|
||||
|
||||
#if defined(__AVX2__)
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline vboold4 shuffle(const vboold4& v) {
|
||||
return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<int i>
|
||||
__forceinline vboold4 shuffle(const vboold4& v) {
|
||||
return _mm256_permute4x64_pd(v, _MM_SHUFFLE(i, i, i, i));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and(const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
|
||||
__forceinline bool reduce_or (const vboold4& a) { return !_mm256_testz_pd(a,a); }
|
||||
|
||||
__forceinline bool all (const vboold4& a) { return _mm256_movemask_pd(a) == (unsigned int)0xf; }
|
||||
__forceinline bool any (const vboold4& a) { return !_mm256_testz_pd(a,a); }
|
||||
__forceinline bool none(const vboold4& a) { return _mm256_testz_pd(a,a) != 0; }
|
||||
|
||||
__forceinline bool all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
|
||||
__forceinline bool any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
|
||||
__forceinline bool none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
|
||||
|
||||
__forceinline unsigned int movemask(const vboold4& a) { return _mm256_movemask_pd(a); }
|
||||
__forceinline size_t popcnt (const vboold4& a) { return __popcnt((size_t)_mm256_movemask_pd(a)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboold4& a, size_t index) { return a[index]; }
|
||||
__forceinline void set (vboold4& a, size_t index) { a[index] = -1; }
|
||||
__forceinline void clear(vboold4& a, size_t index) { a[index] = 0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboold4& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
|
||||
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide AVX-512 bool type */
|
||||
template<>
|
||||
struct vboold<4>
|
||||
{
|
||||
typedef vboold4 Bool;
|
||||
typedef vint4 Int;
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
__mmask8 v; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold() {}
|
||||
__forceinline vboold(const vboold4& t) { v = t.v; }
|
||||
__forceinline vboold4& operator =(const vboold4& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vboold(const __mmask8 &t) { v = t; }
|
||||
__forceinline operator __mmask8() const { return v; }
|
||||
|
||||
__forceinline vboold(bool b) { v = b ? 0xf : 0x0; }
|
||||
__forceinline vboold(int t) { v = (__mmask8)t; }
|
||||
__forceinline vboold(unsigned int t) { v = (__mmask8)t; }
|
||||
|
||||
/* return int8 mask */
|
||||
__forceinline __m128i mask8() const {
|
||||
return _mm_movm_epi8(v);
|
||||
}
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m128i mask32() const {
|
||||
return _mm_movm_epi32(v);
|
||||
}
|
||||
|
||||
/* return int64 mask */
|
||||
__forceinline __m256i mask64() const {
|
||||
return _mm256_movm_epi64(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold(FalseTy) : v(0x0) {}
|
||||
__forceinline vboold(TrueTy) : v(0xf) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator !(const vboold4& a) { return _mm512_kandn(a, 0xf); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator &(const vboold4& a, const vboold4& b) { return _mm512_kand(a, b); }
|
||||
__forceinline vboold4 operator |(const vboold4& a, const vboold4& b) { return _mm512_kor(a, b); }
|
||||
__forceinline vboold4 operator ^(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
|
||||
|
||||
__forceinline vboold4 andn(const vboold4& a, const vboold4& b) { return _mm512_kandn(b, a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4& operator &=(vboold4& a, const vboold4& b) { return a = a & b; }
|
||||
__forceinline vboold4& operator |=(vboold4& a, const vboold4& b) { return a = a | b; }
|
||||
__forceinline vboold4& operator ^=(vboold4& a, const vboold4& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold4 operator !=(const vboold4& a, const vboold4& b) { return _mm512_kxor(a, b); }
|
||||
__forceinline vboold4 operator ==(const vboold4& a, const vboold4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
|
||||
|
||||
__forceinline vboold4 select(const vboold4& s, const vboold4& a, const vboold4& b) {
|
||||
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all (const vboold4& a) { return a.v == 0xf; }
|
||||
__forceinline int any (const vboold4& a) { return _mm512_kortestz(a, a) == 0; }
|
||||
__forceinline int none(const vboold4& a) { return _mm512_kortestz(a, a) != 0; }
|
||||
|
||||
__forceinline int all (const vboold4& valid, const vboold4& b) { return all((!valid) | b); }
|
||||
__forceinline int any (const vboold4& valid, const vboold4& b) { return any(valid & b); }
|
||||
__forceinline int none(const vboold4& valid, const vboold4& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboold4& a) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt (const vboold4& a) { return __popcnt(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Conversion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt(const vboold4& a) { return mm512_mask2int(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboold4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
|
||||
__forceinline void set(vboold4& a, size_t index) { assert(index < 4); a |= 1 << index; }
|
||||
__forceinline void clear(vboold4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboold4& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<4; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 8-wide AVX-512 bool type */
|
||||
template<>
|
||||
struct vboold<8>
|
||||
{
|
||||
typedef vboold8 Bool;
|
||||
typedef vint8 Int;
|
||||
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
__mmask8 v; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold() {}
|
||||
__forceinline vboold(const vboold8& t) { v = t.v; }
|
||||
__forceinline vboold8& operator =(const vboold8& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vboold(const __mmask8& t) { v = t; }
|
||||
__forceinline operator __mmask8() const { return v; }
|
||||
|
||||
__forceinline vboold(bool b) { v = b ? 0xff : 0x00; }
|
||||
__forceinline vboold(int t) { v = (__mmask8)t; }
|
||||
__forceinline vboold(unsigned int t) { v = (__mmask8)t; }
|
||||
|
||||
/* return int8 mask */
|
||||
__forceinline __m128i mask8() const {
|
||||
#if defined(__AVX512BW__)
|
||||
return _mm_movm_epi8(v);
|
||||
#else
|
||||
const __m512i f = _mm512_set1_epi64(0);
|
||||
const __m512i t = _mm512_set1_epi64(-1);
|
||||
const __m512i m = _mm512_mask_or_epi64(f,v,t,t);
|
||||
return _mm512_cvtepi64_epi8(m);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* return int64 mask */
|
||||
__forceinline __m512i mask64() const {
|
||||
#if defined(__AVX512DQ__)
|
||||
return _mm512_movm_epi64(v);
|
||||
#else
|
||||
const __m512i f = _mm512_set1_epi64(0);
|
||||
const __m512i t = _mm512_set1_epi64(-1);
|
||||
return _mm512_mask_or_epi64(f,v,t,t);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold(FalseTy) : v(0x00) {}
|
||||
__forceinline vboold(TrueTy) : v(0xff) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold8 operator !(const vboold8& a) { return _mm512_knot(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold8 operator &(const vboold8& a, const vboold8& b) { return _mm512_kand(a, b); }
|
||||
__forceinline vboold8 operator |(const vboold8& a, const vboold8& b) { return _mm512_kor(a, b); }
|
||||
__forceinline vboold8 operator ^(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
|
||||
|
||||
__forceinline vboold8 andn(const vboold8& a, const vboold8& b) { return _mm512_kandn(b, a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold8& operator &=(vboold8& a, const vboold8& b) { return a = a & b; }
|
||||
__forceinline vboold8& operator |=(vboold8& a, const vboold8& b) { return a = a | b; }
|
||||
__forceinline vboold8& operator ^=(vboold8& a, const vboold8& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboold8 operator !=(const vboold8& a, const vboold8& b) { return _mm512_kxor(a, b); }
|
||||
__forceinline vboold8 operator ==(const vboold8& a, const vboold8& b) { return _mm512_kxnor(a, b); }
|
||||
|
||||
__forceinline vboold8 select(const vboold8& s, const vboold8& a, const vboold8& b) {
|
||||
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all (const vboold8& a) { return a.v == 0xff; }
|
||||
__forceinline int any (const vboold8& a) { return _mm512_kortestz(a, a) == 0; }
|
||||
__forceinline int none(const vboold8& a) { return _mm512_kortestz(a, a) != 0; }
|
||||
|
||||
__forceinline int all (const vboold8& valid, const vboold8& b) { return all((!valid) | b); }
|
||||
__forceinline int any (const vboold8& valid, const vboold8& b) { return any(valid & b); }
|
||||
__forceinline int none(const vboold8& valid, const vboold8& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboold8& a) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt (const vboold8& a) { return __popcnt(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Conversion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt(const vboold8& a) { return mm512_mask2int(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboold8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
|
||||
__forceinline void set(vboold8& a, size_t index) { assert(index < 8); a |= 1 << index; }
|
||||
__forceinline void clear(vboold8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboold8& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<8; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 16-wide AVX-512 bool type */
|
||||
template<>
|
||||
struct vboolf<16>
|
||||
{
|
||||
typedef vboolf16 Bool;
|
||||
typedef vint16 Int;
|
||||
typedef vfloat16 Float;
|
||||
|
||||
enum { size = 16 }; // number of SIMD elements
|
||||
__mmask16 v; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
__forceinline vboolf(const vboolf16& t) { v = t.v; }
|
||||
__forceinline vboolf16& operator =(const vboolf16& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vboolf(const __mmask16& t) { v = t; }
|
||||
__forceinline operator __mmask16() const { return v; }
|
||||
|
||||
__forceinline vboolf(bool b) { v = b ? 0xFFFF : 0x0000; }
|
||||
__forceinline vboolf(int t) { v = (__mmask16)t; }
|
||||
__forceinline vboolf(unsigned int t) { v = (__mmask16)t; }
|
||||
|
||||
/* return int8 mask */
|
||||
__forceinline __m128i mask8() const {
|
||||
#if defined(__AVX512BW__)
|
||||
return _mm_movm_epi8(v);
|
||||
#else
|
||||
const __m512i f = _mm512_set1_epi32(0);
|
||||
const __m512i t = _mm512_set1_epi32(-1);
|
||||
const __m512i m = _mm512_mask_or_epi32(f,v,t,t);
|
||||
return _mm512_cvtepi32_epi8(m);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m512i mask32() const {
|
||||
#if defined(__AVX512DQ__)
|
||||
return _mm512_movm_epi32(v);
|
||||
#else
|
||||
const __m512i f = _mm512_set1_epi32(0);
|
||||
const __m512i t = _mm512_set1_epi32(-1);
|
||||
return _mm512_mask_or_epi32(f,v,t,t);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(0x0000) {}
|
||||
__forceinline vboolf(TrueTy) : v(0xffff) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator [](size_t index) const {
|
||||
assert(index < 16); return (mm512_mask2int(v) >> index) & 1;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf16 operator !(const vboolf16& a) { return _mm512_knot(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf16 operator &(const vboolf16& a, const vboolf16& b) { return _mm512_kand(a,b); }
|
||||
__forceinline vboolf16 operator |(const vboolf16& a, const vboolf16& b) { return _mm512_kor(a,b); }
|
||||
__forceinline vboolf16 operator ^(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a,b); }
|
||||
|
||||
__forceinline vboolf16 andn(const vboolf16& a, const vboolf16& b) { return _mm512_kandn(b,a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf16& operator &=(vboolf16& a, const vboolf16& b) { return a = a & b; }
|
||||
__forceinline vboolf16& operator |=(vboolf16& a, const vboolf16& b) { return a = a | b; }
|
||||
__forceinline vboolf16& operator ^=(vboolf16& a, const vboolf16& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf16 operator !=(const vboolf16& a, const vboolf16& b) { return _mm512_kxor(a, b); }
|
||||
__forceinline vboolf16 operator ==(const vboolf16& a, const vboolf16& b) { return _mm512_kxnor(a, b); }
|
||||
|
||||
__forceinline vboolf16 select(const vboolf16& s, const vboolf16& a, const vboolf16& b) {
|
||||
return _mm512_kor(_mm512_kand(s,a),_mm512_kandn(s,b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all (const vboolf16& a) { return _mm512_kortestc(a,a) != 0; }
|
||||
__forceinline int any (const vboolf16& a) { return _mm512_kortestz(a,a) == 0; }
|
||||
__forceinline int none(const vboolf16& a) { return _mm512_kortestz(a,a) != 0; }
|
||||
|
||||
__forceinline int all (const vboolf16& valid, const vboolf16& b) { return all((!valid) | b); }
|
||||
__forceinline int any (const vboolf16& valid, const vboolf16& b) { return any(valid & b); }
|
||||
__forceinline int none(const vboolf16& valid, const vboolf16& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboolf16& a) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt (const vboolf16& a) { return __popcnt(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Convertion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt (const vboolf16& a) { return mm512_mask2int(a); }
|
||||
__forceinline vboolf16 toMask(const int& a) { return mm512_int2mask(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboolf16& a, size_t index) { assert(index < 16); return (toInt(a) >> index) & 1; }
|
||||
__forceinline void set(vboolf16& a, size_t index) { assert(index < 16); a |= 1 << index; }
|
||||
__forceinline void clear(vboolf16& a, size_t index) { assert(index < 16); a = andn(a, 1 << index); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboolf16& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<16; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide AVX-512 bool type */
|
||||
template<>
|
||||
struct vboolf<4>
|
||||
{
|
||||
typedef vboolf4 Bool;
|
||||
typedef vint4 Int;
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
__mmask8 v; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
__forceinline vboolf(const vboolf4& t) { v = t.v; }
|
||||
__forceinline vboolf4& operator =(const vboolf4& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vboolf(const __mmask8 &t) { v = t; }
|
||||
__forceinline operator __mmask8() const { return v; }
|
||||
|
||||
__forceinline vboolf(bool b) { v = b ? 0xf : 0x0; }
|
||||
__forceinline vboolf(int t) { v = (__mmask8)t; }
|
||||
__forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
|
||||
|
||||
/* return int8 mask */
|
||||
__forceinline __m128i mask8() const {
|
||||
return _mm_movm_epi8(v);
|
||||
}
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m128i mask32() const {
|
||||
return _mm_movm_epi32(v);
|
||||
}
|
||||
|
||||
/* return int64 mask */
|
||||
__forceinline __m256i mask64() const {
|
||||
return _mm256_movm_epi64(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(0x0) {}
|
||||
__forceinline vboolf(TrueTy) : v(0xf) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator !(const vboolf4& a) { return _mm512_kandn(a, 0xf); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm512_kand(a, b); }
|
||||
__forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm512_kor(a, b); }
|
||||
__forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
|
||||
|
||||
__forceinline vboolf4 andn(const vboolf4& a, const vboolf4& b) { return _mm512_kandn(b, a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
|
||||
__forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
|
||||
__forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm512_kxor(a, b); }
|
||||
__forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm512_kand(_mm512_kxnor(a, b), 0xf); }
|
||||
|
||||
__forceinline vboolf4 select(const vboolf4& s, const vboolf4& a, const vboolf4& b) {
|
||||
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all (const vboolf4& a) { return a.v == 0xf; }
|
||||
__forceinline int any (const vboolf4& a) { return _mm512_kortestz(a, a) == 0; }
|
||||
__forceinline int none(const vboolf4& a) { return _mm512_kortestz(a, a) != 0; }
|
||||
|
||||
__forceinline int all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
|
||||
__forceinline int any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
|
||||
__forceinline int none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboolf4& a) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt (const vboolf4& a) { return __popcnt(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Conversion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt(const vboolf4& a) { return mm512_mask2int(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboolf4& a, size_t index) { assert(index < 4); return (toInt(a) >> index) & 1; }
|
||||
__forceinline void set(vboolf4& a, size_t index) { assert(index < 4); a |= 1 << index; }
|
||||
__forceinline void clear(vboolf4& a, size_t index) { assert(index < 4); a = andn(a, 1 << index); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboolf4& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<4; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide SSE bool type */
|
||||
template<>
|
||||
struct vboolf<4>
|
||||
{
|
||||
typedef vboolf4 Bool;
|
||||
typedef vint4 Int;
|
||||
typedef vfloat4 Float;
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { __m128 v; int i[4]; }; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
__forceinline vboolf(const vboolf4& other) { v = other.v; }
|
||||
__forceinline vboolf4& operator =(const vboolf4& other) { v = other.v; return *this; }
|
||||
|
||||
__forceinline vboolf(__m128 input) : v(input) {}
|
||||
__forceinline operator const __m128&() const { return v; }
|
||||
__forceinline operator const __m128i() const { return _mm_castps_si128(v); }
|
||||
__forceinline operator const __m128d() const { return _mm_castps_pd(v); }
|
||||
|
||||
__forceinline vboolf(bool a)
|
||||
: v(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
|
||||
__forceinline vboolf(bool a, bool b)
|
||||
: v(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
|
||||
__forceinline vboolf(bool a, bool b, bool c, bool d)
|
||||
: v(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
|
||||
__forceinline vboolf(int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
|
||||
__forceinline vboolf(unsigned int mask) { assert(mask >= 0 && mask < 16); v = _mm_lookupmask_ps[mask]; }
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m128i mask32() const {
|
||||
return _mm_castps_si128(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(_mm_setzero_ps()) {}
|
||||
__forceinline vboolf(TrueTy) : v(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator [](size_t index) const { assert(index < 4); return (_mm_movemask_ps(v) >> index) & 1; }
|
||||
__forceinline int& operator [](size_t index) { assert(index < 4); return i[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator !(const vboolf4& a) { return _mm_xor_ps(a, vboolf4(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator &(const vboolf4& a, const vboolf4& b) { return _mm_and_ps(a, b); }
|
||||
__forceinline vboolf4 operator |(const vboolf4& a, const vboolf4& b) { return _mm_or_ps (a, b); }
|
||||
__forceinline vboolf4 operator ^(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4& operator &=(vboolf4& a, const vboolf4& b) { return a = a & b; }
|
||||
__forceinline vboolf4& operator |=(vboolf4& a, const vboolf4& b) { return a = a | b; }
|
||||
__forceinline vboolf4& operator ^=(vboolf4& a, const vboolf4& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 operator !=(const vboolf4& a, const vboolf4& b) { return _mm_xor_ps(a, b); }
|
||||
__forceinline vboolf4 operator ==(const vboolf4& a, const vboolf4& b) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
|
||||
|
||||
__forceinline vboolf4 select(const vboolf4& m, const vboolf4& t, const vboolf4& f) {
|
||||
#if defined(__SSE4_1__)
|
||||
return _mm_blendv_ps(f, t, m);
|
||||
#else
|
||||
return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf4 unpacklo(const vboolf4& a, const vboolf4& b) { return _mm_unpacklo_ps(a, b); }
|
||||
__forceinline vboolf4 unpackhi(const vboolf4& a, const vboolf4& b) { return _mm_unpackhi_ps(a, b); }
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline vboolf4 shuffle(const vboolf4& v) {
|
||||
return _mm_shuffle_epi32(v, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline vboolf4 shuffle(const vboolf4& a, const vboolf4& b) {
|
||||
return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<int i0>
|
||||
__forceinline vboolf4 shuffle(const vboolf4& v) {
|
||||
return shuffle<i0,i0,i0,i0>(v);
|
||||
}
|
||||
|
||||
#if defined(__SSE3__)
|
||||
template<> __forceinline vboolf4 shuffle<0, 0, 2, 2>(const vboolf4& v) { return _mm_moveldup_ps(v); }
|
||||
template<> __forceinline vboolf4 shuffle<1, 1, 3, 3>(const vboolf4& v) { return _mm_movehdup_ps(v); }
|
||||
template<> __forceinline vboolf4 shuffle<0, 1, 0, 1>(const vboolf4& v) { return _mm_castpd_ps(_mm_movedup_pd(v)); }
|
||||
#endif
|
||||
|
||||
#if defined(__SSE4_1__)
|
||||
template<int dst, int src, int clr> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
|
||||
template<int dst, int src> __forceinline vboolf4 insert(const vboolf4& a, const vboolf4& b) { return insert<dst, src, 0>(a, b); }
|
||||
template<int dst> __forceinline vboolf4 insert(const vboolf4& a, const bool b) { return insert<dst, 0>(a, vboolf4(b)); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and(const vboolf4& a) { return _mm_movemask_ps(a) == 0xf; }
|
||||
__forceinline bool reduce_or (const vboolf4& a) { return _mm_movemask_ps(a) != 0x0; }
|
||||
|
||||
__forceinline bool all (const vboolf4& b) { return _mm_movemask_ps(b) == 0xf; }
|
||||
__forceinline bool any (const vboolf4& b) { return _mm_movemask_ps(b) != 0x0; }
|
||||
__forceinline bool none(const vboolf4& b) { return _mm_movemask_ps(b) == 0x0; }
|
||||
|
||||
__forceinline bool all (const vboolf4& valid, const vboolf4& b) { return all((!valid) | b); }
|
||||
__forceinline bool any (const vboolf4& valid, const vboolf4& b) { return any(valid & b); }
|
||||
__forceinline bool none(const vboolf4& valid, const vboolf4& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboolf4& a) { return _mm_movemask_ps(a); }
|
||||
#if defined(__SSE4_2__)
|
||||
__forceinline size_t popcnt(const vboolf4& a) { return __popcnt((size_t)_mm_movemask_ps(a)); }
|
||||
#else
|
||||
__forceinline size_t popcnt(const vboolf4& a) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboolf4& a, size_t index) { return a[index]; }
|
||||
__forceinline void set(vboolf4& a, size_t index) { a[index] = -1; }
|
||||
__forceinline void clear(vboolf4& a, size_t index) { a[index] = 0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboolf4& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 8-wide AVX bool type */
|
||||
template<>
|
||||
struct vboolf<8>
|
||||
{
|
||||
typedef vboolf8 Bool;
|
||||
typedef vint8 Int;
|
||||
typedef vfloat8 Float;
|
||||
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256 v;
|
||||
struct { __m128 vl,vh; };
|
||||
int i[8];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
__forceinline vboolf(const vboolf8& a) { v = a.v; }
|
||||
__forceinline vboolf8& operator =(const vboolf8& a) { v = a.v; return *this; }
|
||||
|
||||
__forceinline vboolf(__m256 a) : v(a) {}
|
||||
__forceinline operator const __m256&() const { return v; }
|
||||
__forceinline operator const __m256i() const { return _mm256_castps_si256(v); }
|
||||
__forceinline operator const __m256d() const { return _mm256_castps_pd(v); }
|
||||
|
||||
__forceinline vboolf(int a)
|
||||
{
|
||||
assert(a >= 0 && a <= 255);
|
||||
#if defined (__AVX2__)
|
||||
const __m256i mask = _mm256_set_epi32(0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1);
|
||||
const __m256i b = _mm256_set1_epi32(a);
|
||||
const __m256i c = _mm256_and_si256(b,mask);
|
||||
v = _mm256_castsi256_ps(_mm256_cmpeq_epi32(c,mask));
|
||||
#else
|
||||
vl = _mm_lookupmask_ps[a & 0xF];
|
||||
vh = _mm_lookupmask_ps[a >> 4];
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline vboolf(const vboolf4& a) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),a,1)) {}
|
||||
__forceinline vboolf(const vboolf4& a, const vboolf4& b) : v(_mm256_insertf128_ps(_mm256_castps128_ps256(a),b,1)) {}
|
||||
__forceinline vboolf(__m128 a, __m128 b) : vl(a), vh(b) {}
|
||||
|
||||
__forceinline vboolf(bool a) : v(vboolf8(vboolf4(a), vboolf4(a))) {}
|
||||
__forceinline vboolf(bool a, bool b) : v(vboolf8(vboolf4(a), vboolf4(b))) {}
|
||||
__forceinline vboolf(bool a, bool b, bool c, bool d) : v(vboolf8(vboolf4(a,b), vboolf4(c,d))) {}
|
||||
__forceinline vboolf(bool a, bool b, bool c, bool d, bool e, bool f, bool g, bool h) : v(vboolf8(vboolf4(a,b,c,d), vboolf4(e,f,g,h))) {}
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m256i mask32() const {
|
||||
return _mm256_castps_si256(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(_mm256_setzero_ps()) {}
|
||||
__forceinline vboolf(TrueTy) : v(_mm256_cmp_ps(_mm256_setzero_ps(), _mm256_setzero_ps(), _CMP_EQ_OQ)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool operator [](size_t index) const { assert(index < 8); return (_mm256_movemask_ps(v) >> index) & 1; }
|
||||
__forceinline int& operator [](size_t index) { assert(index < 8); return i[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator !(const vboolf8& a) { return _mm256_xor_ps(a, vboolf8(embree::True)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm256_and_ps(a, b); }
|
||||
__forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm256_or_ps (a, b); }
|
||||
__forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
|
||||
|
||||
__forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
|
||||
__forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
|
||||
__forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(a, b); }
|
||||
__forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm256_xor_ps(_mm256_xor_ps(a,b),vboolf8(embree::True)); }
|
||||
|
||||
__forceinline vboolf8 select(const vboolf8& mask, const vboolf8& t, const vboolf8& f) {
|
||||
return _mm256_blendv_ps(f, t, mask);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 unpacklo(const vboolf8& a, const vboolf8& b) { return _mm256_unpacklo_ps(a, b); }
|
||||
__forceinline vboolf8 unpackhi(const vboolf8& a, const vboolf8& b) { return _mm256_unpackhi_ps(a, b); }
|
||||
|
||||
template<int i>
|
||||
__forceinline vboolf8 shuffle(const vboolf8& v) {
|
||||
return _mm256_permute_ps(v, _MM_SHUFFLE(i, i, i, i));
|
||||
}
|
||||
|
||||
template<int i0, int i1>
|
||||
__forceinline vboolf8 shuffle4(const vboolf8& v) {
|
||||
return _mm256_permute2f128_ps(v, v, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<int i0, int i1>
|
||||
__forceinline vboolf8 shuffle4(const vboolf8& a, const vboolf8& b) {
|
||||
return _mm256_permute2f128_ps(a, b, (i1 << 4) | (i0 << 0));
|
||||
}
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline vboolf8 shuffle(const vboolf8& v) {
|
||||
return _mm256_permute_ps(v, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<int i0, int i1, int i2, int i3>
|
||||
__forceinline vboolf8 shuffle(const vboolf8& a, const vboolf8& b) {
|
||||
return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
|
||||
}
|
||||
|
||||
template<> __forceinline vboolf8 shuffle<0, 0, 2, 2>(const vboolf8& v) { return _mm256_moveldup_ps(v); }
|
||||
template<> __forceinline vboolf8 shuffle<1, 1, 3, 3>(const vboolf8& v) { return _mm256_movehdup_ps(v); }
|
||||
template<> __forceinline vboolf8 shuffle<0, 1, 0, 1>(const vboolf8& v) { return _mm256_castpd_ps(_mm256_movedup_pd(_mm256_castps_pd(v))); }
|
||||
|
||||
template<int i> __forceinline vboolf8 insert4(const vboolf8& a, const vboolf4& b) { return _mm256_insertf128_ps(a, b, i); }
|
||||
template<int i> __forceinline vboolf4 extract4 (const vboolf8& a) { return _mm256_extractf128_ps(a, i); }
|
||||
template<> __forceinline vboolf4 extract4<0>(const vboolf8& a) { return _mm256_castps256_ps128(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool reduce_and(const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
|
||||
__forceinline bool reduce_or (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
|
||||
|
||||
__forceinline bool all (const vboolf8& a) { return _mm256_movemask_ps(a) == (unsigned int)0xff; }
|
||||
__forceinline bool any (const vboolf8& a) { return !_mm256_testz_ps(a,a); }
|
||||
__forceinline bool none(const vboolf8& a) { return _mm256_testz_ps(a,a) != 0; }
|
||||
|
||||
__forceinline bool all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
|
||||
__forceinline bool any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
|
||||
__forceinline bool none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
|
||||
|
||||
__forceinline unsigned int movemask(const vboolf8& a) { return _mm256_movemask_ps(a); }
|
||||
__forceinline size_t popcnt (const vboolf8& a) { return __popcnt((size_t)_mm256_movemask_ps(a)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboolf8& a, size_t index) { return a[index]; }
|
||||
__forceinline void set(vboolf8& a, size_t index) { a[index] = -1; }
|
||||
__forceinline void clear(vboolf8& a, size_t index) { a[index] = 0; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboolf8& a) {
|
||||
return cout << "<" << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", "
|
||||
<< a[4] << ", " << a[5] << ", " << a[6] << ", " << a[7] << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 8-wide AVX-512 bool type */
|
||||
template<>
|
||||
struct vboolf<8>
|
||||
{
|
||||
typedef vboolf8 Bool;
|
||||
typedef vint8 Int;
|
||||
|
||||
enum { size = 8 }; // number of SIMD elements
|
||||
__mmask8 v; // data
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf() {}
|
||||
__forceinline vboolf(const vboolf8& t) { v = t.v; }
|
||||
__forceinline vboolf8& operator =(const vboolf8& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vboolf(const __mmask8 &t) { v = t; }
|
||||
__forceinline operator __mmask8() const { return v; }
|
||||
|
||||
__forceinline vboolf(bool b) { v = b ? 0xff : 0x00; }
|
||||
__forceinline vboolf(int t) { v = (__mmask8)t; }
|
||||
__forceinline vboolf(unsigned int t) { v = (__mmask8)t; }
|
||||
|
||||
/* return int8 mask */
|
||||
__forceinline __m128i mask8() const {
|
||||
return _mm_movm_epi8(v);
|
||||
}
|
||||
|
||||
/* return int32 mask */
|
||||
__forceinline __m256i mask32() const {
|
||||
return _mm256_movm_epi32(v);
|
||||
}
|
||||
|
||||
/* return int64 mask */
|
||||
__forceinline __m512i mask64() const {
|
||||
return _mm512_movm_epi64(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf(FalseTy) : v(0x00) {}
|
||||
__forceinline vboolf(TrueTy) : v(0xff) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator !(const vboolf8& a) { return _mm512_knot(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator &(const vboolf8& a, const vboolf8& b) { return _mm512_kand(a, b); }
|
||||
__forceinline vboolf8 operator |(const vboolf8& a, const vboolf8& b) { return _mm512_kor(a, b); }
|
||||
__forceinline vboolf8 operator ^(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
|
||||
|
||||
__forceinline vboolf8 andn(const vboolf8& a, const vboolf8& b) { return _mm512_kandn(b, a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8& operator &=(vboolf8& a, const vboolf8& b) { return a = a & b; }
|
||||
__forceinline vboolf8& operator |=(vboolf8& a, const vboolf8& b) { return a = a | b; }
|
||||
__forceinline vboolf8& operator ^=(vboolf8& a, const vboolf8& b) { return a = a ^ b; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vboolf8 operator !=(const vboolf8& a, const vboolf8& b) { return _mm512_kxor(a, b); }
|
||||
__forceinline vboolf8 operator ==(const vboolf8& a, const vboolf8& b) { return _mm512_kxnor(a, b); }
|
||||
|
||||
__forceinline vboolf8 select(const vboolf8& s, const vboolf8& a, const vboolf8& b) {
|
||||
return _mm512_kor(_mm512_kand(s, a), _mm512_kandn(s, b));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reduction Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline int all (const vboolf8& a) { return a.v == 0xff; }
|
||||
__forceinline int any (const vboolf8& a) { return _mm512_kortestz(a, a) == 0; }
|
||||
__forceinline int none(const vboolf8& a) { return _mm512_kortestz(a, a) != 0; }
|
||||
|
||||
__forceinline int all (const vboolf8& valid, const vboolf8& b) { return all((!valid) | b); }
|
||||
__forceinline int any (const vboolf8& valid, const vboolf8& b) { return any(valid & b); }
|
||||
__forceinline int none(const vboolf8& valid, const vboolf8& b) { return none(valid & b); }
|
||||
|
||||
__forceinline size_t movemask(const vboolf8& a) { return _mm512_kmov(a); }
|
||||
__forceinline size_t popcnt (const vboolf8& a) { return __popcnt(a.v); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Conversion Operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline unsigned int toInt(const vboolf8& a) { return mm512_mask2int(a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Get/Set Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline bool get(const vboolf8& a, size_t index) { assert(index < 8); return (toInt(a) >> index) & 1; }
|
||||
__forceinline void set(vboolf8& a, size_t index) { assert(index < 8); a |= 1 << index; }
|
||||
__forceinline void clear(vboolf8& a, size_t index) { assert(index < 8); a = andn(a, 1 << index); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& cout, const vboolf8& a)
|
||||
{
|
||||
cout << "<";
|
||||
for (size_t i=0; i<8; i++) {
|
||||
if ((a.v >> i) & 1) cout << "1"; else cout << "0";
|
||||
}
|
||||
return cout << ">";
|
||||
}
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
// ======================================================================== //
|
||||
// Copyright 2009-2017 Intel Corporation //
|
||||
// //
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); //
|
||||
// you may not use this file except in compliance with the License. //
|
||||
// You may obtain a copy of the License at //
|
||||
// //
|
||||
// http://www.apache.org/licenses/LICENSE-2.0 //
|
||||
// //
|
||||
// Unless required by applicable law or agreed to in writing, software //
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, //
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
|
||||
// See the License for the specific language governing permissions and //
|
||||
// limitations under the License. //
|
||||
// ======================================================================== //
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace embree
|
||||
{
|
||||
/* 4-wide AVX 64-bit double type */
|
||||
template<>
|
||||
struct vdouble<4>
|
||||
{
|
||||
typedef vboold4 Bool;
|
||||
|
||||
enum { size = 4 }; // number of SIMD elements
|
||||
union { // data
|
||||
__m256d v;
|
||||
double i[4];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constructors, Assignment & Cast Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble() {}
|
||||
__forceinline vdouble(const vdouble4& t) { v = t.v; }
|
||||
__forceinline vdouble4& operator =(const vdouble4& f) { v = f.v; return *this; }
|
||||
|
||||
__forceinline vdouble(const __m256d& t) { v = t; }
|
||||
__forceinline operator __m256d() const { return v; }
|
||||
|
||||
__forceinline vdouble(double i) {
|
||||
v = _mm256_set1_pd(i);
|
||||
}
|
||||
|
||||
__forceinline vdouble(double a, double b, double c, double d) {
|
||||
v = _mm256_set_pd(d,c,b,a);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble(ZeroTy) : v(_mm256_setzero_pd()) {}
|
||||
__forceinline vdouble(OneTy) : v(_mm256_set1_pd(1)) {}
|
||||
__forceinline vdouble(StepTy) : v(_mm256_set_pd(3.0,2.0,1.0,0.0)) {}
|
||||
__forceinline vdouble(ReverseStepTy) : v(_mm256_setr_pd(3.0,2.0,1.0,0.0)) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Loads and Stores
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static __forceinline void store_nt(double *__restrict__ ptr, const vdouble4& a) {
|
||||
_mm256_stream_pd(ptr, a);
|
||||
}
|
||||
|
||||
static __forceinline vdouble4 loadu(const double* addr) {
|
||||
return _mm256_loadu_pd(addr);
|
||||
}
|
||||
|
||||
static __forceinline vdouble4 load(const vdouble4* addr) {
|
||||
return _mm256_load_pd((double*)addr);
|
||||
}
|
||||
|
||||
static __forceinline vdouble4 load(const double* addr) {
|
||||
return _mm256_load_pd(addr);
|
||||
}
|
||||
|
||||
static __forceinline void store(double* ptr, const vdouble4& v) {
|
||||
_mm256_store_pd(ptr, v);
|
||||
}
|
||||
|
||||
static __forceinline void storeu(double* ptr, const vdouble4& v) {
|
||||
_mm256_storeu_pd(ptr, v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Array Access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline double& operator [](size_t index) { assert(index < 4); return i[index]; }
|
||||
__forceinline const double& operator [](size_t index) const { assert(index < 4); return i[index]; }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble4 operator +(const vdouble4& a) { return a; }
|
||||
__forceinline vdouble4 operator -(const vdouble4& a) { return _mm256_sub_pd(_mm256_setzero_pd(), a); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Binary Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble4 operator +(const vdouble4& a, const vdouble4& b) { return _mm256_add_pd(a, b); }
|
||||
__forceinline vdouble4 operator +(const vdouble4& a, double b) { return a + vdouble4(b); }
|
||||
__forceinline vdouble4 operator +(double a, const vdouble4& b) { return vdouble4(a) + b; }
|
||||
|
||||
__forceinline vdouble4 operator -(const vdouble4& a, const vdouble4& b) { return _mm256_sub_pd(a, b); }
|
||||
__forceinline vdouble4 operator -(const vdouble4& a, double b) { return a - vdouble4(b); }
|
||||
__forceinline vdouble4 operator -(double a, const vdouble4& b) { return vdouble4(a) - b; }
|
||||
|
||||
__forceinline vdouble4 operator *(const vdouble4& a, const vdouble4& b) { return _mm256_mul_pd(a, b); }
|
||||
__forceinline vdouble4 operator *(const vdouble4& a, double b) { return a * vdouble4(b); }
|
||||
__forceinline vdouble4 operator *(double a, const vdouble4& b) { return vdouble4(a) * b; }
|
||||
|
||||
__forceinline vdouble4 operator &(const vdouble4& a, const vdouble4& b) { return _mm256_and_pd(a, b); }
|
||||
__forceinline vdouble4 operator &(const vdouble4& a, double b) { return a & vdouble4(b); }
|
||||
__forceinline vdouble4 operator &(double a, const vdouble4& b) { return vdouble4(a) & b; }
|
||||
|
||||
__forceinline vdouble4 operator |(const vdouble4& a, const vdouble4& b) { return _mm256_or_pd(a, b); }
|
||||
__forceinline vdouble4 operator |(const vdouble4& a, double b) { return a | vdouble4(b); }
|
||||
__forceinline vdouble4 operator |(double a, const vdouble4& b) { return vdouble4(a) | b; }
|
||||
|
||||
__forceinline vdouble4 operator ^(const vdouble4& a, const vdouble4& b) { return _mm256_xor_pd(a, b); }
|
||||
__forceinline vdouble4 operator ^(const vdouble4& a, double b) { return a ^ vdouble4(b); }
|
||||
__forceinline vdouble4 operator ^(double a, const vdouble4& b) { return vdouble4(a) ^ b; }
|
||||
|
||||
__forceinline vdouble4 min(const vdouble4& a, const vdouble4& b) { return _mm256_min_pd(a, b); }
|
||||
__forceinline vdouble4 min(const vdouble4& a, double b) { return min(a,vdouble4(b)); }
|
||||
__forceinline vdouble4 min(double a, const vdouble4& b) { return min(vdouble4(a),b); }
|
||||
|
||||
__forceinline vdouble4 max(const vdouble4& a, const vdouble4& b) { return _mm256_max_pd(a, b); }
|
||||
__forceinline vdouble4 max(const vdouble4& a, double b) { return max(a,vdouble4(b)); }
|
||||
__forceinline vdouble4 max(double a, const vdouble4& b) { return max(vdouble4(a),b); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Assignment Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble4& operator +=(vdouble4& a, const vdouble4& b) { return a = a + b; }
|
||||
__forceinline vdouble4& operator +=(vdouble4& a, double b) { return a = a + b; }
|
||||
|
||||
__forceinline vdouble4& operator -=(vdouble4& a, const vdouble4& b) { return a = a - b; }
|
||||
__forceinline vdouble4& operator -=(vdouble4& a, double b) { return a = a - b; }
|
||||
|
||||
__forceinline vdouble4& operator *=(vdouble4& a, const vdouble4& b) { return a = a * b; }
|
||||
__forceinline vdouble4& operator *=(vdouble4& a, double b) { return a = a * b; }
|
||||
|
||||
__forceinline vdouble4& operator &=(vdouble4& a, const vdouble4& b) { return a = a & b; }
|
||||
__forceinline vdouble4& operator &=(vdouble4& a, double b) { return a = a & b; }
|
||||
|
||||
__forceinline vdouble4& operator |=(vdouble4& a, const vdouble4& b) { return a = a | b; }
|
||||
__forceinline vdouble4& operator |=(vdouble4& a, double b) { return a = a | b; }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Comparison Operators + Select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__AVX512VL__)
|
||||
__forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_EQ); }
|
||||
__forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_NE); }
|
||||
__forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_LT); }
|
||||
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_GE); }
|
||||
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_GT); }
|
||||
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd_mask(a,b,_MM_CMPINT_LE); }
|
||||
#else
|
||||
__forceinline vboold4 operator ==(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_EQ_UQ); }
|
||||
__forceinline vboold4 operator !=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_NEQ_UQ); }
|
||||
__forceinline vboold4 operator < (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_LT_OQ); }
|
||||
__forceinline vboold4 operator >=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_GE_OQ); }
|
||||
__forceinline vboold4 operator > (const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_GT_OQ); }
|
||||
__forceinline vboold4 operator <=(const vdouble4& a, const vdouble4& b) { return _mm256_cmp_pd(a,b,_CMP_LE_OQ); }
|
||||
#endif
|
||||
|
||||
__forceinline vboold4 operator ==(const vdouble4& a, double b) { return a == vdouble4(b); }
|
||||
__forceinline vboold4 operator ==(double a, const vdouble4& b) { return vdouble4(a) == b; }
|
||||
|
||||
__forceinline vboold4 operator !=(const vdouble4& a, double b) { return a != vdouble4(b); }
|
||||
__forceinline vboold4 operator !=(double a, const vdouble4& b) { return vdouble4(a) != b; }
|
||||
|
||||
__forceinline vboold4 operator < (const vdouble4& a, double b) { return a < vdouble4(b); }
|
||||
__forceinline vboold4 operator < (double a, const vdouble4& b) { return vdouble4(a) < b; }
|
||||
|
||||
__forceinline vboold4 operator >=(const vdouble4& a, double b) { return a >= vdouble4(b); }
|
||||
__forceinline vboold4 operator >=(double a, const vdouble4& b) { return vdouble4(a) >= b; }
|
||||
|
||||
__forceinline vboold4 operator > (const vdouble4& a, double b) { return a > vdouble4(b); }
|
||||
__forceinline vboold4 operator > (double a, const vdouble4& b) { return vdouble4(a) > b; }
|
||||
|
||||
__forceinline vboold4 operator <=(const vdouble4& a, double b) { return a <= vdouble4(b); }
|
||||
__forceinline vboold4 operator <=(double a, const vdouble4& b) { return vdouble4(a) <= b; }
|
||||
|
||||
__forceinline vboold4 eq(const vdouble4& a, const vdouble4& b) { return a == b; }
|
||||
__forceinline vboold4 ne(const vdouble4& a, const vdouble4& b) { return a != b; }
|
||||
__forceinline vboold4 lt(const vdouble4& a, const vdouble4& b) { return a < b; }
|
||||
__forceinline vboold4 ge(const vdouble4& a, const vdouble4& b) { return a >= b; }
|
||||
__forceinline vboold4 gt(const vdouble4& a, const vdouble4& b) { return a > b; }
|
||||
__forceinline vboold4 le(const vdouble4& a, const vdouble4& b) { return a <= b; }
|
||||
|
||||
#if defined(__AVX512VL__)
|
||||
__forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_EQ); }
|
||||
__forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_NE); }
|
||||
__forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LT); }
|
||||
__forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GE); }
|
||||
__forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_GT); }
|
||||
__forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return _mm256_mask_cmp_pd_mask(mask, a, b, _MM_CMPINT_LE); }
|
||||
#else
|
||||
__forceinline vboold4 eq(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a == b); }
|
||||
__forceinline vboold4 ne(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a != b); }
|
||||
__forceinline vboold4 lt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a < b); }
|
||||
__forceinline vboold4 ge(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a >= b); }
|
||||
__forceinline vboold4 gt(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a > b); }
|
||||
__forceinline vboold4 le(const vboold4& mask, const vdouble4& a, const vdouble4& b) { return mask & (a <= b); }
|
||||
#endif
|
||||
|
||||
__forceinline vdouble4 select(const vboold4& m, const vdouble4& t, const vdouble4& f) {
|
||||
#if defined(__AVX512VL__)
|
||||
return _mm256_mask_blend_pd(m, f, t);
|
||||
#else
|
||||
return _mm256_blendv_pd(f, t, m);
|
||||
#endif
|
||||
}
|
||||
|
||||
__forceinline void xchg(const vboold4& m, vdouble4& a, vdouble4& b) {
|
||||
const vdouble4 c = a; a = select(m,b,a); b = select(m,c,b);
|
||||
}
|
||||
|
||||
__forceinline vboold4 test(const vdouble4& a, const vdouble4& b) {
|
||||
#if defined(__AVX512VL__)
|
||||
return _mm256_test_epi64_mask(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
|
||||
#else
|
||||
return _mm256_testz_si256(_mm256_castpd_si256(a),_mm256_castpd_si256(b));
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Movement/Shifting/Shuffling Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int i0, int i1>
|
||||
__forceinline vdouble4 shuffle(const vdouble4& v) {
|
||||
return _mm256_permute_pd(v, (i1 << 3) | (i0 << 2) | (i1 << 1) | i0);
|
||||
}
|
||||
|
||||
template<int i>
|
||||
__forceinline vdouble4 shuffle(const vdouble4& v) {
|
||||
return shuffle<i, i>(v);
|
||||
}
|
||||
|
||||
template<int i0, int i1>
|
||||
__forceinline vdouble4 shuffle2(const vdouble4& v) {
|
||||
return _mm256_permute2f128_pd(v, v, (i1 << 4) | i0);
|
||||
}
|
||||
|
||||
__forceinline double toScalar(const vdouble4& v) {
|
||||
return _mm_cvtsd_f64(_mm256_castpd256_pd128(v));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Reductions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline vdouble4 vreduce_min2(const vdouble4& x) { return min(x, shuffle<1,0>(x)); }
|
||||
__forceinline vdouble4 vreduce_min (const vdouble4& y) { const vdouble4 x = vreduce_min2(y); return min(x, shuffle2<1,0>(x)); }
|
||||
|
||||
__forceinline vdouble4 vreduce_max2(const vdouble4& x) { return max(x,shuffle<1,0>(x)); }
|
||||
__forceinline vdouble4 vreduce_max (const vdouble4& y) { const vdouble4 x = vreduce_max2(y); return max(x, shuffle2<1,0>(x)); }
|
||||
|
||||
__forceinline vdouble4 vreduce_and2(const vdouble4& x) { return x & shuffle<1,0>(x); }
|
||||
__forceinline vdouble4 vreduce_and (const vdouble4& y) { const vdouble4 x = vreduce_and2(y); return x & shuffle2<1,0>(x); }
|
||||
|
||||
__forceinline vdouble4 vreduce_or2(const vdouble4& x) { return x | shuffle<1,0>(x); }
|
||||
__forceinline vdouble4 vreduce_or (const vdouble4& y) { const vdouble4 x = vreduce_or2(y); return x | shuffle2<1,0>(x); }
|
||||
|
||||
__forceinline vdouble4 vreduce_add2(const vdouble4& x) { return x + shuffle<1,0>(x); }
|
||||
__forceinline vdouble4 vreduce_add (const vdouble4& y) { const vdouble4 x = vreduce_add2(y); return x + shuffle2<1,0>(x); }
|
||||
|
||||
__forceinline double reduce_add(const vdouble4& a) { return toScalar(vreduce_add(a)); }
|
||||
__forceinline double reduce_min(const vdouble4& a) { return toScalar(vreduce_min(a)); }
|
||||
__forceinline double reduce_max(const vdouble4& a) { return toScalar(vreduce_max(a)); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Memory load and store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// Output Operators
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
__forceinline std::ostream& operator <<(std::ostream& cout, const vdouble4& v)
|
||||
{
|
||||
cout << "<" << v[0];
|
||||
for (size_t i=1; i<4; i++) cout << ", " << v[i];
|
||||
cout << ">";
|
||||
return cout;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user