Update defaults for variability of pointed-to types.

Now, if rate qualifiers aren't used to specify otherwise, varying
pointers point to uniform types by default.  As before, uniform
pointers point to varying types by default.

   float *foo;  // varying pointer to uniform float
   float * uniform foo;  // uniform pointer to varying float

These defaults seem to require the least amount of explicit
uniform/varying qualifiers for most common cases, though TBD if it
would be easier to have a single rule that e.g. the pointed-to type
is always uniform by default.
This commit is contained in:
Matt Pharr
2012-02-17 16:52:03 -08:00
parent ad429db7e8
commit 6d7ff7eba2
54 changed files with 187 additions and 131 deletions

View File

@@ -408,7 +408,11 @@ Declarator::GetType(const Type *base, DeclSpecs *ds) const {
return NULL; return NULL;
} }
sym->type = PointerType::GetUniform(at->GetElementType()); const Type *targetType = at->GetElementType();
targetType =
targetType->ResolveUnboundVariability(Type::Varying);
sym->type = PointerType::GetUniform(targetType);
// Make sure there are no unsized arrays (other than the // Make sure there are no unsized arrays (other than the
// first dimension) in function parameter lists. // first dimension) in function parameter lists.
at = dynamic_cast<const ArrayType *>(at->GetElementType()); at = dynamic_cast<const ArrayType *>(at->GetElementType());

View File

