2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup gpu
|
2018-08-30 01:56:08 +10:00
|
|
|
*/
|
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2024-03-23 01:24:18 +01:00
|
|
|
#include "GPU_shader.hh"
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2024-11-27 17:37:04 +01:00
|
|
|
#include "gpu_shader_private.hh"
|
|
|
|
|
|
2023-02-12 16:09:23 +01:00
|
|
|
/* Cache of built-in shaders (each is created on first use). */
|
|
|
|
|
static GPUShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{nullptr}};
|
2015-12-06 21:20:19 +01:00
|
|
|
|
2023-02-13 12:49:22 +01:00
|
|
|
static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader)
|
|
|
|
|
{
|
|
|
|
|
switch (shader) {
|
|
|
|
|
case GPU_SHADER_TEXT:
|
|
|
|
|
return "gpu_shader_text";
|
|
|
|
|
case GPU_SHADER_KEYFRAME_SHAPE:
|
|
|
|
|
return "gpu_shader_keyframe_shape";
|
|
|
|
|
case GPU_SHADER_SIMPLE_LIGHTING:
|
|
|
|
|
return "gpu_shader_simple_lighting";
|
|
|
|
|
case GPU_SHADER_3D_IMAGE:
|
|
|
|
|
return "gpu_shader_3D_image";
|
|
|
|
|
case GPU_SHADER_3D_IMAGE_COLOR:
|
|
|
|
|
return "gpu_shader_3D_image_color";
|
|
|
|
|
case GPU_SHADER_2D_CHECKER:
|
|
|
|
|
return "gpu_shader_2D_checker";
|
|
|
|
|
case GPU_SHADER_2D_DIAG_STRIPES:
|
|
|
|
|
return "gpu_shader_2D_diag_stripes";
|
|
|
|
|
case GPU_SHADER_ICON:
|
|
|
|
|
return "gpu_shader_icon";
|
|
|
|
|
case GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE:
|
|
|
|
|
return "gpu_shader_2D_image_overlays_merge";
|
|
|
|
|
case GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE:
|
|
|
|
|
return "gpu_shader_2D_image_overlays_stereo_merge";
|
|
|
|
|
case GPU_SHADER_2D_IMAGE_DESATURATE_COLOR:
|
|
|
|
|
return "gpu_shader_2D_image_desaturate_color";
|
|
|
|
|
case GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR:
|
|
|
|
|
return "gpu_shader_2D_image_shuffle_color";
|
|
|
|
|
case GPU_SHADER_2D_IMAGE_RECT_COLOR:
|
|
|
|
|
return "gpu_shader_2D_image_rect_color";
|
2023-02-26 13:23:40 +01:00
|
|
|
case GPU_SHADER_ICON_MULTI:
|
|
|
|
|
return "gpu_shader_icon_multi";
|
2023-02-13 12:49:22 +01:00
|
|
|
case GPU_SHADER_3D_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_uniform_color";
|
|
|
|
|
case GPU_SHADER_3D_FLAT_COLOR:
|
|
|
|
|
return "gpu_shader_3D_flat_color";
|
|
|
|
|
case GPU_SHADER_3D_SMOOTH_COLOR:
|
|
|
|
|
return "gpu_shader_3D_smooth_color";
|
|
|
|
|
case GPU_SHADER_3D_DEPTH_ONLY:
|
|
|
|
|
return "gpu_shader_3D_depth_only";
|
|
|
|
|
case GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_clipped_uniform_color";
|
|
|
|
|
case GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_polyline_uniform_color";
|
|
|
|
|
case GPU_SHADER_3D_POLYLINE_CLIPPED_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_polyline_uniform_color_clipped";
|
|
|
|
|
case GPU_SHADER_3D_POLYLINE_FLAT_COLOR:
|
|
|
|
|
return "gpu_shader_3D_polyline_flat_color";
|
|
|
|
|
case GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR:
|
|
|
|
|
return "gpu_shader_3D_polyline_smooth_color";
|
|
|
|
|
case GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_line_dashed_uniform_color";
|
|
|
|
|
case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA:
|
|
|
|
|
return "gpu_shader_2D_point_uniform_size_uniform_color_aa";
|
|
|
|
|
case GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA:
|
|
|
|
|
return "gpu_shader_2D_point_uniform_size_uniform_color_outline_aa";
|
|
|
|
|
case GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR:
|
|
|
|
|
return "gpu_shader_3D_point_varying_size_varying_color";
|
|
|
|
|
case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA:
|
|
|
|
|
return "gpu_shader_3D_point_uniform_size_uniform_color_aa";
|
|
|
|
|
case GPU_SHADER_2D_AREA_BORDERS:
|
|
|
|
|
return "gpu_shader_2D_area_borders";
|
|
|
|
|
case GPU_SHADER_2D_WIDGET_BASE:
|
|
|
|
|
return "gpu_shader_2D_widget_base";
|
|
|
|
|
case GPU_SHADER_2D_WIDGET_BASE_INST:
|
|
|
|
|
return "gpu_shader_2D_widget_base_inst";
|
|
|
|
|
case GPU_SHADER_2D_WIDGET_SHADOW:
|
|
|
|
|
return "gpu_shader_2D_widget_shadow";
|
2024-11-23 16:42:38 +01:00
|
|
|
case GPU_SHADER_2D_NODE_SOCKET:
|
|
|
|
|
return "gpu_shader_2D_node_socket";
|
|
|
|
|
case GPU_SHADER_2D_NODE_SOCKET_INST:
|
|
|
|
|
return "gpu_shader_2D_node_socket_inst";
|
2023-02-13 12:49:22 +01:00
|
|
|
case GPU_SHADER_2D_NODELINK:
|
|
|
|
|
return "gpu_shader_2D_nodelink";
|
|
|
|
|
case GPU_SHADER_2D_NODELINK_INST:
|
|
|
|
|
return "gpu_shader_2D_nodelink_inst";
|
|
|
|
|
case GPU_SHADER_GPENCIL_STROKE:
|
2023-02-26 15:22:13 +01:00
|
|
|
return "gpu_shader_gpencil_stroke";
|
2024-06-04 20:05:35 +02:00
|
|
|
case GPU_SHADER_SEQUENCER_STRIPS:
|
|
|
|
|
return "gpu_shader_sequencer_strips";
|
VSE: Faster timeline thumbnail drawing
VSE timeline, when many (hundreds/thousands) of thumbnails were visible, was
very slow to redraw. This PR makes them 3-10x faster to redraw, by stopping
doing things that are slow :) Part of #126087 thumbnail improvements task.
- No longer do mute semitransparency or corner rounding on the CPU, do it in
shader instead.
- Stop creating a separate GPU texture for each thumbnail, on every repaint,
and drawing each thumbnail as a separate draw call. Instead, put thumbnails
into a single texture atlas (using a simple shelf packing algorithm), and
draw them in batch, passing data via UBO. The atlas is still re-created every
frame, but that does not seem to be a performance issue. Thumbnails are
cropped horizontally based on how much of their parts are visible (e.g. a
narrow strip on screen), so realistically the atlas size is kinda
proportional to screen size, and ends up being just several megabytes of data
transfer between CPU -> GPU each frame.
On this Sprite Fright edit timeline view (612 visible thumbnails), time taken
to repaint the timeline window:
- Mac (M1 Max, Metal): 68.1ms -> 4.7ms
- Windows (Ryzen 5950X, RTX 3080Ti, OpenGL): 23.7ms -> 6.8ms
This also fixes a visual issue with thumbnails, where when strips are very
tall, the "rounded corners" that were poked right into the thumbnail bitmap
on the CPU were showing up due to actual bitmap being scaled up a lot.
Pull Request: https://projects.blender.org/blender/blender/pulls/126972
2024-09-03 08:25:15 +02:00
|
|
|
case GPU_SHADER_SEQUENCER_THUMBS:
|
|
|
|
|
return "gpu_shader_sequencer_thumbs";
|
2024-02-25 17:22:58 +01:00
|
|
|
case GPU_SHADER_INDEXBUF_POINTS:
|
|
|
|
|
return "gpu_shader_index_2d_array_points";
|
|
|
|
|
case GPU_SHADER_INDEXBUF_LINES:
|
|
|
|
|
return "gpu_shader_index_2d_array_lines";
|
|
|
|
|
case GPU_SHADER_INDEXBUF_TRIS:
|
|
|
|
|
return "gpu_shader_index_2d_array_tris";
|
2023-02-13 12:49:22 +01:00
|
|
|
default:
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-02 01:05:35 +02:00
|
|
|
|
2023-02-13 12:49:22 +01:00
|
|
|
static const char *builtin_shader_create_info_name_clipped(eGPUBuiltinShader shader)
|
|
|
|
|
{
|
|
|
|
|
switch (shader) {
|
|
|
|
|
case GPU_SHADER_3D_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_uniform_color_clipped";
|
|
|
|
|
case GPU_SHADER_3D_FLAT_COLOR:
|
|
|
|
|
return "gpu_shader_3D_flat_color_clipped";
|
|
|
|
|
case GPU_SHADER_3D_SMOOTH_COLOR:
|
|
|
|
|
return "gpu_shader_3D_smooth_color_clipped";
|
|
|
|
|
case GPU_SHADER_3D_DEPTH_ONLY:
|
|
|
|
|
return "gpu_shader_3D_depth_only_clipped";
|
|
|
|
|
case GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_line_dashed_uniform_color_clipped";
|
|
|
|
|
case GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA:
|
|
|
|
|
return "gpu_shader_3D_point_uniform_size_uniform_color_aa_clipped";
|
2025-01-06 15:42:07 +01:00
|
|
|
case GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR:
|
|
|
|
|
return "gpu_shader_3D_polyline_uniform_color_clipped";
|
2023-02-13 12:49:22 +01:00
|
|
|
default:
|
2025-01-06 15:42:07 +01:00
|
|
|
BLI_assert_msg(false, "Clipped shader configuration not available.");
|
2023-02-13 12:49:22 +01:00
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-09-14 09:32:19 -03:00
|
|
|
|
2019-02-06 09:15:16 +11:00
|
|
|
GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
|
2019-02-10 11:02:06 +11:00
|
|
|
eGPUShaderConfig sh_cfg)
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2019-02-06 09:15:16 +11:00
|
|
|
BLI_assert(shader < GPU_SHADER_BUILTIN_LEN);
|
2019-02-10 11:02:06 +11:00
|
|
|
BLI_assert(sh_cfg < GPU_SHADER_CFG_LEN);
|
2024-09-25 20:14:06 +10:00
|
|
|
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
# pragma GCC diagnostic push
|
|
|
|
|
# pragma GCC diagnostic ignored "-Warray-bounds"
|
|
|
|
|
#endif
|
2019-02-10 11:02:06 +11:00
|
|
|
GPUShader **sh_p = &builtin_shaders[sh_cfg][shader];
|
2024-09-25 20:14:06 +10:00
|
|
|
#ifdef __GNUC__
|
|
|
|
|
# pragma GCC diagnostic pop
|
|
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-02-12 16:09:23 +01:00
|
|
|
if (*sh_p == nullptr) {
|
2019-02-10 11:02:06 +11:00
|
|
|
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
|
2023-02-13 12:49:22 +01:00
|
|
|
/* Common case. */
|
|
|
|
|
*sh_p = GPU_shader_create_from_info_name(builtin_shader_create_info_name(shader));
|
2023-02-12 16:09:23 +01:00
|
|
|
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. */
|
|
|
|
|
GPU_shader_bind(*sh_p);
|
|
|
|
|
GPU_shader_uniform_1i(*sh_p, "lineSmooth", 1);
|
2024-11-27 17:37:04 +01:00
|
|
|
/* WORKAROUND: See is_polyline declaration. */
|
|
|
|
|
blender::gpu::unwrap(*sh_p)->is_polyline = true;
|
2022-01-17 14:45:22 +01:00
|
|
|
}
|
2019-02-06 09:15:16 +11:00
|
|
|
}
|
2019-02-10 11:02:06 +11:00
|
|
|
else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
2019-02-06 09:15:16 +11:00
|
|
|
/* In rare cases geometry shaders calculate clipping themselves. */
|
2025-01-06 15:42:07 +01:00
|
|
|
const char *info_name_clipped = builtin_shader_create_info_name_clipped(shader);
|
|
|
|
|
if (!blender::StringRefNull(info_name_clipped).is_empty()) {
|
|
|
|
|
*sh_p = GPU_shader_create_from_info_name(info_name_clipped);
|
|
|
|
|
}
|
2019-02-06 09:15:16 +11:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert(0);
|
|
|
|
|
}
|
2016-11-08 22:53:59 -06:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-06 09:15:16 +11:00
|
|
|
return *sh_p;
|
|
|
|
|
}
|
2020-07-28 20:04:15 +02:00
|
|
|
|
2019-02-06 09:15:16 +11:00
|
|
|
GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
|
|
|
|
|
{
|
|
|
|
|
return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT);
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-02 19:37:22 +10:00
|
|
|
void GPU_shader_free_builtin_shaders()
|
2015-12-06 21:20:19 +01:00
|
|
|
{
|
2025-05-20 12:43:58 +02:00
|
|
|
/* Make sure non is bound before deleting. */
|
|
|
|
|
GPU_shader_unbind();
|
2019-02-06 09:15:16 +11:00
|
|
|
for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
|
|
|
|
|
for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) {
|
|
|
|
|
if (builtin_shaders[i][j]) {
|
|
|
|
|
GPU_shader_free(builtin_shaders[i][j]);
|
2023-02-12 16:09:23 +01:00
|
|
|
builtin_shaders[i][j] = nullptr;
|
2019-02-06 09:15:16 +11:00
|
|
|
}
|
2016-11-08 22:53:59 -06:00
|
|
|
}
|
2016-10-16 18:43:24 -04:00
|
|
|
}
|
2015-12-06 21:20:19 +01:00
|
|
|
}
|