Implémentation du raytracing pour Global Memory/Shared Memory/Constant Memory
authorgburri <gregory.burri@master.hes-so.ch>
Thu, 15 Jan 2015 17:17:50 +0000 (18:17 +0100)
committergburri <gregory.burri@master.hes-so.ch>
Thu, 15 Jan 2015 17:17:50 +0000 (18:17 +0100)
14 files changed:
WCudaMSE/BilatTools_CPP/src/core/tools/cpp/AleaTools.cpp
WCudaMSE/BilatTools_CPP/src/core/tools/cpp/namespace_cpu/IndiceTools_CPU.cpp
WCudaMSE/BilatTools_CPP/src/core/tools/header/AleaTools.h
WCudaMSE/BilatTools_CPP/src/core/tools/header/namespace_cpu/IndiceTools_CPU.h
WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/device/IndiceTools_GPU.h
WCudaMSE/BilatTools_Cuda/src/core/cudatools/header/host/cudaTools.h
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h [new file with mode: 0644]
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.cu
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/RayTracingDevice.h
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/device/Sphere.h
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.cu
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/host/RayTracing.h
WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/provider/RayTracingProvider.cpp
WCudaMSE/Student_Cuda_Image/src/cpp/core/mainGL.cpp

index f55adc1..38912a6 100755 (executable)
@@ -21,6 +21,11 @@ AleaTools::AleaTools()
     srand(time(NULL));\r
     }\r
 \r
+AleaTools::AleaTools(uint seed)\r
+    {\r
+    srand(seed);\r
+    }\r
+\r
 AleaTools::~AleaTools()\r
     {\r
     // rien\r
index b70c829..efc02fe 100755 (executable)
@@ -20,12 +20,19 @@ namespace cpu
        *ptrJ = s - w * (*ptrI);\r
        }\r
 \r
+    float2 IndiceTools::toPixelFloat(int s, int w)\r
+        {\r
+        const float y = (float)s / (float)w;\r
+        const float x = (float)s - (float)w * y;\r
+        return { x, y };\r
+        }\r
+\r
     /**\r
      * i[0,H[ j[0,W[ --> s[0,W*H[\r
      */\r
-    int IndiceTools::toS(int W, int i, int j)\r
+    int IndiceTools::toS(int w, int i, int j)\r
        {\r
-       return (i * W) + j;\r
+       return (i * w) + j;\r
        }\r
 \r
     }\r
index 4420132..287e015 100755 (executable)
@@ -25,6 +25,8 @@ class AleaTools
         */\r
        AleaTools();\r
 \r
+        AleaTools(uint seed);\r
+\r
        /*--------------------------------------*\\r
         |*             Destructor              *|\r
         \*-------------------------------------*/\r
index a97f64b..1c3027e 100755 (executable)
@@ -1,6 +1,8 @@
 #ifndef INDICE_TOOLS_CPU_H_\r
 #define INDICE_TOOLS_CPU_H_\r
 \r
+#include "cudaType_CPU.h"\r
+\r
 /*----------------------------------------------------------------------*\\r
  |*                    Declaration                                     *|\r
  \*---------------------------------------------------------------------*/\r
@@ -29,12 +31,17 @@ namespace cpu
             /**\r
              * s[0,W*H[ --> i[0,H[ j[0,W[\r
              */\r
-            static void toIJ(int s, int W, int* ptri, int* ptrj);\r
+            static void toIJ(int s, int w, int* ptri, int* ptrj);\r
+\r
+            /**\r
+             * s[0,W*H[ --> x[0,W[ y[0,H[\r
+             */\r
+            static float2 toPixelFloat(int s, int w);\r
 \r
             /**\r
              * i[0,H[ j[0,W[ --> s[0,W*H[\r
              */\r
-            static int toS(int W, int i, int j);\r
+            static int toS(int w, int i, int j);\r
 \r
             /*-------------------------------------*\\r
             |*         Attributs                   *|\r
index d230aef..f62ddf3 100755 (executable)
@@ -2,6 +2,7 @@
 #define INDICES_TOOLS_GPU_H_\r
 \r
 #include "both_define.h"\r
+#include "cudaType_CPU.h"\r
 \r
 /*----------------------------------------------------------------------*\\r
  |*                    Declaration                                     *|\r
@@ -34,12 +35,24 @@ namespace gpu
             * h = hauteur\r
             */\r
            __BOTH__\r