@@ -1499,38 +1499,46 @@ Pointer Types
It is possible to have pointers to data in memory; pointer arithmetic, It is possible to have pointers to data in memory; pointer arithmetic,
changing values in memory with pointers, and so forth is supported as in C. changing values in memory with pointers, and so forth is supported as in C.
::
float a = 0;
float *pa = &a;
*pa = 1; // now a == 1
Also as in C, arrays are silently converted into pointers:
::
float a[10] = { ... };
float *pa = a; // pointer to first element of a
float *pb = a + 5; // pointer to 5th element of a
As with other basic types, pointers can be both ``uniform`` and As with other basic types, pointers can be both ``uniform`` and
``varying``. By default, they are varying. The placement of the ``varying``.
``uniform`` qualifier to declare a ``uniform`` pointer may be initially
surprising, but it matches the form of how for example a pointer that is ** Like other types in ``ispc``, pointers are ``varying`` by default, if an
itself ``const`` (as opposed to pointing to a ``const`` type) is declared explicit ``uniform`` qualifier isn't provided. However, the default
in C. variability of the pointed-to type (``uniform`` or ``varying``) is the
opposite of the pointer variability. ** This rule will be illustrated and
explained in examples below.
For example, the ``ptr`` variable in the code below is a varying pointer to
``uniform float`` values. Each program instance has a separate pointer
value and the assignment to ``*ptr`` generally represents a scatter to
memory.
:: ::
uniform float f = 0; uniform float a[] = ...;
uniform float * uniform pf = &f; int index = ...;
float * ptr = &a[index];
*ptr = 1;
A ``uniform`` pointer can be declared with an appropriately-placed
qualifier:
::
float f = 0;
float * uniform pf = &f; // uniform pointer to a varying float
*pf = 1; *pf = 1;
A subtlety comes in when a uniform pointer points to a varying datatype. The placement of the ``uniform`` qualifier to declare a ``uniform`` pointer
In this case, each program instance accesses a distinct location in memory may be initially surprising, but it matches the form of how, for example, a
(because the underlying varying datatype is itself laid out with a separate pointer that is itself ``const`` (as opposed to pointing to a ``const``
location in memory for each program instance.) type) is declared in C. (Reading the declaration from right to left gives
its meaning: a uniform pointer to a float that is varying.)
A subtlety comes in in cases like the where a uniform pointer points to a
varying datatype. In this case, each program instance accesses a distinct
location in memory (because the underlying varying datatype is itself laid
out with a separate location in memory for each program instance.)
:: ::
@@ -1538,17 +1546,26 @@ location in memory for each program instance.)
float * uniform pa = &a; float * uniform pa = &a;
*pa = programIndex; // same as (a = programIndex) *pa = programIndex; // same as (a = programIndex)
Also as in C, arrays are silently converted into pointers:
::
float a[10] = { ... };
float * uniform pa = a; // pointer to first element of a
float * uniform pb = a + 5; // pointer to 5th element of a
Any pointer type can be explicitly typecast to another pointer type, as Any pointer type can be explicitly typecast to another pointer type, as
long as the source type isn't a ``varying`` pointer when the destination long as the source type isn't a ``varying`` pointer when the destination
type is a ``uniform`` pointer. Like other types, ``uniform`` pointers can type is a ``uniform`` pointer.
be typecast to be ``varying`` pointers, however.
:: ::
float *pa = ...; float *pa = ...;
int *pb = (int *)pa; // legal, but beware int *pb = (int *)pa; // legal, but beware
Like other types, ``uniform`` pointers can be typecast to be ``varying``
pointers, however.
Any pointer type can be assigned to a ``void`` pointer without a type cast: Any pointer type can be assigned to a ``void`` pointer without a type cast:
:: ::
@@ -1992,7 +2009,7 @@ based on C++'s ``new`` and ``delete`` operators:
:: ::
int count = ...; int count = ...;
int *ptr = new uniform int[count]; int *ptr = new int[count];
// use ptr... // use ptr...
delete[] ptr; delete[] ptr;
@@ -2002,13 +2019,22 @@ that memory. Uses of ``new`` and ``delete`` in ``ispc`` programs are
serviced by corresponding calls the system C library's ``malloc()`` and serviced by corresponding calls the system C library's ``malloc()`` and
``free()`` functions. ``free()`` functions.
Note that the rules for ``uniform`` and ``varying`` for ``new`` are
analogous to the corresponding rules are for pointers (as described in
`Pointer Types`_.) Specifically, if a specific rate qualifier isn't
provided with the ``new`` expression, then the default is that a "varying"
``new`` is performed, where each program instance performs a unique
allocation. The allocated type, in turn, is by default ``uniform`` for
``varying`` ``new`` expressions, and ``varying`` for ``uniform`` new
expressions.
After a pointer has been deleted, it is illegal to access the memory it After a pointer has been deleted, it is illegal to access the memory it
points to. However, note that deletion happens on a per-program-instance points to. However, that deletion happens on a per-program-instance basis.
basis. In other words, consider the following code: In other words, consider the following code:
:: ::
int *ptr = new uniform int[count]; int *ptr = new int[count];
// use ptr // use ptr
if (count > 1000) if (count > 1000)
delete[] ptr; delete[] ptr;
@@ -2033,7 +2059,9 @@ gang of program instances. A ``new`` statement can be qualified with
While a regular call to ``new`` returns a ``varying`` pointer (i.e. a While a regular call to ``new`` returns a ``varying`` pointer (i.e. a
distinct pointer to separately-allocated memory for each program instance), distinct pointer to separately-allocated memory for each program instance),
a ``uniform new`` performs a single allocation and returns a ``uniform`` a ``uniform new`` performs a single allocation and returns a ``uniform``
pointer. pointer. Recall that with a ``uniform`` ``new``, the default variability
of the allocated type is ``varying``, so the above code is allocating an
array of ten ``varying float`` values.
When using ``uniform new``, it's important to be aware of a subtlety; if When using ``uniform new``, it's important to be aware of a subtlety; if
the returned pointer is stored in a varying pointer variable (as may be the returned pointer is stored in a varying pointer variable (as may be
@@ -2043,7 +2071,7 @@ statement, which is an error: effectively
:: ::
float *ptr = uniform new float[10]; varying float * ptr = uniform new float[10];
// use ptr... // use ptr...
delete ptr; // ERROR: varying pointer is deleted delete ptr; // ERROR: varying pointer is deleted
@@ -2052,28 +2080,31 @@ executing program instance, which is an error (unless it happens that only
a single program instance is active in the above code.) a single program instance is active in the above code.)
When using ``new`` statements, it's important to make an appropriate choice When using ``new`` statements, it's important to make an appropriate choice
of ``uniform`` or ``varying`` (as always, the default), for both the of ``uniform`` or ``varying``, for both the ``new`` operator itself as well
``new`` operator itself as well as the type of data being allocated, based as the type of data being allocated, based on the program's needs.
on the program's needs. Consider the following four memory allocations: Consider the following four memory allocations:
:: ::
uniform float * uniform p1 = uniform new uniform float[10]; uniform float * uniform p1 = uniform new uniform float[10];
float * uniform p2 = uniform new float[10]; float * uniform p2 = uniform new float[10];
uniform float * p3 = new uniform float[10]; float * p3 = new float[10];
float * p4 = new float[10]; varying float * p4 = new varying float[10];
Assuming that a ``float`` is 4 bytes in memory and if the gang size is 8 Assuming that a ``float`` is 4 bytes in memory and if the gang size is 8
program instances, then the first allocation represents a single allocation program instances, then the first allocation represents a single allocation
of 40 bytes, the second is a single allocation of 8*4*10 = 320 bytes, the of 10 ``uniform float`` values (40 bytes), the second is a single
third is 8 allocations of 40 bytes, and the last performs 8 allocations of allocation of 10 ``varying float`` values (8*4*10 = 320 bytes), the third
80 bytes each. is 8 allocations of 10 ``uniform float`` values (8 allocations of 40 bytes
each), and the last performs 8 allocations of 320 bytes each.
Note in particular that varying allocations of varying data types are rarely Note in particular that varying allocations of varying data types are rarely
desirable in practice. In that case, each program instance is performing a desirable in practice. In that case, each program instance is performing a
separate allocation of ``varying float`` memory. In this case, it's likely separate allocation of ``varying float`` memory. In this case, it's likely
that the program instances will only access a single element of each that the program instances will only access a single element of each
``varying float``, which is wasteful. ``varying float``, which is wasteful. (This in turn is partially why the
allocated type is uniform by default with both pointers and ``new``
statements.)
Although ``ispc`` doesn't support constructors or destructors like C++, it Although ``ispc`` doesn't support constructors or destructors like C++, it
is possible to provide initializer values with ``new`` statements: is possible to provide initializer values with ``new`` statements:

View File

@@ -264,9 +264,9 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
if (toType->IsUniformType() && fromType->IsVaryingType()) { if (toType->IsUniformType() && fromType->IsVaryingType()) {
if (!failureOk) if (!failureOk)
Error(pos, "Can't convert from varying type \"%s\" to uniform " Error(pos, "Can't convert from type \"%s\" to type \"%s\" for %s.",
"type \"%s\" for %s.", fromType->GetString().c_str(), fromType->GetString().c_str(), toType->GetString().c_str(),
toType->GetString().c_str(), errorMsgBase); errorMsgBase);
return false; return false;
} }
@@ -5238,7 +5238,10 @@ ConstExpr::GetConstant(const Type *type) const {
int64_t iv[ISPC_MAX_NVEC]; int64_t iv[ISPC_MAX_NVEC];
AsInt64(iv, type->IsVaryingType()); AsInt64(iv, type->IsVaryingType());
for (int i = 0; i < Count(); ++i) for (int i = 0; i < Count(); ++i)
Assert(iv[i] == 0); if (iv[i] != 0)
// We'll issue an error about this later--trying to assign
// a constant int to a pointer, without a typecast.
return NULL;
return llvm::Constant::getNullValue(llvmType); return llvm::Constant::getNullValue(llvmType);
} }
@@ -6152,9 +6155,8 @@ TypeCastExpr::TypeCheck() {
toType = lDeconstifyType(toType); toType = lDeconstifyType(toType);
if (fromType->IsVaryingType() && toType->IsUniformType()) { if (fromType->IsVaryingType() && toType->IsUniformType()) {
Error(pos, "Can't type cast from varying type \"%s\" to uniform " Error(pos, "Can't type cast from type \"%s\" to type \"%s\"",
"type \"%s\"", fromType->GetString().c_str(), fromType->GetString().c_str(), toType->GetString().c_str());
toType->GetString().c_str());
return NULL; return NULL;
} }
@@ -7310,8 +7312,6 @@ NewExpr::NewExpr(int typeQual, const Type *t, Expr *init, Expr *count,
SourcePos tqPos, SourcePos p) SourcePos tqPos, SourcePos p)
: Expr(p) { : Expr(p) {
allocType = t; allocType = t;
if (allocType != NULL && allocType->HasUnboundVariability())
allocType = allocType->ResolveUnboundVariability(Type::Varying);
initExpr = init; initExpr = init;
countExpr = count; countExpr = count;
@@ -7333,6 +7333,18 @@ NewExpr::NewExpr(int typeQual, const Type *t, Expr *init, Expr *count,
// If no type qualifier is given before the 'new', treat it as a // If no type qualifier is given before the 'new', treat it as a
// varying new. // varying new.
isVarying = (typeQual == 0) || (typeQual & TYPEQUAL_VARYING); isVarying = (typeQual == 0) || (typeQual & TYPEQUAL_VARYING);
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);
}
} }

