Fix #139901: UI: Incorrect flow when drawing scopes
When drawing image scope the vulkan backend raised some asserts. After checking them the issue was in the calling code, that could lead to undefined behavior on other platforms as well. It isn't allowed to have an immediate mode shader bound, when performing batch drawing. There was also a point batch that didn't use any point shader resulting in undefined behavior as well. For 5.0 we should add this as a GPU module check. Pull Request: https://projects.blender.org/blender/blender/pulls/139926
This commit is contained in:
@@ -602,6 +602,10 @@ void ui_draw_but_HISTOGRAM(ARegion *region,
|
||||
|
||||
static void waveform_draw_one(const float *waveform, int waveform_num, const float col[3])
|
||||
{
|
||||
BLI_assert_msg(
|
||||
!immIsShaderBound(),
|
||||
"It is not allowed to draw a batch when immediate mode has a shader bound. It will "
|
||||
"use the incorrect shader and is hard to discover.");
|
||||
GPUVertFormat format = {0};
|
||||
const uint pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
|
||||
@@ -653,8 +657,8 @@ static void waveform_draw_rgb(const float *waveform,
|
||||
|
||||
blender::gpu::Batch *batch = GPU_batch_create_ex(
|
||||
GPU_PRIM_POINTS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
|
||||
|
||||
GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_SMOOTH_COLOR);
|
||||
GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POINT_FLAT_COLOR);
|
||||
GPU_batch_uniform_1f(batch, "size", 1.0f);
|
||||
GPU_batch_draw(batch);
|
||||
GPU_batch_discard(batch);
|
||||
}
|
||||
@@ -836,7 +840,9 @@ void ui_draw_but_WAVEFORM(ARegion *region,
|
||||
GPU_matrix_translate_2f(rect.xmin, yofs);
|
||||
GPU_matrix_scale_2f(w, h);
|
||||
|
||||
immUnbindProgram();
|
||||
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
|
||||
GPU_matrix_pop();
|
||||
|
||||
@@ -857,11 +863,11 @@ void ui_draw_but_WAVEFORM(ARegion *region,
|
||||
GPU_matrix_push();
|
||||
GPU_matrix_translate_2f(rect.xmin, yofs);
|
||||
GPU_matrix_scale_2f(w, h);
|
||||
|
||||
immUnbindProgram();
|
||||
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
|
||||
waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
|
||||
waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, colors_alpha[2]);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
GPU_matrix_pop();
|
||||
}
|
||||
/* PARADE / YCC (3 channels) */
|
||||
@@ -872,7 +878,7 @@ void ui_draw_but_WAVEFORM(ARegion *region,
|
||||
SCOPES_WAVEFRM_YCC_JPEG))
|
||||
{
|
||||
const int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
|
||||
|
||||
immUnbindProgram();
|
||||
GPU_matrix_push();
|
||||
GPU_matrix_translate_2f(rect.xmin, yofs);
|
||||
GPU_matrix_scale_2f(w3, h);
|
||||
@@ -889,6 +895,7 @@ void ui_draw_but_WAVEFORM(ARegion *region,
|
||||
scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
|
||||
|
||||
GPU_matrix_pop();
|
||||
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
||||
}
|
||||
|
||||
/* min max */
|
||||
|
||||
@@ -26,6 +26,16 @@ GPUVertFormat *immVertexFormat();
|
||||
void immBindShader(GPUShader *shader);
|
||||
/** Call after your last immEnd, or before binding another program. */
|
||||
void immUnbindProgram();
|
||||
/**
|
||||
* Check if there is a shader bound.
|
||||
*
|
||||
* Useful to trigger asserts when immediate mode drawing and
|
||||
* batch based drawing are mixed. It isn't allowed to have an immediate mode shader bound when a
|
||||
* batch is drawn.
|
||||
*
|
||||
* TODO: We should move these asserts to batch drawing, but didn't do that as it was never forced.
|
||||
*/
|
||||
bool immIsShaderBound();
|
||||
|
||||
/** Must supply exactly vertex_len vertices. */
|
||||
void immBegin(GPUPrimType, uint vertex_len);
|
||||
|
||||
@@ -73,6 +73,11 @@ void immUnbindProgram()
|
||||
imm->shader = nullptr;
|
||||
}
|
||||
|
||||
bool immIsShaderBound()
|
||||
{
|
||||
return imm->shader != nullptr;
|
||||
}
|
||||
|
||||
GPUShader *immGetShader()
|
||||
{
|
||||
return imm->shader;
|
||||
|
||||
Reference in New Issue
Block a user