working on aobench
This commit is contained in:
283
examples_cuda/aobench/ao.cu
Normal file
283
examples_cuda/aobench/ao.cu
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
// -*- mode: c++ -*-
|
||||||
|
/*
|
||||||
|
Copyright (c) 2010-2011, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Based on Syoyo Fujita's aobench: http://code.google.com/p/aobench
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NAO_SAMPLES 8
|
||||||
|
#define M_PI 3.1415926535f
|
||||||
|
|
||||||
|
typedef float<3> vec;
|
||||||
|
|
||||||
|
#ifdef __NVPTX__
|
||||||
|
#warning "emitting DEVICE code"
|
||||||
|
#define programCount warpSize()
|
||||||
|
#define programIndex laneIndex()
|
||||||
|
#define taskIndex blockIndex0()
|
||||||
|
#define taskCount blockCount0()
|
||||||
|
#else
|
||||||
|
#warning "emitting HOST code"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Isect {
|
||||||
|
float t;
|
||||||
|
vec p;
|
||||||
|
vec n;
|
||||||
|
int hit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sphere {
|
||||||
|
vec center;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Plane {
|
||||||
|
vec p;
|
||||||
|
vec n;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ray {
|
||||||
|
vec org;
|
||||||
|
vec dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline float dot(vec a, vec b) {
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vec vcross(vec v0, vec v1) {
|
||||||
|
vec ret;
|
||||||
|
ret.x = v0.y * v1.z - v0.z * v1.y;
|
||||||
|
ret.y = v0.z * v1.x - v0.x * v1.z;
|
||||||
|
ret.z = v0.x * v1.y - v0.y * v1.x;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vnormalize(vec &v) {
|
||||||
|
float len2 = dot(v, v);
|
||||||
|
float invlen = rsqrt(len2);
|
||||||
|
v *= invlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ray_plane_intersect(Isect &isect, Ray &ray, uniform Plane &plane) {
|
||||||
|
float d = -dot(plane.p, plane.n);
|
||||||
|
float v = dot(ray.dir, plane.n);
|
||||||
|
|
||||||
|
if (abs(v) < 1.0e-17)
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
float t = -(dot(ray.org, plane.n) + d) / v;
|
||||||
|
|
||||||
|
if ((t > 0.0) && (t < isect.t)) {
|
||||||
|
isect.t = t;
|
||||||
|
isect.hit = 1;
|
||||||
|
isect.p = ray.org + ray.dir * t;
|
||||||
|
isect.n = plane.n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ray_sphere_intersect(Isect &isect, Ray &ray, uniform Sphere &sphere) {
|
||||||
|
vec rs = ray.org - sphere.center;
|
||||||
|
|
||||||
|
float B = dot(rs, ray.dir);
|
||||||
|
float C = dot(rs, rs) - sphere.radius * sphere.radius;
|
||||||
|
float D = B * B - C;
|
||||||
|
|
||||||
|
if (D > 0.) {
|
||||||
|
float t = -B - sqrt(D);
|
||||||
|
|
||||||
|
if ((t > 0.0) && (t < isect.t)) {
|
||||||
|
isect.t = t;
|
||||||
|
isect.hit = 1;
|
||||||
|
isect.p = ray.org + t * ray.dir;
|
||||||
|
isect.n = isect.p - sphere.center;
|
||||||
|
vnormalize(isect.n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
orthoBasis(vec basis[3], vec n) {
|
||||||
|
basis[2] = n;
|
||||||
|
basis[1].x = 0.0; basis[1].y = 0.0; basis[1].z = 0.0;
|
||||||
|
|
||||||
|
if ((n.x < 0.6) && (n.x > -0.6)) {
|
||||||
|
basis[1].x = 1.0;
|
||||||
|
} else if ((n.y < 0.6) && (n.y > -0.6)) {
|
||||||
|
basis[1].y = 1.0;
|
||||||
|
} else if ((n.z < 0.6) && (n.z > -0.6)) {
|
||||||
|
basis[1].z = 1.0;
|
||||||
|
} else {
|
||||||
|
basis[1].x = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
basis[0] = vcross(basis[1], basis[2]);
|
||||||
|
vnormalize(basis[0]);
|
||||||
|
|
||||||
|
basis[1] = vcross(basis[2], basis[0]);
|
||||||
|
vnormalize(basis[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
ambient_occlusion(Isect &isect, uniform Plane &plane, uniform Sphere spheres[3],
|
||||||
|
RNGState &rngstate) {
|
||||||
|
float eps = 0.0001f;
|
||||||
|
vec p, n;
|
||||||
|
vec basis[3];
|
||||||
|
float occlusion = 0.0;
|
||||||
|
|
||||||
|
p = isect.p + eps * isect.n;
|
||||||
|
|
||||||
|
orthoBasis(basis, isect.n);
|
||||||
|
|
||||||
|
static const uniform int ntheta = NAO_SAMPLES;
|
||||||
|
static const uniform int nphi = NAO_SAMPLES;
|
||||||
|
for (uniform int j = 0; j < ntheta; j++) {
|
||||||
|
for (uniform int i = 0; i < nphi; i++) {
|
||||||
|
Ray ray;
|
||||||
|
Isect occIsect;
|
||||||
|
|
||||||
|
float theta = sqrt(frandom(&rngstate));
|
||||||
|
float phi = 2.0f * M_PI * frandom(&rngstate);
|
||||||
|
float x = cos(phi) * theta;
|
||||||
|
float y = sin(phi) * theta;
|
||||||
|
float z = sqrt(1.0 - theta * theta);
|
||||||
|
|
||||||
|
// local . global
|
||||||
|
float rx = x * basis[0].x + y * basis[1].x + z * basis[2].x;
|
||||||
|
float ry = x * basis[0].y + y * basis[1].y + z * basis[2].y;
|
||||||
|
float rz = x * basis[0].z + y * basis[1].z + z * basis[2].z;
|
||||||
|
|
||||||
|
ray.org = p;
|
||||||
|
ray.dir.x = rx;
|
||||||
|
ray.dir.y = ry;
|
||||||
|
ray.dir.z = rz;
|
||||||
|
|
||||||
|
occIsect.t = 1.0e+17;
|
||||||
|
occIsect.hit = 0;
|
||||||
|
|
||||||
|
for (uniform int snum = 0; snum < 3; ++snum)
|
||||||
|
ray_sphere_intersect(occIsect, ray, spheres[snum]);
|
||||||
|
ray_plane_intersect (occIsect, ray, plane);
|
||||||
|
|
||||||
|
if (occIsect.hit) occlusion += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
occlusion = (ntheta * nphi - occlusion) / (float)(ntheta * nphi);
|
||||||
|
return occlusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute the image for the scanlines from [y0,y1), for an overall image
|
||||||
|
of width w and height h.
|
||||||
|
*/
|
||||||
|
static inline void ao_scanlines(uniform int y0, uniform int y1, uniform int w,
|
||||||
|
uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
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 } };
|
||||||
|
RNGState rngstate;
|
||||||
|
|
||||||
|
seed_rng(&rngstate, programIndex + (y0 << (programIndex & 15)));
|
||||||
|
float invSamples = 1.f / nsubsamples;
|
||||||
|
|
||||||
|
foreach_tiled(y = y0 ... y1, x = 0 ... w,
|
||||||
|
u = 0 ... nsubsamples, v = 0 ... nsubsamples)
|
||||||
|
{
|
||||||
|
float du = (float)u * invSamples, dv = (float)v * invSamples;
|
||||||
|
|
||||||
|
// Figure out x,y pixel in NDC
|
||||||
|
float px = (x + du - (w / 2.0f)) / (w / 2.0f);
|
||||||
|
float py = -(y + dv - (h / 2.0f)) / (h / 2.0f);
|
||||||
|
float ret = 0.f;
|
||||||
|
Ray ray;
|
||||||
|
Isect isect;
|
||||||
|
|
||||||
|
ray.org = 0.f;
|
||||||
|
|
||||||
|
// Poor man's perspective projection
|
||||||
|
ray.dir.x = px;
|
||||||
|
ray.dir.y = py;
|
||||||
|
ray.dir.z = -1.0;
|
||||||
|
vnormalize(ray.dir);
|
||||||
|
|
||||||
|
isect.t = 1.0e+17;
|
||||||
|
isect.hit = 0;
|
||||||
|
|
||||||
|
for (uniform int snum = 0; snum < 3; ++snum)
|
||||||
|
ray_sphere_intersect(isect, ray, spheres[snum]);
|
||||||
|
ray_plane_intersect(isect, ray, plane);
|
||||||
|
|
||||||
|
// Note use of 'coherent' if statement; the set of rays we
|
||||||
|
// trace will often all hit or all miss the scene
|
||||||
|
if (isect.hit) {
|
||||||
|
ret = ambient_occlusion(isect, plane, spheres, rngstate);
|
||||||
|
ret *= invSamples * invSamples;
|
||||||
|
|
||||||
|
int offset = 3 * (y * w + x);
|
||||||
|
atomic_add_local(&image[offset], ret);
|
||||||
|
atomic_add_local(&image[offset+1], ret);
|
||||||
|
atomic_add_local(&image[offset+2], ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void ao_ispc(uniform int w, uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
ao_scanlines(0, h, w, h, nsubsamples, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void task ao_task(uniform int width, uniform int height,
|
||||||
|
uniform int nsubsamples, uniform float image[]) {
|
||||||
|
ao_scanlines(taskIndex, taskIndex+1, width, height, nsubsamples, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void ao_ispc_tasks(uniform int w, uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
launch[h] ao_task(w, h, nsubsamples, image);
|
||||||
|
}
|
||||||
@@ -40,6 +40,16 @@
|
|||||||
|
|
||||||
typedef float<3> vec;
|
typedef float<3> vec;
|
||||||
|
|
||||||
|
#ifdef __NVPTX__
|
||||||
|
#warning "emitting DEVICE code"
|
||||||
|
#define programCount warpSize()
|
||||||
|
#define programIndex laneIndex()
|
||||||
|
#define taskIndex blockIndex0()
|
||||||
|
#define taskCount blockCount0()
|
||||||
|
#else
|
||||||
|
#warning "emitting HOST code"
|
||||||
|
#endif
|
||||||
|
|
||||||
struct Isect {
|
struct Isect {
|
||||||
float t;
|
float t;
|
||||||
vec p;
|
vec p;
|
||||||
|
|||||||
283
examples_cuda/aobench/ao1.ispc
Normal file
283
examples_cuda/aobench/ao1.ispc
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
// -*- mode: c++ -*-
|
||||||
|
/*
|
||||||
|
Copyright (c) 2010-2011, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
Based on Syoyo Fujita's aobench: http://code.google.com/p/aobench
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NAO_SAMPLES 8
|
||||||
|
#define M_PI 3.1415926535f
|
||||||
|
|
||||||
|
typedef float<3> vec;
|
||||||
|
|
||||||
|
#ifdef __NVPTX__
|
||||||
|
#warning "emitting DEVICE code"
|
||||||
|
#define programCount warpSize()
|
||||||
|
#define programIndex laneIndex()
|
||||||
|
#define taskIndex blockIndex0()
|
||||||
|
#define taskCount blockCount0()
|
||||||
|
#else
|
||||||
|
#warning "emitting HOST code"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Isect {
|
||||||
|
float t;
|
||||||
|
vec p;
|
||||||
|
vec n;
|
||||||
|
int hit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Sphere {
|
||||||
|
vec center;
|
||||||
|
float radius;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Plane {
|
||||||
|
vec p;
|
||||||
|
vec n;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ray {
|
||||||
|
vec org;
|
||||||
|
vec dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline float dot(vec a, vec b) {
|
||||||
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline vec vcross(vec v0, vec v1) {
|
||||||
|
vec ret;
|
||||||
|
ret.x = v0.y * v1.z - v0.z * v1.y;
|
||||||
|
ret.y = v0.z * v1.x - v0.x * v1.z;
|
||||||
|
ret.z = v0.x * v1.y - v0.y * v1.x;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vnormalize(vec &v) {
|
||||||
|
float len2 = dot(v, v);
|
||||||
|
float invlen = rsqrt(len2);
|
||||||
|
v *= invlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ray_plane_intersect(Isect &isect, Ray &ray, uniform Plane &plane) {
|
||||||
|
float d = -dot(plane.p, plane.n);
|
||||||
|
float v = dot(ray.dir, plane.n);
|
||||||
|
|
||||||
|
if (abs(v) < 1.0e-17)
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
float t = -(dot(ray.org, plane.n) + d) / v;
|
||||||
|
|
||||||
|
if ((t > 0.0) && (t < isect.t)) {
|
||||||
|
isect.t = t;
|
||||||
|
isect.hit = 1;
|
||||||
|
isect.p = ray.org + ray.dir * t;
|
||||||
|
isect.n = plane.n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ray_sphere_intersect(Isect &isect, Ray &ray, uniform Sphere &sphere) {
|
||||||
|
vec rs = ray.org - sphere.center;
|
||||||
|
|
||||||
|
float B = dot(rs, ray.dir);
|
||||||
|
float C = dot(rs, rs) - sphere.radius * sphere.radius;
|
||||||
|
float D = B * B - C;
|
||||||
|
|
||||||
|
if (D > 0.) {
|
||||||
|
float t = -B - sqrt(D);
|
||||||
|
|
||||||
|
if ((t > 0.0) && (t < isect.t)) {
|
||||||
|
isect.t = t;
|
||||||
|
isect.hit = 1;
|
||||||
|
isect.p = ray.org + t * ray.dir;
|
||||||
|
isect.n = isect.p - sphere.center;
|
||||||
|
vnormalize(isect.n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
orthoBasis(vec basis[3], vec n) {
|
||||||
|
basis[2] = n;
|
||||||
|
basis[1].x = 0.0; basis[1].y = 0.0; basis[1].z = 0.0;
|
||||||
|
|
||||||
|
if ((n.x < 0.6) && (n.x > -0.6)) {
|
||||||
|
basis[1].x = 1.0;
|
||||||
|
} else if ((n.y < 0.6) && (n.y > -0.6)) {
|
||||||
|
basis[1].y = 1.0;
|
||||||
|
} else if ((n.z < 0.6) && (n.z > -0.6)) {
|
||||||
|
basis[1].z = 1.0;
|
||||||
|
} else {
|
||||||
|
basis[1].x = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
basis[0] = vcross(basis[1], basis[2]);
|
||||||
|
vnormalize(basis[0]);
|
||||||
|
|
||||||
|
basis[1] = vcross(basis[2], basis[0]);
|
||||||
|
vnormalize(basis[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
ambient_occlusion(Isect &isect, uniform Plane &plane, uniform Sphere spheres[3],
|
||||||
|
RNGState &rngstate) {
|
||||||
|
float eps = 0.0001f;
|
||||||
|
vec p, n;
|
||||||
|
vec basis[3];
|
||||||
|
float occlusion = 0.0;
|
||||||
|
|
||||||
|
p = isect.p + eps * isect.n;
|
||||||
|
|
||||||
|
orthoBasis(basis, isect.n);
|
||||||
|
|
||||||
|
static const uniform int ntheta = NAO_SAMPLES;
|
||||||
|
static const uniform int nphi = NAO_SAMPLES;
|
||||||
|
for (uniform int j = 0; j < ntheta; j++) {
|
||||||
|
for (uniform int i = 0; i < nphi; i++) {
|
||||||
|
Ray ray;
|
||||||
|
Isect occIsect;
|
||||||
|
|
||||||
|
float theta = sqrt(frandom(&rngstate));
|
||||||
|
float phi = 2.0f * M_PI * frandom(&rngstate);
|
||||||
|
float x = cos(phi) * theta;
|
||||||
|
float y = sin(phi) * theta;
|
||||||
|
float z = sqrt(1.0 - theta * theta);
|
||||||
|
|
||||||
|
// local . global
|
||||||
|
float rx = x * basis[0].x + y * basis[1].x + z * basis[2].x;
|
||||||
|
float ry = x * basis[0].y + y * basis[1].y + z * basis[2].y;
|
||||||
|
float rz = x * basis[0].z + y * basis[1].z + z * basis[2].z;
|
||||||
|
|
||||||
|
ray.org = p;
|
||||||
|
ray.dir.x = rx;
|
||||||
|
ray.dir.y = ry;
|
||||||
|
ray.dir.z = rz;
|
||||||
|
|
||||||
|
occIsect.t = 1.0e+17;
|
||||||
|
occIsect.hit = 0;
|
||||||
|
|
||||||
|
for (uniform int snum = 0; snum < 3; ++snum)
|
||||||
|
ray_sphere_intersect(occIsect, ray, spheres[snum]);
|
||||||
|
ray_plane_intersect (occIsect, ray, plane);
|
||||||
|
|
||||||
|
if (occIsect.hit) occlusion += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
occlusion = (ntheta * nphi - occlusion) / (float)(ntheta * nphi);
|
||||||
|
return occlusion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute the image for the scanlines from [y0,y1), for an overall image
|
||||||
|
of width w and height h.
|
||||||
|
*/
|
||||||
|
static inline void ao_scanlines(uniform int y0, uniform int y1, uniform int w,
|
||||||
|
uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
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 } };
|
||||||
|
RNGState rngstate;
|
||||||
|
|
||||||
|
seed_rng(&rngstate, programIndex + (y0 << (programIndex & 15)));
|
||||||
|
float invSamples = 1.f / nsubsamples;
|
||||||
|
|
||||||
|
foreach_tiled(y = y0 ... y1, x = 0 ... w,
|
||||||
|
u = 0 ... nsubsamples, v = 0 ... nsubsamples)
|
||||||
|
{
|
||||||
|
float du = (float)u * invSamples, dv = (float)v * invSamples;
|
||||||
|
|
||||||
|
// Figure out x,y pixel in NDC
|
||||||
|
float px = (x + du - (w / 2.0f)) / (w / 2.0f);
|
||||||
|
float py = -(y + dv - (h / 2.0f)) / (h / 2.0f);
|
||||||
|
float ret = 0.f;
|
||||||
|
Ray ray;
|
||||||
|
Isect isect;
|
||||||
|
|
||||||
|
ray.org = 0.f;
|
||||||
|
|
||||||
|
// Poor man's perspective projection
|
||||||
|
ray.dir.x = px;
|
||||||
|
ray.dir.y = py;
|
||||||
|
ray.dir.z = -1.0;
|
||||||
|
vnormalize(ray.dir);
|
||||||
|
|
||||||
|
isect.t = 1.0e+17;
|
||||||
|
isect.hit = 0;
|
||||||
|
|
||||||
|
for (uniform int snum = 0; snum < 3; ++snum)
|
||||||
|
ray_sphere_intersect(isect, ray, spheres[snum]);
|
||||||
|
ray_plane_intersect(isect, ray, plane);
|
||||||
|
|
||||||
|
// Note use of 'coherent' if statement; the set of rays we
|
||||||
|
// trace will often all hit or all miss the scene
|
||||||
|
if (isect.hit) {
|
||||||
|
ret = ambient_occlusion(isect, plane, spheres, rngstate);
|
||||||
|
ret *= invSamples * invSamples;
|
||||||
|
|
||||||
|
int offset = 3 * (y * w + x);
|
||||||
|
atomic_add_local(&image[offset], ret);
|
||||||
|
atomic_add_local(&image[offset+1], ret);
|
||||||
|
atomic_add_local(&image[offset+2], ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void ao_ispc(uniform int w, uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
ao_scanlines(0, h, w, h, nsubsamples, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void task ao_task(uniform int width, uniform int height,
|
||||||
|
uniform int nsubsamples, uniform float image[]) {
|
||||||
|
ao_scanlines(taskIndex, taskIndex+1, width, height, nsubsamples, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void ao_ispc_tasks(uniform int w, uniform int h, uniform int nsubsamples,
|
||||||
|
uniform float image[]) {
|
||||||
|
launch[h] ao_task(w, h, nsubsamples, image);
|
||||||
|
}
|
||||||
204
examples_cuda/aobench/ao_cu.cpp
Normal file
204
examples_cuda/aobench/ao_cu.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2010-2011, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define NOMINMAX
|
||||||
|
#pragma warning (disable: 4244)
|
||||||
|
#pragma warning (disable: 4305)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
#include <math.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "ao_ispc.h"
|
||||||
|
using namespace ispc;
|
||||||
|
|
||||||
|
#include "../timing.h"
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
static inline double rtc(void)
|
||||||
|
{
|
||||||
|
struct timeval Tvalue;
|
||||||
|
double etime;
|
||||||
|
struct timezone dummy;
|
||||||
|
|
||||||
|
gettimeofday(&Tvalue,&dummy);
|
||||||
|
etime = (double) Tvalue.tv_sec +
|
||||||
|
1.e-6*((double) Tvalue.tv_usec);
|
||||||
|
return etime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define NSUBSAMPLES 2
|
||||||
|
|
||||||
|
extern void ao_serial(int w, int h, int nsubsamples, float image[]);
|
||||||
|
|
||||||
|
static unsigned int test_iterations;
|
||||||
|
static unsigned int width, height;
|
||||||
|
static unsigned char *img;
|
||||||
|
static float *fimg;
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned char
|
||||||
|
clamp(float f)
|
||||||
|
{
|
||||||
|
int i = (int)(f * 255.5);
|
||||||
|
|
||||||
|
if (i < 0) i = 0;
|
||||||
|
if (i > 255) i = 255;
|
||||||
|
|
||||||
|
return (unsigned char)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
savePPM(const char *fname, int w, int h)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < h; y++) {
|
||||||
|
for (int x = 0; x < w; x++) {
|
||||||
|
img[3 * (y * w + x) + 0] = clamp(fimg[3 *(y * w + x) + 0]);
|
||||||
|
img[3 * (y * w + x) + 1] = clamp(fimg[3 *(y * w + x) + 1]);
|
||||||
|
img[3 * (y * w + x) + 2] = clamp(fimg[3 *(y * w + x) + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(fname, "wb");
|
||||||
|
if (!fp) {
|
||||||
|
perror(fname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "P6\n");
|
||||||
|
fprintf(fp, "%d %d\n", w, h);
|
||||||
|
fprintf(fp, "255\n");
|
||||||
|
fwrite(img, w * h * 3, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
printf("Wrote image file %s\n", fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 4) {
|
||||||
|
printf ("%s\n", argv[0]);
|
||||||
|
printf ("Usage: ao [num test iterations] [width] [height]\n");
|
||||||
|
getchar();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
test_iterations = atoi(argv[1]);
|
||||||
|
width = atoi (argv[2]);
|
||||||
|
height = atoi (argv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate space for output images
|
||||||
|
img = new unsigned char[width * height * 3];
|
||||||
|
fimg = new float[width * height * 3];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Run the ispc path, test_iterations times, and report the minimum
|
||||||
|
// time for any of them.
|
||||||
|
//
|
||||||
|
double minTimeISPC = 1e30;
|
||||||
|
#if 0
|
||||||
|
for (unsigned int i = 0; i < test_iterations; i++) {
|
||||||
|
memset((void *)fimg, 0, sizeof(float) * width * height * 3);
|
||||||
|
assert(NSUBSAMPLES == 2);
|
||||||
|
|
||||||
|
reset_and_start_timer();
|
||||||
|
ao_ispc(width, height, NSUBSAMPLES, fimg);
|
||||||
|
double t = get_elapsed_mcycles();
|
||||||
|
minTimeISPC = std::min(minTimeISPC, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report results and save image
|
||||||
|
printf("[aobench ispc]:\t\t\t[%.3f] million cycles (%d x %d image)\n",
|
||||||
|
minTimeISPC, width, height);
|
||||||
|
savePPM("ao-ispc.ppm", width, height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Run the ispc + tasks path, test_iterations times, and report the
|
||||||
|
// minimum time for any of them.
|
||||||
|
//
|
||||||
|
double minTimeISPCTasks = 1e30;
|
||||||
|
for (unsigned int i = 0; i < test_iterations; i++) {
|
||||||
|
memset((void *)fimg, 0, sizeof(float) * width * height * 3);
|
||||||
|
assert(NSUBSAMPLES == 2);
|
||||||
|
|
||||||
|
reset_and_start_timer();
|
||||||
|
const double t0 = rtc();
|
||||||
|
ao_ispc_tasks(width, height, NSUBSAMPLES, fimg);
|
||||||
|
double t = (rtc() - t0); //get_elapsed_mcycles();
|
||||||
|
minTimeISPCTasks = std::min(minTimeISPCTasks, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report results and save image
|
||||||
|
printf("[aobench ispc + tasks]:\t\t[%.3f] million cycles (%d x %d image)\n",
|
||||||
|
minTimeISPCTasks, width, height);
|
||||||
|
savePPM("ao-ispc-tasks.ppm", width, height);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Run the serial path, again test_iteration times, and report the
|
||||||
|
// minimum time.
|
||||||
|
//
|
||||||
|
double minTimeSerial = 1e30;
|
||||||
|
for (unsigned int i = 0; i < test_iterations; i++) {
|
||||||
|
memset((void *)fimg, 0, sizeof(float) * width * height * 3);
|
||||||
|
reset_and_start_timer();
|
||||||
|
ao_serial(width, height, NSUBSAMPLES, fimg);
|
||||||
|
double t = get_elapsed_mcycles();
|
||||||
|
minTimeSerial = std::min(minTimeSerial, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report more results, save another image...
|
||||||
|
printf("[aobench serial]:\t\t[%.3f] million cycles (%d x %d image)\n", minTimeSerial,
|
||||||
|
width, height);
|
||||||
|
printf("\t\t\t\t(%.2fx speedup from ISPC, %.2fx speedup from ISPC + tasks)\n",
|
||||||
|
minTimeSerial / minTimeISPC, minTimeSerial / minTimeISPCTasks);
|
||||||
|
savePPM("ao-serial.ppm", width, height);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user