View File

@@ -484,7 +484,8 @@ static inline void
aos_to_soa4(uniform int32 a[], int32 * uniform v0, int32 * uniform v1, aos_to_soa4(uniform int32 a[], int32 * uniform v0, int32 * uniform v1,
int32 * uniform v2, int32 * uniform v3) { int32 * uniform v2, int32 * uniform v3) {
aos_to_soa4((uniform float * uniform)a, (float * uniform )v0, aos_to_soa4((uniform float * uniform)a, (float * uniform )v0,
(float * uniform)v1, (float * uniform)v2, (float * uniform)v3); (float * uniform)v1, (float * uniform)v2,
(float * uniform)v3);
} }
static inline void static inline void
@@ -763,24 +764,24 @@ static unsigned int64 exclusive_scan_or(unsigned int64 v) {
// packed load, store // packed load, store
static inline uniform int static inline uniform int
packed_load_active(uniform unsigned int * uniform a, packed_load_active(uniform unsigned int a[],
unsigned int * uniform vals) { unsigned int * uniform vals) {
return __packed_load_active(a, vals, (UIntMaskType)__mask); return __packed_load_active(a, vals, (UIntMaskType)__mask);
} }
static inline uniform int static inline uniform int
packed_store_active(uniform unsigned int * uniform a, packed_store_active(uniform unsigned int a[],
unsigned int vals) { unsigned int vals) {
return __packed_store_active(a, vals, (UIntMaskType)__mask); return __packed_store_active(a, vals, (UIntMaskType)__mask);
} }
static inline uniform int static inline uniform int
packed_load_active(uniform int * uniform a, int * uniform vals) { packed_load_active(uniform int a[], int * uniform vals) {
return __packed_load_active(a, vals, (IntMaskType)__mask); return __packed_load_active(a, vals, (IntMaskType)__mask);
} }
static inline uniform int static inline uniform int
packed_store_active(uniform int * uniform a, int vals) { packed_store_active(uniform int a[], int vals) {
return __packed_store_active(a, vals, (IntMaskType)__mask); return __packed_store_active(a, vals, (IntMaskType)__mask);
} }
@@ -1630,7 +1631,7 @@ static inline uniform float ldexp(uniform float x, uniform int n) {
return floatbits(ix); return floatbits(ix);
} }
static inline float frexp(float x, int * uniform pw2) { static inline float frexp(float x, varying int * uniform pw2) {
unsigned int ex = 0x7F800000u; // exponent mask unsigned int ex = 0x7F800000u; // exponent mask
unsigned int ix = intbits(x); unsigned int ix = intbits(x);
ex &= ix; ex &= ix;
@@ -1909,8 +1910,8 @@ static inline uniform float cos(uniform float x_full) {
} }
static inline void sincos(float x_full, float * uniform sin_result, static inline void sincos(float x_full, varying float * uniform sin_result,
float * uniform cos_result) { varying float * uniform cos_result) {
if (__math_lib == __math_lib_svml) { if (__math_lib == __math_lib_svml) {
__svml_sincos(x_full, sin_result, cos_result); __svml_sincos(x_full, sin_result, cos_result);
} }
@@ -2507,8 +2508,8 @@ static inline uniform float exp(uniform float x_full) {
// Range reduction for logarithms takes log(x) -> log(2^n * y) -> n // Range reduction for logarithms takes log(x) -> log(2^n * y) -> n
// * log(2) + log(y) where y is the reduced range (usually in [1/2, // * log(2) + log(y) where y is the reduced range (usually in [1/2,
// 1)). // 1)).
static inline void __range_reduce_log(float input, float * uniform reduced, static inline void __range_reduce_log(float input, varying float * uniform reduced,
int * uniform exponent) { varying int * uniform exponent) {
int int_version = intbits(input); int int_version = intbits(input);
// single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM // single precision = SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
// exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000 // exponent mask = 0111 1111 1000 0000 0000 0000 0000 0000
@@ -2785,7 +2786,7 @@ static inline uniform double ldexp(uniform double x, uniform int n) {
return doublebits(ix); return doublebits(ix);
} }
static inline double frexp(double x, int * uniform pw2) { static inline double frexp(double x, varying int * uniform pw2) {
unsigned int64 ex = 0x7ff0000000000000; // exponent mask unsigned int64 ex = 0x7ff0000000000000; // exponent mask
unsigned int64 ix = intbits(x); unsigned int64 ix = intbits(x);
ex &= ix; ex &= ix;
@@ -2851,8 +2852,8 @@ static inline uniform double cos(uniform double x) {
return __stdlib_cos(x); return __stdlib_cos(x);
} }
static inline void sincos(double x, double * uniform sin_result, static inline void sincos(double x, varying double * uniform sin_result,
double * uniform cos_result) { varying double * uniform cos_result) {
if (__math_lib == __math_lib_ispc_fast) { if (__math_lib == __math_lib_ispc_fast) {
float sr, cr; float sr, cr;
sincos((float)x, &sr, &cr); sincos((float)x, &sr, &cr);
@@ -3391,7 +3392,7 @@ struct RNGState {
unsigned int z1, z2, z3, z4; unsigned int z1, z2, z3, z4;
}; };
static inline unsigned int random(RNGState * uniform state) static inline unsigned int random(varying RNGState * uniform state)
{ {
unsigned int b; unsigned int b;
@@ -3406,14 +3407,14 @@ static inline unsigned int random(RNGState * uniform state)
return (state->z1 ^ state->z2 ^ state->z3 ^ state->z4); return (state->z1 ^ state->z2 ^ state->z3 ^ state->z4);
} }
static inline float frandom(RNGState * uniform state) static inline float frandom(varying RNGState * uniform state)
{ {
unsigned int irand = random(state); unsigned int irand = random(state);
irand &= (1<<23)-1; irand &= (1<<23)-1;
return floatbits(0x3F800000 | irand)-1.0f; return floatbits(0x3F800000 | irand)-1.0f;
} }
static inline uniform unsigned int __seed4(RNGState * uniform state, static inline uniform unsigned int __seed4(varying RNGState * uniform state,
uniform int start, uniform int start,
uniform unsigned int seed) { uniform unsigned int seed) {
uniform unsigned int c1 = 0xf0f0f0f0; uniform unsigned int c1 = 0xf0f0f0f0;
@@ -3447,7 +3448,7 @@ static inline uniform unsigned int __seed4(RNGState * uniform state,
return seed; return seed;
} }
static inline void seed_rng(uniform RNGState * uniform state, uniform unsigned int seed) { static inline void seed_rng(varying RNGState * uniform state, uniform unsigned int seed) {
if (programCount == 1) { if (programCount == 1) {
state->z1 = seed; state->z1 = seed;
state->z2 = seed ^ 0xbeeff00d; state->z2 = seed ^ 0xbeeff00d;

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) { void foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex]; float a = aFOO[programIndex];
float * uniform buf = uniform new float[programCount+1]; varying float * uniform buf = uniform new varying float[programCount+1];
for (uniform int i = 0; i < programCount+1; ++i) { for (uniform int i = 0; i < programCount+1; ++i) {
buf[i] = i+a; buf[i] = i+a;
} }

View File

@@ -7,7 +7,7 @@ struct Point {
export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) { export void f_fu(uniform float RET[], uniform float aFOO[], uniform float b) {
float a = aFOO[programIndex]; float a = aFOO[programIndex];
Point * varying buf = new Point(0., b, a); uniform Point * buf = new Point(0., b, a);
RET[programIndex] = buf->z; RET[programIndex] = buf->z;
delete buf; delete buf;
} }

View File

@@ -3,9 +3,9 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
float a = aFOO[programIndex]; float a = aFOO[programIndex];
float * uniform pa = &a; varying float * uniform pa = &a;
int * uniform pb = (int *)pa; varying int * uniform pb = (varying int *)pa;
float *uniform pc = (float *)pb; varying float *uniform pc = (varying float *)pb;
*pc = programIndex; *pc = programIndex;
RET[programIndex] = *pc; RET[programIndex] = *pc;
} }

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
RET[programIndex] = *b; RET[programIndex] = *b;
} }

View File

@@ -6,14 +6,14 @@ struct Foo {
uniform float b; uniform float b;
}; };
void update(Foo * varying fp) { void update(uniform Foo * varying fp) {
++fp; ++fp;
fp->a -= 1; fp->a -= 1;
fp->b = 1; fp->b = 1;
} }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } }; uniform Foo f[2] = { { 1234, 4321 }, { aFOO[programIndex], 5 } };
update(f); update(f);
RET[programIndex] = f[1].a; RET[programIndex] = f[1].a;
} }

View File

@@ -6,7 +6,7 @@ struct Foo {
uniform float b; uniform float b;
}; };
void update(float<3> * uniform vp) { void update(varying float<3> * uniform vp) {
vp->x = 0; vp->x = 0;
} }

View File

@@ -1,7 +1,7 @@
export uniform int width() { return programCount; } export uniform int width() { return programCount; }
void update(float<2> * varying vp) { void update(varying float<2> * vp) {
vp->y = 0; vp->y = 0;
} }

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
*b = 2; *b = 2;
RET[programIndex] = *b; RET[programIndex] = *b;
} }

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
++*b; ++*b;
RET[programIndex] = *b; RET[programIndex] = *b;
} }

