Fix #139443: WM: Clear draw region framebuffers to avoid corruption

This PR adds a clear on creation for draw region framebuffers, which
fixes issue https://projects.blender.org/blender/blender/issues/139443.
When using the "Lock Interface" option, redrawing is disabled until the
rendering process has finished. When the GPU driver does not initialize
framebuffer textures with zero, this means that visual corruption can
be perceived when resizing the main window while rendering.
This fix makes sure that framebuffer textures are initialized with zero
on all GPU platforms.

Pull Request: https://projects.blender.org/blender/blender/pulls/139445
This commit is contained in:
Christoph Neuhauser
2025-05-28 13:17:37 +02:00
committed by Nikita Sirgienko
parent eb96c2dfb3
commit 282d703f6b
11 changed files with 42 additions and 7 deletions

View File

@@ -82,7 +82,7 @@ GPUOffScreen *image_render_begin(const int2 &win_size)
char err_out[256] = "unknown";
GPUOffScreen *offscreen = GPU_offscreen_create(
win_size.x, win_size.y, true, GPU_RGBA8, GPU_TEXTURE_USAGE_HOST_READ, err_out);
win_size.x, win_size.y, true, GPU_RGBA8, GPU_TEXTURE_USAGE_HOST_READ, false, err_out);
if (offscreen == nullptr) {
return nullptr;
}

View File

@@ -768,6 +768,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
true,
GPU_RGBA16F,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
false,
err_out);
DRW_gpu_context_disable();

View File

@@ -2029,6 +2029,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
true,
desired_format,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
false,
err_out);
if (ofs == nullptr) {
DRW_gpu_context_disable();

View File

@@ -640,6 +640,7 @@ struct GPUOffScreen;
* Create a #GPUOffScreen with attachment size of \a width by \a height pixels.
* If \a with_depth_buffer is true, a depth buffer attachment will also be created.
* \a format is the format of the color buffer.
* If \a clear is true, the color and depth buffer attachments will be cleared.
* If \a err_out is not `nullptr` it will be use to write any configuration error message..
* \note This function binds the framebuffer to the active context.
* \note `GPU_TEXTURE_USAGE_ATTACHMENT` is added to the usage parameter by default.
@@ -649,6 +650,7 @@ GPUOffScreen *GPU_offscreen_create(int width,
bool with_depth_buffer,
eGPUTextureFormat format,
eGPUTextureUsage usage,
bool clear,
char err_out[256]);
/**

View File

@@ -730,6 +730,7 @@ GPUOffScreen *GPU_offscreen_create(int width,
bool with_depth_buffer,
eGPUTextureFormat format,
eGPUTextureUsage usage,
bool clear,
char err_out[256])
{
GPUOffScreen *ofs = MEM_callocN<GPUOffScreen>(__func__);
@@ -770,6 +771,19 @@ GPUOffScreen *GPU_offscreen_create(int width,
GPU_offscreen_free(ofs);
return nullptr;
}
if (clear) {
float const clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 0.0f;
GPU_framebuffer_bind(fb);
if (with_depth_buffer) {
GPU_framebuffer_clear_color_depth(fb, clear_color, clear_depth);
}
else {
GPU_framebuffer_clear_color(fb, clear_color);
}
}
GPU_framebuffer_restore();
return ofs;
}

View File

@@ -24,6 +24,7 @@ static void test_immediate_one_plane()
GPU_RGBA16F,
GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_HOST_READ,
false,
nullptr);
BLI_assert(offscreen != nullptr);
GPU_offscreen_bind(offscreen, false);
@@ -72,6 +73,7 @@ static void test_immediate_two_planes()
GPU_RGBA16F,
GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_HOST_READ,
false,
nullptr);
BLI_assert(offscreen != nullptr);
GPU_offscreen_bind(offscreen, false);

View File

@@ -27,6 +27,7 @@ void blend_test(float4 source_a, float4 source_b, float4 expected_result)
GPU_RGBA16F,
GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_HOST_READ,
false,
nullptr);
BLI_assert(offscreen != nullptr);
GPU_offscreen_bind(offscreen, false);

View File

@@ -25,7 +25,8 @@ template<GPUVertCompType comp_type, GPUVertFetchMode fetch_mode, typename ColorT
static void vertex_buffer_fetch_mode(ColorType color)
{
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUOffScreen *offscreen = GPU_offscreen_create(Size, Size, false, GPU_RGBA32F, usage, nullptr);
GPUOffScreen *offscreen = GPU_offscreen_create(
Size, Size, false, GPU_RGBA32F, usage, false, nullptr);
BLI_assert(offscreen != nullptr);
GPU_offscreen_bind(offscreen, false);
GPUTexture *color_texture = GPU_offscreen_color_texture(offscreen);

View File

@@ -310,6 +310,7 @@ static PyObject *pygpu_offscreen__tp_new(PyTypeObject * /*self*/, PyObject *args
true,
eGPUTextureFormat(pygpu_textureformat.value_found),
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_HOST_READ,
false,
err_out);
}
else {

View File

@@ -722,6 +722,7 @@ static void wm_draw_region_buffer_create(Scene *scene,
false,
desired_format,
GPU_TEXTURE_USAGE_SHADER_READ,
true,
nullptr);
if (!offscreen) {
WM_global_report(RPT_ERROR, "Region could not be drawn!");
@@ -1215,8 +1216,13 @@ static void wm_draw_window(bContext *C, wmWindow *win)
* an off-screen texture and then draw it. This used to happen for all
* stereo methods, but it's less efficient than drawing directly. */
const blender::int2 win_size = WM_window_native_pixel_size(win);
GPUOffScreen *offscreen = GPU_offscreen_create(
win_size[0], win_size[1], false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, nullptr);
GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
win_size[1],
false,
desired_format,
GPU_TEXTURE_USAGE_SHADER_READ,
false,
nullptr);
if (offscreen) {
GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
@@ -1371,8 +1377,13 @@ uint8_t *WM_window_pixels_read_from_offscreen(bContext *C, wmWindow *win, int r_
/* Determine desired offscreen format depending on HDR availability. */
eGPUTextureFormat desired_format = get_hdr_framebuffer_format(WM_window_get_active_scene(win));
GPUOffScreen *offscreen = GPU_offscreen_create(
win_size[0], win_size[1], false, desired_format, GPU_TEXTURE_USAGE_SHADER_READ, nullptr);
GPUOffScreen *offscreen = GPU_offscreen_create(win_size[0],
win_size[1],
false,
desired_format,
GPU_TEXTURE_USAGE_SHADER_READ,
false,
nullptr);
if (UNLIKELY(!offscreen)) {
return nullptr;
}
@@ -1406,7 +1417,7 @@ bool WM_window_pixels_read_sample_from_offscreen(bContext *C,
}
GPUOffScreen *offscreen = GPU_offscreen_create(
win_size[0], win_size[1], false, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, nullptr);
win_size[0], win_size[1], false, GPU_RGBA8, GPU_TEXTURE_USAGE_SHADER_READ, false, nullptr);
if (UNLIKELY(!offscreen)) {
return false;
}

View File

@@ -1414,6 +1414,7 @@ bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
format,
GPU_TEXTURE_USAGE_SHADER_READ |
GPU_TEXTURE_USAGE_MEMORY_EXPORT,
false,
err_out);
if (offscreen) {
viewport = vp->viewport = GPU_viewport_create();