Added tests and documentation for soa<> rate qualifier.
This commit is contained in:
236
docs/ispc.rst
236
docs/ispc.rst
@@ -94,6 +94,7 @@ Contents:
|
|||||||
* `Short Vector Types`_
|
* `Short Vector Types`_
|
||||||
* `Array Types`_
|
* `Array Types`_
|
||||||
* `Struct Types`_
|
* `Struct Types`_
|
||||||
|
* `Structure of Array Types`_
|
||||||
|
|
||||||
+ `Declarations and Initializers`_
|
+ `Declarations and Initializers`_
|
||||||
+ `Expressions`_
|
+ `Expressions`_
|
||||||
@@ -151,7 +152,6 @@ Contents:
|
|||||||
+ `Data Layout`_
|
+ `Data Layout`_
|
||||||
+ `Data Alignment and Aliasing`_
|
+ `Data Alignment and Aliasing`_
|
||||||
+ `Restructuring Existing Programs to Use ISPC`_
|
+ `Restructuring Existing Programs to Use ISPC`_
|
||||||
+ `Understanding How to Interoperate With the Application's Data`_
|
|
||||||
|
|
||||||
* `Disclaimer and Legal Information`_
|
* `Disclaimer and Legal Information`_
|
||||||
|
|
||||||
@@ -1950,6 +1950,77 @@ still has only a single ``a`` member, since ``a`` was declared with
|
|||||||
indexing operation in the last line results in an error.
|
indexing operation in the last line results in an error.
|
||||||
|
|
||||||
|
|
||||||
|
Structure of Array Types
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
If data can be laid out in memory so that the executing program instances
|
||||||
|
access it via loads and stores of contiguous sections of memory, overall
|
||||||
|
performance can be improved noticably. One way to improve this memory
|
||||||
|
access coherence is to lay out structures in "structure of arrays" (SOA)
|
||||||
|
format in memory; the benefits from SOA layout are discussed in more detail
|
||||||
|
in the `Use "Structure of Arrays" Layout When Possible`_ section in the
|
||||||
|
ispc Performance Guide.
|
||||||
|
|
||||||
|
.. _Use "Structure of Arrays" Layout When Possible: perf.html#use-structure-of-arrays-layout-when-possible
|
||||||
|
|
||||||
|
``ispc`` provides two key language-level capabilities for laying out and
|
||||||
|
accessing data in SOA format:
|
||||||
|
|
||||||
|
* An ``soa`` keyword that transforms a regular ``struct`` into an SOA version
|
||||||
|
of the struct.
|
||||||
|
* Array indexing syntax for SOA arrays that transparently handles SOA
|
||||||
|
indexing.
|
||||||
|
|
||||||
|
As an example, consider a simple struct declaration:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
With the ``soa`` rate qualifier, an array of SOA variants of this structure
|
||||||
|
can be declared:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
soa<8> Point pts[...];
|
||||||
|
|
||||||
|
The in-memory layout of the ``Point``s has had the SOA transformation
|
||||||
|
applied, such that there are 8 ``x`` values in memory followed by 8 ``y``
|
||||||
|
values, and so forth. Here is the effective declaration of ``soa<8>
|
||||||
|
Point``:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct { uniform float x[8], y[8], z[8]; };
|
||||||
|
|
||||||
|
Given an array of SOA data, array indexing (and pointer arithmetic) is done
|
||||||
|
so that the appropriate values from the SOA array are accessed. For
|
||||||
|
example, given:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
soa<8> Point pts[...];
|
||||||
|
uniform float x = pts[10].x;
|
||||||
|
|
||||||
|
The generated code effectively accesses the second 8-wide SOA structure and
|
||||||
|
then loads the third ``x`` value from it. In general, one can write the
|
||||||
|
same code to access arrays of SOA elements as one would write to access
|
||||||
|
them in AOS layout.
|
||||||
|
|
||||||
|
Note that it directly follows from SOA layout that the layout of a single
|
||||||
|
element of the array isn't contiguous in memory--``pts[1].x`` and
|
||||||
|
``pts[1].y`` are separated by 7 ``float`` values in the above example.
|
||||||
|
|
||||||
|
There are a few limitations to the current implementation of SOA types in
|
||||||
|
``ispc``; these may be relaxed in future releases:
|
||||||
|
|
||||||
|
* It's illegal to typecast to ``soa`` data to ``void`` pointers.
|
||||||
|
* Reference types are illegal in SOA structures
|
||||||
|
* All members of SOA structures must have no rate qualifiers--specifically,
|
||||||
|
it's illegal to have an explicitly-qualified ``uniform`` or ``varying``
|
||||||
|
member of a structure that has ``soa`` applied to it.
|
||||||
|
|
||||||
|
|
||||||
Declarations and Initializers
|
Declarations and Initializers
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
@@ -3375,8 +3446,9 @@ Converting Between Array-of-Structures and Structure-of-Arrays Layout
|
|||||||
Applications often lay data out in memory in "array of structures" form.
|
Applications often lay data out in memory in "array of structures" form.
|
||||||
Though convenient in C/C++ code, this layout can make ``ispc`` programs
|
Though convenient in C/C++ code, this layout can make ``ispc`` programs
|
||||||
less efficient than they would be if the data was laid out in "structure of
|
less efficient than they would be if the data was laid out in "structure of
|
||||||
arrays" form. (See the section `Understanding How to Interoperate With the
|
arrays" form. (See the section `Use "Structure of Arrays" Layout When
|
||||||
Application's Data`_ for extended discussion of this topic.)
|
Possible`_ in the performance guide for extended discussion of this topic.)
|
||||||
|
|
||||||
|
|
||||||
The standard library does provide a few functions that efficiently convert
|
The standard library does provide a few functions that efficiently convert
|
||||||
between these two formats, for cases where it's not possible to change the
|
between these two formats, for cases where it's not possible to change the
|
||||||
@@ -3921,9 +3993,9 @@ program instances, ``ispc`` prohibits any varying types from being used in
|
|||||||
parameters to functions with the ``export`` qualifier. (``ispc`` also
|
parameters to functions with the ``export`` qualifier. (``ispc`` also
|
||||||
prohibits passing structures that themselves have varying types as members,
|
prohibits passing structures that themselves have varying types as members,
|
||||||
etc.) Thus, all datatypes that is shared with the application must have
|
etc.) Thus, all datatypes that is shared with the application must have
|
||||||
the ``uniform`` qualifier applied to them. (See `Understanding How to
|
the ``uniform`` or ``soa`` rate qualifier applied to them. (See `Use
|
||||||
Interoperate With the Application's Data`_ for more discussion of how to
|
"Structure of Arrays" Layout When Possible`_ in the Performance Guide for
|
||||||
load vectors of SoA or AoSoA data from the application.)
|
more discussion of how to load vectors of SOA data from the application.)
|
||||||
|
|
||||||
Similarly, ``struct`` types shared with the application can also have
|
Similarly, ``struct`` types shared with the application can also have
|
||||||
embedded pointers.
|
embedded pointers.
|
||||||
@@ -3941,7 +4013,7 @@ On the ``ispc`` side, the corresponding ``struct`` declaration is:
|
|||||||
|
|
||||||
// ispc
|
// ispc
|
||||||
struct Foo {
|
struct Foo {
|
||||||
uniform float * uniform foo, * uniform bar;
|
float * uniform foo, * uniform bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
There is one subtlety related to data layout to be aware of: ``ispc``
|
There is one subtlety related to data layout to be aware of: ``ispc``
|
||||||
@@ -4018,156 +4090,6 @@ program instances improves performance.
|
|||||||
|
|
||||||
.. _ispc Performance Tuning Guide: http://ispc.github.com/perf.html
|
.. _ispc Performance Tuning Guide: http://ispc.github.com/perf.html
|
||||||
|
|
||||||
Understanding How to Interoperate With the Application's Data
|
|
||||||
-------------------------------------------------------------
|
|
||||||
|
|
||||||
One of ``ispc``'s key goals is to be able to interoperate with the
|
|
||||||
application's data, in whatever layout it is stored in. You don't need to
|
|
||||||
worry about reformatting of data or the overhead of a driver model that
|
|
||||||
abstracts the data layout. This section illustrates some of the
|
|
||||||
alternatives with a simple example of computing the length of a large
|
|
||||||
number of vectors.
|
|
||||||
|
|
||||||
Consider for starters a ``Vector`` data-type, defined in C as:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct Vector { float x, y, z; };
|
|
||||||
|
|
||||||
We might have (still in C) an array of ``Vector`` s defined like this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
Vector vectors[1024];
|
|
||||||
|
|
||||||
This is called an "array of structures" (AoS) layout. To compute the
|
|
||||||
lengths of these vectors in parallel, you can write ``ispc`` code like
|
|
||||||
this:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
export void length(uniform Vector vectors[1024], uniform float len[]) {
|
|
||||||
foreach (index = 0 ... 1024) {
|
|
||||||
float x = vectors[index].x;
|
|
||||||
float y = vectors[index].y;
|
|
||||||
float z = vectors[index].z;
|
|
||||||
float l = sqrt(x*x + y*y + z*z);
|
|
||||||
len[index] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The problem with this implementation is that the indexing into the array of
|
|
||||||
structures, ``vectors[index].x`` is relatively expensive. On a target
|
|
||||||
machine that supports four-wide Intel® SSE, this turns into four loads of
|
|
||||||
single ``float`` values from non-contiguous memory locations, which are
|
|
||||||
then packed into a four-wide register corresponding to ``float x``. Once the
|
|
||||||
values are loaded into the local ``x``, ``y``, and ``z`` variables,
|
|
||||||
SIMD-efficient computation can proceed; getting to that point is
|
|
||||||
relatively inefficient.
|
|
||||||
|
|
||||||
(As described previously in `Converting Between Array-of-Structures and
|
|
||||||
Structure-of-Arrays Layout`_, this computation could be written more
|
|
||||||
efficiently using standard library routines to convert from the AoS layout,
|
|
||||||
if we were given a flat array of ``float`` values.)
|
|
||||||
|
|
||||||
An alternative data layout would be the "structure of arrays" (SoA). In C,
|
|
||||||
the data would be declared as:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
float x[1024], y[1024], z[1024];
|
|
||||||
|
|
||||||
The ``ispc`` code might be:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
export void length(uniform float x[1024], uniform float y[1024],
|
|
||||||
uniform float z[1024], uniform float len[]) {
|
|
||||||
foreach (index = 0 ... 1024) {
|
|
||||||
float xx = x[index];
|
|
||||||
float yy = y[index];
|
|
||||||
float zz = z[index];
|
|
||||||
float l = sqrt(xx*xx + yy*yy + zz*zz);
|
|
||||||
len[index] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
In this example, the loads into ``xx``, ``yy``, and ``zz`` are single
|
|
||||||
vector loads of an entire gang's worth of values into the corresponding
|
|
||||||
registers. This processing is more efficient than the multiple scalar
|
|
||||||
loads that are required with the AoS layout above.
|
|
||||||
|
|
||||||
A final alternative is "array of structures of arrays" (AoSoA), a hybrid
|
|
||||||
between these two. A structure is declared that stores a small number of
|
|
||||||
``x``, ``y``, and ``z`` values in contiguous memory locations:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct Vector16 {
|
|
||||||
float x[16], y[16], z[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
The ``ispc`` code has an outer loop over ``Vector16`` elements and
|
|
||||||
then an inner loop that peels off values from the element members:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
#define N_VEC (1024/16)
|
|
||||||
export void length(uniform Vector16 v[N_VEC], uniform float len[]) {
|
|
||||||
foreach (i = 0 ... N_VEC, j = 0 ... 16) {
|
|
||||||
float x = v[i].x[j];
|
|
||||||
float y = v[i].y[j];
|
|
||||||
float z = v[i].z[j];
|
|
||||||
float l = sqrt(x*x + y*y + z*z);
|
|
||||||
len[16*i+j] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
One advantage of the AoSoA layout is that the memory accesses to load
|
|
||||||
values are to nearby memory locations, where as with SoA, each of the three
|
|
||||||
loads above is to locations separated by a few thousand bytes. Thus, AoSoA
|
|
||||||
can be more cache friendly. For structures with many members, this
|
|
||||||
difference can lead to a substantial improvement.
|
|
||||||
|
|
||||||
With some additional complexity, ``ispc`` can also generate code that
|
|
||||||
efficiently processes data in AoSoA layout where the inner array length is
|
|
||||||
less than the machine vector width. For example, consider doing
|
|
||||||
computation with this AoSoA structure definition on a machine with an
|
|
||||||
8-wide vector unit (for example, an Intel® AVX target):
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct Vector4 {
|
|
||||||
float x[4], y[4], z[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
The ``ispc`` code to process this loads elements four at a time from
|
|
||||||
``Vector4`` instances until it has a full ``programCount`` number of
|
|
||||||
elements to work with and then proceeds with the computation.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
#define N_VEC (1024/4)
|
|
||||||
export void length(uniform Vector4 v[N_VEC], uniform float len[]) {
|
|
||||||
for (uniform int i = 0; i < N_VEC; i += programCount / 4) {
|
|
||||||
float x, y, z;
|
|
||||||
for (uniform int j = 0; j < programCount / 4; ++j) {
|
|
||||||
if (programIndex >= 4 * j &&
|
|
||||||
programIndex < 4 * (j+1)) {
|
|
||||||
int index = (programIndex & 0x3);
|
|
||||||
x = v[i+j].x[index];
|
|
||||||
y = v[i+j].y[index];
|
|
||||||
z = v[i+j].z[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float l = sqrt(x*x + y*y + z*z);
|
|
||||||
len[4*i + programIndex] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Disclaimer and Legal Information
|
Disclaimer and Legal Information
|
||||||
================================
|
================================
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ the most out of ``ispc`` in practice.
|
|||||||
+ `Improving Control Flow Coherence With "foreach_tiled"`_
|
+ `Improving Control Flow Coherence With "foreach_tiled"`_
|
||||||
+ `Using Coherent Control Flow Constructs`_
|
+ `Using Coherent Control Flow Constructs`_
|
||||||
+ `Use "uniform" Whenever Appropriate`_
|
+ `Use "uniform" Whenever Appropriate`_
|
||||||
|
+ `Use "Structure of Arrays" Layout When Possible`_
|
||||||
|
|
||||||
* `Tips and Techniques`_
|
* `Tips and Techniques`_
|
||||||
|
|
||||||
@@ -247,6 +248,76 @@ but it's always best to provide the compiler with as much help as possible
|
|||||||
to understand the actual form of your computation.
|
to understand the actual form of your computation.
|
||||||
|
|
||||||
|
|
||||||
|
Use "Structure of Arrays" Layout When Possible
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
In general, memory access performance (for both reads and writes) is best
|
||||||
|
when the running program instances access a contiguous region of memory; in
|
||||||
|
this case efficient vector load and store instructions can often be used
|
||||||
|
rather than gathers and scatters. As an example of this issue, consider an
|
||||||
|
array of a simple point datatype laid out and accessed in conventional
|
||||||
|
"array of structures" (AOS) layout:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
uniform Point pts[...];
|
||||||
|
float v = pts[programIndex].x;
|
||||||
|
|
||||||
|
In the above code, the access to ``pts[programIndex].x`` accesses
|
||||||
|
non-sequential memory locations, due to the ``y`` and ``z`` values between
|
||||||
|
the desired ``x`` values in memory. A "gather" is required to get the
|
||||||
|
value of ``v``, with a corresponding decrease in performance.
|
||||||
|
|
||||||
|
If ``Point`` was defined as a "structure of arrays" (SOA) type, the access
|
||||||
|
can be much more efficient:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct Point8 { float x[8], y[8], z[8]; };
|
||||||
|
uniform Point8 pts8[...];
|
||||||
|
int majorIndex = programIndex / 8;
|
||||||
|
int minorIndex = programIndex % 8;
|
||||||
|
float v = pts8[majorIndex].x[minorIndex];
|
||||||
|
|
||||||
|
In this case, each ``Point8`` has 8 ``x`` values contiguous in memory
|
||||||
|
before 8 ``y`` values and then 8 ``z`` values. If the gang size is 8 or
|
||||||
|
less, the access for ``v`` will have the same value of ``majorIndex`` for
|
||||||
|
all program instances and will access consecutive elements of the ``x[8]``
|
||||||
|
array with a vector load. (For larger gang sizes, two 8-wide vector loads
|
||||||
|
would be issues, which is also quite efficient.)
|
||||||
|
|
||||||
|
However, the syntax in the above code is messy; accessing SOA data in this
|
||||||
|
fashion is much less elegant than the corresponding code for accessing the
|
||||||
|
data with AOS layout. The ``soa`` qualifier in ``ispc`` can be used to
|
||||||
|
cause the corresponding transformation to be made to the ``Point`` type,
|
||||||
|
while preserving the clean syntax for data access that comes with AOS
|
||||||
|
layout:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
soa<8> Point pts[...];
|
||||||
|
float v = pts[programIndex].x;
|
||||||
|
|
||||||
|
Thanks to having SOA layout a first-class concept in the language's type
|
||||||
|
system, it's easy to write functions that convert data between the
|
||||||
|
layouts. For example, the ``aos_to_soa`` function below converts ``count``
|
||||||
|
elements of the given ``Point`` type from AOS to 8-wide SOA layout. (It
|
||||||
|
assumes that the caller has pre-allocated sufficient space in the
|
||||||
|
``pts_soa`` output array.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
void aos_to_soa(uniform Point pts_aos[], uniform int count,
|
||||||
|
soa<8> pts_soa[]) {
|
||||||
|
foreach (i = 0 ... count)
|
||||||
|
pts_soa[i] = pts_aos[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Analogously, a function could be written to convert back from SOA to AOS if
|
||||||
|
needed.
|
||||||
|
|
||||||
|
|
||||||
Tips and Techniques
|
Tips and Techniques
|
||||||
===================
|
===================
|
||||||
|
|
||||||
@@ -339,6 +410,12 @@ based on the index, it can be worth doing. See the example
|
|||||||
``examples/volume_rendering`` in the ``ispc`` distribution for the use of
|
``examples/volume_rendering`` in the ``ispc`` distribution for the use of
|
||||||
this technique in an instance where it is beneficial to performance.
|
this technique in an instance where it is beneficial to performance.
|
||||||
|
|
||||||
|
Understanding Memory Read Coalescing
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
XXXX todo
|
||||||
|
|
||||||
|
|
||||||
Avoid 64-bit Addressing Calculations When Possible
|
Avoid 64-bit Addressing Calculations When Possible
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
30
tests/scatter-struct-with-array-member.ispc
Normal file
30
tests/scatter-struct-with-array-member.ispc
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y[3], z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
//CO soa<8> Point pts[10];
|
||||||
|
uniform Point pts[80];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y[0] = 2*b*i;
|
||||||
|
pts[i].y[1] = 2*b*i+1;
|
||||||
|
pts[i].y[2] = 2*b*i+2;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
a *= -1;
|
||||||
|
Point vp = { a, { 2*a, 3*a, 4*a }, {5*a} };
|
||||||
|
pts[2+programIndex] = vp;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -4 * (programIndex-1);
|
||||||
|
RET[0] = 2;
|
||||||
|
RET[1] = 12;
|
||||||
|
}
|
||||||
21
tests/soa-1.ispc
Normal file
21
tests/soa-1.ispc
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
for (uniform int i = 0; i < 8*10; ++i) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10*programIndex;
|
||||||
|
}
|
||||||
23
tests/soa-10.ispc
Normal file
23
tests/soa-10.ispc
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform Point up = pts[1];
|
||||||
|
|
||||||
|
RET[programIndex] = up.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10;
|
||||||
|
}
|
||||||
15
tests/soa-11.ispc
Normal file
15
tests/soa-11.ispc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
soa<4> Point pts[2] = { { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } },
|
||||||
|
{ { 13, 14, 15, 16 }, { 17, 18, 19, 20, }, { 21, 22, 23, 24 } } };
|
||||||
|
|
||||||
|
RET[programIndex] = pts[1].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 6;
|
||||||
|
}
|
||||||
17
tests/soa-12.ispc
Normal file
17
tests/soa-12.ispc
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<4> Point pts[2] = { { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } },
|
||||||
|
{ { 13, 14, 15, 16 }, { 17, 18, 19, 20, }, { 21, 22, 23, 24 } } };
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex & 1].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = (programIndex & 1) ? 6 : 5;
|
||||||
|
}
|
||||||
26
tests/soa-13.ispc
Normal file
26
tests/soa-13.ispc
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform Point up = { b, 3, 170 };
|
||||||
|
pts[(int64)1] = up;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[(int64)programIndex].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 15*programIndex;
|
||||||
|
RET[1] = 170;
|
||||||
|
}
|
||||||
57
tests/soa-14.ispc
Normal file
57
tests/soa-14.ispc
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
static void p(uniform float *uniform ptr) {
|
||||||
|
//CO for (uniform int s = 0; s < 1; ++s) { // num to print
|
||||||
|
//CO for (uniform int i = 0; i < 3; ++i) { // num float in unif struct
|
||||||
|
//CO for (uniform int j = 0; j < 8; ++j, ++ptr) // soa width
|
||||||
|
//CO print("% ", *ptr);
|
||||||
|
//CO print("\n");
|
||||||
|
//CO }
|
||||||
|
//CO print("\n");
|
||||||
|
//CO }
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Point * uniform aossoa(uniform Point aospts[], uniform int count) {
|
||||||
|
uniform int roundUp = (count + 7) & ~0x7;
|
||||||
|
uniform int nAlloc = roundUp / 8;
|
||||||
|
|
||||||
|
soa<8> Point * uniform ret = uniform new soa<8> Point[nAlloc];
|
||||||
|
foreach (i = 0 ... count) {
|
||||||
|
//CO varying Point gp = { programIndex+1, 2*programIndex+1, 3*programIndex+1 };
|
||||||
|
//CO ret[i] = gp;
|
||||||
|
//CO ret[i].x = gp.x;
|
||||||
|
//CO ret[i].y = gp.y;
|
||||||
|
//CO ret[i].z = gp.z;
|
||||||
|
//CO print("%: % % %\n", i, gp.x, gp.y, gp.z);
|
||||||
|
ret[i] = aospts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)aospts);
|
||||||
|
//CO print("----\n");
|
||||||
|
//CO p((uniform float * uniform)ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
uniform Point pts[programCount+4];
|
||||||
|
foreach (i = 0 ... programCount+4) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Point * uniform soaPts = aossoa(pts, programCount+4);
|
||||||
|
|
||||||
|
RET[programIndex] = soaPts[programIndex+3].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 15*(programIndex+3);
|
||||||
|
}
|
||||||
48
tests/soa-15.ispc
Normal file
48
tests/soa-15.ispc
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y[3], z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
static void p(uniform float *uniform ptr) {
|
||||||
|
for (uniform int s = 0; s < 4; ++s) {
|
||||||
|
for (uniform int i = 0; i < 5; ++i) {
|
||||||
|
for (uniform int j = 0; j < 4; ++j, ++ptr)
|
||||||
|
print("% ", *ptr);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
soa<4> Point pts[10];
|
||||||
|
//CO uniform Point pts[40];
|
||||||
|
//CO foreach (i = 0 ... 40) {
|
||||||
|
for (uniform int i = 0; i < 40; ++i) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y[0] = 2*b*i;
|
||||||
|
pts[i].y[1] = 2*b*i+1;
|
||||||
|
pts[i].y[2] = 2*b*i+2;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
//CO print("delta %\n", ((uniform float * varying)(&pts[2+programIndex]) -
|
||||||
|
//CO (uniform float * uniform)&pts[0]));
|
||||||
|
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
a *= -1;
|
||||||
|
Point vp = { a, { 2*a, 3*a, 4*a }, {5*a} };
|
||||||
|
pts[2+programIndex] = vp;
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -4 * (programIndex-1);
|
||||||
|
RET[0] = 2;
|
||||||
|
RET[1] = 12;
|
||||||
|
}
|
||||||
48
tests/soa-16.ispc
Normal file
48
tests/soa-16.ispc
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
struct Point { double x; double y[3], z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
static void p(uniform float *uniform ptr) {
|
||||||
|
for (uniform int s = 0; s < 4; ++s) {
|
||||||
|
for (uniform int i = 0; i < 5; ++i) {
|
||||||
|
for (uniform int j = 0; j < 4; ++j, ++ptr)
|
||||||
|
print("% ", *ptr);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
soa<4> Point pts[10];
|
||||||
|
//CO uniform Point pts[40];
|
||||||
|
//CO foreach (i = 0 ... 40) {
|
||||||
|
for (uniform int i = 0; i < 40; ++i) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y[0] = 2*b*i;
|
||||||
|
pts[i].y[1] = 2*b*i+1;
|
||||||
|
pts[i].y[2] = 2*b*i+2;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
//CO print("delta %\n", ((uniform float * varying)(&pts[2+programIndex]) -
|
||||||
|
//CO (uniform float * uniform)&pts[0]));
|
||||||
|
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
a *= -1;
|
||||||
|
Point vp = { a, { 2*a, 3*a, 4*a }, {5*a} };
|
||||||
|
pts[2+programIndex] = vp;
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -4 * (programIndex-1);
|
||||||
|
RET[0] = 2;
|
||||||
|
RET[1] = 12;
|
||||||
|
}
|
||||||
50
tests/soa-17.ispc
Normal file
50
tests/soa-17.ispc
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
struct Point { double x; float y[3], z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
static void p(uniform float *uniform ptr) {
|
||||||
|
for (uniform int s = 0; s < 4; ++s) {
|
||||||
|
|
||||||
|
for (uniform int i = 0; i < 5; ++i) {
|
||||||
|
for (uniform int j = 0; j < 4; ++j, ++ptr)
|
||||||
|
print("% ", *ptr);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
soa<4> Point pts[10];
|
||||||
|
//CO uniform Point pts[40];
|
||||||
|
//CO foreach (i = 0 ... 40) {
|
||||||
|
for (uniform int i = 0; i < 40; ++i) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y[0] = 2*b*i;
|
||||||
|
pts[i].y[1] = 2*b*i+1;
|
||||||
|
pts[i].y[2] = 2*b*i+2;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
//CO print("one size %\n", sizeof(soa<4> Point));
|
||||||
|
//CO print("delta %\n", ((uniform int8 * varying)(&pts[2+programIndex]) -
|
||||||
|
//CO (uniform int8 * uniform)&pts[0]));
|
||||||
|
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
a *= -1;
|
||||||
|
Point vp = { a, { 2*a, 3*a, 4*a }, {5*a} };
|
||||||
|
pts[2+programIndex] = vp;
|
||||||
|
|
||||||
|
//CO p((uniform float * uniform)&pts[0]);
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -4 * (programIndex-1);
|
||||||
|
RET[0] = 2;
|
||||||
|
RET[1] = 12;
|
||||||
|
}
|
||||||
25
tests/soa-18.ispc
Normal file
25
tests/soa-18.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Point * ptr = &pts[programIndex];
|
||||||
|
++ptr;
|
||||||
|
ptr->y = -programIndex;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[1+programIndex].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -programIndex;
|
||||||
|
}
|
||||||
24
tests/soa-19.ispc
Normal file
24
tests/soa-19.ispc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Point * ptr = &pts[6+programIndex];
|
||||||
|
ptr->y = -programIndex;;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[6+programIndex].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -programIndex;
|
||||||
|
}
|
||||||
21
tests/soa-2.ispc
Normal file
21
tests/soa-2.ispc
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 15*programIndex;
|
||||||
|
}
|
||||||
22
tests/soa-20.ispc
Normal file
22
tests/soa-20.ispc
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Point * ptr = &pts[6+programIndex];
|
||||||
|
RET[programIndex] = ptr - pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 6 + programIndex;
|
||||||
|
}
|
||||||
32
tests/soa-21.ispc
Normal file
32
tests/soa-21.ispc
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
int x;
|
||||||
|
Point pts[10];
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
foreach (i = 0 ... 32) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].z = -b*i;
|
||||||
|
for (uniform int j = 0; j < 10; ++j) {
|
||||||
|
pts[i].pts[j].x = j + 100*i;
|
||||||
|
pts[i].pts[j].y = j + 1000*i;
|
||||||
|
pts[i].pts[j].z = j + 10000*i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
soa<8> Foo * ptr = &pts[7+programIndex];
|
||||||
|
RET[programIndex] = ptr->pts[3].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10000 * (7 + programIndex) + 3;
|
||||||
|
}
|
||||||
35
tests/soa-22.ispc
Normal file
35
tests/soa-22.ispc
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
int x;
|
||||||
|
Point *pts[3];
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
//CO uniform Foo pts[32];
|
||||||
|
foreach (i = 0 ... 32) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].z = -b*i;
|
||||||
|
for (uniform int j = 0; j < 3; ++j) {
|
||||||
|
pts[i].pts[j] = new uniform Point[4];
|
||||||
|
for (uniform int k = 0; k < 4; ++k) {
|
||||||
|
pts[i].pts[j][k].x = 100*i+10*j+k;
|
||||||
|
pts[i].pts[j][k].y = -1234;
|
||||||
|
pts[i].pts[j][k].z = -(100*i+10*j+k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].pts[programIndex % 3][programIndex % 4].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -(100*programIndex+10*(programIndex % 3)+(programIndex % 4));
|
||||||
|
}
|
||||||
28
tests/soa-23.ispc
Normal file
28
tests/soa-23.ispc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
float<3> vec;
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
//CO uniform Foo pts[32];
|
||||||
|
foreach (i = 0 ... 32) {
|
||||||
|
pts[i].vec.x = b*i;
|
||||||
|
pts[i].vec.y = -b*i;
|
||||||
|
pts[i].vec.z = 2*b*i;
|
||||||
|
pts[i].z = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex+2].vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -(5 * (programIndex+2));
|
||||||
|
}
|
||||||
32
tests/soa-24.ispc
Normal file
32
tests/soa-24.ispc
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
float<3> vec;
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
//CO uniform Foo pts[32];
|
||||||
|
foreach (i = 0 ... 32) {
|
||||||
|
pts[i].vec.x = b*i;
|
||||||
|
pts[i].vec.y = -b*i;
|
||||||
|
pts[i].vec.z = 2*b*i;
|
||||||
|
pts[i].z = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
pts[programIndex+2].vec.z *= -1;
|
||||||
|
float<3> vl = pts[programIndex].vec;
|
||||||
|
RET[programIndex] = vl.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10 * programIndex;
|
||||||
|
if (programIndex >= 2)
|
||||||
|
RET[programIndex] *= -1;
|
||||||
|
}
|
||||||
32
tests/soa-25.ispc
Normal file
32
tests/soa-25.ispc
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
float<3> vec;
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
//CO uniform Foo pts[32];
|
||||||
|
foreach (i = 0 ... 32) {
|
||||||
|
pts[i].vec.x = b*i;
|
||||||
|
pts[i].vec.y = -b*i;
|
||||||
|
pts[i].vec.z = 2*b*i;
|
||||||
|
pts[i].z = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
pts[2].vec.x *= -1;
|
||||||
|
float<3> vl = pts[programIndex].vec;
|
||||||
|
RET[programIndex] = vl.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 5 * programIndex;
|
||||||
|
if (programIndex == 2)
|
||||||
|
RET[programIndex] *= -1;
|
||||||
|
}
|
||||||
28
tests/soa-26.ispc
Normal file
28
tests/soa-26.ispc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
float<3> vec;
|
||||||
|
int8 z;
|
||||||
|
};
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Foo * uniform pts = uniform new soa<8> Foo[4];
|
||||||
|
//CO uniform Foo pts[32];
|
||||||
|
for (uniform int i = 0; i < 32; ++i) {
|
||||||
|
pts[i].vec.x = b*i;
|
||||||
|
pts[i].vec.y = -b*i;
|
||||||
|
pts[i].vec.z = 2*b*i;
|
||||||
|
pts[i].z = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[9].vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -45;
|
||||||
|
}
|
||||||
24
tests/soa-3.ispc
Normal file
24
tests/soa-3.ispc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y[3], z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
//CO uniform Point pts[80];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y[0] = 2*b*i;
|
||||||
|
pts[i].y[1] = 2*b*i+1;
|
||||||
|
pts[i].y[2] = 2*b*i+2;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].y[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 10*programIndex + 2;
|
||||||
|
}
|
||||||
24
tests/soa-4.ispc
Normal file
24
tests/soa-4.ispc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[8];
|
||||||
|
foreach (i = 0 ... 64) {
|
||||||
|
pts[i].x = 0;
|
||||||
|
pts[i].y = 0;
|
||||||
|
pts[i].z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point pv = { a, b, -a };
|
||||||
|
pts[8+programIndex] = pv;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[8+programIndex].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = -(1 + programIndex);
|
||||||
|
}
|
||||||
24
tests/soa-5.ispc
Normal file
24
tests/soa-5.ispc
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[8];
|
||||||
|
foreach (i = 0 ... 64) {
|
||||||
|
pts[i].x = 0;
|
||||||
|
pts[i].y = 0;
|
||||||
|
pts[i].z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point pv = { a, b, -a };
|
||||||
|
pts[6+programIndex] = pv;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[6+programIndex].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = (1 + programIndex);
|
||||||
|
}
|
||||||
25
tests/soa-6.ispc
Normal file
25
tests/soa-6.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[8];
|
||||||
|
foreach (i = 0 ... 64) {
|
||||||
|
pts[i].x = -42;
|
||||||
|
pts[i].y = 0;
|
||||||
|
pts[i].z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point pv = { a, b, -a };
|
||||||
|
pts[8+programIndex] = pv;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[6+programIndex].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = (1 + programIndex - 2);
|
||||||
|
RET[0] = RET[1] = -42;
|
||||||
|
}
|
||||||
27
tests/soa-7.ispc
Normal file
27
tests/soa-7.ispc
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[8];
|
||||||
|
foreach (i = 0 ... 64) {
|
||||||
|
pts[i].x = -42;
|
||||||
|
pts[i].y = 0;
|
||||||
|
pts[i].z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point pv = { a, b, -a };
|
||||||
|
pts[8+programIndex].x = pv.x;
|
||||||
|
pts[8+programIndex].y = pv.y;
|
||||||
|
pts[8+programIndex].z = pv.z;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[6+programIndex].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = (1 + programIndex - 2);
|
||||||
|
RET[0] = RET[1] = -42;
|
||||||
|
}
|
||||||
25
tests/soa-8.ispc
Normal file
25
tests/soa-8.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[8];
|
||||||
|
foreach (i = 0 ... 64) {
|
||||||
|
pts[i].x = -42;
|
||||||
|
pts[i].y = 0;
|
||||||
|
pts[i].z = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point pv = { a, b, -a };
|
||||||
|
pts[7+programIndex] = pv;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[8+programIndex].x;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = (2 + programIndex);
|
||||||
|
RET[programCount-1] = -42;
|
||||||
|
}
|
||||||
25
tests/soa-9.ispc
Normal file
25
tests/soa-9.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
struct Point { float x, y, z; };
|
||||||
|
|
||||||
|
export uniform int width() { return programCount; }
|
||||||
|
|
||||||
|
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||||
|
float a = aFOO[programIndex];
|
||||||
|
|
||||||
|
soa<8> Point pts[10];
|
||||||
|
foreach (i = 0 ... 80) {
|
||||||
|
pts[i].x = b*i;
|
||||||
|
pts[i].y = 2*b*i;
|
||||||
|
pts[i].z = 3*b*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform Point up = { b, 3, 170 };
|
||||||
|
pts[1] = up;
|
||||||
|
|
||||||
|
RET[programIndex] = pts[programIndex].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void result(uniform float RET[]) {
|
||||||
|
RET[programIndex] = 15*programIndex;
|
||||||
|
RET[1] = 170;
|
||||||
|
}
|
||||||
5
tests_errors/int-ptr-fail.ispc
Normal file
5
tests_errors/int-ptr-fail.ispc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Type conversion from "const uniform int32" to "uniform int32 * varying" for initializer is not possible
|
||||||
|
|
||||||
|
int voo() {
|
||||||
|
int * varying foo = 1;
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Type conversion only possible from atomic types
|
// Type conversion from "varying struct P" to "varying unsigned int32" for item count is not possible
|
||||||
|
|
||||||
struct P { int x; };
|
struct P { int x; };
|
||||||
|
|
||||||
|
|||||||
3
tests_errors/soa-1.ispc
Normal file
3
tests_errors/soa-1.ispc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Illegal to provide soa<4> qualifier with non-struct type "void"
|
||||||
|
|
||||||
|
soa<4> void foo() { }
|
||||||
25
tests_errors/soa-10.ispc
Normal file
25
tests_errors/soa-10.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Can't convert between types "uniform struct Foo" and "soa<4> struct Foo" with different SOA widths
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
xyz= uf;
|
||||||
|
}
|
||||||
25
tests_errors/soa-11.ispc
Normal file
25
tests_errors/soa-11.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Type conversion from "const uniform int32" to "soa<4> struct Foo" for assignment operator is not possible
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
xyz = 0;
|
||||||
|
}
|
||||||
25
tests_errors/soa-12.ispc
Normal file
25
tests_errors/soa-12.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Can't convert between types "const uniform int32" and "soa<4> float" with different SOA widths
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
xyz.x = 0;
|
||||||
|
}
|
||||||
25
tests_errors/soa-13.ispc
Normal file
25
tests_errors/soa-13.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Can't apply unary operator to SOA type "soa<4> struct Foo"
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
++xyz;
|
||||||
|
}
|
||||||
25
tests_errors/soa-14.ispc
Normal file
25
tests_errors/soa-14.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Can't apply unary operator to SOA type "soa<4> float"
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
-xyz.x;
|
||||||
|
}
|
||||||
25
tests_errors/soa-15.ispc
Normal file
25
tests_errors/soa-15.ispc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Illegal to use binary operator - with SOA type "soa<4> float"
|
||||||
|
|
||||||
|
struct Pt { float x, y, z; };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
//CO uniform int a;
|
||||||
|
//CO int a;
|
||||||
|
//CO float *x;
|
||||||
|
//CO float y[5], z;
|
||||||
|
double d[5];
|
||||||
|
float x, y, z;
|
||||||
|
//Pt p;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void bar(float);
|
||||||
|
|
||||||
|
uniform Foo uf;
|
||||||
|
varying Foo vf;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
|
||||||
|
export void x(uniform Foo &x, soa<8> Foo f[]) {
|
||||||
|
soa<4> Foo xyz;
|
||||||
|
xyz.x = xyz.y-xyz.x;
|
||||||
|
}
|
||||||
6
tests_errors/soa-2.ispc
Normal file
6
tests_errors/soa-2.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// soa<3> width illegal. Value must be positive power of two
|
||||||
|
|
||||||
|
struct F { float a, b, c; };
|
||||||
|
|
||||||
|
soa<3> F farray[10];
|
||||||
|
|
||||||
6
tests_errors/soa-3.ispc
Normal file
6
tests_errors/soa-3.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// syntax error, unexpected '-', expecting int32 constant
|
||||||
|
|
||||||
|
struct F { float a, b, c; };
|
||||||
|
|
||||||
|
soa<-4> F farray[10];
|
||||||
|
|
||||||
6
tests_errors/soa-4.ispc
Normal file
6
tests_errors/soa-4.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// syntax error, unexpected '-', expecting int32 constant
|
||||||
|
|
||||||
|
struct F { float a, b, c; };
|
||||||
|
|
||||||
|
soa<-4> F farray[10];
|
||||||
|
|
||||||
6
tests_errors/soa-5.ispc
Normal file
6
tests_errors/soa-5.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// "uniform" qualifier and "soa<4>" qualifier can't both be used
|
||||||
|
|
||||||
|
struct F { float a, b, c; };
|
||||||
|
|
||||||
|
uniform soa<4> F farray[10];
|
||||||
|
|
||||||
7
tests_errors/soa-6.ispc
Normal file
7
tests_errors/soa-6.ispc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Can't convert between types "uniform struct Point" and "soa<4> struct Point" with different SOA widths
|
||||||
|
|
||||||
|
struct Point { float a, b, c; };
|
||||||
|
|
||||||
|
void foo(soa<8> Point pts[]) {
|
||||||
|
soa<4> Point x = pts[0];
|
||||||
|
}
|
||||||
7
tests_errors/soa-7.ispc
Normal file
7
tests_errors/soa-7.ispc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Can't convert between types "uniform struct Point" and "soa<4> struct Point" with different SOA widths
|
||||||
|
|
||||||
|
struct Point { float a, b, c; };
|
||||||
|
|
||||||
|
void foo(soa<8> Point pts[]) {
|
||||||
|
soa<4> Point x = pts[0];
|
||||||
|
}
|
||||||
5
tests_errors/soa-8.ispc
Normal file
5
tests_errors/soa-8.ispc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Unable to apply SOA conversion to struct due to "uniform int32" member "x" with bound "uniform"
|
||||||
|
|
||||||
|
struct Point { uniform int x; float a, b, c; };
|
||||||
|
|
||||||
|
void foo(soa<8> Point pts[]);
|
||||||
9
tests_errors/soa-9.ispc
Normal file
9
tests_errors/soa-9.ispc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// Can't convert from pointer to SOA type "soa<8> struct A * uniform" to pointer to non-SOA type "void * varying"
|
||||||
|
|
||||||
|
struct A { float a, b; };
|
||||||
|
|
||||||
|
soa<8> A as[100];
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
void *ptr = &as[0];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user