Implement unbound varibility for struct types.
Now, if a struct member has an explicit 'uniform' or 'varying' qualifier, then that member has that variability, regardless of the variability of the struct's variability. Members without 'uniform' or 'varying' have unbound variability, and in turn inherit the variability of the struct. As a result of this, now structs can properly be 'varying' by default, just like all the other types, while still having sensible semantics.
This commit is contained in:
73
ctx.cpp
73
ctx.cpp
@@ -1169,7 +1169,7 @@ FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) {
|
||||
// values from other lanes that may have executed return
|
||||
// statements previously.
|
||||
StoreInst(retVal, returnValuePtr, GetInternalMask(),
|
||||
PointerType::GetUniform(returnType));
|
||||
returnType, PointerType::GetUniform(returnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2303,9 +2303,9 @@ FunctionEmitContext::maskedStore(llvm::Value *value, llvm::Value *ptr,
|
||||
llvm::Value *eltValue = ExtractInst(value, i, "value_member");
|
||||
llvm::Value *eltPtr =
|
||||
AddElementOffset(ptr, i, ptrType, "struct_ptr_ptr");
|
||||
const Type *eltPtrType =
|
||||
PointerType::GetUniform(collectionType->GetElementType(i));
|
||||
StoreInst(eltValue, eltPtr, mask, eltPtrType);
|
||||
const Type *eltType = collectionType->GetElementType(i);
|
||||
const Type *eltPtrType = PointerType::GetUniform(eltType);
|
||||
StoreInst(eltValue, eltPtr, mask, eltType, eltPtrType);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2391,25 +2391,61 @@ FunctionEmitContext::maskedStore(llvm::Value *value, llvm::Value *ptr,
|
||||
*/
|
||||
void
|
||||
FunctionEmitContext::scatter(llvm::Value *value, llvm::Value *ptr,
|
||||
const Type *ptrType, llvm::Value *mask) {
|
||||
const Type *valueType, const Type *ptrType,
|
||||
llvm::Value *mask) {
|
||||
Assert(dynamic_cast<const PointerType *>(ptrType) != NULL);
|
||||
Assert(ptrType->IsVaryingType());
|
||||
|
||||
const Type *valueType = ptrType->GetBaseType();
|
||||
|
||||
// I think this should be impossible
|
||||
Assert(dynamic_cast<const ArrayType *>(valueType) == NULL);
|
||||
|
||||
const CollectionType *collectionType = dynamic_cast<const CollectionType *>(valueType);
|
||||
if (collectionType != NULL) {
|
||||
const CollectionType *srcCollectionType =
|
||||
dynamic_cast<const CollectionType *>(valueType);
|
||||
if (srcCollectionType != NULL) {
|
||||
// We're scattering a collection type--we need to keep track of the
|
||||
// source type (the type of the data values to be stored) and the
|
||||
// destination type (the type of objects in memory that will be
|
||||
// stored into) separately. This is necessary so that we can get
|
||||
// all of the addressing calculations right if we're scattering
|
||||
// from a varying struct to an array of uniform instances of the
|
||||
// same struct type, versus scattering into an array of varying
|
||||
// instances of the struct type, etc.
|
||||
const CollectionType *dstCollectionType =
|
||||
dynamic_cast<const CollectionType *>(ptrType->GetBaseType());
|
||||
Assert(dstCollectionType != NULL);
|
||||
|
||||
// Scatter the collection elements individually
|
||||
for (int i = 0; i < collectionType->GetElementCount(); ++i) {
|
||||
llvm::Value *eltPtr = AddElementOffset(ptr, i, ptrType);
|
||||
for (int i = 0; i < srcCollectionType->GetElementCount(); ++i) {
|
||||
// First, get the values for the current element out of the
|
||||
// source.
|
||||
llvm::Value *eltValue = ExtractInst(value, i);
|
||||
const Type *eltPtrType =
|
||||
PointerType::GetVarying(collectionType->GetElementType(i));
|
||||
eltPtr = addVaryingOffsetsIfNeeded(eltPtr, eltPtrType);
|
||||
scatter(eltValue, eltPtr, eltPtrType, mask);
|
||||
const Type *srcEltType = srcCollectionType->GetElementType(i);
|
||||
|
||||
// We may be scattering a uniform atomic element; in this case
|
||||
// we'll smear it out to be varying before making the recursive
|
||||
// scatter() call below.
|
||||
if (srcEltType->IsUniformType() &&
|
||||
dynamic_cast<const AtomicType *>(srcEltType) != NULL) {
|
||||
eltValue = SmearUniform(eltValue, "to_varying");
|
||||
srcEltType = srcEltType->GetAsVaryingType();
|
||||
}
|
||||
|
||||
// Get the (varying) pointer to the i'th element of the target
|
||||
// collection
|
||||
llvm::Value *eltPtr = AddElementOffset(ptr, i, ptrType);
|
||||
|
||||
// The destination element type may be uniform (e.g. if we're
|
||||
// scattering to an array of uniform structs). Thus, we need
|
||||
// to be careful about passing the correct type to
|
||||
// addVaryingOffsetsIfNeeded() here.
|
||||
const Type *dstEltType = dstCollectionType->GetElementType(i);
|
||||
const Type *dstEltPtrType = PointerType::GetVarying(dstEltType);
|
||||
eltPtr = addVaryingOffsetsIfNeeded(eltPtr, dstEltPtrType);
|
||||
|
||||
// And recursively scatter() until we hit an atomic or pointer
|
||||
// type, at which point the actual memory operations can be
|
||||
// performed...
|
||||
scatter(eltValue, eltPtr, srcEltType, dstEltPtrType, mask);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2483,7 +2519,8 @@ FunctionEmitContext::StoreInst(llvm::Value *value, llvm::Value *ptr) {
|
||||
|
||||
void
|
||||
FunctionEmitContext::StoreInst(llvm::Value *value, llvm::Value *ptr,
|
||||
llvm::Value *mask, const Type *ptrType) {
|
||||
llvm::Value *mask, const Type *valueType,
|
||||
const Type *ptrType) {
|
||||
if (value == NULL || ptr == NULL) {
|
||||
// may happen due to error elsewhere
|
||||
Assert(m->errorCount > 0);
|
||||
@@ -2509,7 +2546,7 @@ FunctionEmitContext::StoreInst(llvm::Value *value, llvm::Value *ptr,
|
||||
Assert(ptrType->IsVaryingType());
|
||||
// We have a varying ptr (an array of pointers), so it's time to
|
||||
// scatter
|
||||
scatter(value, ptr, ptrType, GetFullMask());
|
||||
scatter(value, ptr, valueType, ptrType, GetFullMask());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2791,7 +2828,7 @@ FunctionEmitContext::CallInst(llvm::Value *func, const FunctionType *funcType,
|
||||
// accumulate the result using the call mask.
|
||||
if (callResult != NULL) {
|
||||
Assert(resultPtr != NULL);
|
||||
StoreInst(callResult, resultPtr, callMask,
|
||||
StoreInst(callResult, resultPtr, callMask, returnType,
|
||||
PointerType::GetUniform(returnType));
|
||||
}
|
||||
else
|
||||
|
||||
7
ctx.h
7
ctx.h
@@ -443,7 +443,8 @@ public:
|
||||
varying, the given storeMask is used to mask the stores so that
|
||||
they only execute for the active program instances. */
|
||||
void StoreInst(llvm::Value *value, llvm::Value *ptr,
|
||||
llvm::Value *storeMask, const Type *ptrType);
|
||||
llvm::Value *storeMask, const Type *valueType,
|
||||
const Type *ptrType);
|
||||
|
||||
/** Copy count bytes of memory from the location pointed to by src to
|
||||
the location pointed to by dest. (src and dest must not be
|
||||
@@ -652,8 +653,8 @@ private:
|
||||
|
||||
CFInfo *popCFState();
|
||||
|
||||
void scatter(llvm::Value *value, llvm::Value *ptr, const Type *ptrType,
|
||||
llvm::Value *mask);
|
||||
void scatter(llvm::Value *value, llvm::Value *ptr, const Type *valueType,
|
||||
const Type *ptrType, llvm::Value *mask);
|
||||
void maskedStore(llvm::Value *value, llvm::Value *ptr, const Type *ptrType,
|
||||
llvm::Value *mask);
|
||||
llvm::Value *gather(llvm::Value *ptr, const Type *ptrType, llvm::Value *mask,
|
||||
|
||||
113
docs/ispc.rst
113
docs/ispc.rst
@@ -92,7 +92,8 @@ Contents:
|
||||
* `Reference Types`_
|
||||
* `Enumeration Types`_
|
||||
* `Short Vector Types`_
|
||||
* `Struct and Array Types`_
|
||||
* `Array Types`_
|
||||
* `Struct Types`_
|
||||
|
||||
+ `Declarations and Initializers`_
|
||||
+ `Expressions`_
|
||||
@@ -859,7 +860,9 @@ A variable that is declared with the ``uniform`` qualifier represents a
|
||||
single value that is shared across the entire gang. (In contrast, the
|
||||
default variability qualifier for variables in ``ispc``, ``varying``,
|
||||
represents a variable that has a distinct storage location for each program
|
||||
instance in the gang.)
|
||||
instance in the gang.) (Though see the discussion in `Struct Types`_ for
|
||||
some subtleties related to ``uniform`` and ``varying`` when used with
|
||||
structures.)
|
||||
|
||||
It is an error to try to assign a ``varying`` value to a ``uniform``
|
||||
variable, though ``uniform`` values can be assigned to ``uniform``
|
||||
@@ -1832,20 +1835,19 @@ expressions:
|
||||
int8<2> bar = ...;
|
||||
foo.yz = bar; // Error: can't assign to left-hand side of expression
|
||||
|
||||
Struct and Array Types
|
||||
----------------------
|
||||
|
||||
More complex data structures can be built using ``struct`` and arrays.
|
||||
Array Types
|
||||
-----------
|
||||
|
||||
Arrays of any type can be declared just as in C and C++:
|
||||
|
||||
::
|
||||
|
||||
struct Foo {
|
||||
float time;
|
||||
int flags[10];
|
||||
};
|
||||
float a[10];
|
||||
uniform int * varying b[20];
|
||||
|
||||
Like in C, multidimensional arrays can be specified; the following declares
|
||||
an array of 5 arrays of 15 floats.
|
||||
Multidimensional arrays can be specified as arrays of arrays; the following
|
||||
declares an array of 5 arrays of 15 floats.
|
||||
|
||||
::
|
||||
|
||||
@@ -1860,6 +1862,27 @@ that functions can be declared to take "unsized arrays" as parameters:
|
||||
|
||||
void foo(float array[], int length);
|
||||
|
||||
Finally, the name of an array will be automatically implicitly converted to
|
||||
a uniform pointer to the array type if needed:
|
||||
|
||||
::
|
||||
|
||||
int a[10];
|
||||
int * uniform ap = a;
|
||||
|
||||
|
||||
Struct Types
|
||||
------------
|
||||
|
||||
Aggregate data structures can be built using ``struct``.
|
||||
|
||||
::
|
||||
|
||||
struct Foo {
|
||||
float time;
|
||||
int flags[10];
|
||||
};
|
||||
|
||||
As in C++, after a ``struct`` is declared, an instance can be created using
|
||||
the ``struct``'s name:
|
||||
|
||||
@@ -1873,6 +1896,60 @@ Alternatively, ``struct`` can be used before the structure name:
|
||||
|
||||
struct Foo f;
|
||||
|
||||
Members in a structure declaration may each have ``uniform`` or ``varying``
|
||||
qualifiers, or may have no rate qualifier, in which case their variability
|
||||
is initially "unbound".
|
||||
|
||||
::
|
||||
|
||||
struct Bar {
|
||||
uniform int a;
|
||||
varying int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
|
||||
In the declaration above, the variability of ``c`` is unbound. The
|
||||
variability of struct members that are unbound is resolved when a struct is
|
||||
defined; if the ``struct`` is ``uniform``, then unbound members are
|
||||
``uniform``, and if the ``struct`` is ``varying``, then unbound members are
|
||||
varying.
|
||||
|
||||
::
|
||||
|
||||
Bar vb;
|
||||
uniform Bar ub;
|
||||
|
||||
Here, ``b`` is a ``varying Bar`` (since ``varying`` is the default
|
||||
variability). If ``Bar`` is defined as above, then ``vb.a`` is still a
|
||||
``uniform int``, since its varaibility was bound in the original
|
||||
declaration of the ``Bar`` type. Similarly, ``vb.b`` is ``varying``. The
|
||||
variability fo ``vb.c`` is ``varying``, since ``vb`` is ``varying``.
|
||||
|
||||
(Similarly, ``ub.a`` is ``uniform``, ``ub.b`` is ``varying``, and ``ub.c``
|
||||
is ``uniform``.)
|
||||
|
||||
In most cases, it's worthwhile to declare ``struct`` members with unbound
|
||||
variability so that all have the same variability for both ``uniform`` and
|
||||
``varying`` structs. In particular, if a ``struct`` has a member with
|
||||
bound ``uniform`` type, it's not possible to index into an array of the
|
||||
struct type with a ``varying`` index. Consider the following example:
|
||||
|
||||
::
|
||||
|
||||
struct Foo { uniform int a; };
|
||||
uniform Foo f[...] = ...;
|
||||
int index = ...;
|
||||
Foo fv = f[index]; // ERROR
|
||||
|
||||
Here, the ``Foo`` type has a member with bound ``uniform`` variability.
|
||||
Because ``index`` has a different value for each program instance in the
|
||||
above code, the value of ``f[index]`` needs to be able to store a different
|
||||
value of ``Foo::a`` for each program instance. However, a ``varying Foo``
|
||||
still has only a single ``a`` member, since ``a`` was declared with
|
||||
``uniform`` variability in the declaration of ``Foo``. Therefore, the
|
||||
indexing operation in the last line results in an error.
|
||||
|
||||
|
||||
Declarations and Initializers
|
||||
-----------------------------
|
||||
@@ -3824,12 +3901,12 @@ equivalents of them.) For example, given a structure in ``ispc``:
|
||||
|
||||
// ispc code
|
||||
struct Node {
|
||||
uniform int count;
|
||||
uniform float pos[3];
|
||||
int count;
|
||||
float pos[3];
|
||||
};
|
||||
|
||||
If the ``Node`` structure is used in the parameters to an ``export`` ed
|
||||
function, then the header file generated by the ``ispc`` compiler will
|
||||
If a ``uniform Node`` structure is used in the parameters to an ``export``
|
||||
ed function, then the header file generated by the ``ispc`` compiler will
|
||||
have a declaration like:
|
||||
|
||||
::
|
||||
@@ -3970,7 +4047,7 @@ this:
|
||||
|
||||
::
|
||||
|
||||
export void length(Vector vectors[1024], uniform float len[]) {
|
||||
export void length(uniform Vector vectors[1024], uniform float len[]) {
|
||||
foreach (index = 0 ... 1024) {
|
||||
float x = vectors[index].x;
|
||||
float y = vectors[index].y;
|
||||
@@ -4038,7 +4115,7 @@ then an inner loop that peels off values from the element members:
|
||||
::
|
||||
|
||||
#define N_VEC (1024/16)
|
||||
export void length(Vector16 v[N_VEC], uniform float len[]) {
|
||||
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];
|
||||
@@ -4075,7 +4152,7 @@ elements to work with and then proceeds with the computation.
|
||||
::
|
||||
|
||||
#define N_VEC (1024/4)
|
||||
export void length(Vector4 v[N_VEC], uniform float len[]) {
|
||||
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) {
|
||||
|
||||
@@ -50,7 +50,6 @@ struct Isect {
|
||||
struct Sphere {
|
||||
vec center;
|
||||
float radius;
|
||||
|
||||
};
|
||||
|
||||
struct Plane {
|
||||
@@ -83,7 +82,7 @@ static inline void vnormalize(vec &v) {
|
||||
|
||||
|
||||
static void
|
||||
ray_plane_intersect(Isect &isect, Ray &ray, Plane &plane) {
|
||||
ray_plane_intersect(Isect &isect, Ray &ray, uniform Plane &plane) {
|
||||
float d = -dot(plane.p, plane.n);
|
||||
float v = dot(ray.dir, plane.n);
|
||||
|
||||
@@ -103,7 +102,7 @@ ray_plane_intersect(Isect &isect, Ray &ray, Plane &plane) {
|
||||
|
||||
|
||||
static inline void
|
||||
ray_sphere_intersect(Isect &isect, Ray &ray, Sphere &sphere) {
|
||||
ray_sphere_intersect(Isect &isect, Ray &ray, uniform Sphere &sphere) {
|
||||
vec rs = ray.org - sphere.center;
|
||||
|
||||
float B = dot(rs, ray.dir);
|
||||
@@ -148,7 +147,7 @@ orthoBasis(vec basis[3], vec n) {
|
||||
|
||||
|
||||
static float
|
||||
ambient_occlusion(Isect &isect, Plane &plane, Sphere spheres[3],
|
||||
ambient_occlusion(Isect &isect, uniform Plane &plane, uniform Sphere spheres[3],
|
||||
RNGState &rngstate) {
|
||||
float eps = 0.0001f;
|
||||
vec p, n;
|
||||
@@ -204,8 +203,8 @@ ambient_occlusion(Isect &isect, Plane &plane, Sphere spheres[3],
|
||||
static void ao_scanlines(uniform int y0, uniform int y1, uniform int w,
|
||||
uniform int h, uniform int nsubsamples,
|
||||
uniform float image[]) {
|
||||
static Plane plane = { { 0.0f, -0.5f, 0.0f }, { 0.f, 1.f, 0.f } };
|
||||
static Sphere spheres[3] = {
|
||||
static uniform Plane plane = { { 0.0f, -0.5f, 0.0f }, { 0.f, 1.f, 0.f } };
|
||||
static uniform Sphere spheres[3] = {
|
||||
{ { -2.0f, 0.0f, -3.5f }, 0.5f },
|
||||
{ { -0.5f, 0.0f, -3.0f }, 0.5f },
|
||||
{ { 1.0f, 0.0f, -2.2f }, 0.5f } };
|
||||
|
||||
@@ -35,35 +35,35 @@
|
||||
|
||||
struct InputDataArrays
|
||||
{
|
||||
uniform float * uniform zBuffer;
|
||||
uniform unsigned int16 * uniform normalEncoded_x; // half float
|
||||
uniform unsigned int16 * uniform normalEncoded_y; // half float
|
||||
uniform unsigned int16 * uniform specularAmount; // half float
|
||||
uniform unsigned int16 * uniform specularPower; // half float
|
||||
uniform unsigned int8 * uniform albedo_x; // unorm8
|
||||
uniform unsigned int8 * uniform albedo_y; // unorm8
|
||||
uniform unsigned int8 * uniform albedo_z; // unorm8
|
||||
uniform float * uniform lightPositionView_x;
|
||||
uniform float * uniform lightPositionView_y;
|
||||
uniform float * uniform lightPositionView_z;
|
||||
uniform float * uniform lightAttenuationBegin;
|
||||
uniform float * uniform lightColor_x;
|
||||
uniform float * uniform lightColor_y;
|
||||
uniform float * uniform lightColor_z;
|
||||
uniform float * uniform lightAttenuationEnd;
|
||||
uniform float *zBuffer;
|
||||
uniform unsigned int16 *normalEncoded_x; // half float
|
||||
uniform unsigned int16 *normalEncoded_y; // half float
|
||||
uniform unsigned int16 *specularAmount; // half float
|
||||
uniform unsigned int16 *specularPower; // half float
|
||||
uniform unsigned int8 *albedo_x; // unorm8
|
||||
uniform unsigned int8 *albedo_y; // unorm8
|
||||
uniform unsigned int8 *albedo_z; // unorm8
|
||||
uniform float *lightPositionView_x;
|
||||
uniform float *lightPositionView_y;
|
||||
uniform float *lightPositionView_z;
|
||||
uniform float *lightAttenuationBegin;
|
||||
uniform float *lightColor_x;
|
||||
uniform float *lightColor_y;
|
||||
uniform float *lightColor_z;
|
||||
uniform float *lightAttenuationEnd;
|
||||
};
|
||||
|
||||
struct InputHeader
|
||||
{
|
||||
uniform float cameraProj[4][4];
|
||||
uniform float cameraNear;
|
||||
uniform float cameraFar;
|
||||
float cameraProj[4][4];
|
||||
float cameraNear;
|
||||
float cameraFar;
|
||||
|
||||
uniform int32 framebufferWidth;
|
||||
uniform int32 framebufferHeight;
|
||||
uniform int32 numLights;
|
||||
uniform int32 inputDataChunkSize;
|
||||
uniform int32 inputDataArrayOffsets[idaNum];
|
||||
int32 framebufferWidth;
|
||||
int32 framebufferHeight;
|
||||
int32 numLights;
|
||||
int32 inputDataChunkSize;
|
||||
int32 inputDataArrayOffsets[idaNum];
|
||||
};
|
||||
|
||||
|
||||
@@ -575,8 +575,6 @@ SplitTileMinMax(
|
||||
uniform float light_positionView_z_array[],
|
||||
uniform float light_attenuationEnd_array[],
|
||||
// Outputs
|
||||
// TODO: ISPC doesn't currently like multidimensionsal arrays so we'll do the
|
||||
// indexing math ourselves
|
||||
uniform int32 subtileIndices[],
|
||||
uniform int32 subtileIndicesPitch,
|
||||
uniform int32 subtileNumLights[]
|
||||
|
||||
@@ -43,17 +43,17 @@ struct Ray {
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
uniform float p[3][4];
|
||||
uniform int id;
|
||||
uniform int pad[3];
|
||||
float p[3][4];
|
||||
int id;
|
||||
int pad[3];
|
||||
};
|
||||
|
||||
struct LinearBVHNode {
|
||||
uniform float bounds[2][3];
|
||||
uniform unsigned int offset; // num primitives for leaf, second child for interior
|
||||
uniform unsigned int8 nPrimitives;
|
||||
uniform unsigned int8 splitAxis;
|
||||
uniform unsigned int16 pad;
|
||||
float bounds[2][3];
|
||||
unsigned int offset; // num primitives for leaf, second child for interior
|
||||
unsigned int8 nPrimitives;
|
||||
unsigned int8 splitAxis;
|
||||
unsigned int16 pad;
|
||||
};
|
||||
|
||||
static inline float3 Cross(const float3 v1, const float3 v2) {
|
||||
@@ -88,9 +88,12 @@ static void generateRay(uniform const float raster2camera[4][4],
|
||||
camy /= camw;
|
||||
camz /= camw;
|
||||
|
||||
ray.dir.x = camera2world[0][0] * camx + camera2world[0][1] * camy + camera2world[0][2] * camz;
|
||||
ray.dir.y = camera2world[1][0] * camx + camera2world[1][1] * camy + camera2world[1][2] * camz;
|
||||
ray.dir.z = camera2world[2][0] * camx + camera2world[2][1] * camy + camera2world[2][2] * camz;
|
||||
ray.dir.x = camera2world[0][0] * camx + camera2world[0][1] * camy +
|
||||
camera2world[0][2] * camz;
|
||||
ray.dir.y = camera2world[1][0] * camx + camera2world[1][1] * camy +
|
||||
camera2world[1][2] * camz;
|
||||
ray.dir.z = camera2world[2][0] * camx + camera2world[2][1] * camy +
|
||||
camera2world[2][2] * camz;
|
||||
|
||||
ray.origin.x = camera2world[0][3] / camera2world[3][3];
|
||||
ray.origin.y = camera2world[1][3] / camera2world[3][3];
|
||||
@@ -143,7 +146,7 @@ static bool BBoxIntersect(const uniform float bounds[2][3],
|
||||
|
||||
|
||||
|
||||
static bool TriIntersect(const Triangle &tri, Ray &ray) {
|
||||
static bool TriIntersect(const uniform Triangle &tri, Ray &ray) {
|
||||
uniform float3 p0 = { tri.p[0][0], tri.p[0][1], tri.p[0][2] };
|
||||
uniform float3 p1 = { tri.p[1][0], tri.p[1][1], tri.p[1][2] };
|
||||
uniform float3 p2 = { tri.p[2][0], tri.p[2][1], tri.p[2][2] };
|
||||
@@ -183,8 +186,8 @@ static bool TriIntersect(const Triangle &tri, Ray &ray) {
|
||||
}
|
||||
|
||||
|
||||
bool BVHIntersect(const LinearBVHNode nodes[], const Triangle tris[],
|
||||
Ray &r) {
|
||||
bool BVHIntersect(const uniform LinearBVHNode nodes[],
|
||||
const uniform Triangle tris[], Ray &r) {
|
||||
Ray ray = r;
|
||||
bool hit = false;
|
||||
// Follow ray through BVH nodes to find primitive intersections
|
||||
@@ -193,7 +196,7 @@ bool BVHIntersect(const LinearBVHNode nodes[], const Triangle tris[],
|
||||
|
||||
while (true) {
|
||||
// Check ray against BVH node
|
||||
LinearBVHNode node = nodes[nodeNum];
|
||||
uniform LinearBVHNode node = nodes[nodeNum];
|
||||
if (any(BBoxIntersect(node.bounds, ray))) {
|
||||
uniform unsigned int nPrimitives = node.nPrimitives;
|
||||
if (nPrimitives > 0) {
|
||||
@@ -239,8 +242,8 @@ static void raytrace_tile(uniform int x0, uniform int x1,
|
||||
const uniform float raster2camera[4][4],
|
||||
const uniform float camera2world[4][4],
|
||||
uniform float image[], uniform int id[],
|
||||
const LinearBVHNode nodes[],
|
||||
const Triangle triangles[]) {
|
||||
const uniform LinearBVHNode nodes[],
|
||||
const uniform Triangle triangles[]) {
|
||||
uniform float widthScale = (float)(baseWidth) / (float)(width);
|
||||
uniform float heightScale = (float)(baseHeight) / (float)(height);
|
||||
|
||||
@@ -262,8 +265,8 @@ export void raytrace_ispc(uniform int width, uniform int height,
|
||||
const uniform float raster2camera[4][4],
|
||||
const uniform float camera2world[4][4],
|
||||
uniform float image[], uniform int id[],
|
||||
const LinearBVHNode nodes[],
|
||||
const Triangle triangles[]) {
|
||||
const uniform LinearBVHNode nodes[],
|
||||
const uniform Triangle triangles[]) {
|
||||
raytrace_tile(0, width, 0, height, width, height, baseWidth, baseHeight,
|
||||
raster2camera, camera2world, image,
|
||||
id, nodes, triangles);
|
||||
@@ -275,8 +278,8 @@ task void raytrace_tile_task(uniform int width, uniform int height,
|
||||
const uniform float raster2camera[4][4],
|
||||
const uniform float camera2world[4][4],
|
||||
uniform float image[], uniform int id[],
|
||||
const LinearBVHNode nodes[],
|
||||
const Triangle triangles[]) {
|
||||
const uniform LinearBVHNode nodes[],
|
||||
const uniform Triangle triangles[]) {
|
||||
uniform int dx = 16, dy = 16; // must match dx, dy below
|
||||
uniform int xBuckets = (width + (dx-1)) / dx;
|
||||
uniform int x0 = (taskIndex % xBuckets) * dx;
|
||||
@@ -295,8 +298,8 @@ export void raytrace_ispc_tasks(uniform int width, uniform int height,
|
||||
const uniform float raster2camera[4][4],
|
||||
const uniform float camera2world[4][4],
|
||||
uniform float image[], uniform int id[],
|
||||
const LinearBVHNode nodes[],
|
||||
const Triangle triangles[]) {
|
||||
const uniform LinearBVHNode nodes[],
|
||||
const uniform Triangle triangles[]) {
|
||||
uniform int dx = 16, dy = 16;
|
||||
uniform int xBuckets = (width + (dx-1)) / dx;
|
||||
uniform int yBuckets = (height + (dy-1)) / dy;
|
||||
|
||||
@@ -123,9 +123,12 @@ static void generateRay(const float raster2camera[4][4],
|
||||
camy /= camw;
|
||||
camz /= camw;
|
||||
|
||||
ray.dir.x = camera2world[0][0] * camx + camera2world[0][1] * camy + camera2world[0][2] * camz;
|
||||
ray.dir.y = camera2world[1][0] * camx + camera2world[1][1] * camy + camera2world[1][2] * camz;
|
||||
ray.dir.z = camera2world[2][0] * camx + camera2world[2][1] * camy + camera2world[2][2] * camz;
|
||||
ray.dir.x = camera2world[0][0] * camx + camera2world[0][1] * camy +
|
||||
camera2world[0][2] * camz;
|
||||
ray.dir.y = camera2world[1][0] * camx + camera2world[1][1] * camy +
|
||||
camera2world[1][2] * camz;
|
||||
ray.dir.z = camera2world[2][0] * camx + camera2world[2][1] * camy +
|
||||
camera2world[2][2] * camz;
|
||||
|
||||
ray.origin.x = camera2world[0][3] / camera2world[3][3];
|
||||
ray.origin.y = camera2world[1][3] / camera2world[3][3];
|
||||
|
||||
221
expr.cpp
221
expr.cpp
@@ -509,6 +509,9 @@ TypeConvertExpr(Expr *expr, const Type *toType, const char *errorMsgBase) {
|
||||
if (expr == NULL)
|
||||
return NULL;
|
||||
|
||||
Debug(expr->pos, "type convert %s -> %s.", expr->GetType()->GetString().c_str(),
|
||||
toType->GetString().c_str());
|
||||
|
||||
const Type *fromType = expr->GetType();
|
||||
Expr *e = expr;
|
||||
if (lDoTypeConv(fromType, toType, &e, false, errorMsgBase,
|
||||
@@ -876,8 +879,9 @@ lMaskForSymbol(Symbol *baseSym, FunctionEmitContext *ctx) {
|
||||
/** Store the result of an assignment to the given location.
|
||||
*/
|
||||
static void
|
||||
lStoreAssignResult(llvm::Value *value, llvm::Value *ptr, const Type *ptrType,
|
||||
FunctionEmitContext *ctx, Symbol *baseSym) {
|
||||
lStoreAssignResult(llvm::Value *value, llvm::Value *ptr, const Type *valueType,
|
||||
const Type *ptrType, FunctionEmitContext *ctx,
|
||||
Symbol *baseSym) {
|
||||
Assert(baseSym == NULL ||
|
||||
baseSym->varyingCFDepth <= ctx->VaryingCFDepth());
|
||||
if (!g->opt.disableMaskedStoreToStore &&
|
||||
@@ -895,10 +899,10 @@ lStoreAssignResult(llvm::Value *value, llvm::Value *ptr, const Type *ptrType,
|
||||
// never be accessed, since those lanes aren't executing, and won't
|
||||
// be executing at this scope or any other one before the variable
|
||||
// goes out of scope.
|
||||
ctx->StoreInst(value, ptr, LLVMMaskAllOn, ptrType);
|
||||
ctx->StoreInst(value, ptr, LLVMMaskAllOn, valueType, ptrType);
|
||||
}
|
||||
else {
|
||||
ctx->StoreInst(value, ptr, lMaskForSymbol(baseSym, ctx), ptrType);
|
||||
ctx->StoreInst(value, ptr, lMaskForSymbol(baseSym, ctx), valueType, ptrType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,7 +968,7 @@ lEmitPrePostIncDec(UnaryExpr::Op op, Expr *expr, SourcePos pos,
|
||||
|
||||
// And store the result out to the lvalue
|
||||
Symbol *baseSym = expr->GetBaseSymbol();
|
||||
lStoreAssignResult(binop, lvalue, lvalueType, ctx, baseSym);
|
||||
lStoreAssignResult(binop, lvalue, type, lvalueType, ctx, baseSym);
|
||||
|
||||
// And then if it's a pre increment/decrement, return the final
|
||||
// computed result; otherwise return the previously-grabbed expression
|
||||
@@ -2439,7 +2443,8 @@ lEmitOpAssign(AssignExpr::Op op, Expr *arg0, Expr *arg1, const Type *type,
|
||||
return NULL;
|
||||
}
|
||||
const Type *lvalueType = arg0->GetLValueType();
|
||||
if (lvalueType == NULL)
|
||||
const Type *resultType = arg0->GetType();
|
||||
if (lvalueType == NULL || resultType == NULL)
|
||||
return NULL;
|
||||
|
||||
// Get the value on the right-hand side of the assignment+operation
|
||||
@@ -2492,7 +2497,7 @@ lEmitOpAssign(AssignExpr::Op op, Expr *arg0, Expr *arg1, const Type *type,
|
||||
}
|
||||
|
||||
// And store the result back to the lvalue.
|
||||
lStoreAssignResult(newValue, lv, lvalueType, ctx, baseSym);
|
||||
lStoreAssignResult(newValue, lv, resultType, lvalueType, ctx, baseSym);
|
||||
|
||||
return newValue;
|
||||
}
|
||||
@@ -2517,29 +2522,30 @@ AssignExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
|
||||
switch (op) {
|
||||
case Assign: {
|
||||
llvm::Value *lv = lvalue->GetLValue(ctx);
|
||||
if (lv == NULL) {
|
||||
llvm::Value *ptr = lvalue->GetLValue(ctx);
|
||||
if (ptr == NULL) {
|
||||
Error(lvalue->pos, "Left hand side of assignment expression can't "
|
||||
"be assigned to.");
|
||||
return NULL;
|
||||
}
|
||||
const Type *lvalueType = lvalue->GetLValueType();
|
||||
if (lvalueType == NULL) {
|
||||
const Type *ptrType = lvalue->GetLValueType();
|
||||
const Type *valueType = rvalue->GetType();
|
||||
if (ptrType == NULL || valueType == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
llvm::Value *rv = rvalue->GetValue(ctx);
|
||||
if (rv == NULL) {
|
||||
llvm::Value *value = rvalue->GetValue(ctx);
|
||||
if (value == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->SetDebugPos(pos);
|
||||
|
||||
lStoreAssignResult(rv, lv, lvalueType, ctx, baseSym);
|
||||
lStoreAssignResult(value, ptr, valueType, ptrType, ctx, baseSym);
|
||||
|
||||
return rv;
|
||||
return value;
|
||||
}
|
||||
case MulAssign:
|
||||
case DivAssign:
|
||||
@@ -2754,7 +2760,7 @@ lEmitVaryingSelect(FunctionEmitContext *ctx, llvm::Value *test,
|
||||
// Use masking to conditionally store the expr1 values
|
||||
Assert(resultPtr->getType() ==
|
||||
PointerType::GetUniform(type)->LLVMType(g->ctx));
|
||||
ctx->StoreInst(expr1, resultPtr, test, PointerType::GetUniform(type));
|
||||
ctx->StoreInst(expr1, resultPtr, test, type, PointerType::GetUniform(type));
|
||||
return ctx->LoadInst(resultPtr, "selectexpr_final");
|
||||
}
|
||||
|
||||
@@ -3643,11 +3649,81 @@ lAddVaryingOffsetsIfNeeded(FunctionEmitContext *ctx, llvm::Value *ptr,
|
||||
}
|
||||
|
||||
|
||||
/** Check to see if the given type is an array of or pointer to a varying
|
||||
struct type that in turn has a member with bound 'uniform' variability.
|
||||
Issue an error and return true if such a member is found.
|
||||
*/
|
||||
static bool
|
||||
lVaryingStructHasUniformMember(const Type *type, SourcePos pos) {
|
||||
if (dynamic_cast<const VectorType *>(type) != NULL ||
|
||||
dynamic_cast<const ReferenceType *>(type) != NULL)
|
||||
return false;
|
||||
|
||||
const StructType *st = dynamic_cast<const StructType *>(type);
|
||||
if (st == NULL) {
|
||||
const ArrayType *at = dynamic_cast<const ArrayType *>(type);
|
||||
if (at != NULL)
|
||||
st = dynamic_cast<const StructType *>(at->GetElementType());
|
||||
else {
|
||||
const PointerType *pt = dynamic_cast<const PointerType *>(type);
|
||||
if (pt == NULL)
|
||||
return false;
|
||||
|
||||
st = dynamic_cast<const StructType *>(pt->GetBaseType());
|
||||
}
|
||||
|
||||
if (st == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (st->IsVaryingType() == false)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < st->GetElementCount(); ++i) {
|
||||
const Type *eltType = st->GetElementType(i);
|
||||
if (eltType == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dynamic_cast<const StructType *>(eltType) != NULL) {
|
||||
// We know that the enclosing struct is varying at this point,
|
||||
// so push that down to the enclosed struct before makign the
|
||||
// recursive call.
|
||||
eltType = eltType->GetAsVaryingType();
|
||||
if (lVaryingStructHasUniformMember(eltType, pos))
|
||||
return true;
|
||||
}
|
||||
else if (eltType->IsUniformType()) {
|
||||
Error(pos, "Gather operation is impossible due to the presence of "
|
||||
"struct member \"%s\" with uniform type \"%s\" in the "
|
||||
"varying struct type \"%s\".",
|
||||
st->GetElementName(i).c_str(), eltType->GetString().c_str(),
|
||||
st->GetString().c_str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
llvm::Value *
|
||||
IndexExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
const Type *baseExprType;
|
||||
const Type *baseExprType, *indexType, *returnType;
|
||||
if (baseExpr == NULL || index == NULL ||
|
||||
((baseExprType = baseExpr->GetType()) == NULL))
|
||||
((baseExprType = baseExpr->GetType()) == NULL) ||
|
||||
((indexType = index->GetType()) == NULL) ||
|
||||
((returnType = GetType()) == NULL)) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If this is going to be a gather, make sure that the varying return
|
||||
// type can represent the result (i.e. that we don't have a bound
|
||||
// 'uniform' member in a varying struct...)
|
||||
if (indexType->IsVaryingType() &&
|
||||
lVaryingStructHasUniformMember(returnType, pos))
|
||||
return NULL;
|
||||
|
||||
ctx->SetDebugPos(pos);
|
||||
@@ -3942,6 +4018,7 @@ public:
|
||||
SourcePos idpos, bool derefLValue);
|
||||
|
||||
const Type *GetType() const;
|
||||
const Type *GetLValueType() const;
|
||||
int getElementNumber() const;
|
||||
const Type *getElementType() const;
|
||||
|
||||
@@ -3960,9 +4037,17 @@ const Type *
|
||||
StructMemberExpr::GetType() const {
|
||||
// It's a struct, and the result type is the element type, possibly
|
||||
// promoted to varying if the struct type / lvalue is varying.
|
||||
const StructType *structType = getStructType();
|
||||
if (structType == NULL)
|
||||
const Type *exprType;
|
||||
const StructType *structType;
|
||||
if (expr == NULL ||
|
||||
((exprType = expr->GetType()) == NULL) ||
|
||||
((structType = getStructType()) == NULL)) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (exprType->IsVaryingType())
|
||||
structType = structType->GetAsVaryingType();
|
||||
|
||||
const Type *elementType = structType->GetElementType(identifier);
|
||||
if (elementType == NULL) {
|
||||
@@ -3973,12 +4058,34 @@ StructMemberExpr::GetType() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const PointerType *pt = dynamic_cast<const PointerType *>(expr->GetType());
|
||||
if (structType->IsVaryingType() ||
|
||||
(pt != NULL && pt->IsVaryingType()))
|
||||
return elementType->GetAsVaryingType();
|
||||
else
|
||||
return elementType;
|
||||
// If the expression we're getting the member of has an lvalue that is
|
||||
// a varying pointer type, then the result type must be the varying
|
||||
// version of the element type.
|
||||
if (GetLValueType()->IsVaryingType())
|
||||
elementType = elementType->GetAsVaryingType();
|
||||
|
||||
return elementType;
|
||||
}
|
||||
|
||||
|
||||
const Type *
|
||||
StructMemberExpr::GetLValueType() const {
|
||||
if (expr == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Type *exprLValueType = dereferenceExpr ? expr->GetType() :
|
||||
expr->GetLValueType();
|
||||
if (exprLValueType == NULL) {
|
||||
Assert(m->errorCount > 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (exprLValueType->IsUniformType() ||
|
||||
dynamic_cast<const ReferenceType *>(exprLValueType) != NULL) ?
|
||||
PointerType::GetUniform(getElementType()) :
|
||||
PointerType::GetVarying(getElementType());
|
||||
}
|
||||
|
||||
|
||||
@@ -3994,6 +4101,7 @@ StructMemberExpr::getElementNumber() const {
|
||||
"Element name \"%s\" not present in struct type \"%s\".%s",
|
||||
identifier.c_str(), structType->GetString().c_str(),
|
||||
getCandidateNearMatches().c_str());
|
||||
|
||||
return elementNumber;
|
||||
}
|
||||
|
||||
@@ -4004,30 +4112,32 @@ StructMemberExpr::getElementType() const {
|
||||
if (structType == NULL)
|
||||
return NULL;
|
||||
|
||||
return structType->GetAsUniformType()->GetElementType(identifier);
|
||||
return structType->GetElementType(identifier);
|
||||
}
|
||||
|
||||
|
||||
/** Returns the type of the underlying struct that we're returning a member
|
||||
of. */
|
||||
const StructType *
|
||||
StructMemberExpr::getStructType() const {
|
||||
const Type *exprType = expr->GetType();
|
||||
if (exprType == NULL)
|
||||
const Type *type = dereferenceExpr ? expr->GetType() :
|
||||
expr->GetLValueType();
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
const StructType *structType = dynamic_cast<const StructType *>(exprType);
|
||||
if (structType == NULL) {
|
||||
const PointerType *pt = dynamic_cast<const PointerType *>(exprType);
|
||||
if (pt != NULL)
|
||||
structType = dynamic_cast<const StructType *>(pt->GetBaseType());
|
||||
else {
|
||||
const ReferenceType *rt =
|
||||
dynamic_cast<const ReferenceType *>(exprType);
|
||||
Assert(rt != NULL);
|
||||
structType = dynamic_cast<const StructType *>(rt->GetReferenceTarget());
|
||||
}
|
||||
Assert(structType != NULL);
|
||||
|
||||
const Type *structType;
|
||||
const ReferenceType *rt = dynamic_cast<const ReferenceType *>(type);
|
||||
if (rt != NULL)
|
||||
structType = rt->GetReferenceTarget();
|
||||
else {
|
||||
const PointerType *pt = dynamic_cast<const PointerType *>(type);
|
||||
Assert(pt != NULL);
|
||||
structType = pt->GetBaseType();
|
||||
}
|
||||
return structType;
|
||||
|
||||
const StructType *ret = dynamic_cast<const StructType *>(structType);
|
||||
Assert(ret != NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -4370,22 +4480,6 @@ MemberExpr::GetLValue(FunctionEmitContext *ctx) const {
|
||||
}
|
||||
|
||||
|
||||
const Type *
|
||||
MemberExpr::GetLValueType() const {
|
||||
if (expr == NULL)
|
||||
return NULL;
|
||||
|
||||
const Type *exprLValueType = dereferenceExpr ? expr->GetType() :
|
||||
expr->GetLValueType();
|
||||
if (exprLValueType == NULL)
|
||||
return NULL;
|
||||
|
||||
return exprLValueType->IsUniformType() ?
|
||||
PointerType::GetUniform(getElementType()) :
|
||||
PointerType::GetVarying(getElementType());
|
||||
}
|
||||
|
||||
|
||||
Expr *
|
||||
MemberExpr::TypeCheck() {
|
||||
return expr ? this : NULL;
|
||||
@@ -6428,6 +6522,9 @@ DereferenceExpr::GetValue(FunctionEmitContext *ctx) const {
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
if (lVaryingStructHasUniformMember(type, pos))
|
||||
return NULL;
|
||||
|
||||
Symbol *baseSym = expr->GetBaseSymbol();
|
||||
llvm::Value *mask = baseSym ? lMaskForSymbol(baseSym, ctx) :
|
||||
ctx->GetFullMask();
|
||||
@@ -7337,14 +7434,8 @@ NewExpr::NewExpr(int typeQual, const Type *t, Expr *init, Expr *count,
|
||||
if (allocType != NULL && allocType->HasUnboundVariability()) {
|
||||
Type::Variability childVariability = isVarying ?
|
||||
Type::Uniform : Type::Varying;
|
||||
if (dynamic_cast<const StructType *>(allocType) != NULL)
|
||||
// FIXME: yet another place where the "structs are varying"
|
||||
// wart pops up..
|
||||
childVariability = Type::Varying;
|
||||
|
||||
allocType = allocType->ResolveUnboundVariability(childVariability);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
expr.h
1
expr.h
@@ -299,7 +299,6 @@ public:
|
||||
llvm::Value *GetValue(FunctionEmitContext *ctx) const;
|
||||
llvm::Value *GetLValue(FunctionEmitContext *ctx) const;
|
||||
const Type *GetType() const;
|
||||
const Type *GetLValueType() const;
|
||||
Symbol *GetBaseSymbol() const;
|
||||
void Print() const;
|
||||
Expr *Optimize();
|
||||
|
||||
14
module.cpp
14
module.cpp
@@ -330,21 +330,23 @@ Module::AddGlobalVariable(Symbol *sym, Expr *initExpr, bool isConst) {
|
||||
|
||||
|
||||
|
||||
/** Given an arbitrary type, see if it or any of the types contained in it
|
||||
are varying. Returns true if so, false otherwise.
|
||||
*/
|
||||
/** Given an arbitrary type, see if it or any of the leaf types contained
|
||||
in it are varying. (Note that it's fine for the original struct or a
|
||||
contained struct to be varying, so long as all of its members have
|
||||
bound 'uniform' variability.) Returns true if so, false otherwise. */
|
||||
static bool
|
||||
lRecursiveCheckVarying(const Type *t) {
|
||||
t = t->GetBaseType();
|
||||
if (t->IsVaryingType()) return true;
|
||||
|
||||
const StructType *st = dynamic_cast<const StructType *>(t);
|
||||
if (st) {
|
||||
if (st != NULL) {
|
||||
for (int i = 0; i < st->GetElementCount(); ++i)
|
||||
if (lRecursiveCheckVarying(st->GetElementType(i)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
else
|
||||
return t->IsVaryingType();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@ struct Foo {
|
||||
float f;
|
||||
};
|
||||
|
||||
float func(uniform Foo foo[], int offset) {
|
||||
float func(Foo foo[], int offset) {
|
||||
return foo[offset].f;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
cfor (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
@@ -7,13 +7,13 @@ struct Foo {
|
||||
float f;
|
||||
};
|
||||
|
||||
float func(uniform Foo foo[], int offset) {
|
||||
float func(Foo foo[], int offset) {
|
||||
return foo[offset].f;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
cfor (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
@@ -9,7 +9,7 @@ struct Foo {
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
cfor (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
@@ -14,7 +14,7 @@ export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||
r[i].v.z = 300*i + 3*programIndex;
|
||||
}
|
||||
|
||||
Ray *rp = &r[programIndex/2];
|
||||
varying Ray *rp = &r[programIndex/2];
|
||||
RET[programIndex] = rp->v.z;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
struct Foo { uniform float x; float y; };
|
||||
struct Foo { float x; float y; };
|
||||
|
||||
export void f_fu(uniform float ret[], uniform float aa[], uniform float b) {
|
||||
float a = aa[programIndex];
|
||||
Foo foo[32];
|
||||
for (uniform int i = 0; i < 32; ++i)
|
||||
uniform Foo foo[32];
|
||||
for (uniform int i = 0; i < 32; ++i) {
|
||||
foo[i].x = i;
|
||||
foo[i].y = -1234 + i;
|
||||
}
|
||||
varying Foo fv = foo[a];
|
||||
fv.x += 1000;
|
||||
//CO print("fv.x = %\n", fv.x);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
struct Point {
|
||||
uniform float x, y, z;
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
|
||||
@@ -7,7 +7,7 @@ struct Point {
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Point * buf = new Point(0., b, a);
|
||||
varying Point * buf = new varying Point(0., b, a);
|
||||
RET[programIndex] = buf->z;
|
||||
delete buf;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ struct Foo {
|
||||
uniform float b;
|
||||
};
|
||||
|
||||
void update(uniform Foo * varying fp) {
|
||||
void update(varying Foo * varying fp) {
|
||||
++fp;
|
||||
fp->a -= 1;
|
||||
fp->b = 1;
|
||||
}
|
||||
|
||||
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||
uniform Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } };
|
||||
Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } };
|
||||
update(f);
|
||||
RET[programIndex] = f[1].a;
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ struct Foo {
|
||||
float f;
|
||||
};
|
||||
|
||||
float func(uniform Foo foo[], int offset) {
|
||||
float func(Foo foo[], int offset) {
|
||||
return foo[offset].f;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
for (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
@@ -7,13 +7,13 @@ struct Foo {
|
||||
float f;
|
||||
};
|
||||
|
||||
float func(uniform Foo foo[], int offset) {
|
||||
float func(Foo foo[], int offset) {
|
||||
return foo[offset].f;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
for (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
@@ -9,7 +9,7 @@ struct Foo {
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
uniform int i;
|
||||
for (i = 0; i < 17; ++i)
|
||||
foo[i].f = i*a;
|
||||
|
||||
34
tests/struct-nested-1.ispc
Normal file
34
tests/struct-nested-1.ispc
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
struct Vector { float x, y, z; };
|
||||
|
||||
struct Ray { Vector o; float t; Vector d; };
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
void init(varying Ray rays[], uniform int count, float v) {
|
||||
for (uniform int i = 0; i < count; ++i) {
|
||||
rays[i].o.x = programIndex;
|
||||
rays[i].o.y = v;
|
||||
rays[i].o.z = -1234;
|
||||
rays[i].t = 42;
|
||||
rays[i].d.x = 2*v;
|
||||
rays[i].d.y = 3*v;
|
||||
rays[i].d.z = 4*v;
|
||||
}
|
||||
}
|
||||
|
||||
void zero_dx(Ray &r) {
|
||||
r.d.x = 0;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float v = aFOO[programIndex];
|
||||
Ray rays[10];
|
||||
init(rays, 10, v);
|
||||
zero_dx(rays[b]);
|
||||
RET[programIndex] = rays[5].d.x + rays[5].d.y;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 3 + 3*programIndex;
|
||||
}
|
||||
34
tests/struct-nested-2.ispc
Normal file
34
tests/struct-nested-2.ispc
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
struct Vector { float x, y, z; };
|
||||
|
||||
struct Ray { Vector o; float t; Vector d; };
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
void init(uniform Ray rays[], uniform int count, float v) {
|
||||
for (uniform int i = 0; i < count; ++i) {
|
||||
rays[i].o.x = i;
|
||||
rays[i].o.y = 2*i;
|
||||
rays[i].o.z = 3*i;
|
||||
rays[i].t = 4*i;
|
||||
rays[i].d.x = 5*i;
|
||||
rays[i].d.y = 6*i;
|
||||
rays[i].d.z = 7*i;
|
||||
}
|
||||
}
|
||||
|
||||
void zero_dx(Ray &r) {
|
||||
r.d.x = 0;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float v = aFOO[programIndex];
|
||||
uniform Ray rays[programCount+1];
|
||||
init(rays, programCount+1, v);
|
||||
Ray rg = rays[v];
|
||||
RET[programIndex] = rg.o.z;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 3 + 3*programIndex;
|
||||
}
|
||||
35
tests/struct-nested-3.ispc
Normal file
35
tests/struct-nested-3.ispc
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
struct Vector { float x, y, z; };
|
||||
|
||||
struct Ray { Vector o; float t; Vector d; };
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
void init(uniform Ray rays[], uniform int count, float v) {
|
||||
for (uniform int i = 0; i < count; ++i) {
|
||||
rays[i].o.x = i;
|
||||
rays[i].o.y = 2*i;
|
||||
rays[i].o.z = 3*i;
|
||||
rays[i].t = 4*i;
|
||||
rays[i].d.x = 5*i;
|
||||
rays[i].d.y = 6*i;
|
||||
rays[i].d.z = 7*i;
|
||||
}
|
||||
}
|
||||
|
||||
void zero_dx(Ray &r) {
|
||||
r.d.x = 0;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float v = aFOO[programIndex];
|
||||
uniform Ray rays[programCount+1];
|
||||
init(rays, programCount+1, v);
|
||||
Ray rg = rays[v];
|
||||
zero_dx(rg);
|
||||
RET[programIndex] = rg.o.z + rg.d.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 3 + 3*programIndex;
|
||||
}
|
||||
35
tests/struct-nested-4.ispc
Normal file
35
tests/struct-nested-4.ispc
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
struct Vector { float x, y, z; };
|
||||
|
||||
struct Ray { Vector o; float t; Vector d; };
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
void init(uniform Ray rays[], uniform int count, float v) {
|
||||
for (uniform int i = 0; i < count; ++i) {
|
||||
rays[i].o.x = i;
|
||||
rays[i].o.y = 2*i;
|
||||
rays[i].o.z = 3*i;
|
||||
rays[i].t = 4*i;
|
||||
rays[i].d.x = 5*i;
|
||||
rays[i].d.y = 6*i;
|
||||
rays[i].d.z = 7*i;
|
||||
}
|
||||
}
|
||||
|
||||
void zero_dx(Ray * uniform r) {
|
||||
r->d.x = 0;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float v = aFOO[programIndex];
|
||||
uniform Ray rays[programCount+1];
|
||||
init(rays, programCount+1, v);
|
||||
Ray rg = rays[v];
|
||||
zero_dx(&rg);
|
||||
RET[programIndex] = rg.o.z + rg.d.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 3 + 3*programIndex;
|
||||
}
|
||||
35
tests/struct-nested-5.ispc
Normal file
35
tests/struct-nested-5.ispc
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
struct Vector { float x, y, z; };
|
||||
|
||||
struct Ray { Vector o; float t; Vector d; };
|
||||
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
void init(uniform Ray rays[], uniform int count, float v) {
|
||||
for (uniform int i = 0; i < count; ++i) {
|
||||
rays[i].o.x = i;
|
||||
rays[i].o.y = 2*i;
|
||||
rays[i].o.z = 3*i;
|
||||
rays[i].t = 4*i;
|
||||
rays[i].d.x = 5*i;
|
||||
rays[i].d.y = 6*i;
|
||||
rays[i].d.z = 7*i;
|
||||
}
|
||||
}
|
||||
|
||||
void zero_dx(uniform Ray * r) {
|
||||
r->d.x = 0;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float v = aFOO[programIndex];
|
||||
uniform Ray rays[programCount+1];
|
||||
init(rays, programCount+1, v);
|
||||
zero_dx(&rays[v]);
|
||||
Ray rg = rays[v];
|
||||
RET[programIndex] = rg.o.z + rg.d.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 3 + 3*programIndex;
|
||||
}
|
||||
@@ -5,13 +5,13 @@ export uniform int width() { return programCount; }
|
||||
|
||||
struct Foo { float f; };
|
||||
|
||||
void f(uniform Foo foo[], float a) {
|
||||
void f(Foo foo[], float a) {
|
||||
++foo[a].f;
|
||||
}
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
for (uniform int i = 0; i < 17; ++i)
|
||||
foo[i].f = a;
|
||||
f(foo, a);
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x;
|
||||
varying float x;
|
||||
uniform float f;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x;
|
||||
uniform float f;
|
||||
float x;
|
||||
float f;
|
||||
};
|
||||
|
||||
export void f_fi(uniform float RET[], uniform float aFOO[], uniform int bFOO[]) {
|
||||
|
||||
@@ -9,9 +9,9 @@ struct Foo {
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo myFoo[3] = { { -1, -2 }, {a, -3}, {-4, -5} };
|
||||
Foo myFoo[3] = { { -1, -2 }, {a, -3}, {-4, -5} };
|
||||
int i = aFOO[0];
|
||||
varying Foo barFoo = myFoo[i];
|
||||
Foo barFoo = myFoo[i];
|
||||
//CO print("% %\n", myFoo[i].x, barFoo.x);
|
||||
RET[programIndex] = barFoo.x;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
varying Foo myFoo[3] = { { b, b, {b, b, b} },
|
||||
{ b, b, {b, b, b} },
|
||||
{ b, b, {b, b, b} } };
|
||||
uniform Foo barFoo;
|
||||
Foo barFoo;
|
||||
barFoo = myFoo[0];
|
||||
RET[programIndex] = barFoo.x + myFoo[1].i[2];
|
||||
}
|
||||
|
||||
@@ -7,10 +7,11 @@ struct Foo { float f; };
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo foo[17];
|
||||
Foo foo[17];
|
||||
for (uniform int i = 0; i < 17; ++i)
|
||||
foo[i].f = a;
|
||||
++foo[a].f;
|
||||
assert(programCount <= 16);
|
||||
uniform int i[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
|
||||
RET[programIndex] = foo[i[programIndex]].f;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
int i;
|
||||
float f;
|
||||
varying int i;
|
||||
varying float f;
|
||||
};
|
||||
export void f_f(uniform float RET[], uniform float aFOO[]) {
|
||||
float a = aFOO[programIndex];
|
||||
|
||||
@@ -6,9 +6,10 @@ struct Foo {
|
||||
float x;
|
||||
float f;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform struct Foo myFoo = {a,a};
|
||||
struct Foo myFoo = {a,a};
|
||||
RET[programIndex] = myFoo.x;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ struct Foo {
|
||||
};
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform struct Foo myFoo[3] = { { a,a}, {a,a}, {a,a} };
|
||||
uniform struct Foo barFoo;
|
||||
struct Foo myFoo[3] = { { a,a}, {a,a}, {a,a} };
|
||||
struct Foo barFoo;
|
||||
barFoo = myFoo[1];
|
||||
RET[programIndex] = barFoo.x;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,13 @@ struct Foo {
|
||||
float f;
|
||||
int i[3];
|
||||
};
|
||||
float bar(uniform struct Foo f) { return f.f; }
|
||||
|
||||
float bar(struct Foo f) { return f.f; }
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
uniform struct Foo myFoo[3] = { { a, a, {a, a, a} },
|
||||
{ a, a, {a, a, a} },
|
||||
{ a, a, {a, a, a} } };
|
||||
struct Foo myFoo[3] = { { a, a, {a, a, a} },
|
||||
{ a, a, {a, a, a} },
|
||||
{ a, a, {a, a, a} } };
|
||||
RET[programIndex] = bar(myFoo[1]);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x;
|
||||
varying float x;
|
||||
};
|
||||
|
||||
float bar(uniform struct Foo f) { ++f.x; return f.x; }
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x;
|
||||
varying float x;
|
||||
};
|
||||
float bar(uniform struct Foo * uniform f) { ++((*f).x); return (*f).x; }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x;
|
||||
varying float x;
|
||||
};
|
||||
void bar(uniform struct Foo * uniform f) { ++((*f).x); }
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
Foo f[3] = { { b, b }, { 2*b, 2*b }, { 3*b, 3*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo f[3] = { { b, b }, { 2*b, 2*b }, { 3*b, 3*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 15;
|
||||
RET[0] = RET[1] = 10;
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
Foo f[3] = { { b, b }, { 2*b, 2*b }, { 3*b, 3*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo f[3] = { { b, b }, { 2*b, 2*b }, { 3*b, 3*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[4]) {
|
||||
RET[programIndex] = 15;
|
||||
RET[0] = RET[1] = 10;
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
Foo f[3] = { { b, 2*b }, { 3*b, 4*b }, { 5*b, 6*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
float a = aFOO[programIndex];
|
||||
uniform Foo f[3] = { { b, 2*b }, { 3*b, 4*b }, { 5*b, 6*b } };
|
||||
int index = (a <= 2) ? 1 : 2;
|
||||
varying Foo g = f[index];
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) {
|
||||
RET[programIndex] = 25;
|
||||
RET[0] = RET[1] = 15;
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
uniform Foo uf;
|
||||
varying Foo vf;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
uniform Foo uf;
|
||||
varying Foo vf;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
// Bar bar = { { b, b }, { a, a } };
|
||||
Bar bar;
|
||||
bar.uf.x = b;
|
||||
bar.vf.y = a;
|
||||
RET[programIndex] = bar.uf.x + bar.vf.y;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) { RET[programIndex] = 6+programIndex; }
|
||||
float a = aFOO[programIndex];
|
||||
// Bar bar = { { b, b }, { a, a } };
|
||||
Bar bar;
|
||||
bar.uf.x = b;
|
||||
bar.vf.y = a;
|
||||
RET[programIndex] = bar.uf.x + bar.vf.y;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) { RET[programIndex] = 6+programIndex; }
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
uniform Foo uf;
|
||||
varying Foo vf;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
uniform Foo uf;
|
||||
varying Foo vf;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
Bar bar = { { b, b }, { a, a } };
|
||||
RET[programIndex] = bar.uf.x + bar.vf.y;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[4]) { RET[programIndex] = 6+programIndex; }
|
||||
float a = aFOO[programIndex];
|
||||
Bar bar = { { b, b }, { a, a } };
|
||||
RET[programIndex] = bar.uf.x + bar.vf.y;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[4]) { RET[programIndex] = 6+programIndex; }
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
export uniform int width() { return programCount; }
|
||||
|
||||
|
||||
|
||||
struct Foo {
|
||||
uniform float x, y;
|
||||
};
|
||||
|
||||
|
||||
struct Foo {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
|
||||
float a = aFOO[programIndex];
|
||||
varying Foo g;
|
||||
g.x = a;
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) { RET[programIndex] = 1+programIndex; }
|
||||
float a = aFOO[programIndex];
|
||||
varying Foo g;
|
||||
g.x = a;
|
||||
RET[programIndex] = g.x;
|
||||
}
|
||||
|
||||
export void result(uniform float RET[]) { RET[programIndex] = 1+programIndex; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Illegal to assign to type "uniform struct Bar" in type "uniform struct Foo" due to element "a" with type "const varying int32"
|
||||
// Illegal to assign to type "varying struct Bar" in type "varying struct Foo" due to element "a" with type "const varying int32"
|
||||
|
||||
struct Bar {
|
||||
const int a;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Illegal to assign to type "uniform struct Foo" due to element "a" with type "const varying int32"
|
||||
// Illegal to assign to type "varying struct Foo" due to element "a" with type "const varying int32"
|
||||
|
||||
struct Foo {
|
||||
const int a;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Dereference operator "->" can't be applied to non-pointer type "uniform struct Foo"
|
||||
// Dereference operator "->" can't be applied to non-pointer type "varying struct Foo"
|
||||
|
||||
struct Foo { int x; };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Can't convert from type "uniform int32 * varying" to type "uniform int32 * uniform" for return
|
||||
// Can't convert from type "uniform int32 * varying" to type "varying int32 * uniform" for return
|
||||
|
||||
int * uniform func(int x) {
|
||||
return new int[x];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "signed" qualifier is illegal with non-integer type "uniform struct Foo"
|
||||
// "signed" qualifier is illegal with non-integer type "varying struct Foo"
|
||||
|
||||
struct Foo {
|
||||
float x;
|
||||
|
||||
7
tests_errors/struct-uniform-gather-1.ispc
Normal file
7
tests_errors/struct-uniform-gather-1.ispc
Normal file
@@ -0,0 +1,7 @@
|
||||
// Gather operation is impossible due to the presence of struct member "x" with uniform type
|
||||
|
||||
struct Foo { uniform int x; };
|
||||
|
||||
void a(uniform Foo array[], int index) {
|
||||
Foo v = array[index];
|
||||
}
|
||||
7
tests_errors/struct-uniform-gather-2.ispc
Normal file
7
tests_errors/struct-uniform-gather-2.ispc
Normal file
@@ -0,0 +1,7 @@
|
||||
// Gather operation is impossible due to the presence of struct member "x" with uniform type
|
||||
|
||||
struct Foo { uniform int x; };
|
||||
|
||||
void a(uniform Foo * uniform array, int index) {
|
||||
Foo v = array[index];
|
||||
}
|
||||
7
tests_errors/struct-uniform-gather-3.ispc
Normal file
7
tests_errors/struct-uniform-gather-3.ispc
Normal file
@@ -0,0 +1,7 @@
|
||||
// Gather operation is impossible due to the presence of struct member "x" with uniform type
|
||||
|
||||
struct Foo { uniform int x; };
|
||||
|
||||
void a(uniform Foo * varying array, int index) {
|
||||
Foo v = array[index];
|
||||
}
|
||||
8
tests_errors/struct-uniform-gather-4.ispc
Normal file
8
tests_errors/struct-uniform-gather-4.ispc
Normal file
@@ -0,0 +1,8 @@
|
||||
// Gather operation is impossible due to the presence of struct member "x" with uniform type
|
||||
|
||||
struct Bar { uniform int x; };
|
||||
struct Foo { varying Bar b; };
|
||||
|
||||
void a(uniform Foo * varying array, int index) {
|
||||
Foo v = array[index];
|
||||
}
|
||||
8
tests_errors/struct-uniform-gather-5.ispc
Normal file
8
tests_errors/struct-uniform-gather-5.ispc
Normal file
@@ -0,0 +1,8 @@
|
||||
// Gather operation is impossible due to the presence of struct member "x" with uniform type
|
||||
|
||||
struct Bar { uniform int x; };
|
||||
struct Foo { Bar b; };
|
||||
|
||||
void a(uniform Foo * varying array, int index) {
|
||||
Foo v = array[index];
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Can't convert between different struct types "uniform struct Foo" and "uniform struct Bar"
|
||||
// Can't convert between different struct types "varying struct Foo" and "varying struct Bar"
|
||||
|
||||
struct Foo {
|
||||
int a;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// "unsigned" qualifier is illegal with "uniform struct Foo" typ
|
||||
// "unsigned" qualifier is illegal with "varying struct Foo" typ
|
||||
|
||||
struct Foo {
|
||||
float x;
|
||||
|
||||
42
type.cpp
42
type.cpp
@@ -991,10 +991,6 @@ PointerType::ResolveUnboundVariability(Variability v) const {
|
||||
Variability ptrVariability = (variability == Unbound) ? v : variability;
|
||||
Variability childVariability = (ptrVariability == Varying) ?
|
||||
Uniform : Varying;
|
||||
if (dynamic_cast<const StructType *>(baseType))
|
||||
// struct members are varying by default.. (FIXME!!!)
|
||||
childVariability = Varying;
|
||||
|
||||
return new PointerType(baseType->ResolveUnboundVariability(childVariability),
|
||||
ptrVariability, isConst);
|
||||
}
|
||||
@@ -1521,6 +1517,7 @@ SOAArrayType::GetAsUnboundVariabilityType() const {
|
||||
const SOAArrayType *
|
||||
SOAArrayType::ResolveUnboundVariability(Variability v) const {
|
||||
const StructType *sc = dynamic_cast<const StructType *>(child->ResolveUnboundVariability(v));
|
||||
Assert(sc != NULL); // ???
|
||||
return new SOAArrayType(sc, numElements, soaWidth);
|
||||
}
|
||||
|
||||
@@ -1916,16 +1913,13 @@ StructType::GetAsUnboundVariabilityType() const {
|
||||
|
||||
const StructType *
|
||||
StructType::ResolveUnboundVariability(Variability v) const {
|
||||
std::vector<const Type *> et;
|
||||
for (unsigned int i = 0; i < elementTypes.size(); ++i)
|
||||
et.push_back((elementTypes[i] == NULL) ? NULL :
|
||||
elementTypes[i]->ResolveUnboundVariability(v));
|
||||
Assert(v != Unbound);
|
||||
// We don't resolve the members here but leave them unbound, so that if
|
||||
// resolve to varying but later want to get the uniform version of this
|
||||
// type, for example, then we still have the information around about
|
||||
// which element types were originally unbound...
|
||||
|
||||
// FIXME
|
||||
if (v == Varying)
|
||||
v = Uniform;
|
||||
|
||||
return new StructType(name, et, elementNames, elementPositions,
|
||||
return new StructType(name, elementTypes, elementNames, elementPositions,
|
||||
isConst, (variability != Unbound) ? variability : v,
|
||||
pos);
|
||||
}
|
||||
@@ -2009,7 +2003,7 @@ StructType::Mangle() const {
|
||||
ret += "_v_";
|
||||
ret += name + std::string("]<");
|
||||
for (unsigned int i = 0; i < elementTypes.size(); ++i)
|
||||
ret += elementTypes[i]->Mangle();
|
||||
ret += GetElementType(i)->Mangle();
|
||||
ret += ">";
|
||||
return ret;
|
||||
}
|
||||
@@ -2017,11 +2011,6 @@ StructType::Mangle() const {
|
||||
|
||||
std::string
|
||||
StructType::GetCDeclaration(const std::string &n) const {
|
||||
if (variability != Uniform) {
|
||||
Assert(m->errorCount > 0);
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
if (isConst) ret += "const ";
|
||||
ret += std::string("struct ") + name;
|
||||
@@ -2104,13 +2093,18 @@ StructType::GetDIType(llvm::DIDescriptor scope) const {
|
||||
|
||||
const Type *
|
||||
StructType::GetElementType(int i) const {
|
||||
Assert(variability != Unbound);
|
||||
Assert(i < (int)elementTypes.size());
|
||||
// If the struct is uniform qualified, then each member comes out with
|
||||
// the same type as in the original source file. If it's varying, then
|
||||
// all members are promoted to varying.
|
||||
const Type *ret = elementTypes[i];
|
||||
if (variability == Varying)
|
||||
ret = ret->GetAsVaryingType();
|
||||
|
||||
// If the element has unbound variability, resolve its variability to
|
||||
// the struct type's variability
|
||||
if (ret->HasUnboundVariability()) {
|
||||
if (variability == Varying)
|
||||
ret = ret->GetAsVaryingType();
|
||||
else
|
||||
ret = ret->GetAsUniformType();
|
||||
}
|
||||
return isConst ? ret->GetAsConstType() : ret;
|
||||
}
|
||||
|
||||
|
||||
2
type.h
2
type.h
@@ -679,6 +679,8 @@ public:
|
||||
/** Returns the total number of elements in the structure. */
|
||||
int GetElementCount() const { return int(elementTypes.size()); }
|
||||
|
||||
SourcePos GetElementPosition(int i) const { return elementPositions[i]; }
|
||||
|
||||
/** Returns the name of the structure type. (e.g. struct Foo -> "Foo".) */
|
||||
const std::string &GetStructName() const { return name; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user