diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-09-20 18:59:20 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-09-21 15:55:54 +0300 |
commit | 08031197250aeecbaca3803254e6f25b8c7b7b37 (patch) | |
tree | 6fe7ab045f0dc0a423d6557c4073f34309ef4740 /source/blender/draw/engines/external/external_engine.c | |
parent | fa6b1007bad065440950cd67deb16a04f368856f (diff) |
Cycles: merge of cycles-x branch, a major update to the renderer
This includes much improved GPU rendering performance, viewport interactivity,
new shadow catcher, revamped sampling settings, subsurface scattering anisotropy,
new GPU volume sampling, improved PMJ sampling pattern, and more.
Some features have also been removed or changed, breaking backwards compatibility.
Including the removal of the OpenCL backend, for which alternatives are under
development.
Release notes and code docs:
https://wiki.blender.org/wiki/Reference/Release_Notes/3.0/Cycles
https://wiki.blender.org/wiki/Source/Render/Cycles
Credits:
* Sergey Sharybin
* Brecht Van Lommel
* Patrick Mours (OptiX backend)
* Christophe Hery (subsurface scattering anisotropy)
* William Leeson (PMJ sampling pattern)
* Alaska (various fixes and tweaks)
* Thomas Dinges (various fixes)
For the full commit history, see the cycles-x branch. This squashes together
all the changes since intermediate changes would often fail building or tests.
Ref T87839, T87837, T87836
Fixes T90734, T89353, T80267, T80267, T77185, T69800
Diffstat (limited to 'source/blender/draw/engines/external/external_engine.c')
-rw-r--r-- | source/blender/draw/engines/external/external_engine.c | 202 |
1 files changed, 193 insertions, 9 deletions
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 89ee3f1b293..cc548a53a8e 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -32,13 +32,19 @@ #include "BKE_object.h" #include "BKE_particle.h" +#include "ED_image.h" #include "ED_screen.h" +#include "GPU_batch.h" +#include "GPU_debug.h" #include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_state.h" #include "GPU_viewport.h" +#include "RE_engine.h" +#include "RE_pipeline.h" + #include "external_engine.h" /* own include */ /* Shaders */ @@ -137,6 +143,22 @@ static void external_engine_init(void *vedata) } } +/* Add shading group call which will take care of writing to the depth buffer, so that the + * alpha-under overlay will happen for the render buffer. */ +static void external_cache_image_add(DRWShadingGroup *grp) +{ + float obmat[4][4]; + unit_m4(obmat); + scale_m4_fl(obmat, 0.5f); + + /* NOTE: Use the same Z-depth value as in the regular image drawing engine. */ + translate_m4(obmat, 1.0f, 1.0f, 0.75f); + + GPUBatch *geom = DRW_cache_quad_get(); + + DRW_shgroup_call_obmat(grp, geom, obmat); +} + static void external_cache_init(void *vedata) { EXTERNAL_PassList *psl = ((EXTERNAL_Data *)vedata)->psl; @@ -162,14 +184,33 @@ static void external_cache_init(void *vedata) stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass); } - /* Do not draw depth pass when overlays are turned off. */ - stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + if (v3d != NULL) { + /* Do not draw depth pass when overlays are turned off. */ + stl->g_data->need_depth = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0; + } + else if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_cache_image_add(stl->g_data->depth_shgrp); + + stl->g_data->need_depth = true; + stl->g_data->update_depth = true; + } + } } static void external_cache_populate(void *vedata, Object *ob) { + const DRWContextState *draw_ctx = DRW_context_state_get(); EXTERNAL_StorageList *stl = ((EXTERNAL_Data *)vedata)->stl; + if (draw_ctx->space_data != NULL) { + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + return; + } + } + if (!(DRW_object_is_renderable(ob) && DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { return; @@ -210,13 +251,11 @@ static void external_cache_finish(void *UNUSED(vedata)) { } -static void external_draw_scene_do(void *vedata) +static void external_draw_scene_do_v3d(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; RegionView3D *rv3d = draw_ctx->rv3d; ARegion *region = draw_ctx->region; - const RenderEngineType *type; DRW_state_reset_ex(DRW_STATE_DEFAULT & ~DRW_STATE_DEPTH_LESS_EQUAL); @@ -229,8 +268,6 @@ static void external_draw_scene_do(void *vedata) } RenderEngine *engine = RE_engine_create(engine_type); - engine->tile_x = scene->r.tilex; - engine->tile_y = scene->r.tiley; engine_type->view_update(engine, draw_ctx->evil_C, draw_ctx->depsgraph); rv3d->render_engine = engine; } @@ -241,7 +278,7 @@ static void external_draw_scene_do(void *vedata) ED_region_pixelspace(region); /* Render result draw. */ - type = rv3d->render_engine->type; + const RenderEngineType *type = rv3d->render_engine->type; type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph); GPU_bgl_end(); @@ -259,6 +296,116 @@ static void external_draw_scene_do(void *vedata) } } +/* Configure current matrix stack so that the external engine can use the same drawing code for + * both viewport and image editor drawing. + * + * The engine draws result in the pixel space, and is applying render offset. For image editor we + * need to switch from normalized space to pixel space, and "un-apply" offset. */ +static void external_image_space_matrix_set(const RenderEngine *engine) +{ + BLI_assert(engine != NULL); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + const DRWView *view = DRW_view_get_active(); + struct SpaceImage *space_image = (struct SpaceImage *)draw_ctx->space_data; + + /* Apply current view as transformation matrix. + * This will configure drawing for normalized space with current zoom and pan applied. */ + + float view_matrix[4][4]; + DRW_view_viewmat_get(view, view_matrix, false); + + float projection_matrix[4][4]; + DRW_view_winmat_get(view, projection_matrix, false); + + GPU_matrix_projection_set(projection_matrix); + GPU_matrix_set(view_matrix); + + /* Switch from normalized space to pixel space. */ + { + int width, height; + ED_space_image_get_size(space_image, &width, &height); + + const float width_inv = width ? 1.0f / width : 0.0f; + const float height_inv = height ? 1.0f / height : 0.0f; + GPU_matrix_scale_2f(width_inv, height_inv); + } + + /* Un-apply render offset. */ + { + Render *render = engine->re; + rctf view_rect; + rcti render_rect; + RE_GetViewPlane(render, &view_rect, &render_rect); + + GPU_matrix_translate_2f(-render_rect.xmin, -render_rect.ymin); + } +} + +static void external_draw_scene_do_image(void *UNUSED(vedata)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + Render *re = RE_GetSceneRender(scene); + RenderEngine *engine = RE_engine_get(re); + + /* Is tested before enabling the drawing engine. */ + BLI_assert(re != NULL); + BLI_assert(engine != NULL); + + const DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + /* Clear the depth buffer to the value used by the background overlay so that the overlay is not + * happening outside of the drawn image. + * + * NOTE: The external engine only draws color. The depth is taken care of using the depth pass + * which initialized the depth to the values expected by the background overlay. */ + GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f); + + GPU_matrix_push_projection(); + GPU_matrix_push(); + + external_image_space_matrix_set(engine); + + GPU_debug_group_begin("External Engine"); + + const RenderEngineType *engine_type = engine->type; + BLI_assert(engine_type != NULL); + BLI_assert(engine_type->draw != NULL); + + engine_type->draw(engine, draw_ctx->evil_C, draw_ctx->depsgraph); + + GPU_debug_group_end(); + + GPU_matrix_pop(); + GPU_matrix_pop_projection(); + + DRW_state_reset(); + GPU_bgl_end(); + + RE_engine_draw_release(re); +} + +static void external_draw_scene_do(void *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + + if (draw_ctx->v3d != NULL) { + external_draw_scene_do_v3d(vedata); + return; + } + + if (draw_ctx->space_data == NULL) { + return; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type == SPACE_IMAGE) { + external_draw_scene_do_image(vedata); + return; + } +} + static void external_draw_scene(void *vedata) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -297,7 +444,7 @@ static void external_engine_free(void) static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data); -static DrawEngineType draw_engine_external_type = { +DrawEngineType draw_engine_external_type = { NULL, NULL, N_("External"), @@ -330,8 +477,45 @@ RenderEngineType DRW_engine_viewport_external_type = { NULL, NULL, NULL, + NULL, + NULL, &draw_engine_external_type, {NULL, NULL, NULL}, }; +bool DRW_engine_external_acquire_for_image_editor(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const SpaceLink *space_data = draw_ctx->space_data; + Scene *scene = draw_ctx->scene; + + if (space_data == NULL) { + return false; + } + + const eSpace_Type space_type = draw_ctx->space_data->spacetype; + if (space_type != SPACE_IMAGE) { + return false; + } + + struct SpaceImage *space_image = (struct SpaceImage *)space_data; + const Image *image = ED_space_image(space_image); + if (image == NULL || image->type != IMA_TYPE_R_RESULT) { + return false; + } + + if (image->render_slot != image->last_render_slot) { + return false; + } + + /* Render is allocated on main thread, so it is safe to access it from here. */ + Render *re = RE_GetSceneRender(scene); + + if (re == NULL) { + return false; + } + + return RE_engine_draw_acquire(re); +} + #undef EXTERNAL_ENGINE |