Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/engines/eevee_next/eevee_instance.cc
| Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
| * well as querying temp texture pool. All DRWPasses should be ready by the end end_sync(). | * well as querying temp texture pool. All DRWPasses should be ready by the end end_sync(). | ||||
| * \{ */ | * \{ */ | ||||
| void Instance::begin_sync() | void Instance::begin_sync() | ||||
| { | { | ||||
| materials.begin_sync(); | materials.begin_sync(); | ||||
| velocity.begin_sync(); /* NOTE: Also syncs camera. */ | velocity.begin_sync(); /* NOTE: Also syncs camera. */ | ||||
| lights.begin_sync(); | lights.begin_sync(); | ||||
| cryptomatte.begin_sync(); | |||||
| gpencil_engine_enabled = false; | gpencil_engine_enabled = false; | ||||
| depth_of_field.sync(); | depth_of_field.sync(); | ||||
| motion_blur.sync(); | motion_blur.sync(); | ||||
| hiz_buffer.sync(); | hiz_buffer.sync(); | ||||
| pipelines.sync(); | pipelines.sync(); | ||||
| main_view.sync(); | main_view.sync(); | ||||
| ▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| void Instance::end_sync() | void Instance::end_sync() | ||||
| { | { | ||||
| velocity.end_sync(); | velocity.end_sync(); | ||||
| lights.end_sync(); | lights.end_sync(); | ||||
| sampling.end_sync(); | sampling.end_sync(); | ||||
| film.end_sync(); | film.end_sync(); | ||||
| cryptomatte.end_sync(); | |||||
| } | } | ||||
| void Instance::render_sync() | void Instance::render_sync() | ||||
| { | { | ||||
| DRW_cache_restart(); | DRW_cache_restart(); | ||||
| begin_sync(); | begin_sync(); | ||||
| DRW_render_object_iter(this, render, depsgraph, object_sync_render); | DRW_render_object_iter(this, render, depsgraph, object_sync_render); | ||||
| Show All 38 Lines | |||||
| { | { | ||||
| eViewLayerEEVEEPassType pass_bits = film.enabled_passes_get(); | eViewLayerEEVEEPassType pass_bits = film.enabled_passes_get(); | ||||
| for (auto i : IndexRange(EEVEE_RENDER_PASS_MAX_BIT)) { | for (auto i : IndexRange(EEVEE_RENDER_PASS_MAX_BIT)) { | ||||
| eViewLayerEEVEEPassType pass_type = eViewLayerEEVEEPassType(pass_bits & (1 << i)); | eViewLayerEEVEEPassType pass_type = eViewLayerEEVEEPassType(pass_bits & (1 << i)); | ||||
| if (pass_type == 0) { | if (pass_type == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| const char *pass_name = Film::pass_to_render_pass_name(pass_type); | Vector<std::string> pass_names = Film::pass_to_render_pass_names(pass_type, view_layer); | ||||
| RenderPass *rp = RE_pass_find_by_name(render_layer, pass_name, view_name); | for (int64_t pass_offset : IndexRange(pass_names.size())) { | ||||
| if (rp) { | RenderPass *rp = RE_pass_find_by_name( | ||||
| float *result = film.read_pass(pass_type); | render_layer, pass_names[pass_offset].c_str(), view_name); | ||||
| if (!rp) { | |||||
| continue; | |||||
| } | |||||
| float *result = film.read_pass(pass_type, pass_offset); | |||||
| if (result) { | if (result) { | ||||
| BLI_mutex_lock(&render->update_render_passes_mutex); | BLI_mutex_lock(&render->update_render_passes_mutex); | ||||
| /* WORKAROUND: We use texture read to avoid using a framebuffer to get the render result. | /* WORKAROUND: We use texture read to avoid using a framebuffer to get the render result. | ||||
| * However, on some implementation, we need a buffer with a few extra bytes for the read to | * However, on some implementation, we need a buffer with a few extra bytes for the read to | ||||
| * happen correctly (see GLTexture::read()). So we need a custom memory allocation. */ | * happen correctly (see GLTexture::read()). So we need a custom memory allocation. */ | ||||
| /* Avoid memcpy(), replace the pointer directly. */ | /* Avoid memcpy(), replace the pointer directly. */ | ||||
| MEM_SAFE_FREE(rp->rect); | MEM_SAFE_FREE(rp->rect); | ||||
| rp->rect = result; | rp->rect = result; | ||||
| BLI_mutex_unlock(&render->update_render_passes_mutex); | BLI_mutex_unlock(&render->update_render_passes_mutex); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */ | /* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */ | ||||
| if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) { | if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) { | ||||
| const char *vector_pass_name = Film::pass_to_render_pass_name(EEVEE_RENDER_PASS_VECTOR); | for (std::string vector_pass_name : | ||||
| RenderPass *vector_rp = RE_pass_find_by_name(render_layer, vector_pass_name, view_name); | Film::pass_to_render_pass_names(EEVEE_RENDER_PASS_VECTOR, view_layer)) { | ||||
| RenderPass *vector_rp = RE_pass_find_by_name( | |||||
| render_layer, vector_pass_name.c_str(), view_name); | |||||
| if (vector_rp) { | if (vector_rp) { | ||||
| memset(vector_rp->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty); | memset(vector_rp->rect, 0, sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Interface | /** \name Interface | ||||
| * \{ */ | * \{ */ | ||||
| void Instance::render_frame(RenderLayer *render_layer, const char *view_name) | void Instance::render_frame(RenderLayer *render_layer, const char *view_name) | ||||
| Show All 12 Lines | if (G.background == false && first_read) { | ||||
| first_read = false; | first_read = false; | ||||
| DRW_render_context_disable(render->re); | DRW_render_context_disable(render->re); | ||||
| /* Allow the 2D viewport to grab the ticket mutex to display the render. */ | /* Allow the 2D viewport to grab the ticket mutex to display the render. */ | ||||
| DRW_render_context_enable(render->re); | DRW_render_context_enable(render->re); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| this->film.cryptomatte_sort(); | |||||
| this->render_read_result(render_layer, view_name); | this->render_read_result(render_layer, view_name); | ||||
| } | } | ||||
| void Instance::draw_viewport(DefaultFramebufferList *dfbl) | void Instance::draw_viewport(DefaultFramebufferList *dfbl) | ||||
| { | { | ||||
| UNUSED_VARS(dfbl); | UNUSED_VARS(dfbl); | ||||
| render_sample(); | render_sample(); | ||||
| velocity.step_swap(); | velocity.step_swap(); | ||||
| /* Do not request redraw during viewport animation to lock the framerate to the animation | /* Do not request redraw during viewport animation to lock the framerate to the animation | ||||
| * playback rate. This is in order to preserve motion blur aspect and also to avoid TAA reset | * playback rate. This is in order to preserve motion blur aspect and also to avoid TAA reset | ||||
| * that can show flickering. */ | * that can show flickering. */ | ||||
| if (!sampling.finished_viewport() && !DRW_state_is_playback()) { | if (!sampling.finished_viewport() && !DRW_state_is_playback()) { | ||||
| DRW_viewport_request_redraw(); | DRW_viewport_request_redraw(); | ||||
| } | } | ||||
| if (materials.queued_shaders_count > 0) { | if (materials.queued_shaders_count > 0) { | ||||
| std::stringstream ss; | std::stringstream ss; | ||||
| ss << "Compiling Shaders " << materials.queued_shaders_count; | ss << "Compiling Shaders " << materials.queued_shaders_count; | ||||
| info = ss.str(); | info = ss.str(); | ||||
| } | } | ||||
| } | } | ||||
| void Instance::store_metadata(RenderResult *render_result) | |||||
| { | |||||
| cryptomatte.store_metadata(render_result); | |||||
| } | |||||
| void Instance::update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) | |||||
| { | |||||
| RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); | |||||
| #define CHECK_PASS_LEGACY(name, type, channels, chanid) \ | |||||
| if (view_layer->passflag & (SCE_PASS_##name)) { \ | |||||
| RE_engine_register_pass( \ | |||||
| engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ | |||||
| } \ | |||||
| ((void)0) | |||||
| #define CHECK_PASS_EEVEE(name, type, channels, chanid) \ | |||||
| if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \ | |||||
| RE_engine_register_pass( \ | |||||
| engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ | |||||
| } \ | |||||
| ((void)0) | |||||
| CHECK_PASS_LEGACY(Z, SOCK_FLOAT, 1, "Z"); | |||||
| CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z"); | |||||
| CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ"); | |||||
| CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB"); | |||||
| CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB"); | |||||
| /* TODO: CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB"); | |||||
| * CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB"); | |||||
| * When available they should be converted from Value textures to RGB. */ | |||||
| LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { | |||||
| if ((aov->flag & AOV_CONFLICT) != 0) { | |||||
| continue; | |||||
| } | |||||
| switch (aov->type) { | |||||
| case AOV_TYPE_COLOR: | |||||
| RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA); | |||||
| break; | |||||
| case AOV_TYPE_VALUE: | |||||
| RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT); | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* NOTE: Name channels lowercase rgba so that compression rules check in OpenEXR DWA code uses | |||||
| * loseless compression. Reportedly this naming is the only one which works good from the | |||||
| * interoperability point of view. Using xyzw naming is not portable. */ | |||||
| auto register_cryptomatte_passes = [&](eViewLayerCryptomatteFlags cryptomatte_layer, | |||||
| eViewLayerEEVEEPassType eevee_pass) { | |||||
| if (view_layer->cryptomatte_flag & cryptomatte_layer) { | |||||
| for (std::string pass_name : Film::pass_to_render_pass_names(eevee_pass, view_layer)) { | |||||
| RE_engine_register_pass( | |||||
| engine, scene, view_layer, pass_name.c_str(), 4, "rgba", SOCK_RGBA); | |||||
| } | |||||
| } | |||||
| }; | |||||
| register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_OBJECT, EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT); | |||||
| register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_ASSET, EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET); | |||||
| register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_MATERIAL, | |||||
| EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL); | |||||
| } | |||||
| /** \} */ | /** \} */ | ||||
| } // namespace blender::eevee | } // namespace blender::eevee | ||||