From ad1bb4602dfa012057722b49beff4f1895e60811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 11 Jun 2025 17:28:30 +0200 Subject: [PATCH] Fix: GPU: Assert on startup in Vulkan caused by polyline The polyline workarounds were not working as expected since #139627 as it was not garanteed that the polylines shader would be correctly initialized with the workaround tag. Adding a wrapper class to ensure the initialization fixes the issue. --- .../blender/gpu/intern/gpu_shader_builtin.cc | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/source/blender/gpu/intern/gpu_shader_builtin.cc b/source/blender/gpu/intern/gpu_shader_builtin.cc index d9c3090aa80..888847065eb 100644 --- a/source/blender/gpu/intern/gpu_shader_builtin.cc +++ b/source/blender/gpu/intern/gpu_shader_builtin.cc @@ -13,9 +13,15 @@ #include "gpu_shader_private.hh" +struct BuiltinShader : blender::gpu::StaticShader { + /* WORKAROUND: This is needed for the polyline workaround default initialization. */ + bool init = false; + + BuiltinShader(std::string info_name) : blender::gpu::StaticShader(info_name) {} +}; + /* Cache of built-in shaders (each is created on first use). */ -static blender::gpu::StaticShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = { - {nullptr}}; +static BuiltinShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{nullptr}}; static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader) { @@ -147,7 +153,7 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" #endif - blender::gpu::StaticShader **sh_p = &builtin_shaders[sh_cfg][shader]; + BuiltinShader **sh_p = &builtin_shaders[sh_cfg][shader]; #ifdef __GNUC__ # pragma GCC diagnostic pop #endif @@ -156,27 +162,13 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { /* Common case. */ const char *info_name = builtin_shader_create_info_name(shader); - *sh_p = MEM_new(__func__, info_name); - if (ELEM(shader, - GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, - GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, - GPU_SHADER_3D_POLYLINE_FLAT_COLOR, - GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR)) - { - /* Set a default value for `lineSmooth`. - * Ideally this value should be set by the caller. */ - GPUShader *sh = (*sh_p)->get(); - GPU_shader_bind(sh); - GPU_shader_uniform_1i(sh, "lineSmooth", 1); - /* WORKAROUND: See is_polyline declaration. */ - blender::gpu::unwrap(sh)->is_polyline = true; - } + *sh_p = MEM_new(__func__, info_name); } else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { /* In rare cases geometry shaders calculate clipping themselves. */ const char *info_name_clipped = builtin_shader_create_info_name_clipped(shader); if (!blender::StringRefNull(info_name_clipped).is_empty()) { - *sh_p = MEM_new(__func__, info_name_clipped); + *sh_p = MEM_new(__func__, info_name_clipped); } } else { @@ -184,6 +176,24 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, } } + if ((*sh_p)->init == false) { + (*sh_p)->init = true; + if (ELEM(shader, + GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR, + GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR, + GPU_SHADER_3D_POLYLINE_FLAT_COLOR, + GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR)) + { + GPUShader *sh = (*sh_p)->get(); + /* Set a default value for `lineSmooth`. + * Ideally this value should be set by the caller. */ + GPU_shader_bind(sh); + GPU_shader_uniform_1i(sh, "lineSmooth", 1); + /* WORKAROUND: See is_polyline declaration. */ + blender::gpu::unwrap(sh)->is_polyline = true; + } + } + return (*sh_p)->get(); } @@ -196,7 +206,7 @@ static void gpu_shader_warm_builtin_shader_async(eGPUBuiltinShader shader, eGPUS # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" #endif - blender::gpu::StaticShader **sh_p = &builtin_shaders[sh_cfg][shader]; + BuiltinShader **sh_p = &builtin_shaders[sh_cfg][shader]; #ifdef __GNUC__ # pragma GCC diagnostic pop #endif @@ -205,13 +215,13 @@ static void gpu_shader_warm_builtin_shader_async(eGPUBuiltinShader shader, eGPUS if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { /* Common case. */ const char *info_name = builtin_shader_create_info_name(shader); - *sh_p = MEM_new(__func__, info_name); + *sh_p = MEM_new(__func__, info_name); } else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { /* In rare cases geometry shaders calculate clipping themselves. */ const char *info_name_clipped = builtin_shader_create_info_name_clipped(shader); if (!blender::StringRefNull(info_name_clipped).is_empty()) { - *sh_p = MEM_new(__func__, info_name_clipped); + *sh_p = MEM_new(__func__, info_name_clipped); } } else {