View File

@@ -4,7 +4,7 @@ export uniform int width() { return programCount; }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
(*b)++; (*b)++;
RET[programIndex] = *b; RET[programIndex] = *b;
} }

View File

@@ -1,13 +1,13 @@
export uniform int width() { return programCount; } export uniform int width() { return programCount; }
void inc(int * uniform v) { void inc(varying int * uniform v) {
++*v; ++*v;
} }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
if (a <= 2) if (a <= 2)
inc(b); inc(b);
RET[programIndex] = a; RET[programIndex] = a;

View File

@@ -1,15 +1,15 @@
export uniform int width() { return programCount; } export uniform int width() { return programCount; }
void inc(int * uniform v) { void inc(varying int * uniform v) {
++*v; ++*v;
} }
export void f_f(uniform float RET[], uniform float aFOO[]) { export void f_f(uniform float RET[], uniform float aFOO[]) {
int a = aFOO[programIndex]; int a = aFOO[programIndex];
int * uniform b = &a; varying int * uniform b = &a;
void * uniform vp = b; void * uniform vp = b;
int * uniform c = (int * uniform)vp; varying int * uniform c = (varying int * uniform)vp;
RET[programIndex] = *c; RET[programIndex] = *c;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) { float foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) { float foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) { void foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) { void foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform a) { void foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x, int y) { void foo(varying float * uniform x, int y) {
*x = y; *x = y;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x, float y) { void foo(varying float * uniform x, float y) {
*x = y; *x = y;
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
void foo(float * uniform x) { void foo(varying float * uniform x) {
if ((*x) <= 2) if ((*x) <= 2)
++(*x); ++(*x);
} }

View File

@@ -3,7 +3,7 @@ export uniform int width() { return programCount; }
float foo(float * uniform a) { float foo(varying float * uniform a) {
*a = 0; *a = 0;
} }

View File

@@ -3,7 +3,7 @@ typedef int<4> int4;
export uniform int width() { return programCount; } export uniform int width() { return programCount; }
void inc(int4 * uniform v) { void inc(varying int4 * uniform v) {
int4 delta = { 1, 1, 1, 1 }; int4 delta = { 1, 1, 1, 1 };
(*v) += delta; (*v) += delta;
} }

View File

@@ -3,7 +3,7 @@ typedef int<4> int4;
export uniform int width() { return programCount; } export uniform int width() { return programCount; }
void incXY(int4 * uniform v) { void incXY(varying int4 * uniform v) {
++(*v).x; ++(*v).x;
++(*v).y; ++(*v).y;
} }

View File

@@ -1,4 +1,4 @@
// Illegal to assign to array type "float[5]" // Illegal to assign to array type "varying float[5]"
void foo(float *x) { void foo(float *x) {
float a[5] = { 1,2,3,4,5}; float a[5] = { 1,2,3,4,5};

View File

@@ -1,4 +1,4 @@
// Illegal to assign to array type "float[5]" // Illegal to assign to array type "varying float[5]"
void foo(float *x) { void foo(float *x) {
float a[5] = { 1,2,3,4,5}; float a[5] = { 1,2,3,4,5};

View File

@@ -1,4 +1,4 @@
// Illegal to assign to type "uniform struct Bar" in type "uniform struct Foo" due to element "a" with type "const int32" // Illegal to assign to type "uniform struct Bar" in type "uniform struct Foo" due to element "a" with type "const varying int32"
struct Bar { struct Bar {
const int a; const int a;

View File

@@ -1,4 +1,4 @@
// Illegal to assign to type "uniform struct Foo" due to element "a" with type "const int32" // Illegal to assign to type "uniform struct Foo" due to element "a" with type "const varying int32"
struct Foo { struct Foo {
const int a; const int a;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand // Can't assign to type "const varying int32" on left-hand
int func() { int func() {
const int x = 2; const int x = 2;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side // Can't assign to type "const varying int32" on left-hand side
const int x = 0; const int x = 0;

View File

@@ -1,4 +1,4 @@
// operator "." can't be used with expression of "int32" type // operator "." can't be used with expression of "uniform int32" type
int func(int *a) { int func(int *a) {
a.x = 0; a.x = 0;

View File

@@ -1,4 +1,4 @@
// Illegal to dereference non-pointer or reference type "float" // Illegal to dereference non-pointer or reference type "varying float"
float func(float a) { float func(float a) {
*a = 0; *a = 0;

View File

@@ -1,4 +1,4 @@
// Member operator "->" can't be used with expression of "int32" type // Member operator "->" can't be used with expression of "uniform int32" type
int func(int *a) { int func(int *a) {
a->x = 0; a->x = 0;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" // Can't assign to type "const varying int32"
int foo() { int foo() {
foreach (i = 0 ... 10) { foreach (i = 0 ... 10) {

View File

@@ -1,4 +1,4 @@
// Can't convert argument of type "void * uniform" to type "float" for function call argument. // Can't convert argument of type "void * uniform" to type "varying float" for function call argument.
float bar(float a, float b); float bar(float a, float b);

View File

@@ -1,3 +1,3 @@
// Initializer list for array "int32[2][4]" must have no more than 2 elements (has 3) // Initializer list for array "varying int32[2][4]" must have no more than 2 elements (has 3)
int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 }, 1 }; int a[2][4] = { { 1, 2, 3 }, { 1, 2, 3, 4 }, 1 };

View File

@@ -1,4 +1,4 @@
// Can't convert from varying type "int32 *" to uniform type "int32 * uniform" for return // Can't convert from type "uniform int32 * varying" to type "uniform int32 * uniform" for return
int * uniform func(int x) { int * uniform func(int x) {
return new int[x]; return new int[x];

View File

@@ -1,4 +1,4 @@
// Can't convert from varying type "float" to uniform type "uniform float" for initializer // Can't convert from type "varying float" to type "uniform float" for initializer
struct Point { struct Point {
uniform float x, y, z; uniform float x, y, z;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32 * const" // Can't assign to type "const uniform int32 * const varying"
void foo(const int * const p) { void foo(const int * const p) {
++p; ++p;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side // Can't assign to type "const varying int32" on left-hand side
void foo(const int * p) { void foo(const int * p) {
*p = 0; *p = 0;

View File

@@ -1,4 +1,4 @@
// Pointer type cast of type "int32 * uniform" to integer type "uniform int32" may lose information. // Pointer type cast of type "varying int32 * uniform" to integer type "uniform int32" may lose information.
int32 foo(int * uniform x) { int32 foo(int * uniform x) {
return (int32) x; return (int32) x;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression // Can't assign to type "const varying int32" on left-hand side of expression
const int x[20]; const int x[20];

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression // Can't assign to type "const varying int32" on left-hand side of expression
struct Foo { struct Foo {
int x; int x;

View File

@@ -1,4 +1,4 @@
// Can't assign to type "const int32" on left-hand side of expression // Can't assign to type "const varying int32" on left-hand side of expression
struct Foo { struct Foo {
int x; int x;

View File

@@ -1,4 +1,4 @@
// Can't apply "signed" qualifier to "float" type // Can't apply "signed" qualifier to "varying float" type
struct Foo { struct Foo {
signed float x; signed float x;

View File

@@ -1,4 +1,4 @@
// "signed" qualifier is illegal with non-integer type "float" // "signed" qualifier is illegal with non-integer type "varying float"
int foo() { int foo() {
signed float x; signed float x;

View File

@@ -1,4 +1,4 @@
// Can't apply "unsigned" qualifier to "float" type // Can't apply "unsigned" qualifier to "varying float" type
struct Foo { struct Foo {
unsigned float x; unsigned float x;

View File

@@ -1,3 +1,3 @@
// "unsigned" qualifier is illegal with "float" type // "unsigned" qualifier is illegal with "varying float" type
unsigned float foo = 1; unsigned float foo = 1;

View File

@@ -1,4 +1,4 @@
// Can't type cast from varying type "int32" to uniform type "uniform int32" // Can't type cast from type "varying int32" to type "uniform int32"
uniform int foo(int x) { uniform int foo(int x) {
return (uniform int) x; return (uniform int) x;

View File

@@ -427,7 +427,7 @@ AtomicType::GetString() const {
if (isConst) ret += "const "; if (isConst) ret += "const ";
switch (variability) { switch (variability) {
case Uniform: ret += "uniform "; break; case Uniform: ret += "uniform "; break;
case Varying: /*ret += "varying ";*/ break; case Varying: ret += "varying "; break;
case Unbound: ret += "/*unbound*/ "; break; case Unbound: ret += "/*unbound*/ "; break;
} }
} }
@@ -986,9 +986,17 @@ PointerType::ResolveUnboundVariability(Variability v) const {
Assert(m->errorCount > 0); Assert(m->errorCount > 0);
return NULL; return NULL;
} }
return new PointerType(baseType->ResolveUnboundVariability(v),
(variability == Unbound) ? v : variability, Assert(v != Unbound);
isConst); 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);
} }
@@ -1030,7 +1038,7 @@ PointerType::GetString() const {
if (isConst) ret += " const"; if (isConst) ret += " const";
switch (variability) { switch (variability) {
case Uniform: ret += " uniform"; break; case Uniform: ret += " uniform"; break;
case Varying: /*ret += " varying";*/ break; case Varying: ret += " varying"; break;
case Unbound: ret += " /*unbound*/"; break; case Unbound: ret += " /*unbound*/"; break;
} }
@@ -1964,7 +1972,7 @@ StructType::GetString() const {
switch (variability) { switch (variability) {
case Uniform: ret += "uniform "; break; case Uniform: ret += "uniform "; break;
case Varying: /*ret += "varying ";*/ break; case Varying: ret += "varying "; break;
case Unbound: ret += "/*unbound*/ "; break; case Unbound: ret += "/*unbound*/ "; break;
} }