GPUOffscreen.draw_view3d() is 25 to 50 times slower #89204
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
7 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#89204
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
System Information
Operating system: macOS Bis Sur 11.2.1
Graphics card: Intel Iris Plus Graphics 1536 MB
Blender Version
Broken: since 2.80
Worked: 2.79b
Short description of error
I am currently working on an add-on which enables a live view of the viewport in a volumetric lightfield display. The display requires to render a scene from 32 to 100 different views from different angles. I use the
gpu.types.GPUOffscreen
class and it's internal methoddraw_view3d()
to obtain the different views by manually calculating the view and projection matrices as required.@GottfriedHofmann put my attention to the fact that this function used to be a lot faster in Blender 2.79b. Since Blender 2.80 it is 25 to 50 times slower. At the current speed of
draw_view3d()
, realizing a rendering of the required amount of views is not possible in a meaningful time. Since it was much faster in 2.79b, I hope it is possible to revert to this.Exact steps for others to reproduce the error
Here is a sample code:
Please do the following:
It will then create 88 offscreen. Each of these of offscreens will call its
draw_view3D()
method to draw the viewport into its offscreen texture every time something in the scene changes. It will print how long this procedure takes to the console. On my computer the results are as follwing:Added subscribers: @GottfriedHofmann, @regcs
Added subscriber: @JulianEisel
I'm pretty sure this is caused by the BPY offscreen functionality using final render quality. Eevee is designed to favor speed over quality for the viewport, and quality over speed in proper renders. The offscreen pipeline works with the latter and doesn't provide an option.
Exposing this as an option would be trivial to add. I did it to some internal offscreen functions already for VR. Don't think the BPY side of it would be difficult either.
(I think this is an important and simple thing to address finally, but technically this is not a bug but a missing API feature - at least if my analysis is right.)
This issue was referenced by
d03b26edbd
Added subscriber: @brecht
It's not about final render quality. The issue is that the framebuffers and associated textures are being reallocated each time, instead of being cached. I've committed a fix that speeds things up here.
The remainder of the cost seems to be in actual Eevee or Workbench rendering. That may be slower or faster depending on the scene, it's completely different and depends on the scene contents and settings, so hard to compare. In general there will be more overhead for simpler scenes in 2.80, but it can also be faster with more objects. Any optimizations there are outside the scope of the bug tracker.
Changed status from 'Needs Triage' to: 'Resolved'
Many thanks for taking action so quickly, @brecht. I just built the new version and getting something between 120 to 300 ms now. Definitely better than before, but still one order of magnitude slower than in 2.79b.
Could you shortly explain, what has been so fundamentally different in 2.79b that offscreen rendering was so amazingly fast there? And is there any chance to get back to these levels or is that out of the scope with the current Workbench render engine (not talking about EEVEE here, I just tested the Workbench rendering)?
Edit: Unfortunately, the fix introduced a new bug :
This issue was referenced by
c73be23e17
Changed status from 'Resolved' to: 'Needs Triage'
Reopened since the commit had a bug.
Started to look a bit into the timings of the calls that are involved in the offscreen drawing (with the reverted Blender version rbc73be). Don't know if it helps, but got the following insights so far:
Python level:
GPUOffscreen.draw_view3d()
Blender internal:
GPUOffscreen.draw_view3d()
is spent inDRW_draw_render_loop_offscreen()
DRW_draw_render_loop_ex()
; these 2 ms are spent as following:drw_engines_draw_scene()
; these 1.1 ms are spent as following:Preliminary conclusion:
So, the biggest potential for improving the offscreen rendering speed is in:
engine->idname
gave as output in thedrw_engines_draw_scene
loop)Any idea what takes so long with the latter?
Edit: Timings are given for drawing 88 views from different angles one after another. Drawing the first view usually takes significantly longer (10 to 20 ms) than drawing the following views.
Are you talking about an argument for ED_view3d_draw_offscreen , maybe even 'bool is_image_render' ? I tried setting that to false but it helped only little to not at all :-(
Changed status from 'Needs Triage' to: 'Confirmed'
Ok, I think I found the reason why d03b26 did introduced a redrawing problem for the offscreen.
.../engines/workbench/workbench_engine.c
:In
workbench_draw_scene()
the "wpd->taa_sample" is not reset after the first drawing. The most-likely cause is that inworkbench_antialiasing_engine_init()
the property is only reset if certain conditions are met. One of the conditions is, the "is_navigating", which is probably true when the camera is moving(?), which would explain why the issue did not occur when the camera was moved.I guess something similar is true for EEVEE somewhere in the engine, which would explain why there was a ghosting effect introduced in the offscreen when moving the object.
How to fix this?
I see several options, but don't know what would be the best:
1.) setting the
wpd->is_navigating
totrue
if an object is moved.2.) introduce another state variable in "wpd" which is set if offscreen rendering is active and handle the resetting in the corresponding functions.
Probably there are even better solutions since I don't have the overview that would be required to judge.
So I think, I am now at a point where I can't do anything without further input from you, @brecht, or anybody else with deeper insights.
Resetting the property all the time in workbench_antialiasing_engine_init() does not make a change, it seems like that function is not called for every frame.
Maybe RV3D_NAVIGATING is the key here?
@regcs had the idea to enforce RV3D_NAVIGATING for all offscreen rendering by adding
rv3d->rflag |= RV3D_NAVIGATING;
to .../editors/space_view3d/view3d_draw.c right after line 1647.
That way RV3D_NAVIGATING is always set for offscreen rendering which fixes the problem for the workbench engine but not for EEVEE. When using the latter engine, the grid does not update at all anymore, no matter how I navigate the viewport. Neither by rotating, nor by panning, dollying or using the walk- and fly navigations.
I have created a new revision of https://developer.blender.org/rBd03b26edbdc3a9fe87fde44bd8db8c4a67a36757 that is rebased to 3.1 trunk:
https://developer.blender.org/D13104
Before the rebase, commenting out viewport->depth_tx = depth; in https://developer.blender.org/diffusion/B/browse/master/source/blender/gpu/intern/gpu_viewport.c$210 would result in the drawing of one frame without visual artifacts and a subsequent crash. After the rebase, the crash does not happen anymore but the result seems to have the artifacts as well.
One important observation: The issue does not arise when the offscreen is fed with a different view- and/or projection matrix each time.
Here is a demo file that slightly modifies the view matrix each time before offscreen rendering is called, it seems to "fix" all of the aforementioned problems:
testfile_offscreen_viewscramble.blend
A short explanation for my proposed fix:
The issue was that the views of a GPUViewport are usually updated by the
ED_render_scene_update()
on depsgraph changes https://developer.blender.org/diffusion/B/browse/master/source/blender/windowmanager/intern/wm_init_exit.c$260. However, this function only handles GPUViewports which are bound to a SpaceView3D. Since this is not the case for the GPUViewport created for the offscreen rendering in Brecht's patch, we need to make sure that the views are updated before drawing into the offscreen.D13235 re-introduces Brecht's patch and adds a function which takes care of the view updates.
This issue was referenced by
bba6fe83e2
Changed status from 'Confirmed' to: 'Resolved'