-           static  void toIJ( int s, int w, int* ptrI, int* ptrJ)\r
+           static void toIJ( int s, int w, int* ptrI, int* ptrJ)\r
                {\r
                *ptrI = s / w;\r
                *ptrJ = s - w * (*ptrI);\r
                }\r
 \r
+            /**\r
+             * s[0,W*H[ --> x[0,W[ y[0,H[\r
+             */\r
+            __BOTH__\r
+            static float2 toPixelFloat(int s, int w)\r
+                {\r
+                const int y = s / w;\r
+                const int x = s - w * y;\r
+                const float2 pixel = { (float)x, (float)y };\r
+                return pixel;\r
+                }\r
+\r
            /**\r
             * i[0,H[ j[0,W[ --> s[0,W*H[\r
             * w = largeur\r
@@ -60,7 +73,7 @@ namespace gpu
        };\r
     }\r
 \r
-#endif \r
+#endif\r
 \r
 /*----------------------------------------------------------------------*\\r
  |*                    End                                             *|\r
index 8c0834d..5b48c74 100755 (executable)
 // cublas\r
 #include "cublas_v2.h"         // Pour specifier la version qu'on veut! (definition CUBLASAPI)\r
 //#include "cublas.h"          // Pour specifier la version qu'on veut!(definition CUBLASAPI)\r
-#include "cublas_api.h" // Après include "cublas_v2.h" ou "cublas.h"\r
+#include "cublas_api.h" // Aprs include "cublas_v2.h" ou "cublas.h"\r
 \r
-\r
-\r
-\r
-typedef unsigned char uchar;\r
+#ifndef uchar\r
+    typedef unsigned char uchar;\r
+#endif\r
 \r
 /*----------------------------------------------------------------------*\\r
  |*                    Declaration                                     *|\r
diff --git a/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h b/WCudaMSE/Student_Cuda_Image/src/cpp/core/04_RayTracing/moo/RayTracingCommon.h
new file mode 100644 (file)
index 0000000..0f2d3ae
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef RAY_TRACING_COMMON
+#define RAY_TRACING_COMMON
+
+#define NB_SPHERES 2000
+
+
+#define MEMORY_MODEL_GLOBAL 1
+#define MEMORY_MODEL_CONSTANT 2
+#define MEMORY_MODEL_SHARED 3
+
+#define CURRENT_MEMORY_MODEL MEMORY_MODEL_SHARED
+
+#endif
index 3d80bc4..97fc839 100644 (file)
 #include <iostream>
-#include <stdio.h>
+#include <cstdio>
+#include <cfloat>
 using namespace std;
 
+#include "Indice1D.h"
 #include "Indice2D.h"
 #include "IndiceTools.h"
+#include "ColorTools.h"
 #include "cudaTools.h"
 #include "Device.h"
 
 #include "RayTracingDevice.h"
 
-__global__
-void rayTracing(uchar4* ptrDevPixels, int w, int h, float t)
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+// Les spheres dans la constant memory.
+__constant__ Sphere CONST_SPHERES[NB_SPHERES];
+
+ConstantMemoryLink constantMemorySpheresLink()
+    {
+    float* ptrDevTabData;
+    size_t sizeAll = NB_SPHERES * sizeof(Sphere);
+    HANDLE_ERROR(cudaGetSymbolAddress((void**)&ptrDevTabData, CONST_SPHERES));
+    ConstantMemoryLink cmLink =
+        {
+          (void**)ptrDevTabData, NB_SPHERES, sizeAll
+        };
+    return cmLink;
+    }
+#endif
+
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+    __global__
+    void rayTracing(uchar4* ptrDevPixels, const Sphere* ptrDevSpheres, int w, int h, float t)
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+    __global__
+    void rayTracing(uchar4* ptrDevPixels, int w, int h, float t)
+#endif
     {
+
     const int TID = Indice2D::tid();
     const int NB_THREAD = Indice2D::nbThread();
     const int WH = w * h;
 
-    uchar4 color;
-    color.w = 255; // Par défaut, l'image est opaque.
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+    __shared__ Sphere tabSpheresSM[NB_SPHERES];
 
-    double x, y;
-    int pixelI, pixelJ;
+    // Copy the global memory to shared memory.
+    const int NB_THREAD_LOCAL = Indice1D::nbThreadBlock();
+    const int TID_LOCAL = Indice1D::tidLocal();
+    int sLocal = TID_LOCAL;
+    while (sLocal < NB_SPHERES)
+        {
+        tabSpheresSM[sLocal] = ptrDevSpheres[sLocal];
+        sLocal += NB_THREAD_LOCAL;
+        }
+
+    __syncthreads();
+#endif
 
     int s = TID;
     while (s < WH)
         {
-        IndiceTools::toIJ(s, w, &pixelI, &pixelJ); // update (pixelI, pixelJ)
+        const float2 pixel = IndiceTools::toPixelFloat(s, w);
+
+        // Les données de la sphère sélectionnée.
+        float selectedSphereDistance = FLT_MAX;
+        float brightness = 0;
+        float hue = 0;
+
+        // Sélectionne la sphere la plus proche, il peut ne pas y avoir de sphère.
+        for (int i = 0; i < NB_SPHERES; ++i)
+            {
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL
+            const Sphere& sphere = ptrDevSpheres[i];
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+            const Sphere& sphere = CONST_SPHERES[i];
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+            const Sphere& sphere = tabSpheresSM[i];
+#endif
+            const float hSquare = sphere.hSquare(pixel);
+
+            if (sphere.isBelow(hSquare))
+                {
+                const float dz = sphere.dz(hSquare);
+                const float sphereDistance = sphere.distance(dz);
 
-        // (i,j) domaine écran.
-        // (x,y) domaine math.
-        // domaineMath.toXY(pixelI, pixelJ, &x, &y); // (i,j) -> (x,y).
+                if (sphereDistance < selectedSphereDistance)
+                    {
+                    selectedSphereDistance = sphereDistance;
+                    brightness = sphere.brightness(dz);
+                    hue = sphere.hue(t);
+                    }
+                }
+            }
 
-        // newtonMath.colorXY(&color, x, y);
+        // Si une sphere a pu être trouvée.
+        if (selectedSphereDistance != FLT_MAX)
+            {
+            ColorTools::HSB_TO_RVB(hue, 1, brightness, &ptrDevPixels[s]);
+            }
 
-        ptrDevPixels[s] = color;
+        ptrDevPixels[s].w = 255;
 
         s += NB_THREAD;
         }
index 1500c43..350ba9c 100644 (file)
@@ -1,7 +1,26 @@
 #ifndef RAY_TRACING_DEVICE_H
 #define RAY_TRACING_DEVICE_H
 
-__global__
-void rayTracing(uchar4* ptrDevPixels, int w, int h, float t);
+#include "ConstantMemoryLink.h"
+
+#include "Sphere.h"
+#include "RayTracingCommon.h"
+
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+
+    __global__
+    void rayTracing(uchar4* ptrDevPixels, const Sphere* ptrDevSpheres, int w, int h, float t);
+
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+
+    /**
+     * Accès à la mémoire constante contenant les sphères.
+     */
+    ConstantMemoryLink constantMemorySpheresLink();
+
+    __global__
+    void rayTracing(uchar4* ptrDevPixels, int w, int h, float t);
+
+#endif
 
 #endif
