[Bf-blender-cvs] [2526a355bca] master: Fix bad image drawing during rendering on certain GPUs

Sergey Sharybin noreply at git.blender.org
Wed Sep 22 14:29:21 CEST 2021


Commit: 2526a355bcae7292d6945903def69f982f88990d
Author: Sergey Sharybin
Date:   Wed Sep 22 10:59:49 2021 +0200
Branches: master
https://developer.blender.org/rB2526a355bcae7292d6945903def69f982f88990d

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

===================================================================

M	intern/cycles/blender/blender_gpu_display.cpp
M	intern/cycles/blender/blender_gpu_display.h
M	intern/cycles/blender/blender_session.cpp
M	intern/cycles/blender/blender_session.h

===================================================================

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 &params)
 {
   /* See do_update_begin() for why no locking is required here. */
@@ -508,6 +513,27 @@ void BlenderGPUDisplay::do_draw(const GPUDisplayParams &params)
   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 &params,
                                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_;
 };



More information about the Bf-blender-cvs mailing list