Files
test2/source/blender/gpu/intern/gpu_shader_builtin.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

288 lines
11 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2005 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
2018-08-30 01:56:08 +10:00
*/
#include "BKE_global.hh"
#include "BLI_utildefines.h"
#include "GPU_capabilities.hh"
#include "GPU_shader.hh"
#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 BuiltinShader *builtin_shaders[GPU_SHADER_CFG_LEN][GPU_SHADER_BUILTIN_LEN] = {{nullptr}};
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";
case GPU_SHADER_ICON_MULTI:
return "gpu_shader_icon_multi";
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_3D_POINT_FLAT_COLOR:
return "gpu_shader_3D_point_flat_color";
case GPU_SHADER_3D_POINT_UNIFORM_COLOR:
return "gpu_shader_3D_point_uniform_color";
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";
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";
case GPU_SHADER_2D_NODELINK:
return "gpu_shader_2D_nodelink";
case GPU_SHADER_GPENCIL_STROKE:
return "gpu_shader_gpencil_stroke";
case GPU_SHADER_SEQUENCER_STRIPS:
return "gpu_shader_sequencer_strips";
2024-09-03 08:25:15 +02:00
case GPU_SHADER_SEQUENCER_THUMBS:
return "gpu_shader_sequencer_thumbs";
VSE: Do Scopes on the GPU, improve their look, HDR for waveform/parade Faster and better looking VSE scopes & "show overexposed". Waveform & RGB Parade now can also show HDR color intensities. (Note: this is only about VSE scopes; Image Space scopes are to be improved separately) - Waveform, RGB Parade, Vectorscope scopes are done on the GPU now, by drawing points for each input pixel, and placing them according to scope logic. The point drawing is implemented in a compute shader, with a fragment shader resolve pass; this is because drawing lots of points in the same location is very slow on some GPUs (e.g. Apple). The compute shader rasterizer is several times faster on regular desktop GPU as well. - If a non-default color management is needed (e.g. VSE colorspace is not the same as display colorspace, or a custom look transform is used etc. etc.), then transform the VSE preview texture into display space RGBA 16F texture using OCIO GPU machinery, and calculate scopes from that. - The "show overexposed" (zebra) preview option is also done on the GPU now. - Waveform/Parade scopes unlock zoom X/Y aspect for viewing HDR scope, similar to how it was done for HDR histograms recently. - Added SEQ_preview_cache.hh that holds GPU textures of VSE preview, this is so that when you have a preview and several scopes, each of them does not have to create/upload their own GPU texture (that would both waste memory, and be slow). Screenshots and performance details in the PR. Pull Request: https://projects.blender.org/blender/blender/pulls/144867
2025-08-26 12:25:43 +02:00
case GPU_SHADER_SEQUENCER_SCOPE_RASTER:
return "gpu_shader_sequencer_scope_raster";
case GPU_SHADER_SEQUENCER_SCOPE_RESOLVE:
return "gpu_shader_sequencer_scope_resolve";
case GPU_SHADER_SEQUENCER_ZEBRA:
return "gpu_shader_sequencer_zebra";
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";
default:
BLI_assert_unreachable();
return "";
}
}
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";
case GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR:
return "gpu_shader_3D_polyline_uniform_color_clipped";
default:
BLI_assert_msg(false, "Clipped shader configuration not available.");
return "";
}
}
blender::gpu::Shader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
eGPUShaderConfig sh_cfg)
{
BLI_assert(shader < GPU_SHADER_BUILTIN_LEN);
2024-09-25 20:14:06 +10:00
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Warray-bounds"
#endif
BuiltinShader **sh_p = &builtin_shaders[sh_cfg][shader];
2024-09-25 20:14:06 +10:00
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
if (*sh_p == nullptr) {
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
/* Common case. */
const char *info_name = builtin_shader_create_info_name(shader);
*sh_p = MEM_new<BuiltinShader>(__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<BuiltinShader>(__func__, info_name_clipped);
}
}
else {
BLI_assert(0);
}
}
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))
{
blender::gpu::Shader *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. */
sh->is_polyline = true;
}
}
return (*sh_p)->get();
}
static void gpu_shader_warm_builtin_shader_async(eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg)
{
BLI_assert(shader < GPU_SHADER_BUILTIN_LEN);
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Warray-bounds"
#endif
BuiltinShader **sh_p = &builtin_shaders[sh_cfg][shader];
#ifdef __GNUC__
# pragma GCC diagnostic pop
#endif
if (*sh_p == nullptr) {
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
/* Common case. */
const char *info_name = builtin_shader_create_info_name(shader);
*sh_p = MEM_new<BuiltinShader>(__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<BuiltinShader>(__func__, info_name_clipped);
}
}
else {
BLI_assert(0);
}
}
(*sh_p)->ensure_compile_async();
}
blender::gpu::Shader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader)
{
return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT);
}
void GPU_shader_builtin_warm_up()
{
if ((G.debug & G_DEBUG_GPU) && (GPU_backend_get_type() == GPU_BACKEND_OPENGL)) {
/* On some system (Mesa OpenGL), doing this warm up seems to breaks something related to debug
* hooks and makes the Blender application hang. */
return;
}
if (GPU_use_subprocess_compilation() && (GPU_backend_get_type() == GPU_BACKEND_OPENGL)) {
/* The overhead of creating the subprocesses at this exact moment can create bubbles during the
* startup process. It is usually fast enough on OpenGL that we can skip it. */
return;
}
/* Ordered by first usage in default startup screen.
* Adding more to this list will delay the scheduling of engine shaders and increase time to
* first pixel. */
gpu_shader_warm_builtin_shader_async(GPU_SHADER_TEXT, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_WIDGET_BASE, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_3D_UNIFORM_COLOR, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR,
GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_3D_IMAGE_COLOR, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_NODE_SOCKET, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_WIDGET_BASE_INST, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR,
GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_IMAGE_DESATURATE_COLOR,
GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR,
GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_WIDGET_SHADOW, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_DIAG_STRIPES, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_IMAGE_RECT_COLOR, GPU_SHADER_CFG_DEFAULT);
gpu_shader_warm_builtin_shader_async(GPU_SHADER_2D_AREA_BORDERS, GPU_SHADER_CFG_DEFAULT);
}
void GPU_shader_free_builtin_shaders()
{
/* Make sure non is bound before deleting. */
GPU_shader_unbind();
for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) {
MEM_SAFE_DELETE(builtin_shaders[i][j]);
}
}
}