diff options
author | Brecht Van Lommel <brecht@blender.org> | 2021-09-14 16:37:47 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-09-30 21:48:08 +0300 |
commit | a754e35198d852ea34e2b82cd2b126538e6f5a3b (patch) | |
tree | 9118b3fa19ab70aa1b50440ce62e5d028d940cfd /intern/cycles/blender | |
parent | ac582056e2e70f3b0d91ff69d0307dd357e2e2ed (diff) |
Cycles: refactor API for GPU display
* Split GPUDisplay into two classes. PathTraceDisplay to implement the Cycles side,
and DisplayDriver to implement the host application side. The DisplayDriver is now
a fully abstract base class, embedded in the PathTraceDisplay.
* Move copy_pixels_to_texture implementation out of the host side into the Cycles side,
since it can be implemented in terms of the texture buffer mapping.
* Move definition of DeviceGraphicsInteropDestination into display driver header, so
that we do not need to expose private device headers in the public API.
* Add more detailed comments about how the DisplayDriver should be implemented.
The "driver" terminology might not be obvious, but is also used in other renderers.
Differential Revision: https://developer.blender.org/D12626
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 4 | ||||
-rw-r--r-- | intern/cycles/blender/blender_display_driver.cpp (renamed from intern/cycles/blender/blender_gpu_display.cpp) | 107 | ||||
-rw-r--r-- | intern/cycles/blender/blender_display_driver.h (renamed from intern/cycles/blender/blender_gpu_display.h) | 37 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 15 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 6 |
5 files changed, 64 insertions, 105 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 64d226cb9ec..2660eee017b 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -31,9 +31,9 @@ set(INC_SYS set(SRC blender_camera.cpp blender_device.cpp + blender_display_driver.cpp blender_image.cpp blender_geometry.cpp - blender_gpu_display.cpp blender_light.cpp blender_mesh.cpp blender_object.cpp @@ -51,7 +51,7 @@ set(SRC CCL_api.h blender_device.h - blender_gpu_display.h + blender_display_driver.h blender_id_map.h blender_image.h blender_object_cull.h diff --git a/intern/cycles/blender/blender_gpu_display.cpp b/intern/cycles/blender/blender_display_driver.cpp index 5a4567deac3..5267f41eef7 100644 --- a/intern/cycles/blender/blender_gpu_display.cpp +++ b/intern/cycles/blender/blender_display_driver.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "blender/blender_gpu_display.h" +#include "blender/blender_display_driver.h" #include "device/device.h" #include "util/util_logging.h" @@ -273,17 +273,17 @@ uint BlenderDisplaySpaceShader::get_shader_program() } /* -------------------------------------------------------------------- - * BlenderGPUDisplay. + * BlenderDisplayDriver. */ -BlenderGPUDisplay::BlenderGPUDisplay(BL::RenderEngine &b_engine, BL::Scene &b_scene) +BlenderDisplayDriver::BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene) : b_engine_(b_engine), display_shader_(BlenderDisplayShader::create(b_engine, b_scene)) { /* Create context while on the main thread. */ gl_context_create(); } -BlenderGPUDisplay::~BlenderGPUDisplay() +BlenderDisplayDriver::~BlenderDisplayDriver() { gl_resources_destroy(); } @@ -292,19 +292,18 @@ BlenderGPUDisplay::~BlenderGPUDisplay() * Update procedure. */ -bool BlenderGPUDisplay::do_update_begin(const GPUDisplayParams ¶ms, +bool BlenderDisplayDriver::update_begin(const Params ¶ms, int texture_width, int texture_height) { - /* Note that it's the responsibility of BlenderGPUDisplay to ensure updating and drawing + /* Note that it's the responsibility of BlenderDisplayDriver to ensure updating and drawing * the texture does not happen at the same time. This is achieved indirectly. * * When enabling the OpenGL context, it uses an internal mutex lock DST.gl_context_lock. * This same lock is also held when do_draw() is called, which together ensure mutual * exclusion. * - * This locking is not performed at the GPU display level, because that would cause lock - * inversion. */ + * This locking is not performed on the Cycles side, because that would cause lock inversion. */ if (!gl_context_enable()) { return false; } @@ -361,7 +360,7 @@ bool BlenderGPUDisplay::do_update_begin(const GPUDisplayParams ¶ms, return true; } -void BlenderGPUDisplay::do_update_end() +void BlenderDisplayDriver::update_end() { gl_upload_sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); glFlush(); @@ -370,53 +369,17 @@ void BlenderGPUDisplay::do_update_end() } /* -------------------------------------------------------------------- - * Texture update from CPU buffer. - */ - -void BlenderGPUDisplay::do_copy_pixels_to_texture( - const half4 *rgba_pixels, int texture_x, int texture_y, int pixels_width, int pixels_height) -{ - /* This call copies pixels to a Pixel Buffer Object (PBO) which is much cheaper from CPU time - * point of view than to copy data directly to the OpenGL texture. - * - * The possible downside of this approach is that it might require a higher peak memory when - * doing partial updates of the texture (although, in practice even partial updates might peak - * with a full-frame buffer stored on the CPU if the GPU is currently occupied). */ - - half4 *mapped_rgba_pixels = map_texture_buffer(); - if (!mapped_rgba_pixels) { - return; - } - - if (texture_x == 0 && texture_y == 0 && pixels_width == texture_.width && - pixels_height == texture_.height) { - const size_t size_in_bytes = sizeof(half4) * texture_.width * texture_.height; - memcpy(mapped_rgba_pixels, rgba_pixels, size_in_bytes); - } - else { - const half4 *rgba_row = rgba_pixels; - half4 *mapped_rgba_row = mapped_rgba_pixels + texture_y * texture_.width + texture_x; - for (int y = 0; y < pixels_height; - ++y, rgba_row += pixels_width, mapped_rgba_row += texture_.width) { - memcpy(mapped_rgba_row, rgba_row, sizeof(half4) * pixels_width); - } - } - - unmap_texture_buffer(); -} - -/* -------------------------------------------------------------------- * Texture buffer mapping. */ -half4 *BlenderGPUDisplay::do_map_texture_buffer() +half4 *BlenderDisplayDriver::map_texture_buffer() { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture_.gl_pbo_id); half4 *mapped_rgba_pixels = reinterpret_cast<half4 *>( glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY)); if (!mapped_rgba_pixels) { - LOG(ERROR) << "Error mapping BlenderGPUDisplay pixel buffer object."; + LOG(ERROR) << "Error mapping BlenderDisplayDriver pixel buffer object."; } if (texture_.need_clear) { @@ -431,7 +394,7 @@ half4 *BlenderGPUDisplay::do_map_texture_buffer() return mapped_rgba_pixels; } -void BlenderGPUDisplay::do_unmap_texture_buffer() +void BlenderDisplayDriver::unmap_texture_buffer() { glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); @@ -442,9 +405,9 @@ void BlenderGPUDisplay::do_unmap_texture_buffer() * Graphics interoperability. */ -DeviceGraphicsInteropDestination BlenderGPUDisplay::do_graphics_interop_get() +BlenderDisplayDriver::GraphicsInterop BlenderDisplayDriver::graphics_interop_get() { - DeviceGraphicsInteropDestination interop_dst; + GraphicsInterop interop_dst; interop_dst.buffer_width = texture_.buffer_width; interop_dst.buffer_height = texture_.buffer_height; @@ -456,12 +419,12 @@ DeviceGraphicsInteropDestination BlenderGPUDisplay::do_graphics_interop_get() return interop_dst; } -void BlenderGPUDisplay::graphics_interop_activate() +void BlenderDisplayDriver::graphics_interop_activate() { gl_context_enable(); } -void BlenderGPUDisplay::graphics_interop_deactivate() +void BlenderDisplayDriver::graphics_interop_deactivate() { gl_context_disable(); } @@ -470,17 +433,17 @@ void BlenderGPUDisplay::graphics_interop_deactivate() * Drawing. */ -void BlenderGPUDisplay::clear() +void BlenderDisplayDriver::clear() { texture_.need_clear = true; } -void BlenderGPUDisplay::set_zoom(float zoom_x, float zoom_y) +void BlenderDisplayDriver::set_zoom(float zoom_x, float zoom_y) { zoom_ = make_float2(zoom_x, zoom_y); } -void BlenderGPUDisplay::do_draw(const GPUDisplayParams ¶ms) +void BlenderDisplayDriver::draw(const Params ¶ms) { /* See do_update_begin() for why no locking is required here. */ const bool transparent = true; // TODO(sergey): Derive this from Film. @@ -584,7 +547,7 @@ void BlenderGPUDisplay::do_draw(const GPUDisplayParams ¶ms) } } -void BlenderGPUDisplay::gl_context_create() +void BlenderDisplayDriver::gl_context_create() { /* When rendering in viewport there is no render context available via engine. * Check whether own context is to be created here. @@ -613,7 +576,7 @@ void BlenderGPUDisplay::gl_context_create() } } -bool BlenderGPUDisplay::gl_context_enable() +bool BlenderDisplayDriver::gl_context_enable() { if (use_gl_context_) { if (!gl_context_) { @@ -628,7 +591,7 @@ bool BlenderGPUDisplay::gl_context_enable() return true; } -void BlenderGPUDisplay::gl_context_disable() +void BlenderDisplayDriver::gl_context_disable() { if (use_gl_context_) { if (gl_context_) { @@ -641,7 +604,7 @@ void BlenderGPUDisplay::gl_context_disable() RE_engine_render_context_disable(reinterpret_cast<RenderEngine *>(b_engine_.ptr.data)); } -void BlenderGPUDisplay::gl_context_dispose() +void BlenderDisplayDriver::gl_context_dispose() { if (gl_context_) { const bool drw_state = DRW_opengl_context_release(); @@ -653,7 +616,7 @@ void BlenderGPUDisplay::gl_context_dispose() } } -bool BlenderGPUDisplay::gl_draw_resources_ensure() +bool BlenderDisplayDriver::gl_draw_resources_ensure() { if (!texture_.gl_id) { /* If there is no texture allocated, there is nothing to draw. Inform the draw call that it can @@ -680,7 +643,7 @@ bool BlenderGPUDisplay::gl_draw_resources_ensure() return true; } -void BlenderGPUDisplay::gl_resources_destroy() +void BlenderDisplayDriver::gl_resources_destroy() { gl_context_enable(); @@ -703,7 +666,7 @@ void BlenderGPUDisplay::gl_resources_destroy() gl_context_dispose(); } -bool BlenderGPUDisplay::gl_texture_resources_ensure() +bool BlenderDisplayDriver::gl_texture_resources_ensure() { if (texture_.creation_attempted) { return texture_.is_created; @@ -740,7 +703,7 @@ bool BlenderGPUDisplay::gl_texture_resources_ensure() return true; } -void BlenderGPUDisplay::texture_update_if_needed() +void BlenderDisplayDriver::texture_update_if_needed() { if (!texture_.need_update) { return; @@ -754,7 +717,7 @@ void BlenderGPUDisplay::texture_update_if_needed() texture_.need_update = false; } -void BlenderGPUDisplay::vertex_buffer_update(const GPUDisplayParams ¶ms) +void BlenderDisplayDriver::vertex_buffer_update(const Params ¶ms) { /* Invalidate old contents - avoids stalling if the buffer is still waiting in queue to be * rendered. */ @@ -767,23 +730,23 @@ void BlenderGPUDisplay::vertex_buffer_update(const GPUDisplayParams ¶ms) vpointer[0] = 0.0f; vpointer[1] = 0.0f; - vpointer[2] = params.offset.x; - vpointer[3] = params.offset.y; + vpointer[2] = params.full_offset.x; + vpointer[3] = params.full_offset.y; vpointer[4] = 1.0f; vpointer[5] = 0.0f; - vpointer[6] = (float)params.size.x + params.offset.x; - vpointer[7] = params.offset.y; + vpointer[6] = (float)params.size.x + params.full_offset.x; + vpointer[7] = params.full_offset.y; vpointer[8] = 1.0f; vpointer[9] = 1.0f; - vpointer[10] = (float)params.size.x + params.offset.x; - vpointer[11] = (float)params.size.y + params.offset.y; + vpointer[10] = (float)params.size.x + params.full_offset.x; + vpointer[11] = (float)params.size.y + params.full_offset.y; vpointer[12] = 0.0f; vpointer[13] = 1.0f; - vpointer[14] = params.offset.x; - vpointer[15] = (float)params.size.y + params.offset.y; + vpointer[14] = params.full_offset.x; + vpointer[15] = (float)params.size.y + params.full_offset.y; glUnmapBuffer(GL_ARRAY_BUFFER); } diff --git a/intern/cycles/blender/blender_gpu_display.h b/intern/cycles/blender/blender_display_driver.h index 89420567037..558997c6b4f 100644 --- a/intern/cycles/blender/blender_gpu_display.h +++ b/intern/cycles/blender/blender_display_driver.h @@ -22,12 +22,14 @@ #include "RNA_blender_cpp.h" -#include "render/gpu_display.h" +#include "render/display_driver.h" + +#include "util/util_thread.h" #include "util/util_unique_ptr.h" CCL_NAMESPACE_BEGIN -/* Base class of shader used for GPU display rendering. */ +/* Base class of shader used for display driver rendering. */ class BlenderDisplayShader { public: static constexpr const char *position_attribute_name = "pos"; @@ -96,11 +98,11 @@ class BlenderDisplaySpaceShader : public BlenderDisplayShader { uint shader_program_ = 0; }; -/* GPU display implementation which is specific for Blender viewport integration. */ -class BlenderGPUDisplay : public GPUDisplay { +/* Display driver implementation which is specific for Blender viewport integration. */ +class BlenderDisplayDriver : public DisplayDriver { public: - BlenderGPUDisplay(BL::RenderEngine &b_engine, BL::Scene &b_scene); - ~BlenderGPUDisplay(); + BlenderDisplayDriver(BL::RenderEngine &b_engine, BL::Scene &b_scene); + ~BlenderDisplayDriver(); virtual void graphics_interop_activate() override; virtual void graphics_interop_deactivate() override; @@ -110,22 +112,15 @@ class BlenderGPUDisplay : public GPUDisplay { void set_zoom(float zoom_x, float zoom_y); protected: - virtual bool do_update_begin(const GPUDisplayParams ¶ms, - int texture_width, - int texture_height) override; - virtual void do_update_end() override; + virtual bool update_begin(const Params ¶ms, int texture_width, int texture_height) override; + virtual void update_end() override; - virtual void do_copy_pixels_to_texture(const half4 *rgba_pixels, - int texture_x, - int texture_y, - int pixels_width, - int pixels_height) override; - virtual void do_draw(const GPUDisplayParams ¶ms) override; + virtual half4 *map_texture_buffer() override; + virtual void unmap_texture_buffer() override; - virtual half4 *do_map_texture_buffer() override; - virtual void do_unmap_texture_buffer() override; + virtual GraphicsInterop graphics_interop_get() override; - virtual DeviceGraphicsInteropDestination do_graphics_interop_get() override; + virtual void draw(const Params ¶ms) override; /* Helper function which allocates new GPU context. */ void gl_context_create(); @@ -152,13 +147,13 @@ class BlenderGPUDisplay : public GPUDisplay { * This buffer is used to render texture in the viewport. * * NOTE: The buffer needs to be bound. */ - void vertex_buffer_update(const GPUDisplayParams ¶ms); + void vertex_buffer_update(const Params ¶ms); BL::RenderEngine b_engine_; /* OpenGL context which is used the render engine doesn't have its own. */ void *gl_context_ = nullptr; - /* The when Blender RenderEngine side context is not available and the GPUDisplay is to create + /* The when Blender RenderEngine side context is not available and the DisplayDriver is to create * its own context. */ bool use_gl_context_ = false; /* Mutex used to guard the `gl_context_`. */ diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 88edc7eafe7..1a42456eda0 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -42,7 +42,7 @@ #include "util/util_progress.h" #include "util/util_time.h" -#include "blender/blender_gpu_display.h" +#include "blender/blender_display_driver.h" #include "blender/blender_session.h" #include "blender/blender_sync.h" #include "blender/blender_util.h" @@ -159,9 +159,10 @@ void BlenderSession::create_session() /* Create GPU display. */ if (!b_engine.is_preview() && !headless) { - unique_ptr<BlenderGPUDisplay> gpu_display = make_unique<BlenderGPUDisplay>(b_engine, b_scene); - gpu_display_ = gpu_display.get(); - session->set_gpu_display(move(gpu_display)); + unique_ptr<BlenderDisplayDriver> display_driver = make_unique<BlenderDisplayDriver>(b_engine, + b_scene); + display_driver_ = display_driver.get(); + session->set_display_driver(move(display_driver)); } /* Viewport and preview (as in, material preview) does not do tiled rendering, so can inform @@ -446,7 +447,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) /* Use final write for preview renders, otherwise render result wouldn't be be updated on Blender * side. */ - /* TODO(sergey): Investigate whether GPUDisplay can be used for the preview as well. */ + /* TODO(sergey): Investigate whether DisplayDriver can be used for the preview as well. */ if (b_engine.is_preview()) { session->update_render_tile_cb = [&]() { write_render_tile(); }; } @@ -708,7 +709,7 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, session->read_render_tile_cb = [&]() { read_render_tile(); }; session->write_render_tile_cb = [&]() { write_render_tile(); }; - session->set_gpu_display(nullptr); + session->set_display_driver(nullptr); if (!session->progress.get_cancel()) { /* Sync scene. */ @@ -895,7 +896,7 @@ void BlenderSession::draw(BL::SpaceImageEditor &space_image) } BL::Array<float, 2> zoom = space_image.zoom(); - gpu_display_->set_zoom(zoom[0], zoom[1]); + display_driver_->set_zoom(zoom[0], zoom[1]); session->draw(); } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 58683ee07a1..1ca8fdf87d0 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN -class BlenderGPUDisplay; +class BlenderDisplayDriver; class BlenderSync; class ImageMetaData; class Scene; @@ -164,8 +164,8 @@ class BlenderSession { int last_pass_index = -1; } draw_state_; - /* NOTE: The BlenderSession references the GPU display. */ - BlenderGPUDisplay *gpu_display_ = nullptr; + /* NOTE: The BlenderSession references the display driver. */ + BlenderDisplayDriver *display_driver_ = nullptr; vector<string> full_buffer_files_; }; |