From 3cdc3a9ef7af0ed61981add9da50909ec2746994 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Fri, 30 Jul 2021 13:53:57 -0700 Subject: [PATCH] ParsedScene: create (some) lights asynchronously --- src/pbrt/cpu/render.cpp | 3 +- src/pbrt/scene.cpp | 67 +++++++++++++++++++++++-------- src/pbrt/scene.h | 15 +++---- src/pbrt/wavefront/integrator.cpp | 2 +- 4 files changed, 60 insertions(+), 27 deletions(-) diff --git a/src/pbrt/cpu/render.cpp b/src/pbrt/cpu/render.cpp index 106ab8b..b93e4e8 100644 --- a/src/pbrt/cpu/render.cpp +++ b/src/pbrt/cpu/render.cpp @@ -79,8 +79,7 @@ void RenderCPU(ParsedScene &parsedScene) { // Lights std::map *> shapeIndexToAreaLights; - std::vector lights = - parsedScene.CreateLights(alloc, media, textures, &shapeIndexToAreaLights); + std::vector lights = parsedScene.CreateLights(textures, &shapeIndexToAreaLights); LOG_VERBOSE("Starting materials"); std::map namedMaterials; diff --git a/src/pbrt/scene.cpp b/src/pbrt/scene.cpp index 2aedc51..46630c8 100644 --- a/src/pbrt/scene.cpp +++ b/src/pbrt/scene.cpp @@ -797,7 +797,30 @@ void ParsedScene::AddSpectrumTexture(std::string name, TextureSceneEntity textur void ParsedScene::AddLight(LightSceneEntity light) { std::lock_guard lock(lightMutex); - lights.push_back(std::move(light)); + if (!light.medium.empty()) { + // If the light has a medium associated with it, punt for now since + // the Medium may not yet be initialized; these lights will be + // taken care of when CreateLights() is called. At the cost of + // some complexity, we could check and see if it's already in the + // medium map and wait for its in-flight future if it's not yet + // ready, though the most important case here is probably infinite + // image lights and those can't have media associated with them + // anyway... + lightsWithMedia.push_back(std::move(light)); + return; + } + + if (light.renderFromObject.IsAnimated()) + Warning(&light.loc, + "Animated lights aren't supported. Using the start transform."); + + auto create = [this](LightSceneEntity light) { + return Light::Create(light.name, light.parameters, + light.renderFromObject.startTransform, + camera.cameraTransform, nullptr /* Medium */, &light.loc, + threadAllocators.Get()); + }; + lightFutures.push_back(RunAsync(create, light)); } int ParsedScene::AddAreaLight(SceneEntity light) { @@ -875,10 +898,10 @@ void ParsedScene::Done() { } LOG_VERBOSE("Scene stats: %d shapes, %d animated shapes, %d instance definitions, " - "%d instance uses, %d lights, %d float textures, %d spectrum textures, " + "%d instance uses, %d float textures, %d spectrum textures, " "%d named materials, %d materials", shapes.size(), animatedShapes.size(), instanceDefinitions.size(), - instances.size(), lights.size(), floatTextures.size(), + instances.size(), floatTextures.size(), spectrumTextures.size(), namedMaterials.size(), materials.size()); // And complain about what's left. @@ -1131,33 +1154,38 @@ NamedTextures ParsedScene::CreateTextures(ThreadLocal &threadAllocato return textures; } -std::map ParsedScene::CreateMedia() const { - std::map mediaMap; +std::map ParsedScene::CreateMedia() { + std::lock_guard lock(mediaMutex); LOG_VERBOSE("Consume media futures start"); - for (auto &m : mediaFutures) + for (auto &m : mediaFutures) { + CHECK(mediaMap.find(m.first) == mediaMap.end()); mediaMap[m.first] = m.second.Get(); - LOG_VERBOSE("Consume media futures finished"); - + } mediaFutures.clear(); + LOG_VERBOSE("Consume media futures finished"); return mediaMap; } std::vector ParsedScene::CreateLights( - Allocator alloc, const std::map &media, const NamedTextures &textures, std::map *> *shapeIndexToAreaLights) { - auto findMedium = [&media](const std::string &s, const FileLoc *loc) -> Medium { + // Ensure that media are all ready + (void)CreateMedia(); + + auto findMedium = [this](const std::string &s, const FileLoc *loc) -> Medium { if (s.empty()) return nullptr; - auto iter = media.find(s); - if (iter == media.end()) + auto iter = mediaMap.find(s); + if (iter == mediaMap.end()) ErrorExit(loc, "%s: medium not defined", s); return iter->second; }; + Allocator alloc = threadAllocators.Get(); + auto getAlphaTexture = [&](const ParameterDictionary ¶meters, const FileLoc *loc) -> FloatTexture { std::string alphaTexName = parameters.GetTexture("alpha"); @@ -1178,11 +1206,11 @@ std::vector ParsedScene::CreateLights( return nullptr; }; - // Lights (area lights will be done later, with shapes...) - LOG_VERBOSE("Starting lights"); + LOG_VERBOSE("Starting non-future lights"); std::vector lights; - lights.reserve(lights.size() + areaLights.size()); - for (const auto &light : this->lights) { + + // Lights with media (punted in AddLight() earlier.) + for (const auto &light : lightsWithMedia) { Medium outsideMedium = findMedium(light.medium, &light.loc); if (light.renderFromObject.IsAnimated()) Warning(&light.loc, @@ -1243,8 +1271,13 @@ std::vector ParsedScene::CreateLights( (*shapeIndexToAreaLights)[i] = shapeLights; } + LOG_VERBOSE("Finished non-future lights"); + + LOG_VERBOSE("Starting to consume non-area light futures"); + for (auto &fut : lightFutures) + lights.push_back(fut.Get()); + LOG_VERBOSE("Finished consuming non-area light futures"); - LOG_VERBOSE("Finished Lights"); return lights; } diff --git a/src/pbrt/scene.h b/src/pbrt/scene.h index fccd494..95360af 100644 --- a/src/pbrt/scene.h +++ b/src/pbrt/scene.h @@ -334,11 +334,9 @@ class ParsedScene : public SceneProcessor { std::map *namedMaterials, std::vector *materials) const; - std::map CreateMedia() const; + std::map CreateMedia(); - std::vector CreateLights( - Allocator alloc, const std::map &media, - const NamedTextures &textures, + std::vector CreateLights(const NamedTextures &textures, std::map *> *shapeIndexToAreaLights); Primitive CreateAggregate( @@ -359,8 +357,6 @@ class ParsedScene : public SceneProcessor { std::map media; std::vector> floatTextures; std::vector> spectrumTextures; - std::vector lights; - std::vector areaLights; std::vector shapes; std::vector animatedShapes; std::vector instances; @@ -369,7 +365,12 @@ class ParsedScene : public SceneProcessor { private: ThreadLocal &threadAllocators; - mutable std::map> mediaFutures; + std::map> mediaFutures; + std::map mediaMap; + + std::vector lightsWithMedia; + std::vector> lightFutures; + std::vector areaLights; std::mutex namedMaterialMutex, materialMutex, mediaMutex; std::mutex floatTextureMutex, spectrumTextureMutex; diff --git a/src/pbrt/wavefront/integrator.cpp b/src/pbrt/wavefront/integrator.cpp index faa2e6a..cc9e663 100644 --- a/src/pbrt/wavefront/integrator.cpp +++ b/src/pbrt/wavefront/integrator.cpp @@ -152,7 +152,7 @@ WavefrontPathIntegrator::WavefrontPathIntegrator( std::map *> shapeIndexToAreaLights; infiniteLights = alloc.new_object>(alloc); - for (Light l : scene.CreateLights(alloc, media, textures, &shapeIndexToAreaLights)) { + for (Light l : scene.CreateLights(textures, &shapeIndexToAreaLights)) { if (l.Is() || l.Is() || l.Is()) infiniteLights->push_back(l); -- GitLab