index a437dab..3c8df6e 100644 (file)
@@ -7,19 +7,28 @@
 class Sphere
     {
     public:
-        __host__
+        /*__host__
         Sphere(float3 centre, float r, float hue) :
             centre(centre),
             hueInitial(hue)
             {
             this->setR(r);
-            }
+            }*/
 
         __host__
+        __device__
         Sphere()
             {
             }
 
+        /*Sphere(const Sphere& other) :
+            r(other.r),
+            centre(other.centre),
+            rCarre(other.rCarre),
+            T(other.T)
+            {
+            }*/
+
         __host__
         void setCentre(const float3& centre)
             {
@@ -30,64 +39,74 @@ class Sphere
         void setR(float r)
             {
             this->r = r;
-            this->rCarre = r*r;
+            this->rCarre = r * r;
             }
 
         __host__
         void setHueInitial(float hue)
             {
-            this->hueInitial = hue;
+            this->T = asinf(2 * hue - 1) - 3 * PI / 2;
             }
 
+        /*
+         * Calcul de h².
+         */
         __device__
-        float hCarre(float2 xySol)
+        float hSquare(float2 xySol) const
             {
-            float a = (centre.x - xySol.x);
-            float b = (centre.y - xySol.y);
+            const float a = (this->centre.x - xySol.x);
+            const float b = (this->centre.y - xySol.y);
             return a * a + b * b;
             }
 
+        /*
+         * Est-ce que la sphre se trouve en dessous d'un point (x, y) en fonction de h².
+         * Voir la méthode 'hCarre(..)'.
+         */
         __device__
-        bool isEnDessous(float hCarre)
+        bool isBelow(float hCarre) const
             {
-            return hCarre < rCarre;
+            return hCarre < this->rCarre;
             }
 
+        /*
+         * Hauteur du point de collision du rayon par rapport au centre de la sphère.
+         */
         __device__
-        float dz(float hCarre)
+        float dz(float hCarre) const
             {
             return sqrtf(rCarre - hCarre);
             }
 
         __device__
-        float brightness(float dz)
+        float distance(float dz) const
             {
-            return dz / r;
+            return this->centre.z - dz;
             }
 
+        /**
+         * Renvoie la le B de HSB compris entre 0 et 1.
+         */
         __device__
-        float distance(float dz)
+        float brightness(float dz) const
             {
-            return centre.z - dz;
+            return dz / this->r;
             }
 
+        /*
+         * La couleur
+         */
         __device__
-        float getHueInitial()
+        float hue(float t) const
             {
-            return this->hueInitial;
-            }
-
-        __device__
-        float hue(float t) // usefull for animation
-            {
-            return 0.5 + 0.5 * sin(t + T + 3 * PI / 2);
+            return 0.5 + 0.5 * sinf(t + this->T + 3 * PI / 2);
             }
 
     private:
-        float r;
-        float3 centre;
-        float hueInitial;
-        float rCarre;
+        float r; // Rayon.
+        float3 centre; // Position.
+
+        float rCarre; // Précalul de r².
 
         float T; // Utilisé pour l'animation.
     };
index 1623820..8742692 100644 (file)
@@ -9,19 +9,39 @@ using namespace std;
 #include "Device.h"
 #include "RayTracingDevice.h"
 #include "Sphere.h"
-
-RayTracing::RayTracing(int w, int h)
-    : w(w), h(h),
-      dg(8, 8, 1),
-      db(32, 32, 1),
-      title("Ray Tracing")
+#include "RayTracingCommon.h"
+
+RayTracing::RayTracing(int w, int h) :
+    t(0), w(w), h(h),
+    dg(8, 8, 1),
+    db(32, 32, 1),
+    alea(42),
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL
+    title("Ray Tracing (Global memory)")
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+    title("Ray Tracing (Constant memory)")
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+    title("Ray Tracing (Shared memory)")
+#endif
     {
     Device::assertDim(dg, db);
 
-    const int nbSpheres = 10;
-    Sphere* shperes = this->createSpheres(10);
-
-    // Copie les spheres dans la constant memory.
+    Sphere* spheres = this->createSpheres(NB_SPHERES);
+
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+    // Copie des spheres dans la global memory.
+    const size_t sizeSpheres = NB_SPHERES * sizeof(Sphere);
+    HANDLE_ERROR(cudaMalloc(&this->ptrDevSpheres, sizeSpheres));
+    HANDLE_ERROR(cudaMemcpy(this->ptrDevSpheres, spheres, sizeSpheres, cudaMemcpyHostToDevice));
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
+    // Copie des spheres en constant memory.
+    ConstantMemoryLink cmSpheresLink = constantMemorySpheresLink();
+    Sphere* ptrDevConstSperes = (Sphere*)cmSpheresLink.ptrDevTab;
+    size_t sizeALL = cmSpheresLink.sizeAll;
+    HANDLE_ERROR(cudaMemcpy(ptrDevConstSperes, spheres, sizeALL, cudaMemcpyHostToDevice));
+#endif
+
+    cout << "sizeof(Sphere): " << sizeof(Sphere) << endl;
     }
 
 RayTracing::~RayTracing()
@@ -30,14 +50,18 @@ RayTracing::~RayTracing()
 
 void RayTracing::runGPU(uchar4* ptrDevPixels)
     {
+#if CURRENT_MEMORY_MODEL == MEMORY_MODEL_GLOBAL or CURRENT_MEMORY_MODEL == MEMORY_MODEL_SHARED
+    rayTracing<<<dg,db>>>(ptrDevPixels, this->ptrDevSpheres, this->w, this->h, this->t);
+#elif CURRENT_MEMORY_MODEL == MEMORY_MODEL_CONSTANT
     rayTracing<<<dg,db>>>(ptrDevPixels, this->w, this->h, this->t);
+#endif
 
-    // HANDLE_ERROR(cudaDeviceSynchronize()); // Pour flusher les 'printf' (pour le DEBUG).
+    HANDLE_ERROR(cudaDeviceSynchronize()); // Pour flusher les 'printf' (pour le DEBUG).
     }
 
 void RayTracing::animationStep()
     {
-    this->t += 0.1; // TODO.
+    this->t += 0.005;
     }
 
 int RayTracing::getW()
@@ -63,20 +87,25 @@ string RayTracing::getTitle()
 Sphere* RayTracing::createSpheres(int n)
     {
     Sphere* spheres = new Sphere[n];
-    const float bord = 200;
+    const int RAYON_MIN = 10;
+    const int RAYON_MAX = this->w / 10 - 1;
+
+    const float bord = RAYON_MAX + 1;
 
     for (int i = 0; i < n; ++i)
         {
-        spheres[i].setR(float(this->alea.uniformeAB(20, this->w / 10 - 1)));
+        spheres[i].setR(float(this->alea.uniformeAB(RAYON_MIN, RAYON_MAX)));
 
-        float3 centre
+        const float3 centre =
             {
-            float(this->alea.uniformeAB(double(bord), double(this->w - bord))),
-            float(this->alea.uniformeAB(double(bord), double(this->h - bord))),
-            float(this->alea.uniformeAB(10.0, 2.0 * this->w))
+            float(this->alea.uniformeAB(double(bord), double(this->w - bord))), // x.
+            float(this->alea.uniformeAB(double(bord), double(this->h - bord))), // y.
+            float(this->alea.uniformeAB(10.0, 2.0 * this->w))                   // z.
             };
 
         spheres[i].setCentre(centre);
         spheres[i].setHueInitial(float(this->alea.uniformeAB(0.0, 1.0)));
         }
+
+    return spheres;
     }
index 313fa6b..1f9536d 100644 (file)
@@ -25,8 +25,13 @@ class RayTracing : public Animable_I
         std::string getTitle(void) /*override*/;
 
     private:
+        /**
+         * Crée un tablean de 'n' sphères dont le rayon, la couleur et la position sont générés aléatoirement.
+         */
         Sphere* createSpheres(int n);
 
+        Sphere* ptrDevSpheres; // Pointeur sur la mémoire du GPU.
+
         AleaTools alea;
 
         float t;
index f232f0b..2d82571 100644 (file)
@@ -10,6 +10,6 @@ RayTracing* RayTracingProvider::create()
 
 Image* RayTracingProvider::createGL()
     {
-    ColorRGB_01* ptrColorTitre = new ColorRGB_01(0, 0, 0);
+    ColorRGB_01* ptrColorTitre = new ColorRGB_01(255, 255, 255);
     return new Image(create(), ptrColorTitre); // both ptr destroy by destructor of ImageFonctionel
     }
index d7a9fec..13dd2db 100755 (executable)
@@ -20,7 +20,7 @@ using namespace std;
 \r
 int mainGL(const vector<string>& args)\r
     {\r
-    const string defaultCommand = "demo";\r
+    const string defaultCommand = "raytracing";\r
     const string command = args.size() > 0 ? args[0] : defaultCommand;\r
 \r
     // AutoViewer<Rippling0Image, Rippling0Provider> rippling0(true, true, 10, 10); // Warmup.\r
@@ -40,6 +40,8 @@ int mainGL(const vector<string>& args)
         AutoViewer<ImageFonctionel, NewtonProvider> newtown(true, true, 10, 10);\r
     else if (command == "heat-transfert")\r
         AutoViewer<Image, HeatTransfertProvider> heatTransfert(true, false, 10, 10);\r
+    else if (command == "raytracing")\r
+        AutoViewer<Image, RayTracingProvider> rayTracing(true, true, 20, 20);\r
     else if (command == "convolution")\r
         {\r
         const string videoPath = args.size() >= 2 ? args[1] : "/media/Data/Video/nasaFHD_short.avi"; // Vidéo par défaut si pas donnée en paramètre.\r
@@ -60,7 +62,5 @@ int mainGL(const vector<string>& args)
         cout << "Command unknown: " << command << endl;\r
         }\r
 \r
-    // AutoViewer<ImageFonctionel, RayTracingProvider> rayTracing(true, true, 20, 20); // Commenté car projet approfondit.\r
-\r
     return EXIT_SUCCESS;\r
     }\r