예제 #1
0
void EnqueueTasks(const vector<Task *> &tasks) {
    if (PbrtOptions.nCores == 1) {
        for (unsigned int i = 0; i < tasks.size(); ++i)
            tasks[i]->Run();
        return;
    }
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    for (uint32_t i = 0; i < tasks.size(); ++i)
        dispatch_group_async_f(gcdGroup, gcdQueue, tasks[i], lRunTask);
#else
    if (!threads)
        TasksInit();

    {   MutexLock lock(*taskQueueMutex);
        for (unsigned int i = 0; i < tasks.size(); ++i)
            taskQueue.push_back(tasks[i]);
    }
    tasksRunningCondition.Lock();
    numUnfinishedTasks += tasks.size();
    tasksRunningCondition.Unlock();

    workerSemaphore.Post(tasks.size());
#endif
}
예제 #2
0
void EnqueueTasks(const vector<Task *> &tasks) {
#ifdef PBRT_USE_GRAND_CENTRAL_DISPATCH
    static bool oneThread = (getenv("PBRT_NTHREADS") &&
                               atoi(getenv("PBRT_NTHREADS")) == 1);
    for (u_int i = 0; i < tasks.size(); ++i)
        if (oneThread)
            dispatch_sync_f(gcdQueue, tasks[i], lRunTask);
        else
            dispatch_group_async_f(gcdGroup, gcdQueue, tasks[i], lRunTask);
#else
    if (!threads)
        TasksInit();

    { MutexLock lock(*taskQueueMutex);
    for (unsigned int i = 0; i < tasks.size(); ++i)
        taskQueue.push_back(tasks[i]);
    }
    tasksRunningCondition.Lock();
    numUnfinishedTasks += tasks.size();
    tasksRunningCondition.Unlock();

    workerSemaphore.Post(tasks.size());
#endif
}
예제 #3
0
파일: main.cpp 프로젝트: alexunder/X-toys
int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "usage: mbrast [grid_file.out]\n");
        return 1;
    }

    // Read grids from grid dump file
    std::vector<ShadedGrid> grids;
    if (!ReadGrids(argv[1], &grids))
        return 1;

    InitSamples();

    // Extract the name of the scene in case a full pathname was provided
    // on the command line
    char *sceneName = rindex(argv[1], '/');
    if (sceneName != NULL)
        ++sceneName;
    else
        sceneName = argv[1];

    // Remove trailing ".grids" from scene name
    char *end = rindex(sceneName, '.');
    assert(end);
    *end = '\0';

    printf("Rendering scene \"%s\"\n", sceneName);

    // Change this call to switch to creating an instance of your 3D
    // rasterizer once you start implementing it.

#if MBRAST_MODE == NAIVE_RAST_2D || MBRAST_MODE == SMART_RAST_2D
    Rasterizer *rast = Create2DRasterizer();
#elif MBRAST_MODE == BASIC_RAST_3D || MBRAST_MODE == INTER_RAST_3D
    Rasterizer *rast = Create3DRasterizer();
#elif MBRAST_MODE == BASIC_RAST_5D
    Rasterizer *rast = Create5DRasterizer();
