diff options
author | Sergey Sharybin <sergey@blender.org> | 2021-09-22 11:59:49 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey@blender.org> | 2021-09-22 15:28:56 +0300 |
commit | 2526a355bcae7292d6945903def69f982f88990d (patch) | |
tree | ab6984d1195d1a3de183669bc084fa3c936b1193 /intern/cycles/blender | |
parent | 7633548d60ccba95005efee41e836f90d0379f79 (diff) |
Fix bad image drawing during rendering on certain GPUs
Reported by Thomas DInges: the default cube render in Cycles has jagged
edges during rendering. Happens on AMD Radeon RX 5500 XT.
Force linear interpolation at zoom level 1 and less.
Reviewed by @fclem
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/blender_gpu_display.cpp | 26 | ||||
-rw-r--r-- | intern/cycles/blender/blender_gpu_display.h | 4 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 4 |
4 files changed, 40 insertions, 1 deletions
diff --git a/intern/cycles/blender/blender_gpu_display.cpp b/intern/cycles/blender/blender_gpu_display.cpp index aa2a9c17a8a..c5c3a2bd155 100644 --- a/intern/cycles/blender/blender_gpu_display.cpp +++ b/intern/cycles/blender/blender_gpu_display.cpp @@ -475,6 +475,11 @@ void BlenderGPUDisplay::clear() texture_.need_clear = true; } +void BlenderGPUDisplay::set_zoom(float zoom_x, float zoom_y) +{ + zoom_ = make_float2(zoom_x, zoom_y); +} + void BlenderGPUDisplay::do_draw(const GPUDisplayParams ¶ms) { /* See do_update_begin() for why no locking is required here. */ @@ -508,6 +513,27 @@ void BlenderGPUDisplay::do_draw(const GPUDisplayParams ¶ms) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture_.gl_id); + /* Trick to keep sharp rendering without jagged edges on all GPUs. + * + * The idea here is to enforce driver to use linear interpolation when the image is not zoomed + * in. + * For the render result with a resolution divider in effect we always use nearest interpolation. + * + * Use explicit MIN assignment to make sure the driver does not have an undefined behavior at + * the zoom level 1. The MAG filter is always NEAREST. */ + const float zoomed_width = params.size.x * zoom_.x; + const float zoomed_height = params.size.y * zoom_.y; + if (texture_.width != params.size.x || texture_.height != params.size.y) { + /* Resolution divider is different from 1, force enarest interpolation. */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else if (zoomed_width - params.size.x > 0.5f || zoomed_height - params.size.y > 0.5f) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); texture_update_if_needed(); diff --git a/intern/cycles/blender/blender_gpu_display.h b/intern/cycles/blender/blender_gpu_display.h index 1014c96cee4..89420567037 100644 --- a/intern/cycles/blender/blender_gpu_display.h +++ b/intern/cycles/blender/blender_gpu_display.h @@ -107,6 +107,8 @@ class BlenderGPUDisplay : public GPUDisplay { virtual void clear() override; + void set_zoom(float zoom_x, float zoom_y); + protected: virtual bool do_update_begin(const GPUDisplayParams ¶ms, int texture_width, @@ -206,6 +208,8 @@ class BlenderGPUDisplay : public GPUDisplay { void *gl_render_sync_ = nullptr; void *gl_upload_sync_ = nullptr; + + float2 zoom_ = make_float2(1.0f, 1.0f); }; CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 5aafa605526..d65d89a7ddd 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -158,7 +158,9 @@ void BlenderSession::create_session() /* Create GPU display. */ if (!b_engine.is_preview() && !headless) { - session->set_gpu_display(make_unique<BlenderGPUDisplay>(b_engine, b_scene)); + unique_ptr<BlenderGPUDisplay> gpu_display = make_unique<BlenderGPUDisplay>(b_engine, b_scene); + gpu_display_ = gpu_display.get(); + session->set_gpu_display(move(gpu_display)); } /* Viewport and preview (as in, material preview) does not do tiled rendering, so can inform @@ -878,6 +880,9 @@ void BlenderSession::draw(BL::SpaceImageEditor &space_image) draw_state_.last_pass_index = pass_index; } + BL::Array<float, 2> zoom = space_image.zoom(); + gpu_display_->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 cf52359ea5d..11e2657a325 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -29,6 +29,7 @@ CCL_NAMESPACE_BEGIN +class BlenderGPUDisplay; class BlenderSync; class ImageMetaData; class Scene; @@ -159,6 +160,9 @@ class BlenderSession { int last_pass_index = -1; } draw_state_; + /* NOTE: The BlenderSession references the GPU display. */ + BlenderGPUDisplay *gpu_display_ = nullptr; + vector<string> full_buffer_files_; }; |