#endif

    // Initialize task system for multithreading if the rasterizer
    // indicates that it's thread safe.
    bool useTasks = rast->IsThreadSafe();
    int nThreads = NumSystemCores();
    assert(nThreads < MAX_CORES);
    if (useTasks) {
        printf("Using %d threads!\n", nThreads);
        TasksInit();
    }

    // Render the scene multiple times, with each of the pixelSamples
    // sample counts.  The sample counts must all be powers of two.
    // The bucketSize array, which must be the same size as
    // pixelSamples[], gives the length of the side of the bucket we'll
    // decompose the image into for the corresponding sample count.
    int pixelSamples[] = { 1, 4, 32 };
    int bucketSize[] = { 64, 32, 8 };
    assert(sizeof(pixelSamples) == sizeof(bucketSize));
    int samplesSize = sizeof(pixelSamples) / sizeof(pixelSamples[0]);

    int failures = 0;
    for (int samplesIndex = 0; samplesIndex < samplesSize; ++samplesIndex) {
        assert(pixelSamples[samplesIndex] <= MAX_SAMPLES_PER_PIXEL);
        int nPixelSamples = pixelSamples[samplesIndex];
        int bucketExtent = bucketSize[samplesIndex];

        printf("Rendering with %d samples per pixel\n", nPixelSamples);

        // 720p resolution.  (This can't be easily changed, as it's baked
        // into the xy coordinates of the micropolygons.  So changing this
        // here would require a corresponding adjustment to those
        // coordinate values when the grids are read in....)
        int xRes = 1280, yRes = 720;

        // Allow the rasterizer to preprocess the grids
        ResetAndStartTimer();
        rast->PreprocessGrids(grids, bucketExtent, xRes, yRes);
        double preprocessCycles = GetElapsedMCycles() / 1024.;
        printf("  Spent %.3f billion cycles on grid preprocessing.\n",
               preprocessCycles);

        // Allocate final output image as well as one Bucket structure for
        // each rasterization task thread we're running; this way the
        // rasterizer can update the framebuffer in its Bucket directly
        // without needing to coordinate with any other rasterizer threads.
        uint8_t *image = new uint8_t[xRes * yRes * 3];
        Bucket *buckets[MAX_CORES];
        int nBuckets = useTasks ? nThreads : 1;
        for (int i = 0; i < nBuckets; ++i)
            buckets[i] = new Bucket(bucketExtent, nPixelSamples);

        // Render with intervals set from 1 to the number of pixel samples
        // in multiples of two.
        for (int logIntervals = 0; (1 << logIntervals) <= nPixelSamples;
             ++logIntervals) {
            int nIntervals = (1 << logIntervals);

            printf("  Rendering with %d intervals: ", nIntervals);
            fflush(stdout);

            if (useTasks) {
                // Create a RastTask instance for each of the buckets of
                // the image; do this outside of the timer so as not to
                // penalize for the unnecessary dynamic allocation overhead
                // in the implementation here.
                std::vector<Task *> rastTasks;
                for (int y = 0; y < yRes; y += bucketExtent) {
                    for (int x = 0; x < xRes; x += bucketExtent) {
                        int x1 = std::min(x + bucketExtent, xRes);
                        int y1 = std::min(y + bucketExtent, yRes);
                        RastTask *rt = new RastTask(rast, &buckets[0], x, y,
                                                    x1, y1, nIntervals, grids,
                                                    image, xRes, yRes);
                        rastTasks.push_back(rt);
                    }
                }

                ResetAndStartTimer();
                EnqueueTasks(rastTasks);
                WaitForAllTasks();
            }
            else {
                // If not using tasks, just loop over all of the buckets
                // and rasterize.
                ResetAndStartTimer();
                for (int y = 0; y < yRes; y += bucketExtent) {
                    for (int x = 0; x < xRes; x += bucketExtent) {
                        buckets[0]->Start(x, y, std::min(x + bucketExtent, xRes),
                                          std::min(y + bucketExtent, yRes));
                        rast->Rasterize(grids, nIntervals, buckets[0]);
                        buckets[0]->Resolve(image, xRes, yRes);
                    }
                }
            }

            // Report total time for rasterization
            double rastGCycles = GetElapsedMCycles() / 1024.;
            printf("  %.3f billion cycles\n", rastGCycles);

            // Write the image
            char outName[256];
            sprintf(outName, "%s_int%d_samp%d.ppm", sceneName, nIntervals,
                    nPixelSamples);
            WritePPM(image, xRes, yRes, outName);
            printf("  Wrote output image \"%s\"\n", outName);

            // Compare to the "golden" image for correctness
            char goldenName[256];
            sprintf(goldenName, "golden/%s_%d.ppm", sceneName,
                    nPixelSamples);
            if (!CompareToGolden(image, xRes, yRes, goldenName, outName))
                ++failures;
        }
        printf("\n");

        for (int i = 0; i < nBuckets; ++i)
            delete buckets[i];

        delete[] image;
    }

    if (useTasks)
        TasksCleanup();

    delete rast;
    return failures;
}